# HG changeset patch # User verrierj # Date 1325840956 -3600 # Node ID 07448cec6e8aa86bad3e5a6c15d0548d8f92964e # Parent b4b11979cd4acd67a61d5c21f155dae5c982bc0c# Parent c28d4dc49a50141899cfd5adfbefe7ab69f4e565 Merge with c28d4dc49a50141899cfd5adfbefe7ab69f4e565 diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/api/ldt/handlers.py --- a/src/ldt/ldt/api/ldt/handlers.py Thu Jan 05 17:33:44 2012 +0100 +++ b/src/ldt/ldt/api/ldt/handlers.py Fri Jan 06 10:09:16 2012 +0100 @@ -19,7 +19,7 @@ @require_extended def update(self, request, project_id): """ - This method is called when a PUT request is sent to http:///api/ldt/projects/.format. + This method is called when a PUT request is sent to http:///api/ldt/projects/.. is the ldt_id field of the project. If does not match any project on the platform, a 410 ("Gone") error will be returned. is the format of the data sent back by the server. It can be 'json', 'yaml', 'xml' or 'pickle'. @@ -45,10 +45,76 @@ A platform is reachable at http://localhost/. It contains a project with ID a0593b58-f258-11df-80e1-00145ea4a2be. This project has a content milosforman_amadeus, which has a cutting Salieri inside the view "View at the last recording". The following JSON file exists in the current directory : + Example of ajax call with 2 differents annotations : + $('#mon_ajax').click(function(e) { + var url = "{% url project_api project_id='c8448f21-272d-11e1-876b-c8bcc896c290.' emitter_format='json' %}"; + + var monjson = '{\ + "annotations": [\ + {\ + "type": "c_07BA1284-5F24-71A8-1EE2-423EED999B8A",\ + "type_title": "New cutting name if necessary",\ + "media": "briandepalma_scarfacedepalma",\ + "begin": 1600000,\ + "end": 2100000,\ + "content": {\ + "data": "new scar annot"\ + },\ + "tags": [ "json","dude" ]\ + }\ + ],\ + "meta": {\ + "creator": "John Doe",\ + "created": "2011-09-10T09:12:58"\ + }\ + }'; + var monjson2 = '{\ + "annotations": [\ + {\ + "type": "c_07BA1284-5F24-71A8-1EE2-423EED999B8A",\ + "type_title": "New cutting name if necessary",\ + "media": "briandepalma_scarfacedepalma",\ + "begin": 2400000,\ + "end": 3000000,\ + "content": {\ + "data": "ntm iam 2"\ + },\ + "tags": [ "jak" ]\ + }\ + ],\ + "meta": {\ + "creator": "John Doe",\ + "created": "2011-09-10T09:12:58"\ + }\ + }'; + + $.ajax({ + url: url, + type: 'PUT', + contentType: 'application/json', + data: monjson, + // bug with jquery >= 1.5, "json" adds a callback so we don't specify dataType + //dataType: 'json', + success: function(json, textStatus, XMLHttpRequest) { + alert("success = " + json); + }, + error: function(jqXHR, textStatus, errorThrown) { + alert("ERROR = " + jqXHR.responseText + ", " + errorThrown); + } + }); + }); + + If we send a PUT request with curl : + $curl -X PUT http://localhost/api/ldt/projects/a0593b58-f258-11df-80e1-00145ea4a2be.json -d @example.JSON -H "content-type:application/json" + A new cutting titled "New cutting name" will be created with the first annotation inside, and the annotation "Annotation about Salieri" + will be added to the Salieri cutting. The returned file is : + { "annotations": [ { - "type": "New cutting name", + "id": "6d8baf01-ffb1-11e0-810c-001485352c9a", + "type": "id_annot_type", + "type_title": "New cutting name", "media": "milosforman_amadeus", "begin": 50000, "end": 900000, @@ -58,44 +124,9 @@ "tags": [ "json" ] }, { - "type": "Salieri", - "media": "milosforman_amadeus", - "begin": 700000, - "end": 1200000, - "content": { - "data": "Annotation about Salieri" - }, - "tags": [ "xml", "test", "blop" ] - } - ], - - "meta": { - "creator": "John Doe", - "created": "2011-09-10T09:12:58" - } - } - - If we send a PUT request with curl : - $curl -X PUT http://localhost/api/ldt/projects/a0593b58-f258-11df-80e1-00145ea4a2be.json -d @example.JSON -H "content-type:application/json" - A new cutting titled "New cutting name" will be created with the first annotation inside, and the annotation "Annotation about Salieri" - will be added to the Salieri cutting. The returned file is : - - { - "annotations": [ - { - "id": "6d8baf01-ffb1-11e0-810c-001485352c9a", - "type": "New cutting name", - "media": "milosforman_amadeus", - "begin": 50000, - "end": 900000, - "content": { - "data": "new annotation" - }, - "tags": [ "json" ] - }, - { - "id": "6d8baf00-ffb1-11e0-8097-001485352c9a", - "type": "Salieri", + "id": "6d8baf00-ffb1-11e0-8097-001485352c9b", + "type": "another_id_annot_type", + "type_title": "Salieri", "media": "milosforman_amadeus", "begin": 700000, "end": 1200000, @@ -112,16 +143,17 @@ } } - """ - - if request.content_type == 'application/json': + """ + #return rc.ALL_OK + #assert False, " TIBO str(request.data) = " + str(request.data) + if request.content_type.lower().find("application/json") > -1 : try: project = Project.objects.get(ldt_id=project_id) except Project.DoesNotExist: - return rc.NOT_HERE + return rc.NOT_HERE adder = LdtAnnotation(project) - logging.debug("request json " + repr(request.data)) + logging.debug("request json " + repr(request.data)) meta = request.data['meta'] author = meta['creator'] @@ -131,9 +163,10 @@ for a in new_annotations: dur = str(a['end'] - a['begin']) begin = str(a['begin']) - new_id = adder.add(a['media'], a['type'], a['content']['data'], '', a['tags'], begin, dur, author, date) + new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['data'], '', a['tags'], begin, dur, author, date) if not new_id: return rc.BAD_REQUEST + adder.save() a['id'] = new_id return request.data @@ -141,12 +174,12 @@ else: logging.debug("request " + repr(request)) data = request.data - ldt_str = data["ldt"] + ldt_str = data["ldt"] logging.debug("request data" + repr(ldt_str)) if not ldt_str: - return rc.ALL_OK + return rc.BAD_REQUEST project = Project.objects.get(ldt_id=project_id) diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/api/ldt/urls.py --- a/src/ldt/ldt/api/ldt/urls.py Thu Jan 05 17:33:44 2012 +0100 +++ b/src/ldt/ldt/api/ldt/urls.py Fri Jan 06 10:09:16 2012 +0100 @@ -5,5 +5,5 @@ project_handler = Resource(ProjectHandler, None) urlpatterns = patterns('', - url(r'projects/(?P[^/.]+)\.?(?P.*)$', project_handler), + url(r'projects/(?P[^/.]+)\.?(?P.*)$', project_handler, name='project_api'), ) diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/api/middleware/__init__.py diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/api/middleware/pistonput.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/api/middleware/pistonput.py Fri Jan 06 10:09:16 2012 +0100 @@ -0,0 +1,18 @@ +""" +This middleware changes the request header content type because +piston does not like 'charset=UTF-8" in PUT request +""" + +from django.conf import settings + +class PistonPutMiddleware(object): + + def process_request(self, request): + if request.method in ('PUT') and not 'boundary=' in request.META['CONTENT_TYPE']: + request.META['CONTENT_TYPE'] = [c.strip() for c in request.META['CONTENT_TYPE'].split(";") ][0] + return None +# if request.method == 'PUT' and request.META.has_key('CONTENT_TYPE') : +# if request.META['CONTENT_TYPE'] == 'application/x-www-form-urlencoded; charset=UTF-8': +# request.META['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' +# if request.META['CONTENT_TYPE'] == 'application/json; charset=UTF-8': +# request.META['CONTENT_TYPE'] = 'application/json' \ No newline at end of file diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/ldt_utils/utils.py --- a/src/ldt/ldt/ldt_utils/utils.py Thu Jan 05 17:33:44 2012 +0100 +++ b/src/ldt/ldt/ldt_utils/utils.py Fri Jan 06 10:09:16 2012 +0100 @@ -152,6 +152,7 @@ elementfile = lxml.etree.SubElement(elementInit, 'file') elementfile.set('src', settings.WEB_URL + django.core.urlresolvers.reverse(method, args=url)) + elementfile.set('src', django.core.urlresolvers.reverse(method, args=url)) if(search): elementfile.set("segsel", settings.WEB_URL + django.core.urlresolvers.reverse(search, args=url)) @@ -168,78 +169,89 @@ self.parser = lxml.etree.XMLParser(remove_blank_text=True) self.ldtdoc = lxml.etree.parse(StringIO(project.ldt.encode("utf-8")), self.parser) self.to_add = True - - def add(self, media, cutting, title, text, tags_list, begin, dur, author, date, view="View at the last recording", color="16776960"): + # add( a['media'], a['type'], a['type_title, a[data], '', a['tags'], begin, dur, author, date) + def add(self, media, cutting_id, cutting_title, title, text, tags_list, begin, dur, author, date, view_id=None, color="16776960"): """ Add an annotation to a project. begin and dur must be strings. Default color is yellow. """ + # We check if the project references the media. path_media = self.ldtdoc.xpath('/iri/medias/media[@id="%s"]' % media) - if len(path_media) == 0: self.to_add = False return False - + + # We get the content node path_annotations = self.ldtdoc.xpath('/iri/annotations')[0] path_content = path_annotations.xpath('content[@id="%s"]' % media) - + # If the content node does not exist, we create it if len(path_content) == 0: path_content = lxml.etree.SubElement(path_annotations, 'content') path_content.set('id', media) path_content = [path_content] - - path_ensemble = path_content[0].xpath('ensemble[decoupage[title="%s"]]' % cutting) + + # We generate the cutting id if necessary + if cutting_id is None or cutting_id=="" : + cutting_id = 'c_' + generate_uuid() + + # We get the ensemble node + path_ensemble = path_content[0].xpath('ensemble[decoupage[@id="%s"]]' % cutting_id) if len(path_ensemble) == 0: - path_ensemble = path_content[0].xpath('ensemble') - - if len(path_ensemble) == 0: + # If the ensemble node does not exist, we create it path_ensemble = lxml.etree.SubElement(path_content[0], 'ensemble') path_ensemble.set('id', 'g_' + generate_uuid()) path_ensemble.set('title', _('Personal cutting')) path_ensemble.set('author', 'undefined') - path_ensemble = [path_ensemble] - + path_ensemble = [path_ensemble] + #else: + # path_ensemble = path_content[0].xpath('ensemble') + + + # We get the elements node in the good decoupage node ensemble_id = path_ensemble[0].get('id') - decoupage_elements = path_ensemble[0].xpath('decoupage[title="%s"]/elements' % cutting) + decoupage_elements = path_ensemble[0].xpath('decoupage[@id="%s"]/elements' % cutting_id) if len(decoupage_elements) == 0: + # If the decoupage node does not exist, we create it and its elements node decoupage = lxml.etree.SubElement(path_ensemble[0], 'decoupage') - cutting_id = 'c_' + generate_uuid() + #cutting_id = "c_" + generate_uuid() decoupage.set('id', cutting_id) decoupage.set('author', author) decoupage_title = lxml.etree.SubElement(decoupage, 'title') - decoupage_title.text = cutting + decoupage_title.text = cutting_title lxml.etree.SubElement(decoupage, 'abstract') decoupage_elements = lxml.etree.SubElement(decoupage, 'elements') decoupage_elements = [decoupage_elements] - else: - cutting_id = path_ensemble[0].xpath('decoupage[title="%s"]' % cutting)[0].get('id') - - path_view = self.ldtdoc.xpath('/iri/displays/display[@title="%s"]' % view) - if len(path_view) == 0: - path_view = self.ldtdoc.xpath('/iri/displays/display[@title="Init view"]') + #else: + # cutting_id = path_ensemble[0].xpath('decoupage[title="%s"]' % cutting_title)[0].get('id') - if len(path_view) != 0: - content_display = path_view[0].xpath('content[@id="%s"]' % media) - if len(content_display) == 0: - content_display = lxml.etree.SubElement(path_view[0], 'content') - content_display.set('id', media) - content_display = [content_display] - - dec = lxml.etree.SubElement(content_display[0], 'decoupage') - dec.set('idens', ensemble_id) - dec.set('id', cutting_id) - dec.set('tagsSelect', '') - + # We add the cutting to the view + if view_id is not None and view_id!="" : + path_view = self.ldtdoc.xpath('/iri/displays/display[@id="%s"]' % view_id) + if len(path_view) == 0: + path_view = self.ldtdoc.xpath('/iri/displays/display[@title="Init view"]') + else : + content_display = path_view[0].xpath('content[@id="%s"]' % media) + if len(content_display) == 0: + content_display = lxml.etree.SubElement(path_view[0], 'content') + content_display.set('id', media) + content_display = [content_display] + # We add the decoupage node to the content node + dec = lxml.etree.SubElement(content_display[0], 'decoupage') + dec.set('idens', ensemble_id) + dec.set('id', cutting_id) + dec.set('tagsSelect', '') + + # We add the annotation/element node element = lxml.etree.SubElement(decoupage_elements[0], 'element') - id_annotation = generate_uuid() - element.set('id', 's_' + id_annotation) + id_annotation = 's_' + generate_uuid() + element.set('id', id_annotation) element.set('begin', begin) element.set('dur', dur) element.set('author', author) element.set('date', date) element.set('color', color) abstract = lxml.etree.SubElement(element, 'abstract') - abstract.text = text + abstract.text = text title_node = lxml.etree.SubElement(element, 'title') title_node.text = title audio = lxml.etree.SubElement(element, 'audio') @@ -249,12 +261,13 @@ for tag in tags_list: tag_node = lxml.etree.SubElement(tags, 'tag') tag_node.text = tag - + return id_annotation def save(self): if self.to_add: self.project.ldt = lxml.etree.tostring(self.ldtdoc, pretty_print=True) + #assert False, " TIBO SAVE " + self.project.ldt self.project.save() def __del__(self): diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/ldt_utils/views/workspace.py --- a/src/ldt/ldt/ldt_utils/views/workspace.py Thu Jan 05 17:33:44 2012 +0100 +++ b/src/ldt/ldt/ldt_utils/views/workspace.py Fri Jan 06 10:09:16 2012 +0100 @@ -2,7 +2,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth.models import Group from django.core.cache import cache -from django.core.urlresolvers import reverse +from django.core.urlresolvers import reverse#, resolve from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.http import (HttpResponseRedirect, HttpResponseForbidden ) from ldt.indexation import get_results_with_context, highlight_documents @@ -36,10 +36,19 @@ is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + # Resolve a URL + #project_api_view, project_api_args, project_api_kwargs = resolve('/api/ldt/projects/c8448f21-272d-11e1-876b-c8bcc896c290.json') + #match = resolve('/api/ldt/projects/c8448f21-272d-11e1-876b-c8bcc896c290.json') + + # Print the URL pattern that matches the URL + #print match.url_name + # render list return render_to_response("ldt/ldt_utils/workspace.html", {'contents': content_list, 'projects': project_list, - 'is_gecko': is_gecko}, + 'is_gecko': is_gecko, #'project_api_url':"match.url_name", + #'project_api_view':match.url_name,'project_api_args':"project_api_args",'project_api_kwargs':"project_api_kwargs" + }, context_instance=RequestContext(request)) @login_required diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/ldt_utils/views_old.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/ldt_utils/views_old.py Fri Jan 06 10:09:16 2012 +0100 @@ -0,0 +1,1383 @@ +from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User, Group +from django.core.cache import cache +from django.core.urlresolvers import reverse +from django.core.paginator import Paginator, InvalidPage, EmptyPage +from django.db.models import Q +from django.forms.models import model_to_dict +from django.forms.util import ErrorList +from django.http import (HttpResponse, HttpResponseRedirect, + HttpResponseForbidden, HttpResponseServerError) +from ldt.indexation import get_results_with_context, highlight_documents +from django.shortcuts import (render_to_response, get_object_or_404, + get_list_or_404) +from django.template import RequestContext +from django.template.loader import render_to_string +from django.utils import simplejson +from django.utils.html import escape +from django.utils.translation import ugettext as _, ungettext +from forms import (LdtAddForm, SearchForm, AddProjectForm, CopyProjectForm, + ContentForm, MediaForm, GroupAddForm) +from guardian.shortcuts import remove_perm, get_objects_for_group, get_objects_for_user +from ldt.ldt_utils.models import Content +from ldt.ldt_utils.utils import boolean_convert, LdtUtils, LdtSearch +from ldt.security.utils import (assign_perm_to_obj, set_forbidden_stream, + add_change_attr, get_userlist, get_userlist_model, get_userlist_group) +from ldt.security.cache import get_cached_checker, cached_assign +from lxml.html import fragment_fromstring +from models import Media, Project +from projectserializer import ProjectSerializer +from urllib2 import urlparse +from operator import itemgetter +from itertools import groupby +import base64 +import django.core.urlresolvers +import ldt.auth as ldt_auth +import ldt.utils.path as ldt_utils_path +import logging +import lxml.etree +import mimetypes +import os +import urllib2 +import subprocess +import re +import datetime + + +@login_required +def workspace(request): + + # list of contents + content_list = add_change_attr(request.user, Content.safe_objects.all()) #@UndefinedVariable + + # get list of projects owned by the current user + project_list = add_change_attr(request.user, Project.safe_objects.filter(owner=request.user)) #@UndefinedVariable + + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + + # render list + return render_to_response("ldt/ldt_utils/workspace.html", + {'contents': content_list, 'projects': project_list, + 'is_gecko': is_gecko}, + context_instance=RequestContext(request)) + +@login_required +def groups(request): + + # get list of all published projects + group_list = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME) + + group_list = sorted(group_list.all(), key=lambda group: group.name.lower()) + group_list = add_change_attr(request.user, group_list) + + can_add_group = True if request.user.user_permissions.filter(codename='add_group') else False + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + # render list + return render_to_response("ldt/ldt_utils/groups.html", + {'groups': group_list, + 'is_gecko': is_gecko, + 'can_add_group': can_add_group}, + context_instance=RequestContext(request)) + + +@login_required +def published_project(request): + + # get list of all published projects + project_list = Project.safe_objects.filter(state=2) #@UndefinedVariable + # Search form + form = SearchForm() + + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + + # render list + return render_to_response("ldt/ldt_utils/published_projects.html", + {'projects': project_list, 'form': form, + 'is_gecko': is_gecko}, + context_instance=RequestContext(request)) + + +def popup_embed(request): + + json_url = request.GET.get("json_url") + player_id = request.GET.get("player_id") + ldt_id = request.GET.get("ldt_id") + + project = Project.safe_objects.get(ldt_id=ldt_id); #@UndefinedVariable + + stream_mode = project.stream_mode + if stream_mode != "video": + stream_mode = 'radio' + + player_width = 650 + player_height = 480 + + if stream_mode == 'radio': + player_height = 1 + + if not ldt_auth.check_access(request.user, project): + return HttpResponseForbidden(_("You can not access this project")) + + ps = ProjectSerializer(project, from_contents=False, from_display=True) + annotations = ps.get_annotations(first_cutting=True) + + rend_dict = {'json_url':json_url, 'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id, 'stream_mode': stream_mode, 'player_width': player_width, 'player_height': player_height} + + embed_rendered = dict((typestr, + (lambda s:escape(lxml.etree.tostring(fragment_fromstring(render_to_string("ldt/ldt_utils/partial/embed_%s.html" % (s), rend_dict, context_instance=RequestContext(request))), pretty_print=True)))(typestr)) + for typestr in ('player', 'seo_body', 'seo_meta', 'links')) + + rend_dict['embed_rendered'] = embed_rendered + + return render_to_response("ldt/ldt_utils/embed_popup.html", + rend_dict, + context_instance=RequestContext(request)) + + +@login_required +def projects_filter(request, filter, is_owner=False, status=0, id_group=0): + is_owner = boolean_convert(is_owner) + status = int(status) + id_group = int(id_group) + query = Q() + + if is_owner: + owner = None + try: + owner = request.user + except: + return HttpResponseServerError("

