<commit_before>#
# This file is part of Fidus Writer <http://www.fiduswriter.org>
#
# Copyright (C) 2013 <NAME>, <NAME>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import time

from django.conf import settings
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.utils import simplejson
from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf
from django.core.exceptions import ValidationError
from django.template import RequestContext
from django.db import transaction, IntegrityError
from django.contrib.auth.models import User
from django.db.models import Max, Count

from bibliography.models import Entry, EntryType, EntryField, EntryCategory, EntryTypeAlias, EntryFieldAlias

from text.models import AccessRight

from django.core.serializers.python import Serializer

class SimpleSerializer(Serializer):
    def end_object( self, obj ):
        self._current['id'] = obj._get_pk_val()
        self.objects.append( self._current )
serializer = SimpleSerializer()

@login_required
def index(request):
    response = {}
    
    response.update(csrf(request))
    return render_to_response('bibliography/index.html', response, context_instance = RequestContext(request))

def save_bib_to_db(inserting_obj):
    try:
        the_entry = Entry(**inserting_obj)
        the_entry.save()
        return the_entry
    except IntegrityError:
        similar = Entry.objects.filter(**inserting_obj)
        if (len(similar) == 0):
            inserting_obj['entry_key'] = inserting_obj['entry_key']+ '+'
            return save_bib_to_db(inserting_obj)
        else:
            return False

