class Material(models.Model):
    material_id = CharField(max_length=64, blank=True, default="")
    material_type = IntegerField(default=1)
    text = TextField(blank=True, default='')
    version = IntegerField(null=True, blank=True, default=0)
    title = CharField(max_length=255, verbose_name=_("Title"))
    description = TextField(blank=True)
    categories = CharField(max_length=256, blank=True, verbose_name=_("Categories"))
    keywords = TextField(blank=True, default="")
    language = CharField(max_length=2, blank=True, default="vi", verbose_name=_("Language"))
    license_id = IntegerField(null=True, default=1)
    modified = DateTimeField(auto_now=True, blank=True)
    derived_from = CharField(max_length=64, blank=True)
    creator = models.ForeignKey(User)
    status = IntegerField(null=True, default=1)
    author = CharField(max_length=100, blank=True, default="")
    editor = CharField(max_length=100, blank=True, default="")
    licensor = CharField(max_length=100, blank=True, default="")
    maintainer = CharField(max_length=100, blank=True, default="")
    translator = CharField(max_length=100, blank=True, default="")
    coeditor = CharField(max_length=100, blank=True, default="")

    def to_dict(self):
        material = dict()
        material['id'] = self.id
        material['material_id'] = self.material_id
        material['material_type'] = int(self.material_type)
        material['text'] = self.text
        material['version'] = self.version
        material['title'] = self.title
        material['description'] = self.description
        material['categories'] = self.categories
        material['status'] = self.status
        material['modified'] = self.modified

        if self.author:
            material['author'] = self.author

        return material class Author(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    author_id = models.IntegerField() class Settings(models.Model):
    """
    A table to store configurable settings with a pair of name and value,
    also support multiple languagues.
    """
    name = CharField(max_length=64)
    value = TextField(blank=True, default='')
    language= CharField(max_length=8, default='vi') class MaterialFeature(models.Model):
    material_id = CharField(max_length=64, null=True)
    weight = IntegerField(default=1) class FeaturedAuthor(models.Model):
    author_id = IntegerField(null=False)
    weight = IntegerField(default=1) def normalize_string(value):
    """
    Converts to lowercase, removes non-word characters but still keep alphanumerics
    and converts spaces to hyphens. Also strips leading and trailing whitespace.
    Also converts vietnamese characters 'Đ' and 'đ'.
    """
    value = re.sub(u'Đ', 'D', value)
    value = re.sub(u'đ', 'd', value)
    value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
    value = re.sub('[^\w\d\s-]', '', value).strip().lower()
    return mark_safe(re.sub('[-\s]+', '-', value)) def normalize_filename(value):
    value = re.sub(u'Đ', 'D', value)
    value = re.sub(u'đ', 'd', value)
    value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
    value = re.sub('[^\.\w\d\s-]', '', value).strip().lower()
    return mark_safe(re.sub('[-\s]+', '-', value)) def extract_images(content):
    image_parse = ImageParse()
    image_parse.feed(content)
    return image_parse.url_images def vpr_get_material(mid, version=1):
    version = version or 1
    result = vpr_request("GET", "materials/%s/%s" % (mid, str(version)))
    return result def vpr_get_category(cat_id):
    result = vpr_request("GET", "categories/%s" % cat_id)
    return result def vpr_get_person(pid, is_count=False):
    if not pid:
        return None
    if is_count:
        result = vpr_request("GET", "persons/%s?count=1" % pid)
    else:
        result = vpr_request("GET", "persons/%s" % pid)
    return result def vpr_get_persons():
    result = vpr_request("GET", "persons")
    return result def vpr_get_categories():
    from django.utils.translation import ugettext as _

    result = vpr_request("GET", "categories")
    for r in result:
        r['name'] = _(r['name'])
    return result def vpr_browse(**kwargs):
    page = kwargs.get("page", 1)
    categories = kwargs.get("categories", "")
    types = kwargs.get("types", "")
    languages = kwargs.get("languages", "")
    author = kwargs.get("author", "")
    sort = kwargs.get("sort", "title")
    params = ["page=%s" % page]
    if categories and categories != "0":
        params.append("categories=%s&or=categories" % categories)

    if types and types != "0" and types != '1,2':
        params.append("material_type=%s" % types)

    if languages and languages != "0" and languages != 'vi,en':
        params.append("language=%s" % languages)

    if author:
        params.append("author=%s" % author)

    params.append("sort_on=%s" % sort)
    params = "&".join(params)

    result = vpr_request("GET", "materials?names=1&%s" % params)

    # update image url
    items = []
    for material in result.get('results', []):
        if material['image']:
            material['image'] = os.path.join(settings.VPR_URL, 'materials',
                material['material_id'], str(material['version']), 'image')
        items.append(material)
    result['results'] = items

    #Get information facet
    facet = vpr_request("GET", "facet?%s" % params)
    result['facet'] = facet
    return result def vpr_materials_by_author(aid, page=1, sort_on=''):
    result = vpr_request("GET", "materials?author=%s&page=%s&sort_on=%s" % (aid, str(page), sort_on))
    return result def vpr_search(**kwargs):
    keyword = kwargs.get('keyword', '')
    page = kwargs.get("page", 1)
    search_type = kwargs.get('search_type', '')
    material_type = kwargs.get('material_type', '')

    search_string = "search?kw=%s&page=%s"
    if search_type == "m":
        search_string += "&on=m"
    elif search_type == "p":
        search_string += "&on=p"

    if material_type != "":
        search_string += "&type=" + material_type

    result = vpr_request("GET", search_string % (urllib.quote(keyword.encode("utf8")), page))
    return result def vpr_delete_person(pid):
    result = vpr_request("DELETE", "persons/%s" % pid)
    return result def vpr_get_statistic_data(mid, version, field_name):
    if not version:
        result = vpr_request('GET', "materials/%s/%s" % (mid, field_name))
    else:
        result = vpr_request('GET', "materials/%s/%s/%s" % (mid, version, field_name))

    return result def voer_get_attachment_info(attach_id):
    result = vpr_request('GET', "mfiles/%s/" % attach_id)

    return result def vpr_create_material(material, files=None):
    # result = vpr_request("POST", "materials", material)
    # return result
    url = settings.VPR_URL + "materials"
    if not files:
        result = vpr_request("POST", "materials", data=material)
        # r = requests.post(url, data=material)
    else:
        result = vpr_request("POST", "materials", data=material, files=files)
        # r = requests.post(url, files=files, data=material)

    return result def vpr_get_material_images(mid):
    list_ids = vpr_request('GET', 'materials/%s/mfiles/' % mid)
    list_images = {}
    for image_id in list_ids:
        image = vpr_request('GET', 'mfiles/%s' % image_id)
        if 'name' in image:
            list_images[image['name']] = '%s' % image_id
    return list_images def voer_update_author(author):
    url = settings.VPR_URL
    files = {}
    if 'avatar' in author:
        file_path = author['avatar']

        file_name = os.path.basename(file_path)
        file_data = open(file_path, 'rb').read()
        files = {'avatar': (file_name, file_data)}

        os.remove(file_path)

    r = requests.put(url + 'persons/%s/' % author['id'], files=files, data=author)

    if r.status_code == 200:
        result = json.loads(r.text)
    else:
        result = {}

    return result def voer_add_favorite(pid, mid, version):
    if not version:
        result = vpr_request('POST', "materials/%s/favorites" % mid, {'person': pid})
    else:
        result = vpr_request('POST', "materials/%s/%s/favorites" % (mid, version), {'person': pid})

    return result def vpr_search_author(author_name):
    """
    Search author by name
    """
    result = vpr_request('GET', 'search?kw=%s&on=p' % author_name)
    return result def vpr_search_module(keyword):
    result = vpr_request('GET', 'search?kw=%s&on=m&type=1' % keyword)
    return result def voer_add_view_count(mid, version):
    if not version:
        result = vpr_request('PUT', "materials/%s/counter" % mid, {'increment': 1})
    else:
        result = vpr_request('PUT', "materials/%s/%s/counter" % (mid, version), {'increment': 1})

    return result def vpr_get_content_file(fid):
    url = settings.VPR_URL + "mfiles/%s/get" % fid
    r = requests.request("GET", url)
    return r def vpr_get_user_avatar(pid, detele_flag=False):
    if detele_flag:
        url = settings.VPR_URL + "persons/%s/avatar?delete=1" % pid
    else:
        url = settings.VPR_URL + "persons/%s/avatar" % pid

    r = requests.request("GET", url)

    if r.status_code == 200:
        return r def vpr_get_favorite(pid, page=1):
    result = vpr_request("GET", "persons/%s/favorites/?page=%s" % (pid, str(page)))
    return result def vpr_delete_favorite(pid, mid, version=''):
    if not version:
        url = settings.VPR_URL + 'materials/%s/favorites?person=%s' % (mid, pid)
    else:
        url = settings.VPR_URL + 'materials/%s/%s/favorites?person=%s' % (mid, version, pid)

    r = requests.request('DELETE', url)

    result = json.loads(r.content)

    return result def vpr_user_add_rate(pid, rate, mid, version=''):
    if version == '' or version == 0:
        result = vpr_request('POST', "materials/%s/rates" % mid, {'person': pid, 'rate': rate})
    else:
        result = vpr_request('POST', "materials/%s/%s/rates" % (mid, version), {'person': pid, 'rate': rate})
    return result def vpr_user_delete_rate(pid, mid, version=''):
    if version == '' or version == 0 or version is None:
        url = settings.VPR_URL + 'materials/%s/rates?person=%s' % (mid, pid)
    else:
        url = settings.VPR_URL + 'materials/%s/%s/rates?person=%s' % (mid, version, pid)

    r = requests.request('DELETE', url)

    result = json.loads(r.content)

    return result def is_material_rated(mid, version, pid):
    is_rated = False

    if pid:
        if version == '' or version == 0 or version is None:
            result = vpr_request('GET', "materials/%s/rates?person=%s" % (mid, pid))
        else:
            result = vpr_request('GET', "materials/%s/%s/rates?person=%s" % (mid, version, pid))

        if result['rate']:
            is_rated = True

    return is_rated def vpr_is_favorited(mid, version, pid):
    is_favorited = False

    if pid:
        if version == '' or version == 0 or version is None:
            result = vpr_request('GET', "materials/%s/favorites?person=%s" % (mid, pid))
        else:
            result = vpr_request('GET', "materials/%s/%s/favorites?person=%s" % (mid, version, pid))

        if result['favorite'] == 1:
            is_favorited = True

    return is_favorited def vpt_import(file_path):
    import_url = settings.VPT_URL + 'import'
    token = 'a9af1d6ca60243a38eb7d52dd344f7cb'
    cid = 'vietdt'
    payload = {'token': token, 'cid': cid}

    file_name = os.path.basename(file_path)
    file_data = open(file_path, 'rb').read()
    files = {'file': (file_name, file_data)}
    r = requests.post(import_url, files=files, data=payload)
    return json.loads(r.text) def vpt_get_url(task_id):
    """
    ping status continuosly to get download url
    """
    # TODO: should perform at client side
    # TODO: should put these defaults in settings
    retry = 20
    interval = 5

    n = 0
    while n < retry:
        result = vpt_check_status(task_id)
        if result.has_key('url'):
            return result['url']
        # pause a few second before continue
        time.sleep(interval)
        n += 1 def vpt_download(url):
    """
    download transformed file
    """
    r = requests.get(url, stream=True)
    return r def vpr_request(method, path, data=None, **kwargs):
    client_token, created = vpw.models.Settings.objects.get_or_create(name=settings.CLIENT_ID)
    token = client_token.value
    cookies = {"vpr_client": settings.CLIENT_ID, "vpr_token": token}
    url = settings.VPR_URL + path
    r = requests.request(method, url, data=data, cookies=cookies, **kwargs)
    status_code = r.status_code
    if status_code == 401:  #UNAUTHORIZED retry one more
        token = vpr_request_token()
        cookies = {"vpr_client": settings.CLIENT_ID, "vpr_token": token}
        r = requests.request(method, url, data=data, cookies=cookies, **kwargs)

    if method == "DELETE":
        result = r.status_code
    else:
        try:
            result = json.loads(r.text)
        except:
            result = {}
    return result class ModuleForm(MaterialForm):
    body = forms.CharField(widget=TinyMCE(attrs={'rows': 7}), required=False)

    def __init__(self, *args, **kwargs):
        super(ModuleForm, self).__init__(*args, **kwargs)
        if kwargs.get('instance'):
            self.fields['body'].initial = kwargs['instance'].text class EditProfileForm(forms.Form):
    current_password = forms.CharField(required=True, max_length=50)
    email = forms.EmailField(max_length=255)
    new_password = forms.CharField(max_length=255, required=False)
    confirm_password = forms.CharField(max_length=255, required=False)
    fullname = forms.CharField(max_length=255)
    homepage = forms.URLField(max_length=255, required=False, widget=forms.TextInput(attrs={'class': 'form-control typetext', 'id': 'InputHomepage', 'placeholder': _('Enter homepage')}))
    affiliation_url = forms.URLField(max_length=255, required=False, widget=forms.TextInput(attrs={'class': 'form-control typetext', 'id': 'InputAffiliationURL', 'placeholder': _('Enter affiliaton URL')}))
    biography = forms.CharField(widget=TinyMCE(attrs={'rows': 7}), required=False)

    def clean(self):
        cleaned_data = self.cleaned_data # individual field's clean methods have already been called
        new_password = cleaned_data.get("new_password")
        confirm_password = cleaned_data.get("confirm_password")
        if new_password != confirm_password:
            self._errors["confirm_password"] = self.error_class([u"Confirm password is not matchs"])

        return cleaned_data class CollectionForm(MaterialForm):
    body = forms.CharField(required=False) class SettingsForm(forms.Form):
    module_license = forms.CharField(widget=TinyMCE(attrs={'rows': 4}), required=False)
    collection_license = forms.CharField(widget=TinyMCE(attrs={'rows': 4}), required=False) class RecaptchaRegistrationForm(RegistrationForm):
    recaptcha = forms.CharField(max_length=512, required=False, widget=forms.HiddenInput())

    def clean(self):
        cleaned_data = super(RecaptchaRegistrationForm, self).clean()

        recaptcha_response = cleaned_data.get('recaptcha', '')
        data = {
            'response': recaptcha_response,
            'secret': settings.RECAPTCHA_SECRET_KEY
        }
        resp = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
        result_json = resp.json()
        if not result_json.get('success', False):
            raise ValidationError("Captcha validation failed")

        return cleaned_data
import json
import math
import os
import urllib
import zipfile
import re
import random
import csv
import time
from string import lower
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
from django.db.models.query_utils import Q
from django.forms.forms import NON_FIELD_ERRORS
from django.forms.util import ErrorList
from django.template.defaultfilters import filesizeformat
from django.utils.datetime_safe import datetime
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib import messages
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.http.response import HttpResponseRedirect, Http404
from django.contrib.auth.decorators import login_required, user_passes_test
from django.conf import settings
from django.utils.translation import ugettext as _, get_language
from registration.backends.default.views import RegistrationView
from django.core.urlresolvers import reverse
from UniversalAnalytics import Tracker
from vpw.models import Material, Author, Settings, MaterialFeature, FeaturedAuthor
from vpw.utils import normalize_string, normalize_filename, extract_images
from vpw.vpr_api import vpr_get_material, vpr_get_category, vpr_get_person, vpr_get_persons, \
    vpr_get_categories, vpr_browse, vpr_materials_by_author, vpr_search, vpr_delete_person, vpr_get_statistic_data, \
    voer_get_attachment_info, vpr_create_material, vpr_get_material_images, voer_update_author, voer_add_favorite, vpr_search_author, vpr_search_module, \
    voer_add_view_count, vpr_get_content_file, vpr_get_user_avatar, vpr_get_favorite, vpr_delete_favorite,vpr_user_add_rate, vpr_user_delete_rate, is_material_rated, vpr_is_favorited
from vpw.vpr_api import vpt_import, vpt_get_url, vpt_download, vpr_request
from vpw.forms import ModuleForm, EditProfileForm, CollectionForm, SettingsForm, RecaptchaRegistrationForm
                material['text'] = content

            file_data = []
            file_attachments = vpr_get_statistic_data(mid, material['version'], 'mfiles')
            for file_attachment_id in file_attachments:
                attachment_info = voer_get_attachment_info(file_attachment_id)

                image_mime_types = ['image/gif', 'image/jpeg', 'image/png', 'image/bmp', 'image/tiff', 'image/jp2',
                                    'image/iff']
                if attachment_info.get('mime_type') not in image_mime_types:
                    file_tmp = {}
                    file_tmp['title'] = attachment_info['name']
                    file_tmp['attachment_id'] = file_attachment_id
                    file_data.append(file_tmp)

        else:
            file_data = []

        link_data = vpr_get_statistic_data(mid, material['version'], 'links')
        new_links = []
        for link in link_data:
            if link['material_id'] != cid:
                new_links.append(link)

        material['links'] = new_links

        if material['author']:
            material_authors = []
            author_ids = material['author'].split(',')

            for pid in author_ids:
                pid = pid.strip()
                person = vpr_get_person(pid)
                if person:
                    material_authors.append(person)
            material['material_authors'] = material_authors

    else:
        material = {}
        file_data = []

    rate_data = vpr_get_statistic_data(cid, '', 'rates')
    collection['rates'] = _calculate_rate_data(rate_data)
    collection['is_rated'] = is_material_rated(cid, '', person_id)

    # Generate outline html
    strOutline = "<ul id='outline-collection' class='list-module-name-content'>%s</ul>" % get_outline(cid, outline[
        'content'])

    # Lay thong tin tac gia bao gom ca thong ke
    author = []
    if 'author' in collection and collection['author']:
        author_id_list = collection['author'].split(',')

        for pid in author_id_list:
            pid = pid.strip()
            person = vpr_get_person(pid, True)
            if person:
                author.append(person)

    category = vpr_get_category(collection['categories'])

    voer_facebook_id = settings.VOER_FACEBOOK_APP_ID

    response = render(request, "frontend/collection_detail.html", {"collection": collection, "material": material, "author": author,
                       "category": category, "outline": strOutline, 'file_data': file_data, 'voer_fb_id': voer_facebook_id})

    if cookie_name not in request.COOKIES:
        max_age = settings.VPW_SESSION_MAX_AGE * 24 * 60 * 60
        response.set_cookie(cookie_name, True, max_age)

    if delete_cookie:
        response.delete_cookie(key=rating_name_cookie)

    return response


@login_required
def user_module_detail(request, mid):
    try:
        material = Material.objects.get(id=mid)
        # Chi co tac gia moi vao xem duoc bai
        if material.creator_id != request.user.id:
            raise PermissionDenied
        author_id = request.user.author.author_id
        author = vpr_get_person(author_id, True)
        authors = [author]
        category = vpr_get_category(material.categories)

        # get origin material
        origin_mid = getattr(material, "material_id", "")
        origin_version = getattr(material, "version", "")
        if origin_mid:
            origin_material = vpr_get_material(origin_mid, origin_version)
            origin_authors = _get_author(origin_material)
        else:
            origin_material = None
            origin_authors = None

        if material.material_type == MODULE_TYPE:
            return render(request, "frontend/module_detail.html", {
                "material": material, "author": authors,
                "category": category, "unpublished": True,
                "origin_material": origin_material, "origin_authors": origin_authors,
            })
        else:
            raise PermissionDenied
    except Material.DoesNotExist:
        raise PermissionDenied


@login_required
def user_collection_detail(request, cid, mid):
    try:
        collection = Material.objects.get(id=cid)

        # Chi co tac gia moi vao xem duoc bai
        if collection.creator_id != request.user.id:
            raise PermissionDenied
        author_id = request.user.author.author_id

        author = vpr_get_person(author_id)