User not found

") + query &= Q(owner=owner) + + if status > 0: + query &= Q(state=status) + + if filter: + if len(filter) > 0 and filter[0] == '_': + filter = filter[1:] + query &= Q(title__icontains=filter) + + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + show_username = True + + if id_group > 0: # Search inside a group + grp = Group.objects.get(id=id_group) + project_list = get_objects_for_group(grp, 'ldt_utils.view_project').filter(query) + elif id_group == -1:# Search inside projects shared with a specific user + project_list = get_objects_for_user(request.user, 'ldt_utils.view_project', use_groups=False).exclude(owner=request.user) + else: + project_list = Project.safe_objects.filter(query) + show_username = False + + project_list = add_change_attr(request.user, project_list) + + if status == 2: + url_templ = "ldt/ldt_utils/partial/publishedprojectslist.html" + else: + url_templ = "ldt/ldt_utils/partial/projectslist.html" + + return render_to_response(url_templ, + {'projects': project_list, 'show_username':show_username, + 'is_gecko': is_gecko, 'group_id':id_group}, + context_instance=RequestContext(request)) + +def share_filter(request, filter, use_groups=False): + use_groups = boolean_convert(use_groups) + if not filter or len(filter) == 0: + raise AttributeError("filter should be a string") + + filter = filter[1:] + resp = get_userlist(request.user, filter=filter) + + if use_groups: + groups = Group.objects.filter(name__icontains=filter).exclude(name=settings.PUBLIC_GROUP_NAME)[0:20] + + for g in groups: + resp.append({'name': g.name, 'id': g.id, 'type': 'group'}) + + resp = sorted(resp, key=lambda elem: elem['name'].lower()) + + return render_to_response("ldt/ldt_utils/partial/sharewith.html", {'elem_list' : resp}, context_instance=RequestContext(request)) + +@login_required +def contents_filter(request, filter): + if filter and len(filter) > 0 and filter[0] == '_': + filter = filter[1:] + + if filter: + content_list = Content.safe_objects.filter(title__icontains=filter) #@UndefinedVariable + else: + content_list = Content.safe_objects.all() #@UndefinedVariable + + content_list = add_change_attr(request.user, content_list) + + return render_to_response("ldt/ldt_utils/partial/contentslist.html", + {'contents': content_list}, + context_instance=RequestContext(request)) + +@login_required +def groups_filter(request, filter): + if filter and len(filter) > 0 and filter[0] == '_': + filter = filter[1:] + + if filter: + group_list = request.user.groups.filter(name__icontains=filter) + search_active = True + else: + group_list = request.user.groups.all() + search_active = False + + group_list = group_list.exclude(name=settings.PUBLIC_GROUP_NAME) + group_list = sorted(group_list.all(), key=lambda group: group.name.lower()) + group_list = add_change_attr(request.user, group_list) + + + return render_to_response("ldt/ldt_utils/partial/groupslist.html", + {'groups': group_list, 'search_active': search_active}, + context_instance=RequestContext(request)) + + +def search_form(request): + form = SearchForm() + return render_to_response('ldt/ldt_utils/search_form.html', {'form': form} , context_instance=RequestContext(request)) + + +@login_required +def search_index(request): + + sform = SearchForm(request.POST) + if sform.is_valid(): + search = sform.cleaned_data["search"] + queryStr = base64.urlsafe_b64encode(search.encode('utf8')) + field = request.POST["field"] + language_code = request.LANGUAGE_CODE[:2] + + if request.POST.has_key("ldt_pres"): + url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.search_init", args=[field, queryStr]) + return render_to_response('ldt/ldt_utils/init_ldt_full.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': url}, context_instance=RequestContext(request)) + else: + results = get_results_with_context(field, search) + complete_results = [] + proj_list = Project.safe_objects.all() + results.sort(key=lambda k: k['iri_id']) + for iri_id, item in groupby(results, itemgetter('iri_id')): + try: + content = Content.objects.get(iri_id=iri_id) + except Content.DoesNotExist: + continue + segments = list(item) + to_delete = [] + for s in segments: + if not s['project_id']: + s['project_id'] = '_' + else: + project = proj_list.filter(ldt_id=s['project_id']) + if len(project) == 0: + to_delete.append(s) + + for e in to_delete: + segments.remove(e) + + if not segments: + continue + + score = sum([seg['score'] for seg in segments]) + desc = content.description if content.description else '' + complete_results.append({'list' : segments, 'score' : score, 'content_title' : content.title, 'content_id' : content.iri_id, 'content_description' : desc }) + + complete_results.sort(key=lambda k: k['score']) + + cache.set('complete_results_%s' % request.user.username, complete_results) + cache.set('search_%s' % request.user.username, search) + cache.set('field_%s' % request.user.username, field) + + paginator = Paginator (complete_results, settings.LDT_RESULTS_PER_PAGE) + page = 1 + + try: + results = paginator.page(page) + except (EmptyPage, InvalidPage): + results = paginator.page(paginator.num_pages) + + results.object_list = highlight_documents(results.object_list, search, field) + + return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request)) + + else: + return HttpResponseRedirect(reverse('ldt.ldt_utils.views.published_project')) + + +def search_listing(request): + if not cache.get('complete_results_%s' % request.user.username): + return HttpResponseRedirect(reverse('ldt.ldt_utils.views.published_project')) + + complete_results = cache.get('complete_results_%s' % request.user.username) + search = cache.get('search_%s' % request.user.username) + field = cache.get('field_%s' % request.user.username) + paginator = Paginator(complete_results, settings.LDT_RESULTS_PER_PAGE) + language_code = request.LANGUAGE_CODE[:2] + + try: + page = int(request.GET.get('page', '1')) + except ValueError: + page = 1 + + try: + results = paginator.page(page) + except (EmptyPage, InvalidPage): + results = paginator.page(paginator.num_pages) + + results.object_list = highlight_documents(results.object_list, search, field) + + return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request)) + +def search_index_get(request, field, query): + + language_code = request.LANGUAGE_CODE[:2] + + url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.search_init", args=[field, query]) + return render_to_response('ldt/ldt_utils/init_ldt.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': url}, context_instance=RequestContext(request)) + +def search_init(request, field, query): + + ldtgen = LdtUtils() + + doc = ldtgen.generate_init([field, query], 'ldt.ldt_utils.views.search_ldt', 'ldt.ldt_utils.views.search_segments') + + resp = HttpResponse(mimetype="text/xml;charset=utf-8") + resp.write(lxml.etree.tostring(doc, pretty_print=True, encoding="utf-8")) + return resp + +def search_ldt(request, field, query, edition=None): + + contentList = [] + resp = HttpResponse(mimetype="text/xml") + queryStr = "" + + if query and len(query) > 0: + queryStr = base64.urlsafe_b64decode(query.encode("ascii")).decode("utf8") + searcher = LdtSearch() + ids = {} + projIds = {} + + for result in searcher.query(field, queryStr): + ids[result["iri_id"]] = "" + projIds[result["project_id"]] = "" + + id_list = ids.keys() + projId_list = projIds.keys() + + #if edition is not None: + # ids_editions = map(lambda t:t[0], filter(lambda id: id[0] is not None, Speak.objects.filter(session__day__edition=edition).order_by("session__start_ts", "order").values_list("content__iri_id"))) + # id_list = filter(lambda id: id in id_list, ids_editions) + + contentList = Content.objects.filter(iri_id__in=id_list) #@UndefinedVariable + projectList = Project.safe_objects.filter(ldt_id__in=projId_list) + + ldtgen = LdtUtils() + # generate_ldt(contentList, title=u"", author=u"IRI Web", web_url=u"", startSegment=None, projects=None): + doc = ldtgen.generate_ldt(contentList, title=u"Recherche : " + queryStr, projects=projectList) + doc = set_forbidden_stream(doc, request.user) + doc.write(resp, pretty_print=True) + + return resp + + +def search_segments(request, field, query, edition=None): + + if query and len(query) > 0: + searcher = LdtSearch() + + queryStr = base64.urlsafe_b64decode(query.encode("ascii")).decode("utf8") + res = searcher.query(field, queryStr) + else: + res = [] + + iri_ids = None + + #if edition is not None: + # iri_ids = map(lambda t:t[0], filter(lambda id: id[0] is not None, Speak.objects.filter(session__day__edition=edition).order_by("session__start_ts", "order").values_list("content__iri_id"))) + + iri = lxml.etree.Element('iri') + doc = lxml.etree.ElementTree(iri) + + for resultMap in res: + if iri_ids is None or resultMap['iri_id'] in iri_ids: + seg = lxml.etree.SubElement(iri, 'seg') + seg.set('idctt', resultMap['iri_id']) + seg.set('idens', resultMap['ensemble_id']) + seg.set('iddec', resultMap['decoupage_id']) + seg.set('idseg', resultMap['element_id']) + seg.set('idvue', "") + seg.set('crit', "") + + #return doc + + return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8") + + +@login_required +def list_ldt(request): + contents = Content.safe_objects.all() #@UndefinedVariable + try: + owner = request.user #@UndefinedVariable + except: + return HttpResponseRedirect(settings.LOGIN_URL) + ldtProjects = Project.safe_objects.filter(owner=owner) #@UndefinedVariable + context = { + 'contents': contents, + 'projects': ldtProjects.reverse(), + } + return render_to_response('ldt/ldt_utils/ldt_list.html', context, context_instance=RequestContext(request)) + +@login_required +def list_content(request): + contents = Content.safe_objects.all() #@UndefinedVariable + context = { + 'contents': contents, + } + return render_to_response('ldt/ldt_utils/content_list.html', context, context_instance=RequestContext(request)) + +@login_required +def create_ldt_view(request): + groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME) + redirect_to = '' + if request.method == "POST" : + form = LdtAddForm(request.POST) + form_status = "none" + contents = Content.safe_objects.all() + + if form.is_valid(): + + user = request.user + project = Project.create_project(title=form.cleaned_data['title'], user=user, + contents=form.cleaned_data['contents'], + description=form.cleaned_data['description']) + + if form.cleaned_data["share"]: + assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], user) + form_status = "saved" + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + if is_gecko : + redirect_to = reverse('index_project_full', args=[project.ldt_id]) + else: + return HttpResponseRedirect(reverse('index_project', args=[project.ldt_id])) + + else: + form = LdtAddForm() + contents = Content.safe_objects.all() + form_status = "none" + + return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form, 'form_status':form_status, + 'redirect_to': redirect_to, 'create_project_action':reverse(create_ldt_view), 'language_code' : settings.LANGUAGE_CODE[2:], + 'elem_list': get_userlist(request.user)}, context_instance=RequestContext(request)) + +def created_ldt(request): + return render_to_response('ldt/ldt_utils/save_done.html', context_instance=RequestContext(request)) + + +def index_segment(request, project_id, content_id, cutting_id, ensemble_id, segment_id): + url_str = settings.WEB_URL + reverse("ldt.ldt_utils.views.init_segment", args=[project_id, content_id, ensemble_id, cutting_id, segment_id]) + post_url = "" + language_code = request.LANGUAGE_CODE[:2] + readonly = 'true' + template_path = 'ldt/ldt_utils/init_ldt.html' + + return render_to_response(template_path, {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': url_str, 'posturl': post_url, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request)) + +def init_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id): + + if project_id != u"_": + get_object_or_404(Project.safe_objects, ldt_id=project_id) + + ldtgen = LdtUtils() + doc = ldtgen.generate_init([project_id, content_id, ensemble_id, cutting_id, segment_id], 'ldt.ldt_utils.views.ldt_segment', 'ldt.ldt_utils.views.highlight_segment') + + return HttpResponse(lxml.etree.tostring(lxml.etree.ElementTree(doc), pretty_print=True), mimetype="text/xml;charset=utf-8") + +def highlight_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id): + if project_id != u"_": + get_object_or_404(Project.safe_objects, ldt_id=project_id) + + iri = lxml.etree.Element('iri') + doc = lxml.etree.ElementTree(iri) + + seg = lxml.etree.SubElement(iri, 'seg') + seg.set('idctt', content_id) + seg.set('idens', ensemble_id) + seg.set('iddec', cutting_id) + seg.set('idseg', segment_id) + seg.set('idvue', "") + seg.set('crit', "") + + return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8") + + +def ldt_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id): + + resp = HttpResponse(mimetype="text/xml") + resp['Cache-Control'] = 'no-cache, must-revalidate' + resp['Pragma'] = 'no-cache' + + if project_id and project_id != "_" : + project = Project.safe_objects.get(ldt_id=project_id) #@UndefinedVariable + ldtdoc = lxml.etree.fromstring(project.ldt.encode("utf-8")) + ldtdoc = set_forbidden_stream(ldtdoc, request.user) + displays_node = ldtdoc.find("displays") + if not displays_node: + displays_node = lxml.etree.SubElement(ldtdoc, u"displays") + res = displays_node.xpath("display") + if len(res) > 0: + display_node = res[0] + else: + display_node = lxml.etree.SubElement(displays_node, u"display", attrib={u'id':u'0', u'title': u'generated', u'idsel':unicode(content_id), u'tc':u'0'}) + + res = display_node.xpath("content[@id='%s']/decoupage[(@id='%s') and (@idens='%s')]" % (content_id, cutting_id, ensemble_id)) + if len(res) == 0: + #create node + res = display_node.xpath("content[@id='%s']" % (content_id)) + if len(res) == 0: + content_node = lxml.etree.SubElement(display_node, u"content") + else: + content_node = res[0] + lxml.etree.SubElement(content_node, u"decoupage", attrib={u'id':unicode(cutting_id), u'idens':unicode(ensemble_id)}) + active_segment_node = displays_node.find(u"activeSegment") + if not active_segment_node: + active_segment_node = lxml.etree.SubElement(displays_node, u"activeSegment") + id_node = active_segment_node.find(u"id") + if id_node: + active_segment_node.remove(id_node) + lxml.etree.SubElement(active_segment_node, u"id", attrib={u"idctt":unicode(content_id), u"idens": unicode(ensemble_id), "idcut":unicode(cutting_id), u"idseg":unicode(segment_id)}) + + resp.write(lxml.etree.tostring(ldtdoc, xml_declaration=True, encoding='utf-8', pretty_print=True)) + else: + # generate ldt from + ldtgen = LdtUtils() + content_list = Content.safe_objects.filter(iri_id=content_id) + if request.user and request.user.username: + username = request.user.username + else: + username = "webuser" + + start_segment = { + 'idcontent': content_id, + 'idgroup' : ensemble_id, + 'idcutting' : cutting_id, + 'idsegment' : segment_id + } + + doc = ldtgen.generate_ldt(content_list, "segment : ", author=username, startSegment=start_segment) + doc = set_forbidden_stream(doc, request.user) + doc.write(resp, pretty_print=('DEBUG' in dir(settings) and settings.DEBUG)) + + return resp + + +@login_required +def index_project(request, id, full=False): + + urlStr = settings.WEB_URL + reverse("space_ldt_init", args=['ldt_project', id]) + posturl = settings.WEB_URL + reverse("ldt.ldt_utils.views.save_ldt_project") + language_code = request.LANGUAGE_CODE[:2] + + try: + ldt = Project.safe_objects.get(ldt_id=id) + except Project.DoesNotExist: + return HttpResponseRedirect(reverse("ldt.ldt_utils.views.workspace")) + + if ldt.state == 2 or not request.user.has_perm('change_project', ldt): #published + readonly = 'true' + else: + readonly = 'false' + + if full: + template_path = 'ldt/ldt_utils/init_ldt_full.html' + else: + template_path = 'ldt/ldt_utils/init_ldt.html' + + return render_to_response(template_path, {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': urlStr, 'posturl': posturl, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request)) + + +def init(request, method, url): + ldtgen = LdtUtils() + + doc = ldtgen.generate_init([url], 'ldt.ldt_utils.views.' + method, None) + + library = doc.xpath('/iri/files/library')[0] + for c in Content.safe_objects.all(): + elem = lxml.etree.SubElement(library, 'file') + elem.set('src', c.iri_url()) + elem.set('video', c.videopath) + elem.set('title', c.title) + elem.set('author', '') + elem.set('category', '') + elem.set('pict', '') + elem.set('img', '') + + resp = HttpResponse(mimetype="text/xml") + resp['Cache-Control'] = 'no-cache, must-revalidate' + resp['Pragma'] = 'no-cache' + + resp.write(lxml.etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8")) + return resp + +def ldt_project(request, id): + resp = HttpResponse(mimetype="text/xml") + resp['Cache-Control'] = 'no-cache, must-revalidate' + resp['Pragma'] = 'no-cache' + + project = Project.safe_objects.get(ldt_id=id) #@UndefinedVariable + + doc = lxml.etree.fromstring(project.ldt) + doc = set_forbidden_stream(doc, request.user) + resp.write(lxml.etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8")) + + return resp + + +def project_json_id(request, id): + + project = get_object_or_404(Project.safe_objects, ldt_id=id) + + return project_json(request, project, False) + + +def project_json_externalid(request, id): + + res_proj = get_list_or_404(Project.safe_objects.order_by('-modification_date'), contents__external_id=id) #@UndefinedVariable + + return project_json(request, res_proj[0], False) + + + +def project_json(request, project, serialize_contents=True): # Not checked + + if not ldt_auth.check_access(request.user, project): + return HttpResponseForbidden(_("You can not access this project")) + + mimetype = request.REQUEST.get("mimetype") + if mimetype is None: + mimetype = "application/json; charset=utf-8" + else: + mimetype = mimetype.encode("utf-8") + if "charset" not in mimetype: + mimetype += "; charset=utf-8" + resp = HttpResponse(mimetype=mimetype) + resp['Cache-Control'] = 'no-cache, must-revalidate' + resp['Pragma'] = 'no-cache' + + indent = request.REQUEST.get("indent") + if indent is None: + indent = settings.LDT_JSON_DEFAULT_INDENT + else: + indent = int(indent) + + callback = request.REQUEST.get("callback") + escape_str = request.REQUEST.get("escape") + escape_bool = False + if escape_str: + escape_bool = {'true': True, 'false': False, "0": False, "1": True}.get(escape_str.lower()) + + + ps = ProjectSerializer(project, serialize_contents) + project_dict = ps.serialize_to_cinelab() + + json_str = simplejson.dumps(project_dict, ensure_ascii=False, indent=indent) + + if callback is not None: + json_str = "%s(%s)" % (callback, json_str) + + if escape_bool: + json_str = escape(json_str) + + resp.write(json_str) + + return resp + +def project_annotations_rdf(request, ldt_id): + + project = Project.safe_objects.get(ldt_id=ldt_id); #@UndefinedVariable + + if not ldt_auth.check_access(request.user, project): + return HttpResponseForbidden(_("You can not access this project")) + + mimetype = request.REQUEST.get("mimetype") + if mimetype is None: + mimetype = "application/rdf+xml; charset=utf-8" + else: + mimetype = mimetype.encode("utf-8") + if "charset" not in mimetype: + mimetype += "; charset=utf-8" + resp = HttpResponse(mimetype=mimetype) + resp['Cache-Control'] = 'no-cache, must-revalidate' + resp['Pragma'] = 'no-cache' + + ps = ProjectSerializer(project, from_contents=False, from_display=True) + annotations = ps.get_annotations(first_cutting=True) + + rdf_ns = u"http://www.w3.org/1999/02/22-rdf-syntax-ns#" + dc_ns = u"http://purl.org/dc/elements/1.1/" + rdf = u"{%s}" % rdf_ns + dc = u"{%s}" % dc_ns + nsmap = {u'rdf' : rdf_ns, u'dc':dc_ns} + + rdf_root = lxml.etree.Element(rdf + u"RDF", nsmap=nsmap) + + logging.debug("RDF annotations : " + repr(annotations)) #@UndefinedVariable + + for annotation in annotations: + uri = u"" + if 'uri' in annotation and annotation['uri']: + uri = unicode(annotation['uri']) + annot_desc = lxml.etree.SubElement(rdf_root, rdf + u"Description") + annot_desc.set(rdf + u'about', uri) + if annotation['title']: + lxml.etree.SubElement(annot_desc, dc + 'title').text = lxml.etree.CDATA(unicode(annotation['title'])) + if annotation['desc']: + lxml.etree.SubElement(annot_desc, dc + 'description').text = lxml.etree.CDATA(unicode(annotation['desc'])) + if annotation['tags']: + for tag in annotation['tags']: + lxml.etree.SubElement(annot_desc, dc + 'subject').text = lxml.etree.CDATA(unicode(tag)) + lxml.etree.SubElement(annot_desc, dc + 'coverage').text = u"start=%s, duration=%s" % (annotation['begin'], annotation['duration']) + + resp.write(u"\n") + resp.write(u"\n") + + resp.write(lxml.etree.tostring(rdf_root, xml_declaration=False, encoding="utf-8", pretty_print=True)) + + return resp + +def save_ldt_project(request): + if request.method == "POST": + ldt = request.POST['ldt'] + id = request.POST['id'] + ldtproject = Project.safe_objects.get(ldt_id=id) #@UndefinedVariable + + #save xml ldt + ldtproject.ldt = ldt + + doc = lxml.etree.fromstring(ldtproject.ldt.encode("utf-8")) + result = doc.xpath("/iri/project") + + #set new title + ldtproject.title = result[0].get("title") + + #get new content list + new_contents = [] + result = doc.xpath("/iri/medias/media") + for medianode in result: + id = medianode.get("id") + new_contents.append(id) + + #set new content list + for c in ldtproject.contents.all(): + if not c.iri_id in new_contents: + ldtproject.contents.remove(c) + + ldtproject.save() + else: + ldt = '' + new_contents = [] + + return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request)) + +@login_required +def publish(request, id, redirect=True): + ldt = get_object_or_404(Project.safe_objects, ldt_id=id) + ldt.publish() + ldt.save() + redirect = boolean_convert(redirect) + if redirect: + return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt")) + else: + return HttpResponse(simplejson.dumps({'res':True, 'ldt': {'id': ldt.id, 'state':ldt.state, 'ldt_id': ldt.ldt_id}}, ensure_ascii=False), mimetype='application/json') + +@login_required +def unpublish(request, id, redirect=True): + ldt = get_object_or_404(Project.safe_objects, ldt_id=id) + ldt.unpublish() + ldt.save() + redirect = boolean_convert(redirect) + if redirect: + return HttpResponseRedirect(reverse("ldt.ldt_utils.views.list_ldt")) + else: + return HttpResponse(simplejson.dumps({'res':True, 'ldt': {'id': ldt.id, 'state':ldt.state, 'ldt_id': ldt.ldt_id}}, ensure_ascii=False), mimetype='application/json') + + +def index(request, url): + + urlStr = settings.WEB_URL + reverse("ldt_init", args=['ldt', url]) + language_code = request.LANGUAGE_CODE[:2] + + return render_to_response('ldt/ldt_utils/init_ldt.html', {'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/', 'url': urlStr, 'weburl':settings.WEB_URL + settings.BASE_URL}, context_instance=RequestContext(request)) + + +def ldt(request, url, startSegment=None): + + resp = HttpResponse(mimetype="text/xml; charset=utf-8") + resp['Cache-Control'] = 'no-cache' + + contentList = Content.safe_objects.filter(iri_id=url) #@UndefinedVariable + + ldtgen = LdtUtils() + doc = ldtgen.generate_ldt(contentList, title=contentList[0].title, startSegment=startSegment) + doc = set_forbidden_stream(doc, request.user) + doc.write(resp, pretty_print=True) + + return resp + + +def loading(request): + return render_to_response('ldt/ldt_utils/loading.html', context_instance=RequestContext(request)) + + +@login_required +def create_project(request, iri_id): + content = get_object_or_404(Content.safe_objects, iri_id=iri_id) + contents = [ content, ] + groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME) + redirect_to = '' + form_status = "none" + + if request.method == "POST" : + form = AddProjectForm(request.POST) + + if form.is_valid(): + user = request.user + project = Project.create_project(title=form.cleaned_data['title'], user=user, contents=contents, description=form.cleaned_data['description']) + form_status = "saved" + + if form.cleaned_data["share"]: + assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], user) + + # Modal window is not used with firefox + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + if is_gecko : + redirect_to = reverse('index_project_full', args=[project.ldt_id]) + else: + return HttpResponseRedirect(reverse('index_project', args=[project.ldt_id])) + else: + form = AddProjectForm() + + return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status': form_status, 'contents':contents,'groups' : groups, + 'redirect_to': redirect_to, 'elem_list': get_userlist(request.user), 'create_project_action':reverse("ldt.ldt_utils.views.create_project", args=[iri_id])}, context_instance=RequestContext(request)) + +@login_required +def update_project(request, ldt_id): + project = get_object_or_404(Project.safe_objects, ldt_id=ldt_id) + contents = project.contents.all() + groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME) + member_list, admin_list = get_userlist_model(project, request.user) + + if request.method == "POST" : + submit_action = request.REQUEST.get("submit_button", False) + if submit_action == "prepare_delete": + errors = [] + if project.state == 2: + errors.append(_("the project %(title)s is published. please unpublish before deleting.") % {'title':project.title}) + message = _("can not delete the project. Please correct the following error") + title = _('title error deleting project') + else: + message = _("please confirm deleting project %(title)s") % {'title':project.title} + title = _("confirm deletion") + return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request)) + elif submit_action == "delete": + if project.state != 2: + project.delete() + form_status = 'deleted' + form = AddProjectForm() + else: + form_status = 'none' + form = AddProjectForm(request.POST) + + if form.is_valid(): + if project.title != form.cleaned_data['title'] or project.description != form.cleaned_data['description']: + project.title = form.cleaned_data['title'] + project.description = form.cleaned_data['description'] + ldt = lxml.etree.fromstring(project.ldt.encode("utf-8")) + res = ldt.xpath("/iri/project") + res[0].set("title", project.title) + res[0].set("abstract", project.description) + project.ldt = lxml.etree.tostring(ldt, pretty_print=True) + project.save() + + if form.cleaned_data["share"]: + assign_perm_to_obj(project, form.cleaned_data["read_list"], form.cleaned_data["write_list"], request.user) + form_status = "saved" + else: + form = AddProjectForm({'title':unicode(project.title), 'description':unicode(project.get_description())}) + + form_status = 'none' + + return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'groups': groups, 'elem_list': get_userlist(request.user), + 'ldt_id': ldt_id, 'contents':contents, 'member_list': member_list, 'admin_list': admin_list, + 'create_project_action':reverse("ldt.ldt_utils.views.update_project", args=[ldt_id])}, context_instance=RequestContext(request)) + +@login_required +def copy_project(request, ldt_id, group_id=0): + + project = get_object_or_404(Project.safe_objects, ldt_id=ldt_id) + if request.method == "POST" : + form = CopyProjectForm(request.POST) + + if form.is_valid(): + user = request.user + group_id = form.cleaned_data['group'] + group = Group.objects.get(id=group_id) if group_id and group_id > 0 else None + project = project.copy_project(title=form.cleaned_data['title'], user=user, group=group) + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + if is_gecko: + return HttpResponseRedirect(reverse('index_project_full', args=[project.ldt_id])) + else: + return HttpResponseRedirect(reverse('index_project', args=[project.ldt_id])) + else: + form = CopyProjectForm() + # Modal window is not used with firefox, so we ask to submit the form in _parent in firefox case. + target_parent = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + return render_to_response('ldt/ldt_utils/copy_ldt.html', {'form':form, 'project':project, 'group_id':group_id, 'target_parent':target_parent}, context_instance=RequestContext(request)) + + +def write_content_base(request, iri_id=None): + + if iri_id: + instance_content = Content.safe_objects.get(iri_id=iri_id) #@UndefinedVariable + instance_media = instance_content.media_obj + logging.debug("write_content_base : valid form: for instance : media -> " + repr(instance_media) + " content : for instance : " + repr(instance_content)) #@UndefinedVariable + else: + logging.debug("No iri_id") #@UndefinedVariable + instance_content = None + instance_media = None + + form_status = 'none' + if request.method == "POST": + + if instance_content is not None: + content_instance_val = model_to_dict(instance_content, exclude=ContentForm.Meta.exclude) + else: + content_instance_val = {} + + if instance_media is not None: + media_instance_val = model_to_dict(instance_media, exclude=MediaForm.Meta.exclude) + else: + media_instance_val = {} + #add prefix + + def add_prefix(dict, prefix): + for key, value in dict.items(): + dict['%s-%s' % (prefix, key)] = value + del(dict[key]) + + add_prefix(content_instance_val, "content") + add_prefix(media_instance_val, "media") + + for k in request.POST.keys(): + value = request.POST.get(k) + content_instance_val[k] = value + media_instance_val[k] = value + + content_instance_val['read_list'] = request.POST.getlist('read_list') + content_instance_val['write_list'] = request.POST.getlist('write_list') + content_instance_val['share'] = request.POST.get('share', False) + + content_form = ContentForm(content_instance_val, prefix="content", instance=instance_content) + media_form = MediaForm(media_instance_val, request.FILES, prefix="media", instance=instance_media) + + media_valid = media_form.is_valid() + content_valid = content_form.is_valid() + logging.debug("write_content_base : valid form: for instance : " + repr(instance_media) + " -> media " + str(media_valid) + " content : for instance : " + repr(instance_content) + " : " + str(content_valid)) #@UndefinedVariable + + if media_valid and content_valid: + + # see if media must be created + cleaned_data = {} + cleaned_data.update(media_form.cleaned_data) + + media_input_type = content_form.cleaned_data["media_input_type"] + + if media_input_type == "none": + media = None + elif media_input_type == "link": + media = content_form.cleaned_data["media_obj"] + created = False + elif media_input_type == "create": + del cleaned_data["media_file"] + if not cleaned_data['videopath']: + cleaned_data['videopath'] = settings.STREAM_URL + # if the source is already http:// or rtmp:// we don't have to add STREAM_URL + if cleaned_data['src'].startswith("rtmp://") or cleaned_data['src'].startswith("http://"): + cleaned_data['videopath'] = '' + media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable + elif media_input_type == "url" or media_input_type == "upload" : + # copy file + #complet src + destination_file = None + source_file = None + try: + if media_input_type == "url": + url = cleaned_data["external_src_url"] + source_file = urllib2.urlopen(url) + source_filename = source_file.info().get('Content-Disposition', None) + if not source_filename: + source_filename = urlparse.urlparse(url).path.rstrip("/").split('/')[-1] + elif media_input_type == "upload": + #source_file = request.FILES['media-media_file'] + # At this point the file has already be uploaded thanks to the upload view, and original file name is sent through a post var + source_filename = request.POST["media-local_file_name"] + + source_filename = ldt_utils_path.sanitize_filename(source_filename) + destination_filepath = os.path.join(settings.STREAM_PATH, source_filename) + base_source_filename = source_filename + extension = base_source_filename.split(".")[-1] + if extension == base_source_filename: + extension = "" + base_basename_filename = base_source_filename + else: + base_basename_filename = base_source_filename[:-1 * (len(extension) + 1)] + i = 0 + + while os.path.exists(destination_filepath): + base_source_filename = "%s.%d.%s" % (base_basename_filename, i, extension) + destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename) + i += 1 + + if media_input_type == "url": + # we upload the file if we are in url case + destination_file = open(destination_filepath, "wb") + chunck = source_file.read(2048) + while chunck: + destination_file.write(chunck) + chunck = source_file.read(2048) + + elif media_input_type == "upload": + # The media file has been uploaded in the session temp folder + # so we just have to move to the regular folder and rename it. + if os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename)): + os.rename(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename), os.path.join(settings.STREAM_PATH, base_source_filename)) + + + src_prefix = settings.STREAM_SRC_PREFIX.rstrip("/") + if len(src_prefix) > 0: + cleaned_data["src"] = src_prefix + "/" + base_source_filename + else: + cleaned_data["src"] = base_source_filename + + + except Exception as inst: + logging.debug("write_content_base : POST error when processing file:" + str(inst)) #@UndefinedVariable + form_status = "error" + #set error for form + if media_input_type == "url": + errors = media_form._errors.setdefault("external_src_url", ErrorList()) + errors.append(_("Problem when downloading file from url : ") + url) + elif media_input_type == "upload": + errors = media_form._errors.setdefault("media_file", ErrorList()) + errors.append(_("Problem when uploading file : ") + str(inst)) + finally: + if media_input_type == "url": + if destination_file: + destination_file.close() + if source_file: + source_file.close() + + + if form_status != "error": + #try: + del cleaned_data["media_file"] + if not cleaned_data['videopath']: + cleaned_data['videopath'] = settings.STREAM_URL + mimetype = cleaned_data.get('mimetype_field', None) + if not mimetype: + mimetype = mimetypes.guess_type(cleaned_data['src']) + cleaned_data['mimetype_field'] = mimetype + media, created = Media.safe_objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable + cached_assign('view_media', request.user, media) + else: + media = None + + + if media and not created: + for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title'): + setattr(media, attribute, cleaned_data.get(attribute)) + mimetype = cleaned_data.get('mimetype_field', None) + if not mimetype: + mimetype = mimetypes.guess_type(media.src) + media.mimetype_field = mimetype + cached_assign('view_media', request.user, media) + cached_assign('change_media', request.user, media) + media.save() + + if form_status != "error": + content_defaults = {} + content_defaults.update(content_form.cleaned_data) + content_defaults['media_obj'] = media + + for key in ["media_input_type", "groups", "is_public", "read_list", "write_list", "share" ]: + del content_defaults[key] + + content, created = Content.safe_objects.get_or_create(iri_id=content_form.cleaned_data['iri_id'], defaults=content_defaults) #@UndefinedVariable + if not created: + content.save() # Check if user is allowed to change object before assigning permissions. + cached_assign('change_content', request.user, content) + cached_assign('view_content', request.user, content) + everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME) + if content_form.cleaned_data['is_public']: + cached_assign('view_content', everyone, content) + if media: + cached_assign('view_media', everyone, media) + elif content_form.cleaned_data["share"]: + remove_perm('view_content', everyone, content) + assign_perm_to_obj(content, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user) + if media: + assign_perm_to_obj(media, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user) + if not created: + for attribute in ('iriurl', 'title', 'description', 'duration', 'content_creation_date', 'tags', 'media_obj'): + setattr(content, attribute, content_defaults[attribute]) + content.save() + form_status = 'saved' + media_form = MediaForm(instance=media, prefix="media") + content_form = ContentForm(instance=content, prefix="content") + else: + form_status = 'error' + else: + form_status = 'empty' + initial = { 'media_input_type':"link"} + if instance_content: + initial['is_public'] = instance_content.is_public + + content_form = ContentForm(prefix="content", instance=instance_content, initial=initial) + media_form = MediaForm(prefix="media", instance=instance_media) + + if instance_content is not None: + content_form.media_input_type = "link" + + return content_form, media_form, form_status + +@login_required +def write_content(request, iri_id=None): + submit_action = request.REQUEST.get("submit_button", False) + groups = request.user.groups.exclude(name=settings.PUBLIC_GROUP_NAME) + member_list = admin_list = [] + + if submit_action == "prepare_delete": + errors, titles = prepare_delete_content(request, iri_id) + if errors and len(errors) > 0: + message = ungettext("There is %(count)d error when deleting content", "There are %(count)d errors when deleting content", len(errors)) % { 'count': len(errors)} + title_msg = _('title error deleting content') + else: + message = _("Confirm delete content %(titles)s") % { 'titles' : ",".join(titles) } + title_msg = _("confirm delete content") + return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors, 'message':message, 'title': title_msg}, context_instance=RequestContext(request)) + elif submit_action == "delete": + delete_content(request, iri_id) + form_status = "deleted" + content_form = ContentForm() + media_form = MediaForm() + else: + content_form, media_form, form_status = write_content_base(request, iri_id) + if iri_id: + member_list, admin_list = get_userlist_model(Content.objects.get(iri_id=iri_id), request.user) + + if iri_id: + create_content_action = reverse('ldt.ldt_utils.views.write_content', kwargs={'iri_id':iri_id}) + else: + create_content_action = reverse('ldt.ldt_utils.views.write_content') + + session_key = request.COOKIES[settings.SESSION_COOKIE_NAME] + cookie_name = settings.SESSION_COOKIE_NAME + content_form.fields["media_obj"].queryset = Media.safe_objects.all() + + return render_to_response('ldt/ldt_utils/create_content.html', {'content_form': content_form, 'media_form': media_form, 'form_status': form_status, 'create_content_action': create_content_action, + 'elem_list': get_userlist(request.user), 'member_list': member_list, 'admin_list': admin_list, 'iri_id': iri_id, 'session_key':session_key, 'cookie_name':cookie_name}, context_instance=RequestContext(request)) + +@login_required +def prepare_delete_content(request, iri_id=None): + errors = [] + titles = [] + if not iri_id: + iri_id = request.REQUEST.get("iri_id", None) + + if iri_id: + for content in Content.safe_objects.filter(iri_id=iri_id): + titles.append(unicode(content.title)) + projects = content.project_set.all() + projects_nb = len(projects) + if projects_nb > 0: + project_titles = map(lambda p: unicode(p.title), projects) + errors.append(ungettext("Content '%(title)s' is referenced by this project : %(project_titles)s. Please delete it beforehand.", "Content '%(title)s' is referenced by %(count)d projects: %(project_titles)s. Please delete them beforehand.", projects_nb) % {'title':unicode(content.title), 'count':projects_nb, 'project_titles': ",".join(project_titles)}) + + return errors, titles + + +@login_required +def delete_content(request, iri_id=None): + if not iri_id: + iri_id = request.REQUEST.get("iri_id", None) + + if iri_id: + Content.safe_objects.get(iri_id=iri_id).delete() + + +def upload(request): + if request.method == 'POST': + for field_name in request.FILES: + # We get the file name + source_file = request.FILES[field_name] + source_filename = source_file.name + # We sanitize the file name : no space, only lower case. + source_filename = ldt_utils_path.sanitize_filename(source_filename) + # We create the session temp folder if necessary + if not os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME])): + os.makedirs(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME])) + destination_filepath = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename) + # We delete the existing file if necessary + if os.path.exists(destination_filepath): + os.remove(destination_filepath) + + destination_file = open(destination_filepath, "wb") + + for chunk in source_file.chunks(): + destination_file.write(chunk) + destination_file.close() + + # indicate that everything is OK for SWFUpload + return HttpResponse("ok", mimetype="text/plain") + else: + return HttpResponse("notok", mimetype="text/plain") + +def remove_temp_file(request): + # The filename arrives with a GET var. + file_path = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", ldt_utils_path.sanitize_filename(request.GET["filename"])) + if os.path.exists(file_path): + os.remove(file_path) + return HttpResponse("remove ok", mimetype="text/plain") + +def get_duration(request): + try: + # The filename arrives with a GET var. + file_path = os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", ldt_utils_path.sanitize_filename(request.GET["filename"])) + if hasattr(settings, 'FFMPEG_PATH') and os.path.exists(file_path): + output = str(subprocess.Popen([settings.FFMPEG_PATH, "-i", file_path], stderr=subprocess.PIPE).communicate()[1]) + m = re.search("Duration:\s*?([\d.:]+)", output, re.M) + dur_arr = m.group(1).split(":") + td = datetime.timedelta(hours=int(dur_arr[0]), minutes=int(dur_arr[1]), seconds=float(dur_arr[2])) + str_duration = str((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 3) + return HttpResponse(str_duration, mimetype="text/plain") + else: + return HttpResponse("", mimetype="text/plain") + except Exception as inst: + return HttpResponse(str(inst), mimetype="text/plain") + + +@login_required +def get_group_projects(request): + + # Get group, user and project_list + grp_id = request.POST["id_group"] + if grp_id == "-1": + project_list = get_objects_for_user(request.user, 'ldt_utils.view_project', use_groups=False).exclude(owner=request.user) + else: + grp = Group.objects.get(id=grp_id) + everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME) + project_list = get_objects_for_group(grp, 'ldt_utils.view_project') | get_objects_for_group(everyone, 'ldt_utils.view_project').filter(owner__in=[grp]) + + project_list = add_change_attr(request.user, project_list) + + is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); + + return render_to_response("ldt/ldt_utils/partial/projectslist.html", + {'projects': project_list, 'show_username':True, + 'is_gecko': is_gecko, 'group_id': grp_id}, + context_instance=RequestContext(request)) + +@login_required +def create_group(request): + if not request.user.user_permissions.filter(codename='add_group'): + return HttpResponseServerError('