#bibtex file import
@login_required
@transaction.commit_on_success
def import_bibtex_js(request):
    response = {}
    status = 405
    if request.is_ajax() and request.method == 'POST' :
        from bibliography.bib import Persons
        from bibliography.bib import BibDate
        response['errors'] = []
        response['warning'] = []
        bibs = simplejson.loads(request.POST['bibs'])
        status = 200
        e_types = {}
        for e_type in EntryType.objects.all():
            e_types[e_type.type_name] = e_type
        e_types_alias = {}
        for e_type in EntryTypeAlias.objects.all():
            e_types_alias[e_type.type_name] = e_type
        e_fields = {}
        for e_field in EntryField.objects.all():
            e_fields[e_field.field_name] = e_field
        e_fields_alias = {}
        for e_field in EntryFieldAlias.objects.all():
            e_fields_alias[e_field.field_name] = e_field
        new_bibs = []
        response['bib_ids']=[]
        for bib_key in bibs :
            bib = bibs[bib_key]
            bib_type_name = bib['bibtype']
            #the entry type must exists
            try:
                the_type = e_types[bib_type_name]
            except KeyError:
                try:
                    type_alias = e_types_alias[bib_type_name]
                    the_type = type_alias.type_alias
                except KeyError:
                    the_type  = e_types['misc']
                    response['warning'].append(bib_key + ' is saved as misc. Fidus Writer does not support "' + bib_type_name + '"')
            inserting_obj = {
                'entry_key': bib_key,
                'entry_owner': request.user,
                'entry_type': the_type
            }
            the_fields = {}
            #save the posted values
            for key, val in bib.iteritems() :
                if key in ['bibtype', 'year', 'month'] :
                    #do not save the value of type, year and month
                    continue
                else :
                    try:
                        field_type = e_fields[key]
                    except KeyError:
                        try:
                            field_alias = e_fields_alias[key]
                            field_type = field_alias.field_alias
                        except KeyError:
                            response['errors'].append(key + ' of ' + bib_key + ' could not be saved. Fidus Writer does not support the field.')
                            continue
                    if 'l_name' == field_type.field_type :
                        #restore name list value like "author"
                        persons = Persons(val)
                        val = persons.get_names()
                    elif 'f_date' == field_type.field_type :
                        #restore date value like "date"
                        bib_date = BibDate(val)
                        val = bib_date.date
                    if isinstance(val, basestring) :
                        val = val.strip("{}")
                    if isinstance(val, list) :
                        val = ' and '.join(val)
                    the_fields[field_type.field_name] = val
            inserting_obj['fields'] = simplejson.dumps(the_fields)        
            the_entry = save_bib_to_db(inserting_obj)
            if the_entry != False:
                new_bibs.append(the_entry)
                response['bib_ids'].append(the_entry.id)
            response['bibs'] = serializer.serialize(new_bibs, fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
    return HttpResponse(
        simplejson.dumps(response),
        content_type = 'application/json; charset=utf8',
        status=status
    )

def check_access_rights(other_user_id, this_user):
    other_user_id = int(other_user_id)
    has_access = False
    if other_user_id == 0:
        has_access = True
    elif other_user_id == this_user.id:
        has_access = True
    elif AccessRight.objects.filter(text__owner=other_user_id, user=this_user).count() > 0:
        has_access = True
    return has_access    

#returns list of bibliography items
@login_required
def biblist_js(request):
    response = {}
    status = 403
    if request.is_ajax() and request.method == 'POST' :
        user_id = request.POST['owner_id']
        if len(user_id.split(',')) > 1:
            user_ids = user_id.split(',')
            status = 200
            for user_id in user_ids:
                if check_access_rights(user_id, request.user) == False:
                    status = 403
            if status == 200:
                response['bibList'] = serializer.serialize(Entry.objects.filter(entry_owner__in = user_ids), fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
                response['bibCategories']  = serializer.serialize(EntryCategory.objects.filter(category_owner__in = user_ids)) 
        else:
            if check_access_rights(user_id, request.user):
                if int(user_id) == 0:
                    user_id = request.user.id
                if user_id == request.user.id:    
                    last_modified_onclient = int(request.POST['last_modified'])
                    number_of_entries_onclient = int(request.POST['number_of_entries'])
                    aggregation_values = Entry.objects.filter(entry_owner=user_id).aggregate(Max('last_modified'),Count('id'))
                    last_modified__max = aggregation_values['last_modified__max']
                    number_of_entries_onserver = aggregation_values['id__count']
                    if last_modified__max:
                        last_modified_onserver = int(time.mktime(last_modified__max.timetuple()))
                    else:
                        last_modified_onserver = 0
                    if last_modified_onclient < last_modified_onserver or number_of_entries_onclient > number_of_entries_onserver:
                        response['bibList'] = serializer.serialize(Entry.objects.filter(entry_owner = user_id), fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
                        response['last_modified'] = last_modified_onserver
                        response['number_of_entries'] = number_of_entries_onserver
                else:
                    response['bibList'] = serializer.serialize(Entry.objects.filter(entry_owner = user_id), fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
                response['bibCategories']  = serializer.serialize(EntryCategory.objects.filter(category_owner = user_id))
                status = 200                
    return HttpResponse(
        simplejson.dumps(response),
        content_type = 'application/json; charset=utf8',
        status=status
    )
           

#save changes or create a new entry
@login_required
def save_js(request):<commit_msg>don't cache when not showing own bib entries<commit_after>#
# This file is part of Fidus Writer <http://www.fiduswriter.org>
#
# Copyright (C) 2013 <NAME>, <NAME>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import time

from django.conf import settings
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.utils import simplejson
from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf
from django.core.exceptions import ValidationError
from django.template import RequestContext
from django.db import transaction, IntegrityError
from django.contrib.auth.models import User
from django.db.models import Max, Count

from bibliography.models import Entry, EntryType, EntryField, EntryCategory, EntryTypeAlias, EntryFieldAlias

from text.models import AccessRight

from django.core.serializers.python import Serializer

class SimpleSerializer(Serializer):
    def end_object( self, obj ):
        self._current['id'] = obj._get_pk_val()
        self.objects.append( self._current )
serializer = SimpleSerializer()

@login_required
def index(request):
    response = {}
    
    response.update(csrf(request))
    return render_to_response('bibliography/index.html', response, context_instance = RequestContext(request))

def save_bib_to_db(inserting_obj):
    try:
        the_entry = Entry(**inserting_obj)
        the_entry.save()
        return the_entry
    except IntegrityError:
        similar = Entry.objects.filter(**inserting_obj)
        if (len(similar) == 0):
            inserting_obj['entry_key'] = inserting_obj['entry_key']+ '+'
            return save_bib_to_db(inserting_obj)
        else:
            return False

#bibtex file import
@login_required
@transaction.commit_on_success
def import_bibtex_js(request):
    response = {}
    status = 405
    if request.is_ajax() and request.method == 'POST' :
        from bibliography.bib import Persons
        from bibliography.bib import BibDate
        response['errors'] = []
        response['warning'] = []
        bibs = simplejson.loads(request.POST['bibs'])
        status = 200
        e_types = {}
        for e_type in EntryType.objects.all():
            e_types[e_type.type_name] = e_type
        e_types_alias = {}
        for e_type in EntryTypeAlias.objects.all():
            e_types_alias[e_type.type_name] = e_type
        e_fields = {}
        for e_field in EntryField.objects.all():
            e_fields[e_field.field_name] = e_field
        e_fields_alias = {}
        for e_field in EntryFieldAlias.objects.all():
            e_fields_alias[e_field.field_name] = e_field
        new_bibs = []
        response['bib_ids']=[]
        for bib_key in bibs :
            bib = bibs[bib_key]
            bib_type_name = bib['bibtype']
            #the entry type must exists
            try:
                the_type = e_types[bib_type_name]
            except KeyError:
                try:
                    type_alias = e_types_alias[bib_type_name]
                    the_type = type_alias.type_alias
                except KeyError:
                    the_type  = e_types['misc']
                    response['warning'].append(bib_key + ' is saved as misc. Fidus Writer does not support "' + bib_type_name + '"')
            inserting_obj = {
                'entry_key': bib_key,
                'entry_owner': request.user,
                'entry_type': the_type
            }
            the_fields = {}
            #save the posted values
            for key, val in bib.iteritems() :
                if key in ['bibtype', 'year', 'month'] :
                    #do not save the value of type, year and month
                    continue
                else :
                    try:
                        field_type = e_fields[key]
                    except KeyError:
                        try:
                            field_alias = e_fields_alias[key]
                            field_type = field_alias.field_alias
                        except KeyError:
                            response['errors'].append(key + ' of ' + bib_key + ' could not be saved. Fidus Writer does not support the field.')
                            continue
                    if 'l_name' == field_type.field_type :
                        #restore name list value like "author"
                        persons = Persons(val)
                        val = persons.get_names()
                    elif 'f_date' == field_type.field_type :
                        #restore date value like "date"
                        bib_date = BibDate(val)
                        val = bib_date.date
                    if isinstance(val, basestring) :
                        val = val.strip("{}")
                    if isinstance(val, list) :
                        val = ' and '.join(val)
                    the_fields[field_type.field_name] = val
            inserting_obj['fields'] = simplejson.dumps(the_fields)        
            the_entry = save_bib_to_db(inserting_obj)
            if the_entry != False:
                new_bibs.append(the_entry)
                response['bib_ids'].append(the_entry.id)
            response['bibs'] = serializer.serialize(new_bibs, fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
    return HttpResponse(
        simplejson.dumps(response),
        content_type = 'application/json; charset=utf8',
        status=status
    )

def check_access_rights(other_user_id, this_user):
    other_user_id = int(other_user_id)
    has_access = False
    if other_user_id == 0:
        has_access = True
    elif other_user_id == this_user.id:
        has_access = True
    elif AccessRight.objects.filter(text__owner=other_user_id, user=this_user).count() > 0:
        has_access = True
    return has_access    

#returns list of bibliography items
@login_required
def biblist_js(request):
    response = {}
    status = 403
    if request.is_ajax() and request.method == 'POST' :
        user_id = request.POST['owner_id']
        if len(user_id.split(',')) > 1:
            user_ids = user_id.split(',')
            status = 200
            for user_id in user_ids:
                if check_access_rights(user_id, request.user) == False:
                    status = 403
            if status == 200:
                response['bibList'] = serializer.serialize(Entry.objects.filter(entry_owner__in = user_ids), fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
                response['bibCategories']  = serializer.serialize(EntryCategory.objects.filter(category_owner__in = user_ids)) 
        else:
            if check_access_rights(user_id, request.user):
                if int(user_id) == 0:
                    user_id = request.user.id
                if user_id == request.user.id and request.POST.__contains__('last_modified'):    
                    last_modified_onclient = int(request.POST['last_modified'])
                    number_of_entries_onclient = int(request.POST['number_of_entries'])
                    aggregation_values = Entry.objects.filter(entry_owner=user_id).aggregate(Max('last_modified'),Count('id'))
                    last_modified__max = aggregation_values['last_modified__max']
                    number_of_entries_onserver = aggregation_values['id__count']
                    if last_modified__max:
                        last_modified_onserver = int(time.mktime(last_modified__max.timetuple()))
                    else:
                        last_modified_onserver = 0
                    if last_modified_onclient < last_modified_onserver or number_of_entries_onclient > number_of_entries_onserver:
                        response['bibList'] = serializer.serialize(Entry.objects.filter(entry_owner = user_id), fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
                        response['last_modified'] = last_modified_onserver
                        response['number_of_entries'] = number_of_entries_onserver
                else:
                    response['bibList'] = serializer.serialize(Entry.objects.filter(entry_owner = user_id), fields=('entry_key', 'entry_owner', 'entry_type', 'entry_cat', 'fields'))
                response['bibCategories']  = serializer.serialize(EntryCategory.objects.filter(category_owner = user_id))
                status = 200                
    return HttpResponse(
        simplejson.dumps(response),
        content_type = 'application/json; charset=utf8',
        status=status
    )
           

#save changes or create a new entry
@login_required
def save_js(request):
{'fraction_non_alphanumeric': 0.08964359224352725, 'fraction_numerical': 0.003683241252302026, 'mean_word_length': 2.17233676975945, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6018770', 'n_tokens_mistral': 5214, 'n_tokens_neox': 4911, 'n_words': 1202}