User %s can not create a group.

' % request.user.username) + + form_status = '' + + if request.method == 'POST': + form = GroupAddForm(request.POST) + + if form.is_valid(): + name = form.cleaned_data['name'] + members_list = form.cleaned_data['read_list'] + admin_list = form.cleaned_data['write_list'] + + group = Group.objects.create(name=name) + group.save() + cached_assign('is_owner_group', request.user, group) + cached_assign('change_group', request.user, group) + request.user.groups.add(group) + + for elem in members_list: + if hasattr(elem, 'username'): + elem.groups.add(group) + if elem in admin_list: + cached_assign('change_group', elem, group) + + form_status = 'saved' + + else: + form = GroupAddForm() + + return render_to_response("ldt/ldt_utils/create_group.html", {'group_edition': True, 'form' : form, 'form_status' : form_status, 'elem_list' : get_userlist(request.user)}, context_instance=RequestContext(request)) + +@login_required +def update_group(request, group_id): + group = get_object_or_404(Group, id=group_id) + checker = get_cached_checker(request.user) + + if not checker.has_perm('change_group', group): + form_status = 'none' + return render_to_response("ldt/ldt_utils/create_group.html", {'form_status' : form_status}, context_instance=RequestContext(request)) + + form_status = '' + is_owner_group = checker.has_perm('is_owner_group', group) + + if request.method == "POST": + form = GroupAddForm(request.POST, instance=group) + submit_action = request.REQUEST.get("submit_button", False) + + if submit_action == 'delete': + if is_owner_group: + group.delete() + form_status = 'deleted' + else: + if form.is_valid(): + name = form.cleaned_data['name'] + new_member_list = form.cleaned_data['read_list'] + old_member_list = group.user_set.exclude(id=request.user.id) + admin_list = form.cleaned_data['write_list'] + group.name = name + + for user in new_member_list: + if not hasattr(user, 'username'): + raise AttributeError('new_member_list should only contain users') + if user != request.user: + group.user_set.add(user) + if is_owner_group: + if user in admin_list: + cached_assign('change_group', user, group) + else: + remove_perm('change_group', user, group) + + for user in old_member_list: + if user not in new_member_list: + group.user_set.remove(user) + remove_perm('change_group', user, group) + + group.save() + form_status = 'saved' + else: + form = GroupAddForm(initial={'name':unicode(group.name)}) + + if form_status != 'deleted': + member_list, admin_list = get_userlist_group(group, request.user) + else: + member_list = admin_list = [] + + return render_to_response("ldt/ldt_utils/create_group.html", {'group_id' : group_id, 'form' : form, 'form_status' : form_status, 'group_edition': True, + 'elem_list' : get_userlist(request.user), 'member_list': member_list, 'admin_list': admin_list, + 'is_owner_group': is_owner_group}, context_instance=RequestContext(request)) diff -r b4b11979cd4a -r 07448cec6e8a src/ldt/ldt/settings.py --- a/src/ldt/ldt/settings.py Thu Jan 05 17:33:44 2012 +0100 +++ b/src/ldt/ldt/settings.py Fri Jan 06 10:09:16 2012 +0100 @@ -47,6 +47,7 @@ 'django.contrib.messages.middleware.MessageMiddleware', 'django_openid_consumer.middleware.OpenIDMiddleware', 'ldt.ldt_utils.middleware.userprofile.LanguageMiddleware', + 'ldt.api.middleware.pistonput.PistonPutMiddleware', ) @@ -92,4 +93,3 @@ DEFAULT_PROJECT_ICON = "thumbnails/projects/project_default_icon.png" DEFAULT_USER_ICON = "thumbnails/users/user_default_icon.png" DEFAULT_GROUP_ICON = "thumbnails/groups/group_default_icon.png" - diff -r b4b11979cd4a -r 07448cec6e8a web/ldtplatform/settings.py --- a/web/ldtplatform/settings.py Thu Jan 05 17:33:44 2012 +0100 +++ b/web/ldtplatform/settings.py Fri Jan 06 10:09:16 2012 +0100 @@ -91,6 +91,7 @@ 'django_openid_consumer.middleware.OpenIDMiddleware', 'ldt.ldt_utils.middleware.userprofile.LanguageMiddleware', 'ldt.security.middleware.SecurityMiddleware', + 'ldt.api.middleware.pistonput.PistonPutMiddleware', ) TEMPLATE_CONTEXT_PROCESSORS = (