improve releasing of resources when indexing + convert line endings to unix
authorymh <ymh.work@gmail.com>
Mon, 16 May 2011 20:00:36 +0200
changeset 111 4535dafa6007
parent 110 06b1221142ac
child 112 9886ab183b09
improve releasing of resources when indexing + convert line endings to unix
.hgignore
src/ldt/ldt/core/handlers/modwsgi.py
src/ldt/ldt/ldt_utils/admin.py
src/ldt/ldt/ldt_utils/contentindexer.py
src/ldt/ldt/ldt_utils/forms.py
src/ldt/ldt/ldt_utils/models.py
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/copy_ldt.html
src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/save_done.html
src/ldt/ldt/ldt_utils/tests.py
src/ldt/ldt/ldt_utils/urls.py
src/ldt/ldt/ldt_utils/views.py
src/ldt/ldt/settings.py
src/ldt/ldt/static/ldt/css/LdtPlayer.css
src/ldt/ldt/static/ldt/css/blueprint/plugins/fancy-type/screen.css
src/ldt/ldt/static/ldt/css/ldt.css
src/ldt/ldt/static/ldt/js/jquery.nyroModal-ie6.min.js
src/ldt/ldt/static/ldt/js/jquery.nyroModal.min.js
src/ldt/ldt/static/ldt/js/swfupload/swfupload.cookies.js
src/ldt/ldt/static/ldt/js/swfupload/swfupload.js
src/ldt/ldt/static/ldt/js/swfupload/swfupload.queue.js
src/ldt/ldt/static/ldt/js/swfupload/swfupload.speed.js
src/ldt/ldt/static/ldt/js/swfupload/swfupload.swfobject.js
src/ldt/ldt/templates/base.html
src/ldt/ldt/templates/socialauth/createprofile.html
src/ldt/ldt/text/annotindexer.py
src/ldt/ldt/text/models.py
src/ldt/ldt/text/urls.py
src/ldt/ldt/text/views.py
src/ldt/ldt/user/admin.py
src/ldt/ldt/user/forms.py
src/ldt/ldt/user/models.py
src/ldt/ldt/user/templates/ldt/user/change_email.html
src/ldt/ldt/user/templates/ldt/user/change_email_done.html
src/ldt/ldt/user/templates/ldt/user/home.html
src/ldt/ldt/user/templates/ldt/user/login_form.html
src/ldt/ldt/user/templates/ldt/user/space.html
src/ldt/ldt/user/templates/registration/activation_complete.html
src/ldt/ldt/user/templates/registration/registration_complete.html
src/ldt/ldt/user/templatetags/logintag.py
src/ldt/ldt/user/tests.py
src/ldt/ldt/user/urls.py
src/ldt/ldt/user/views.py
src/ldt/ldt/utils/__init__.py
--- a/.hgignore	Mon May 16 17:43:34 2011 +0200
+++ b/.hgignore	Mon May 16 20:00:36 2011 +0200
@@ -42,4 +42,4 @@
 syntax: regexp
 ^src/ldt/distribute-0\.6\.14-py2\.6\.egg$
 syntax: regexp
-^src/ldt/MANIFEST\.in$
\ No newline at end of file
+^src/ldt/MANIFEST\.in$
--- a/src/ldt/ldt/core/handlers/modwsgi.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/core/handlers/modwsgi.py	Mon May 16 20:00:36 2011 +0200
@@ -1,26 +1,26 @@
-import os
-import sys
-import site
-
-def application(environ, start_response):
-    os.environ['DJANGO_SETTINGS_MODULE'] = environ['DJANGO_SETTINGS_MODULE']
-
-    prev_sys_path = list(sys.path)
-
-    sys.path.append(environ['PROJECT_PATH'])
-    for path in environ.get('PYTHON_PATH', "").split(os.pathsep):
-        if path:
-            site.addsitedir(path)
-
-    new_sys_path = [] 
-    for item in list(sys.path): 
-        if item not in prev_sys_path: 
-            new_sys_path.append(item) 
-            sys.path.remove(item)
-    sys.path[:0] = new_sys_path 
-
-    import django.core.handlers.wsgi
-
-    _application = django.core.handlers.wsgi.WSGIHandler()
-
-    return _application(environ, start_response)
+import os
+import sys
+import site
+
+def application(environ, start_response):
+    os.environ['DJANGO_SETTINGS_MODULE'] = environ['DJANGO_SETTINGS_MODULE']
+
+    prev_sys_path = list(sys.path)
+
+    sys.path.append(environ['PROJECT_PATH'])
+    for path in environ.get('PYTHON_PATH', "").split(os.pathsep):
+        if path:
+            site.addsitedir(path)
+
+    new_sys_path = [] 
+    for item in list(sys.path): 
+        if item not in prev_sys_path: 
+            new_sys_path.append(item) 
+            sys.path.remove(item)
+    sys.path[:0] = new_sys_path 
+
+    import django.core.handlers.wsgi
+
+    _application = django.core.handlers.wsgi.WSGIHandler()
+
+    return _application(environ, start_response)
--- a/src/ldt/ldt/ldt_utils/admin.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/admin.py	Mon May 16 20:00:36 2011 +0200
@@ -48,17 +48,18 @@
             if form.is_valid():    
                 # try:
                 writer = ldt.indexation.get_writer()
-                contentList = form.cleaned_data["contents"]
-                indexer = ContentIndexer(contentList, writer)
-                indexer.index_all()
-                
-                index_projects = form.cleaned_data["index_projects"]
-                if index_projects:
-                    projectList = Project.objects.filter(contents__in=contentList).distinct() #filter(contents__in=contentList) @UndefinedVariable
-                    indexer = ProjectIndexer(projectList, writer)
+                try:
+                    contentList = form.cleaned_data["contents"]
+                    indexer = ContentIndexer(contentList, writer)
                     indexer.index_all()
-
-                writer.close()
+                    
+                    index_projects = form.cleaned_data["index_projects"]
+                    if index_projects:
+                        projectList = Project.objects.filter(contents__in=contentList).distinct() #filter(contents__in=contentList) @UndefinedVariable
+                        indexer = ProjectIndexer(projectList, writer)
+                        indexer.index_all()
+                finally:
+                    writer.close()
                 message = "Indexation ok : " + repr(form.cleaned_data["contents"]) 
                 form = ReindexForm()
                 # except Exception, inst:
--- a/src/ldt/ldt/ldt_utils/contentindexer.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/contentindexer.py	Mon May 16 20:00:36 2011 +0200
@@ -1,196 +1,197 @@
-from django.conf import settings
-from django.db.models.signals import post_save
-from django.dispatch import receiver
-from ldt.ldt_utils.models import Segment, Content, Project
-from ldt.ldt_utils.utils import reduce_text_node
-import ldt.indexation
-import lucene
-import lxml.etree
-import urllib #@UnresolvedImport
-# import ldt.utils.log
-
-def Property(func):
-    return property(**func()) 
-
-
-class LdtIndexer(object):
-    
-    def __init__(self, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
-            self.__decoupage_blacklist = decoupage_blackList
-            self.__writer = writer
-        
-    @Property
-    def decoupage_blacklist(): #@NoSelf
-        doc = """get blacklist""" #@UnusedVariable
-       
-        def fget(self):
-            if self.__decoupage_blacklist is None:
-                self.__decoupage_blacklist = ()
-            return self.__decoupage_blacklist
-           
-        def fset(self, value):
-            self.__decoupage_blacklist = value
-           
-        def fdel(self):
-            del self.__decoupage_blacklist
-           
-        return locals()
-    
-    @Property
-    def writer(): #@NoSelf
-        def fget(self):
-            return self.__writer
-        return locals()
-
-    def index_all(self):
-        raise NotImplemented
-    
-    def index_ensemble(self, ensemble, content, project=None):
-        ensembleId = ensemble.get(u"id", None)
-        
-        for decoupageNode in ensemble.getchildren():
-            if decoupageNode.tag != "decoupage"  or decoupageNode.get(u"id", None) in self.decoupage_blacklist:
-                continue
-            
-            decoupId = decoupageNode.get(u"id", None)
-            res = decoupageNode.xpath("elements/element")
-            for elementNode in res:
-                
-                elementId = elementNode.get(u"id", None)
-                tags = elementNode.get(u"tags", None)
-                
-                if tags is not None:                            
-                    tags.replace(u",", u";")
-                
-                if tags is None or len(tags) == 0:
-                    tags = u""
-                    restagnode = elementNode.xpath("tag/text()", smart_strings=False)
-                    for tagnode in restagnode:
-                        tags = tags + u" ; " + tagnode
-                        
-                if tags is None or len(tags) == 0:
-                    tags = u""
-                    restagnode = elementNode.xpath("tags/tag/text()", smart_strings=False)
-
-                    for tagnode in restagnode:
-                        tags = tags + u" ; " + tagnode
-                
-                if tags is None:
-                    tags = u""
-                tags = u";".join([tag[0:50] for tag in tags.split(u";")])
-                
-
-                title = reduce_text_node(elementNode, "title/text()")                
-                abstract = reduce_text_node(elementNode, "abstract/text()")
-                
-                author = elementNode.get("author", "")
-                start_ts = int(float(elementNode.get("begin", "-1")))
-                duration = int(float(elementNode.get("dur", "0")))
-                date_str = elementNode.get("date", "")
-                ldt_id = u""
-                if project:
-                    ldt_id = project.ldt_id
-
-                doc = lucene.Document()
-                doc.add(lucene.Field("type_doc", "annotation", lucene.Field.Store.NO, lucene.Field.Index.NOT_ANALYZED))        
-                doc.add(lucene.Field("iri_id", content.iri_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
-                doc.add(lucene.Field("project_id", ldt_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
-                doc.add(lucene.Field("ensemble_id", ensembleId, lucene.Field.Store.YES, lucene.Field.Index.NO))
-                doc.add(lucene.Field("decoupage_id", decoupId, lucene.Field.Store.YES, lucene.Field.Index.NO))
-                doc.add(lucene.Field("element_id", elementId, lucene.Field.Store.YES, lucene.Field.Index.NO))                        
-                doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-                doc.add(lucene.Field("title", title, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-                doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-                doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-
-                seg = Segment(content=content,
-                              iri_id=content.iri_id,
-                              ensemble_id=ensembleId,
-                              cutting_id=decoupId,
-                              element_id=elementId,
-                              tags=tags,
-                              title=title,
-                              abstract=abstract,
-                              duration=duration,
-                              author=author,
-                              start_ts=start_ts,
-                              date=date_str,
-                              project_obj=project,
-                              project_id=ldt_id)
-                seg.save()
-                self.writer.addDocument(doc)
-
-
-
-class ContentIndexer(LdtIndexer):
-        
-        def __init__(self, contentList, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
-            super(ContentIndexer, self).__init__(writer, decoupage_blackList)
-            self.__contentList = contentList
-                                       
-        def index_all(self):
-            for content in self.__contentList:
-                self.index_content(content)
-                
-        def index_content(self, content):
-            url = content.iri_url()
-            filepath = urllib.urlopen(url)
-            doc = lxml.etree.parse(filepath) #@UndefinedVariable
-           
-            self.writer.deleteDocuments(lucene.Term("iri_id", content.iri_id))
-            Segment.objects.filter(iri_id=content.iri_id).delete() #@UndefinedVariable
-            
-            res = doc.xpath("/iri/body/ensembles/ensemble")
-
-            for ensemble in res:                
-                self.index_ensemble(ensemble, content)
-            
-            self.writer.commit()
-            
-            
-class ProjectIndexer(LdtIndexer):
-        
-        def __init__(self, projectList, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
-            super(ProjectIndexer, self).__init__(writer, decoupage_blackList)                
-            self.__projectList = projectList
-                                   
-        def index_all(self):
-            for project in self.__projectList:
-                self.index_project(project)
- 
-        def index_project(self, project):
-            
-            # pocketfilms.utils.log.debug("Indexing project : "+str(project.iri_id))
-            doc = lxml.etree.fromstring(project.ldt) #@UndefinedVariable
-
-            self.writer.deleteDocuments(lucene.Term("project_id", project.ldt_id))
-            Segment.objects.filter(project_obj__ldt_id=project.ldt_id).delete() #@UndefinedVariable
-            
-            res = doc.xpath("/iri/annotations/content")
-
-            for content in res:
-                contentId = content.get(u"id", None)
-                content_obj = None
-                
-                clist = Content.objects.filter(iri_id = contentId) #@UndefinedVariable
-                if len(clist) > 0:
-                    content_obj = clist[0]
- 
-                for ensemble in content.getchildren():
-                    self.index_ensemble(ensemble, content_obj, project)
-            
-            self.writer.commit()
-
-@receiver(post_save, sender=Project)
-def index_project(sender, **kwargs):
-    if settings.AUTO_INDEX_AFTER_SAVE:
-        instance = kwargs['instance']
-        writer = ldt.indexation.get_writer()
-        if instance.state != 2:
-            writer.deleteDocuments(lucene.Term("project_id", instance.ldt_id))
-            Segment.objects.filter(project_obj__ldt_id=instance.ldt_id).delete() #@UndefinedVariable
-        else:
-            projectIndexer = ProjectIndexer([instance], writer)
-            projectIndexer.index_all()
-        
-
+from django.conf import settings
+from django.db.models.signals import post_save
+from django.dispatch import receiver
+from ldt.ldt_utils.models import Segment, Content, Project
+from ldt.ldt_utils.utils import reduce_text_node
+import ldt.indexation
+import lucene
+import lxml.etree
+import urllib #@UnresolvedImport
+# import ldt.utils.log
+
+def Property(func):
+    return property(**func()) 
+
+
+class LdtIndexer(object):
+    
+    def __init__(self, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
+            self.__decoupage_blacklist = decoupage_blackList
+            self.__writer = writer
+        
+    @Property
+    def decoupage_blacklist(): #@NoSelf
+        doc = """get blacklist""" #@UnusedVariable
+       
+        def fget(self):
+            if self.__decoupage_blacklist is None:
+                self.__decoupage_blacklist = ()
+            return self.__decoupage_blacklist
+           
+        def fset(self, value):
+            self.__decoupage_blacklist = value
+           
+        def fdel(self):
+            del self.__decoupage_blacklist
+           
+        return locals()
+    
+    @Property
+    def writer(): #@NoSelf
+        def fget(self):
+            return self.__writer
+        return locals()
+
+    def index_all(self):
+        raise NotImplemented
+    
+    def index_ensemble(self, ensemble, content, project=None):
+        ensembleId = ensemble.get(u"id", None)
+        
+        for decoupageNode in ensemble.getchildren():
+            if decoupageNode.tag != "decoupage"  or decoupageNode.get(u"id", None) in self.decoupage_blacklist:
+                continue
+            
+            decoupId = decoupageNode.get(u"id", None)
+            res = decoupageNode.xpath("elements/element")
+            for elementNode in res:
+                
+                elementId = elementNode.get(u"id", None)
+                tags = elementNode.get(u"tags", None)
+                
+                if tags is not None:                            
+                    tags.replace(u",", u";")
+                
+                if tags is None or len(tags) == 0:
+                    tags = u""
+                    restagnode = elementNode.xpath("tag/text()", smart_strings=False)
+                    for tagnode in restagnode:
+                        tags = tags + u" ; " + tagnode
+                        
+                if tags is None or len(tags) == 0:
+                    tags = u""
+                    restagnode = elementNode.xpath("tags/tag/text()", smart_strings=False)
+
+                    for tagnode in restagnode:
+                        tags = tags + u" ; " + tagnode
+                
+                if tags is None:
+                    tags = u""
+                tags = u";".join([tag[0:50] for tag in tags.split(u";")])
+                
+
+                title = reduce_text_node(elementNode, "title/text()")                
+                abstract = reduce_text_node(elementNode, "abstract/text()")
+                
+                author = elementNode.get("author", "")
+                start_ts = int(float(elementNode.get("begin", "-1")))
+                duration = int(float(elementNode.get("dur", "0")))
+                date_str = elementNode.get("date", "")
+                ldt_id = u""
+                if project:
+                    ldt_id = project.ldt_id
+
+                doc = lucene.Document()
+                doc.add(lucene.Field("type_doc", "annotation", lucene.Field.Store.NO, lucene.Field.Index.NOT_ANALYZED))        
+                doc.add(lucene.Field("iri_id", content.iri_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
+                doc.add(lucene.Field("project_id", ldt_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
+                doc.add(lucene.Field("ensemble_id", ensembleId, lucene.Field.Store.YES, lucene.Field.Index.NO))
+                doc.add(lucene.Field("decoupage_id", decoupId, lucene.Field.Store.YES, lucene.Field.Index.NO))
+                doc.add(lucene.Field("element_id", elementId, lucene.Field.Store.YES, lucene.Field.Index.NO))                        
+                doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+                doc.add(lucene.Field("title", title, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+                doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+                doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+
+                seg = Segment(content=content,
+                              iri_id=content.iri_id,
+                              ensemble_id=ensembleId,
+                              cutting_id=decoupId,
+                              element_id=elementId,
+                              tags=tags,
+                              title=title,
+                              abstract=abstract,
+                              duration=duration,
+                              author=author,
+                              start_ts=start_ts,
+                              date=date_str,
+                              project_obj=project,
+                              project_id=ldt_id)
+                seg.save()
+                self.writer.addDocument(doc)
+
+
+
+class ContentIndexer(LdtIndexer):
+        
+        def __init__(self, contentList, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
+            super(ContentIndexer, self).__init__(writer, decoupage_blackList)
+            self.__contentList = contentList
+                                       
+        def index_all(self):
+            for content in self.__contentList:
+                self.index_content(content)
+                
+        def index_content(self, content):
+            url = content.iri_url()
+            filepath = urllib.urlopen(url)
+            doc = lxml.etree.parse(filepath) #@UndefinedVariable
+           
+            self.writer.deleteDocuments(lucene.Term("iri_id", content.iri_id))
+            Segment.objects.filter(iri_id=content.iri_id).delete() #@UndefinedVariable
+            
+            res = doc.xpath("/iri/body/ensembles/ensemble")
+
+            for ensemble in res:                
+                self.index_ensemble(ensemble, content)
+            
+            self.writer.commit()
+            
+            
+class ProjectIndexer(LdtIndexer):
+        
+        def __init__(self, projectList, writer, decoupage_blackList=settings.DECOUPAGE_BLACKLIST):
+            super(ProjectIndexer, self).__init__(writer, decoupage_blackList)                
+            self.__projectList = projectList
+                                   
+        def index_all(self):
+            for project in self.__projectList:
+                self.index_project(project)
+ 
+        def index_project(self, project):
+            
+            # pocketfilms.utils.log.debug("Indexing project : "+str(project.iri_id))
+            doc = lxml.etree.fromstring(project.ldt) #@UndefinedVariable
+
+            self.writer.deleteDocuments(lucene.Term("project_id", project.ldt_id))
+            Segment.objects.filter(project_obj__ldt_id=project.ldt_id).delete() #@UndefinedVariable
+            
+            res = doc.xpath("/iri/annotations/content")
+
+            for content in res:
+                contentId = content.get(u"id", None)
+                content_obj = None
+                
+                clist = Content.objects.filter(iri_id = contentId) #@UndefinedVariable
+                if len(clist) > 0:
+                    content_obj = clist[0]
+ 
+                for ensemble in content.getchildren():
+                    self.index_ensemble(ensemble, content_obj, project)
+            
+            self.writer.commit()
+
+@receiver(post_save, sender=Project)
+def index_project(sender, **kwargs):
+    if settings.AUTO_INDEX_AFTER_SAVE:
+        instance = kwargs['instance']
+        writer = ldt.indexation.get_writer()
+        try:
+            if instance.state != 2:
+                writer.deleteDocuments(lucene.Term("project_id", instance.ldt_id))
+                Segment.objects.filter(project_obj__ldt_id=instance.ldt_id).delete() #@UndefinedVariable
+            else:
+                projectIndexer = ProjectIndexer([instance], writer)
+                projectIndexer.index_all()
+        finally:
+            writer.close()
--- a/src/ldt/ldt/ldt_utils/forms.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/forms.py	Mon May 16 20:00:36 2011 +0200
@@ -1,82 +1,82 @@
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from ldt.forms import widgets as ldt_widgets
-from models import Project, Content, Media
-from utils import generate_uuid
-
-class LdtImportForm(forms.Form):
-    importFile = forms.FileField()
-    videoPath = forms.CharField(required=False)
-    flatten = forms.BooleanField(required=False, initial=True)   
-    
-class LdtAddForm(forms.ModelForm):
-    title = forms.CharField()
-    contents = forms.ModelMultipleChoiceField(Content.objects.all()) #@UndefinedVariable
-    # owner = forms.ModelChoiceField(Author.objects.all())
-    class Meta:
-        model = Project
-        exclude = ("ldt_id", "ldt", "created_by", "changed_by", "creation_date", "modification_date", "state", "owner")   
-
-class ReindexForm(forms.Form):
-    contents = forms.ModelMultipleChoiceField(Content.objects.all()) #@UndefinedVariable
-    index_projects = forms.BooleanField(required=False, initial=False)
-
-class SearchForm(forms.Form):
-    search = forms.CharField()
-    field = forms.ChoiceField([(u"all", u"all"), (u"title", u"title"), (u"abstract", u"resume"), (u"tags", u"tags")])
-
-class AddProjectForm (forms.Form):
-    title = forms.CharField(widget=forms.TextInput(attrs={'class':'inputbox required'}))
-
-class CopyProjectForm (forms.Form):
-    title = forms.CharField()
-    
-
-class ContentForm(forms.ModelForm):
-
-    #iri_id = forms.CharField(max_length=1024, widget=forms.HiddenInput, initial=generate_uuid)
-    iriurl = forms.CharField(max_length=1024, widget=forms.HiddenInput, required=False)
-    content_creation_date = forms.SplitDateTimeField(widget=ldt_widgets.LdtSplitDateTime, required=False, label=_("content.content_creation_date"))
-    media_input_type = forms.ChoiceField(required=False, label=_("content.media_input_type"), choices=(("upload", _("file_upload")), ("url", _("url")), ("link", _("existing_media")), ("create", _("create_media")), ("none", _("none_media"))))
-    
-    def clean_iri_id(self):
-        data = self.cleaned_data.get('iri_id')
-        if not data:
-            data = generate_uuid()
-        return data
-    
-    def clean(self):
-        cleaned_data = self.cleaned_data
-        iriurl_data = cleaned_data.get('iriurl')
-        iri_id_data = cleaned_data['iri_id']
-        if not iriurl_data:
-            iriurl_data = "%s/%s.iri" % (iri_id_data, iri_id_data)    
-        cleaned_data['iriurl'] = iriurl_data
-        return cleaned_data
-    
-    class Meta:
-        model = Content
-        exclude = ("creation_date", "update_date", "authors")
-        widgets = {
-                   'iri_id': forms.HiddenInput,
-        }
-        
-    class Media:
-        css = {
-            'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css')
-               }
-        
-class MediaForm(forms.ModelForm):
-    
-    media_creation_date = forms.SplitDateTimeField(widget=ldt_widgets.LdtSplitDateTime, required=False)
-    media_file = forms.FileField(required=False);
-    src = forms.CharField(required=False, max_length=1024)
-
-    class Meta:
-        model = Media
-        exclude = ("creation_date", "update_date", "creator")
-    
-    class Media:
-        css = {
-            'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css')
-               }
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+from ldt.forms import widgets as ldt_widgets
+from models import Project, Content, Media
+from utils import generate_uuid
+
+class LdtImportForm(forms.Form):
+    importFile = forms.FileField()
+    videoPath = forms.CharField(required=False)
+    flatten = forms.BooleanField(required=False, initial=True)   
+    
+class LdtAddForm(forms.ModelForm):
+    title = forms.CharField()
+    contents = forms.ModelMultipleChoiceField(Content.objects.all()) #@UndefinedVariable
+    # owner = forms.ModelChoiceField(Author.objects.all())
+    class Meta:
+        model = Project
+        exclude = ("ldt_id", "ldt", "created_by", "changed_by", "creation_date", "modification_date", "state", "owner")   
+
+class ReindexForm(forms.Form):
+    contents = forms.ModelMultipleChoiceField(Content.objects.all()) #@UndefinedVariable
+    index_projects = forms.BooleanField(required=False, initial=False)
+
+class SearchForm(forms.Form):
+    search = forms.CharField()
+    field = forms.ChoiceField([(u"all", u"all"), (u"title", u"title"), (u"abstract", u"resume"), (u"tags", u"tags")])
+
+class AddProjectForm (forms.Form):
+    title = forms.CharField(widget=forms.TextInput(attrs={'class':'inputbox required'}))
+
+class CopyProjectForm (forms.Form):
+    title = forms.CharField()
+    
+
+class ContentForm(forms.ModelForm):
+
+    #iri_id = forms.CharField(max_length=1024, widget=forms.HiddenInput, initial=generate_uuid)
+    iriurl = forms.CharField(max_length=1024, widget=forms.HiddenInput, required=False)
+    content_creation_date = forms.SplitDateTimeField(widget=ldt_widgets.LdtSplitDateTime, required=False, label=_("content.content_creation_date"))
+    media_input_type = forms.ChoiceField(required=False, label=_("content.media_input_type"), choices=(("upload", _("file_upload")), ("url", _("url")), ("link", _("existing_media")), ("create", _("create_media")), ("none", _("none_media"))))
+    
+    def clean_iri_id(self):
+        data = self.cleaned_data.get('iri_id')
+        if not data:
+            data = generate_uuid()
+        return data
+    
+    def clean(self):
+        cleaned_data = self.cleaned_data
+        iriurl_data = cleaned_data.get('iriurl')
+        iri_id_data = cleaned_data['iri_id']
+        if not iriurl_data:
+            iriurl_data = "%s/%s.iri" % (iri_id_data, iri_id_data)    
+        cleaned_data['iriurl'] = iriurl_data
+        return cleaned_data
+    
+    class Meta:
+        model = Content
+        exclude = ("creation_date", "update_date", "authors")
+        widgets = {
+                   'iri_id': forms.HiddenInput,
+        }
+        
+    class Media:
+        css = {
+            'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css')
+               }
+        
+class MediaForm(forms.ModelForm):
+    
+    media_creation_date = forms.SplitDateTimeField(widget=ldt_widgets.LdtSplitDateTime, required=False)
+    media_file = forms.FileField(required=False);
+    src = forms.CharField(required=False, max_length=1024)
+
+    class Meta:
+        model = Media
+        exclude = ("creation_date", "update_date", "creator")
+    
+    class Media:
+        css = {
+            'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css')
+               }
--- a/src/ldt/ldt/ldt_utils/models.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/models.py	Mon May 16 20:00:36 2011 +0200
@@ -1,390 +1,393 @@
-from django.conf import settings
-from django.contrib.auth.models import User
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from ldt.core.models import Document, Owner
-import ldt.indexation
-from utils import (create_ldt, copy_ldt, create_empty_iri, update_iri, 
-    generate_uuid)
-import lucene
-import lxml.etree
-import mimetypes
-import os.path
-import tagging.fields
-import uuid
-
-class Author(models.Model):
-
-    handle = models.CharField(max_length=512, unique=True, blank=True, null=True)
-    email = models.EmailField(unique=False, blank=True, null=True)
-    firstname = models.CharField(max_length=512, blank=True, null=True)
-    lastname = models.CharField(max_length=512, blank=True, null=True)
-    
-    def __unicode__(self):
-        return unicode(self.id) + " - " + self.handle + ", " + self.email + ", " + self.firstname + " " + self.lastname
-
-class Media(models.Model):
-    external_id = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_id'))
-    external_permalink = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_permalink'))
-    external_publication_url = models.URLField(max_length=1024, verify_exists=True, null=True, blank=True, verbose_name=_('media.external_publication_url'))
-    external_src_url = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_src_url'))
-    creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('media.creation_date'))
-    media_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('media.media_creation_date'))
-    update_date = models.DateTimeField(auto_now=True, verbose_name=_('media.update_date'))
-    videopath = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.videopath'))
-    duration = models.IntegerField(null=True, blank=True, verbose_name=_('media.duration'))
-    creator = models.ForeignKey(User, blank=True, null=True, verbose_name=_('media.creator'))
-    description = models.TextField(null=True, blank=True, verbose_name=_('description'))
-    title = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('title'))
-    src = models.CharField(max_length=1024, unique=True, verbose_name=_('media.src'))
-    mimetype_field = models.CharField(max_length=512, null=True, blank=True, verbose_name=_('media.mimetype'))
-    
-    def mimetype(): #@NoSelf
-        def fget(self):
-            if self.mimetype_field :
-                return self.mimetype_field
-            elif self.src:
-                return mimetypes.guess_type(self.src.rstrip())
-            else:
-                return None
-        
-        def fset(self, value):
-            self.mimetype_field = value
-        
-        return locals()
-    mimetype = property(**mimetype())
-    
-    def stream_src(): #@NoSelf
-        
-        def fget(self):
-            res_src = self.src.rstrip()
-            if self.videopath and self.videopath.startswith("rtmp://") and "mp3:" not in res_src and "mp4:" not in res_src:
-                extension = res_src.split(".")[-1]
-                res_src = {
-                    'flv': lambda s: s,
-                    'mp3': lambda s: "%s:%s" % ("mp3", res_src[:-4]),
-                    'mp4': lambda s: "%s:%s" % ("mp4", res_src),
-                    'f4v': lambda s: "%s:%s" % ("mp4", res_src),
-                    'mov': lambda s: "%s:%s" % ("mp4", res_src),
-                }.get(extension, lambda s:s)(res_src)
-            return res_src
-        
-        return locals()
-    
-    stream_src = property(**stream_src())
-    
-    def save(self, *args, **kwargs):
-        super(Media, self).save(*args, **kwargs)
-        for content in self.content_set.all():
-            content.sync_iri_file()
-    
-    def __unicode__(self):
-        strings = []
-        if self.title:
-            strings.append(unicode(self.title))
-        else:
-            strings.append(unicode(self.src))
-        if self.external_id:
-            strings.append(unicode(self.external_id))
-        return "|".join(strings)
-
-
-class Content(models.Model):
-    iri_id = models.CharField(max_length=1024, unique=True, default=generate_uuid, verbose_name=_('content.iri_id'))
-    iriurl = models.CharField(max_length=1024, verbose_name=_('content.iriurl'))
-    creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('content.creation_date'))
-    update_date = models.DateTimeField(auto_now=True, verbose_name=_('content.update_date'))
-    title = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('content.title'))
-    description = models.TextField(null=True, blank=True, verbose_name=_('content.description'))
-    authors = models.ManyToManyField(Author, blank=True, verbose_name=_('content.authors'))
-    duration = models.IntegerField(null=True, blank=True, verbose_name=_('content.duration'))
-    content_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('content.content_creation_date'))
-    tags = tagging.fields.TagField(max_length=2048, null=True, blank=True)
-    media_obj = models.ForeignKey('Media', blank=True, null=True)
-    
-    class Meta:
-        ordering = ["title"]
-
-    def get_duration(self):
-        if self.duration is None:
-            doc = lxml.etree.parse(self.iri_file_path())
-            res = doc.xpath("/iri/body/medias/media[@id='video']/video")
-            if len(res) > 0:
-                try:
-                    self.duration = int(res[0].get(u'dur', 0) or 0)
-                except:
-                    self.duration = 0
-            else:
-                self.duration = 0
-            self.save()
-        return self.duration
-    
-    def mimetype(): #@NoSelf
-        def fget(self):
-            if self.media_obj:
-                return self.media_obj.mimetype
-            else:
-                return None
-        return locals()
-    
-    mimetype = property(**mimetype())
-    
-    def delete(self):
-        super(Content, self).delete()
-        writer = ldt.indexation.get_writer()
-        writer.deleteDocuments(lucene.Term("iri_id", self.iri_id))
-        writer.commit()
-        
-    def sync_iri_file(self):
-        # create iri file if needed
-        created = False
-        try:
-            iri_file_path = self.iri_file_path()
-            if not os.path.exists(iri_file_path):
-                dir = os.path.dirname(iri_file_path)
-                if not os.path.exists(dir):
-                    os.makedirs(dir)
-                created = True
-                file = open(iri_file_path, "w")
-                create_empty_iri(file, self, "IRI")
-            else:
-                created = False
-                update_iri(iri_file_path, self, "IRI")
-                
-        except Exception, e:
-            if created:
-                if os.path.exists(iri_file_path):
-                    os.remove(iri_file_path)
-            raise e
-        
-        
-    #TODO: better manage the change in .iri name and error scenario (save in temp file + rename
-    def save(self, *args, **kwargs):
-        
-        self.sync_iri_file()        
-        # update it 
-        super(Content, self).save(*args, **kwargs)
-    
-    def __unicode__(self):
-        return str(self.id) + ": " + self.iri_id
-        
-    def iri_url(self, web_url=settings.WEB_URL):
-        if 'http' in self.iriurl or 'https' in self.iriurl:
-            return self.iriurl
-        else:
-            return unicode(web_url) + unicode(settings.MEDIA_URL) + u"ldt/" + unicode(self.iriurl)
-    
-    def iri_file_path(self):
-        return os.path.join(os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "media"), "ldt"), self.iri_id), os.path.basename(self.iriurl))
-
-    def iri_url_template(self):
-        return "${web_url}${media_url}ldt/" + unicode(self.iri_id) + "/" + os.path.basename(self.iriurl)
-
-
-    def __get_empty_media(self):
-        if settings.EMPTY_MEDIA_EXTERNALID:
-            empty_media = Media.objects.get(external_id=settings.EMPTY_MEDIA_EXTERNALID)
-            return empty_media
-        else:
-            return None
-            
-    
-    def stream_src(): #@NoSelf
-        
-        def fget(self):
-            if self.media_obj is not None:
-                return self.media_obj.stream_src
-            else:
-                empty_media = self.__get_empty_media()
-                if empty_media:
-                    return empty_media.stream_src
-                else:
-                    return ""
-        
-        return locals()
-    
-    stream_src = property(**stream_src())
-    
-    def videopath(): #@NoSelf
-        doc = """simulate videopath""" #@UnusedVariable
-       
-        def fget(self):
-            if self.media_obj is None:
-                empty_media = self.__get_empty_media()
-                if empty_media:
-                    return empty_media.videopath
-                else:
-                    return None
-            else:
-                return self.media_obj.videopath
-           
-        def fset(self, value):
-            if self.media_obj is not None:
-                self.media_obj.videopath = value
-                      
-        return locals()
-       
-    videopath = property(**videopath())
-
-    def src(): #@NoSelf
-        doc = """simulate videopath""" #@UnusedVariable
-       
-        def fget(self):
-            if self.media_obj is None:
-                empty_media = self.__get_empty_media()
-                if empty_media:
-                    return empty_media.src
-                else:
-                    return None
-            else:
-                return self.media_obj.src
-           
-        def fset(self, value):
-            if self.media_obj is None or self.media_obj.src != value:
-                media, created = Media.objects.get_or_create(src=value, defaults={'src':value})                #@UnusedVariable
-                self.media_obj = media
-                self.save()
-                      
-        return locals()
-       
-    src = property(**src())
-
-    def external_id(): #@NoSelf
-        doc = """simulate externalid""" #@UnusedVariable
-       
-        def fget(self):
-            if self.media_obj is None:
-                empty_media = self.__get_empty_media()
-                if empty_media:
-                    return empty_media.external_id
-                else: 
-                    return None
-            else:
-                return self.media_obj.external_id
-           
-        def fset(self, value):
-            if self.media_obj is not None:
-                self.media_obj.external_id = value
-                      
-        return locals()
-       
-    external_id = property(**external_id())
-
-        
-        
-class Project(Document):  
-    STATE_CHOICES = (
-    (1, 'edition'),
-    (2, 'published'),
-    (3, 'moderated'),
-    (4, 'rejected'),
-    (5, 'deleted')
-    )
-    ldt_id = models.CharField(max_length=1024, unique=True)
-    ldt = models.TextField(null=True)
-    title = models.CharField(max_length=1024)
-    contents = models.ManyToManyField(Content)
-    creation_date = models.DateTimeField(auto_now_add=True)
-    modification_date = models.DateTimeField(auto_now=True)
-    created_by = models.CharField(_("created by"), max_length=70)
-    changed_by = models.CharField(_("changed by"), max_length=70)
-    state = models.IntegerField(choices=STATE_CHOICES, default=1)
-    
-    class Meta:
-        ordering = ["title"]
-
-    
-    def __unicode__(self):
-        return unicode(self.id) + u"::" + unicode(self.ldt_id) + u"::" + unicode(self.title)
-    
-    def get_description(self, doc=None):
-        
-        if doc is None:
-            doc = lxml.etree.fromstring(self.ldt)
-        
-        res = doc.xpath("/iri/project")
-        if len(res) > 0:
-            return res[0].get(u'abstract')
-        else:
-            return None
-
-    def stream_mode(): #@NoSelf
-        def fget(self):
-            modes = []
-            for content in self.contents.all():
-                mimetype = content.mimetype
-                if mimetype:
-                    mode = mimetype.split("/")[0]
-                    if "audio" == mode or "video" == mode:
-                        modes.append(mode)
-                    else:
-                        modes.append("video")
-                else:
-                    modes.append("video")
-            def filter_video(current, item):
-                if not current:
-                    return item
-                elif current == item:
-                    return item
-                else:
-                    return "video"
-            return reduce(filter_video, modes)
-        return locals()
-    
-    stream_mode = property(**stream_mode())
-
-    @staticmethod
-    def create_project(user, title, contents):
-        owner = Owner.objects.get(user=user) #@UndefinedVariable
-        project = Project(title=title, owner=owner)
-        project.ldt_id = str(uuid.uuid1()) #@UndefinedVariable
-        project.created_by = user.username
-        project.changed_by = user.username
-        project.state = 1
-        project.save()
-        for content in contents:
-            project.contents.add(content)
-        project.save()
-        return create_ldt(project, user)
-
-    def copy_project(self, user, title):
-        owner = Owner.objects.get(user=user) #@UndefinedVariable
-        project = Project(title=title, owner=owner)
-        project = copy_ldt(self, project, user)
-        project.save()
-        for content in self.contents.all():
-            project.contents.add(content)
-        project.save()
-        return project
-    
-    def checkAccess(self, user):
-        if (user and user.is_staff) or self.state == 2: 
-            return True
-        else:
-            return False
-        
-
-class Segment(models.Model):
-    
-    project_obj = models.ForeignKey(Project, null=True)
-    content = models.ForeignKey(Content)
-    project_id = models.CharField(max_length=1024, unique=False, blank=True, null=True)
-    iri_id = models.CharField(max_length=1024, unique=False)
-    ensemble_id = models.CharField(max_length=1024, unique=False)
-    cutting_id = models.CharField(max_length=1024, unique=False)    
-    element_id = models.CharField(max_length=1024, unique=False)
-    tags = tagging.fields.TagField(max_length=2048, null=True, blank=True, unique=False)
-    title = models.CharField(max_length=2048, unique=False, null=True, blank=True)
-    duration = models.IntegerField(null=True)
-    start_ts = models.IntegerField(null=True)
-    author = models.CharField(max_length=1024, unique=False, null=True, blank=True)
-    date = models.CharField(max_length=128, unique=False, null=True, blank=True)
-    abstract = models.TextField(null=True, blank=True)
-    
-    def __unicode__(self):
-        return "/".join((unicode(self.project_id), unicode(self.iri_id), unicode(self.ensemble_id), unicode(self.cutting_id), unicode(self.element_id)))
-    
-    class Meta:
-        unique_together = (('project_id', 'iri_id', 'ensemble_id', 'cutting_id', 'element_id'),)
-
-
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from ldt.core.models import Document, Owner
+import ldt.indexation
+from utils import (create_ldt, copy_ldt, create_empty_iri, update_iri, 
+    generate_uuid)
+import lucene
+import lxml.etree
+import mimetypes
+import os.path
+import tagging.fields
+import uuid
+
+class Author(models.Model):
+
+    handle = models.CharField(max_length=512, unique=True, blank=True, null=True)
+    email = models.EmailField(unique=False, blank=True, null=True)
+    firstname = models.CharField(max_length=512, blank=True, null=True)
+    lastname = models.CharField(max_length=512, blank=True, null=True)
+    
+    def __unicode__(self):
+        return unicode(self.id) + " - " + self.handle + ", " + self.email + ", " + self.firstname + " " + self.lastname
+
+class Media(models.Model):
+    external_id = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_id'))
+    external_permalink = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_permalink'))
+    external_publication_url = models.URLField(max_length=1024, verify_exists=True, null=True, blank=True, verbose_name=_('media.external_publication_url'))
+    external_src_url = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_src_url'))
+    creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('media.creation_date'))
+    media_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('media.media_creation_date'))
+    update_date = models.DateTimeField(auto_now=True, verbose_name=_('media.update_date'))
+    videopath = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.videopath'))
+    duration = models.IntegerField(null=True, blank=True, verbose_name=_('media.duration'))
+    creator = models.ForeignKey(User, blank=True, null=True, verbose_name=_('media.creator'))
+    description = models.TextField(null=True, blank=True, verbose_name=_('description'))
+    title = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('title'))
+    src = models.CharField(max_length=1024, unique=True, verbose_name=_('media.src'))
+    mimetype_field = models.CharField(max_length=512, null=True, blank=True, verbose_name=_('media.mimetype'))
+    
+    def mimetype(): #@NoSelf
+        def fget(self):
+            if self.mimetype_field :
+                return self.mimetype_field
+            elif self.src:
+                return mimetypes.guess_type(self.src.rstrip())
+            else:
+                return None
+        
+        def fset(self, value):
+            self.mimetype_field = value
+        
+        return locals()
+    mimetype = property(**mimetype())
+    
+    def stream_src(): #@NoSelf
+        
+        def fget(self):
+            res_src = self.src.rstrip()
+            if self.videopath and self.videopath.startswith("rtmp://") and "mp3:" not in res_src and "mp4:" not in res_src:
+                extension = res_src.split(".")[-1]
+                res_src = {
+                    'flv': lambda s: s,
+                    'mp3': lambda s: "%s:%s" % ("mp3", res_src[:-4]),
+                    'mp4': lambda s: "%s:%s" % ("mp4", res_src),
+                    'f4v': lambda s: "%s:%s" % ("mp4", res_src),
+                    'mov': lambda s: "%s:%s" % ("mp4", res_src),
+                }.get(extension, lambda s:s)(res_src)
+            return res_src
+        
+        return locals()
+    
+    stream_src = property(**stream_src())
+    
+    def save(self, *args, **kwargs):
+        super(Media, self).save(*args, **kwargs)
+        for content in self.content_set.all():
+            content.sync_iri_file()
+    
+    def __unicode__(self):
+        strings = []
+        if self.title:
+            strings.append(unicode(self.title))
+        else:
+            strings.append(unicode(self.src))
+        if self.external_id:
+            strings.append(unicode(self.external_id))
+        return "|".join(strings)
+
+
+class Content(models.Model):
+    iri_id = models.CharField(max_length=1024, unique=True, default=generate_uuid, verbose_name=_('content.iri_id'))
+    iriurl = models.CharField(max_length=1024, verbose_name=_('content.iriurl'))
+    creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('content.creation_date'))
+    update_date = models.DateTimeField(auto_now=True, verbose_name=_('content.update_date'))
+    title = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('content.title'))
+    description = models.TextField(null=True, blank=True, verbose_name=_('content.description'))
+    authors = models.ManyToManyField(Author, blank=True, verbose_name=_('content.authors'))
+    duration = models.IntegerField(null=True, blank=True, verbose_name=_('content.duration'))
+    content_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('content.content_creation_date'))
+    tags = tagging.fields.TagField(max_length=2048, null=True, blank=True)
+    media_obj = models.ForeignKey('Media', blank=True, null=True)
+    
+    class Meta:
+        ordering = ["title"]
+
+    def get_duration(self):
+        if self.duration is None:
+            doc = lxml.etree.parse(self.iri_file_path())
+            res = doc.xpath("/iri/body/medias/media[@id='video']/video")
+            if len(res) > 0:
+                try:
+                    self.duration = int(res[0].get(u'dur', 0) or 0)
+                except:
+                    self.duration = 0
+            else:
+                self.duration = 0
+            self.save()
+        return self.duration
+    
+    def mimetype(): #@NoSelf
+        def fget(self):
+            if self.media_obj:
+                return self.media_obj.mimetype
+            else:
+                return None
+        return locals()
+    
+    mimetype = property(**mimetype())
+    
+    def delete(self):
+        super(Content, self).delete()
+        writer = ldt.indexation.get_writer()
+        try:
+            writer.deleteDocuments(lucene.Term("iri_id", self.iri_id))
+            writer.commit()
+        finally:
+            writer.close()
+        
+    def sync_iri_file(self):
+        # create iri file if needed
+        created = False
+        try:
+            iri_file_path = self.iri_file_path()
+            if not os.path.exists(iri_file_path):
+                dir = os.path.dirname(iri_file_path)
+                if not os.path.exists(dir):
+                    os.makedirs(dir)
+                created = True
+                file = open(iri_file_path, "w")
+                create_empty_iri(file, self, "IRI")
+            else:
+                created = False
+                update_iri(iri_file_path, self, "IRI")
+                
+        except Exception, e:
+            if created:
+                if os.path.exists(iri_file_path):
+                    os.remove(iri_file_path)
+            raise e
+        
+        
+    #TODO: better manage the change in .iri name and error scenario (save in temp file + rename
+    def save(self, *args, **kwargs):
+        
+        self.sync_iri_file()        
+        # update it 
+        super(Content, self).save(*args, **kwargs)
+    
+    def __unicode__(self):
+        return str(self.id) + ": " + self.iri_id
+        
+    def iri_url(self, web_url=settings.WEB_URL):
+        if 'http' in self.iriurl or 'https' in self.iriurl:
+            return self.iriurl
+        else:
+            return unicode(web_url) + unicode(settings.MEDIA_URL) + u"ldt/" + unicode(self.iriurl)
+    
+    def iri_file_path(self):
+        return os.path.join(os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "media"), "ldt"), self.iri_id), os.path.basename(self.iriurl))
+
+    def iri_url_template(self):
+        return "${web_url}${media_url}ldt/" + unicode(self.iri_id) + "/" + os.path.basename(self.iriurl)
+
+
+    def __get_empty_media(self):
+        if settings.EMPTY_MEDIA_EXTERNALID:
+            empty_media = Media.objects.get(external_id=settings.EMPTY_MEDIA_EXTERNALID)
+            return empty_media
+        else:
+            return None
+            
+    
+    def stream_src(): #@NoSelf
+        
+        def fget(self):
+            if self.media_obj is not None:
+                return self.media_obj.stream_src
+            else:
+                empty_media = self.__get_empty_media()
+                if empty_media:
+                    return empty_media.stream_src
+                else:
+                    return ""
+        
+        return locals()
+    
+    stream_src = property(**stream_src())
+    
+    def videopath(): #@NoSelf
+        doc = """simulate videopath""" #@UnusedVariable
+       
+        def fget(self):
+            if self.media_obj is None:
+                empty_media = self.__get_empty_media()
+                if empty_media:
+                    return empty_media.videopath
+                else:
+                    return None
+            else:
+                return self.media_obj.videopath
+           
+        def fset(self, value):
+            if self.media_obj is not None:
+                self.media_obj.videopath = value
+                      
+        return locals()
+       
+    videopath = property(**videopath())
+
+    def src(): #@NoSelf
+        doc = """simulate videopath""" #@UnusedVariable
+       
+        def fget(self):
+            if self.media_obj is None:
+                empty_media = self.__get_empty_media()
+                if empty_media:
+                    return empty_media.src
+                else:
+                    return None
+            else:
+                return self.media_obj.src
+           
+        def fset(self, value):
+            if self.media_obj is None or self.media_obj.src != value:
+                media, created = Media.objects.get_or_create(src=value, defaults={'src':value})                #@UnusedVariable
+                self.media_obj = media
+                self.save()
+                      
+        return locals()
+       
+    src = property(**src())
+
+    def external_id(): #@NoSelf
+        doc = """simulate externalid""" #@UnusedVariable
+       
+        def fget(self):
+            if self.media_obj is None:
+                empty_media = self.__get_empty_media()
+                if empty_media:
+                    return empty_media.external_id
+                else: 
+                    return None
+            else:
+                return self.media_obj.external_id
+           
+        def fset(self, value):
+            if self.media_obj is not None:
+                self.media_obj.external_id = value
+                      
+        return locals()
+       
+    external_id = property(**external_id())
+
+        
+        
+class Project(Document):  
+    STATE_CHOICES = (
+    (1, 'edition'),
+    (2, 'published'),
+    (3, 'moderated'),
+    (4, 'rejected'),
+    (5, 'deleted')
+    )
+    ldt_id = models.CharField(max_length=1024, unique=True)
+    ldt = models.TextField(null=True)
+    title = models.CharField(max_length=1024)
+    contents = models.ManyToManyField(Content)
+    creation_date = models.DateTimeField(auto_now_add=True)
+    modification_date = models.DateTimeField(auto_now=True)
+    created_by = models.CharField(_("created by"), max_length=70)
+    changed_by = models.CharField(_("changed by"), max_length=70)
+    state = models.IntegerField(choices=STATE_CHOICES, default=1)
+    
+    class Meta:
+        ordering = ["title"]
+
+    
+    def __unicode__(self):
+        return unicode(self.id) + u"::" + unicode(self.ldt_id) + u"::" + unicode(self.title)
+    
+    def get_description(self, doc=None):
+        
+        if doc is None:
+            doc = lxml.etree.fromstring(self.ldt)
+        
+        res = doc.xpath("/iri/project")
+        if len(res) > 0:
+            return res[0].get(u'abstract')
+        else:
+            return None
+
+    def stream_mode(): #@NoSelf
+        def fget(self):
+            modes = []
+            for content in self.contents.all():
+                mimetype = content.mimetype
+                if mimetype:
+                    mode = mimetype.split("/")[0]
+                    if "audio" == mode or "video" == mode:
+                        modes.append(mode)
+                    else:
+                        modes.append("video")
+                else:
+                    modes.append("video")
+            def filter_video(current, item):
+                if not current:
+                    return item
+                elif current == item:
+                    return item
+                else:
+                    return "video"
+            return reduce(filter_video, modes)
+        return locals()
+    
+    stream_mode = property(**stream_mode())
+
+    @staticmethod
+    def create_project(user, title, contents):
+        owner = Owner.objects.get(user=user) #@UndefinedVariable
+        project = Project(title=title, owner=owner)
+        project.ldt_id = str(uuid.uuid1()) #@UndefinedVariable
+        project.created_by = user.username
+        project.changed_by = user.username
+        project.state = 1
+        project.save()
+        for content in contents:
+            project.contents.add(content)
+        project.save()
+        return create_ldt(project, user)
+
+    def copy_project(self, user, title):
+        owner = Owner.objects.get(user=user) #@UndefinedVariable
+        project = Project(title=title, owner=owner)
+        project = copy_ldt(self, project, user)
+        project.save()
+        for content in self.contents.all():
+            project.contents.add(content)
+        project.save()
+        return project
+    
+    def checkAccess(self, user):
+        if (user and user.is_staff) or self.state == 2: 
+            return True
+        else:
+            return False
+        
+
+class Segment(models.Model):
+    
+    project_obj = models.ForeignKey(Project, null=True)
+    content = models.ForeignKey(Content)
+    project_id = models.CharField(max_length=1024, unique=False, blank=True, null=True)
+    iri_id = models.CharField(max_length=1024, unique=False)
+    ensemble_id = models.CharField(max_length=1024, unique=False)
+    cutting_id = models.CharField(max_length=1024, unique=False)    
+    element_id = models.CharField(max_length=1024, unique=False)
+    tags = tagging.fields.TagField(max_length=2048, null=True, blank=True, unique=False)
+    title = models.CharField(max_length=2048, unique=False, null=True, blank=True)
+    duration = models.IntegerField(null=True)
+    start_ts = models.IntegerField(null=True)
+    author = models.CharField(max_length=1024, unique=False, null=True, blank=True)
+    date = models.CharField(max_length=128, unique=False, null=True, blank=True)
+    abstract = models.TextField(null=True, blank=True)
+    
+    def __unicode__(self):
+        return "/".join((unicode(self.project_id), unicode(self.iri_id), unicode(self.ensemble_id), unicode(self.cutting_id), unicode(self.element_id)))
+    
+    class Meta:
+        unique_together = (('project_id', 'iri_id', 'ensemble_id', 'cutting_id', 'element_id'),)
+
+
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/copy_ldt.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/copy_ldt.html	Mon May 16 20:00:36 2011 +0200
@@ -1,24 +1,24 @@
-{% extends "ldt/ldt_raw_base.html" %}
-
-{% load i18n %} {# form of copy of project ldt #}
-{% block css_import %}
-    {{ block.super }}
-    <link rel="stylesheet" href="{{LDT_MEDIA_PREFIX}}css/ldt.css" />  
-    <link rel="stylesheet" href="{{LDT_MEDIA_PREFIX}}css/ldtform.css" />
-    <link rel="stylesheet" href="{{LDT_MEDIA_PREFIX}}css/workspace.css" />
-{% endblock %}
-{% block body %}
-	<div id="add_contribution" class="span-12 last">
-	<div class="projectscontentstitle span-12 last">{% trans "Copy your project" %}</div>
-	
-	<form action="" method="POST">{% csrf_token %}
-	    <div class="span-12 last">
-		<label for="title">{%trans "Title" %}:</label>
-		<input class="inputbox required" type="text" name="title" size="80"  value="" id="title" />
-		</div>
-		<div id="submitcontent-buttons" class="span-12 last">
-		  <input class="button" id="ldt_submit" type="submit" value="{% trans 'Copy' %}" />
-		 </div>
-	</form>
-	</div>
-{% endblock %}
+{% extends "ldt/ldt_raw_base.html" %}
+
+{% load i18n %} {# form of copy of project ldt #}
+{% block css_import %}
+    {{ block.super }}
+    <link rel="stylesheet" href="{{LDT_MEDIA_PREFIX}}css/ldt.css" />  
+    <link rel="stylesheet" href="{{LDT_MEDIA_PREFIX}}css/ldtform.css" />
+    <link rel="stylesheet" href="{{LDT_MEDIA_PREFIX}}css/workspace.css" />
+{% endblock %}
+{% block body %}
+	<div id="add_contribution" class="span-12 last">
+	<div class="projectscontentstitle span-12 last">{% trans "Copy your project" %}</div>
+	
+	<form action="" method="POST">{% csrf_token %}
+	    <div class="span-12 last">
+		<label for="title">{%trans "Title" %}:</label>
+		<input class="inputbox required" type="text" name="title" size="80"  value="" id="title" />
+		</div>
+		<div id="submitcontent-buttons" class="span-12 last">
+		  <input class="button" id="ldt_submit" type="submit" value="{% trans 'Copy' %}" />
+		 </div>
+	</form>
+	</div>
+{% endblock %}
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/save_done.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/save_done.html	Mon May 16 20:00:36 2011 +0200
@@ -1,5 +1,5 @@
-<p>done</p>
-<p>{{ldt}}
-<p>
-<p>{{id}}</p>
+<p>done</p>
+<p>{{ldt}}
+<p>
+<p>{{id}}</p>
 <p>title:{{title}}</p>
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/tests.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/tests.py	Mon May 16 20:00:36 2011 +0200
@@ -1,168 +1,168 @@
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
-
-Replace these with more appropriate tests for your application.
-"""
-
-from django.conf import settings
-from django.test import TestCase
-from ldt.core.models import Owner
-from models import Project, Content
-from utils import LdtUtils, create_ldt, create_empty_iri, copy_ldt
-import lxml.etree
-import tempfile
-import unittest
-import uuid
-
-
-
-class SimpleTest(TestCase):
-    def test_basic_addition(self):
-        """
-        Tests that 1 + 1 always equals 2.
-        """
-        self.failUnlessEqual(1 + 1, 2)
-
-__test__ = {"doctest": """
-Another way to test that 1 + 1 is equal to 2.
-
->>> 1 + 1 == 2
-True
-"""}
-
-
-
-class UtilsTest(unittest.TestCase):
-    def setUp(self):
-        self.user = Owner()
-        self.user.username = "toto"
-        self.LU = LdtUtils()
-    
-        self.project = Project(title="titleproj1", owner=self.user)
-        self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
-        self.project.id = "11"
-        self.project.ldt_id = str(uuid.uuid1())
-        self.project.save()
-        
-        self.projectcopy = Project(title="the2ndproject")
-        self.projectcopy.id = "22"
-
-    def tearDown(self):
-        self.project.delete()
-        self.projectcopy.delete()
-        #self.cont1.delete()
-        #self.cont2.delete()
-
-    def test_generate_ldt(self):
-        self.cont1 = Content(iriurl="id1/iriurl1")
-        self.cont1.iri_id = "id1"
-        self.cont1.save()
-        
-        self.cont2 = Content(iriurl="id2/iriurl2")
-        self.cont2.iri_id = "id2"
-        self.cont2.save()
-        
-        self.project.contents.add(self.cont1, self.cont2)
-    
-        f = tempfile.TemporaryFile(mode='r+')
-        self.LU.generateLdt(Content.objects.all(), f)
-        f.seek(0)
-        ldoc = lxml.etree.parse(f)
-        self.assertEqual(ldoc.xpath("/iri/displays/display/content")[9].get("id"), self.cont2.iri_id)
-        self.assertEqual(ldoc.xpath("/iri/medias/media")[8].get("id"), self.cont1.iri_id)
-        f.close()
-
-    def test_generate_init(self):
-        self.cont3 = Content(iriurl="id3/iriurl1")
-        self.cont3.iri_id = "id3"
-        self.cont3.save()
-        
-        self.cont4 = Content(iriurl="id4/iriurl2")
-        self.cont4.iri_id = "id4"
-        self.cont4.save()
-        
-        self.project.contents.add(self.cont3, self.cont4)
-        ldoc = self.LU.generateInit(None, None)
-        self.assertEqual(ldoc.xpath("/iri/files/init")[0].tag, "init")
-        self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library")
-        self.assertEqual(ldoc.xpath("/iri/files/init/file")[0].get("video"), settings.STREAM_URL)
-
-    def test_create_ldt(self):
-        self.cont5 = Content(iriurl="id5/iriurl1")
-        self.cont5.iri_id = "id5"
-        self.cont5.save()
-        
-        self.cont6 = Content(iriurl="id6/iriurl2")
-        self.cont6.iri_id = "id6"
-        self.cont6.save()
-        
-        self.project.contents.add(self.cont5, self.cont6)
-        self.project.ldt = ""
-        create_ldt(self.project, self.user)
-        ldt = lxml.etree.fromstring(self.project.ldt)
-        self.assertEqual(ldt.xpath("/iri")[0].tag, "iri")
-        self.assertEqual(ldt.xpath("/iri/project")[0].get("title"), self.project.title)
-        self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.iri_url())
-        self.assertEqual(ldt.xpath("/iri/medias/media")[1].get("id"), self.cont6.iri_id)
-
-    def test_copy_ldt(self):
-        self.cont7 = Content(iriurl="id7/iriurl1")
-        self.cont7.iri_id = "id7"
-        self.cont7.save()
-        
-        self.cont8 = Content(iriurl="id8/iriurl2")
-        self.cont8.iri_id = "id8"
-        self.cont8.save()
-        
-        self.project.contents.add(self.cont7, self.cont8)
-        copy_ldt(self.project, self.projectcopy, self.user)
-        ldt1 = lxml.etree.fromstring(self.project.ldt)
-        ldt2 = lxml.etree.fromstring(self.projectcopy.ldt)
-        self.assertTrue(ldt1.xpath("/iri/project")[0].get("id") != ldt2.xpath("/iri/project")[0].get("id"))
-        self.assertEqual(ldt1.xpath("/iri/medias/media")[0].get("id"), ldt2.xpath("/iri/medias/media")[0].get("id"))
-        self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble")[0].get("title"), ldt2.xpath("/iri/annotations/content/ensemble")[0].get("title"))
-        self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"), ldt2.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"))
-        self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text, ldt2.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text.strip("\n\t"))
-
-    def test_create_empty_iri(self):
-        self.cont9 = Content(iriurl="id9/iriurl1")
-        self.cont9.iri_id = "id9"
-        self.cont9.save()
-        
-        self.cont10 = Content(iriurl="id10/iriurl2")
-        self.cont10.iri_id = "id10"
-        self.cont10.save()
-        
-        self.project.contents.add(self.cont9, self.cont10)
-        tmp = tempfile.TemporaryFile(mode='r+')
-        create_empty_iri(tmp, self.cont9, "admin")
-        tmp.seek(0)
-        ldoc = lxml.etree.parse(tmp)
-        self.assertEqual(ldoc.xpath("/iri/head/meta")[0].get("content"), self.cont9.iri_id)
-        self.assertEqual(ldoc.xpath("/iri/body/medias/media/video")[0].get("id"), self.cont9.iri_id)
-        tmp.close()
-    
-
-
-
-class ViewsTest(unittest.TestCase):
-    def setUp(self):
-        self.project = Project()
-        self.project.id = "121"
-        self.project.save()
-        self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>' 
-    
-        self.cont1 = Content(iriurl="/laurentcantet_entrelesmurs/iriurl1")
-        self.cont1.iri_id = 'laurentcantet_entrelesmurs'
-        self.cont1.save()
-    
-        self.cont2 = Content(iriurl="/content_notinldt/iriurl2")
-        self.cont2.iri_id = 'content_notinldt'
-        self.cont2.save()
-        
-        self.project.contents.add(self.cont1, self.cont2)
-
-    def tearDown(self):
-        self.project.delete()
-
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.conf import settings
+from django.test import TestCase
+from ldt.core.models import Owner
+from models import Project, Content
+from utils import LdtUtils, create_ldt, create_empty_iri, copy_ldt
+import lxml.etree
+import tempfile
+import unittest
+import uuid
+
+
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
+
+
+class UtilsTest(unittest.TestCase):
+    def setUp(self):
+        self.user = Owner()
+        self.user.username = "toto"
+        self.LU = LdtUtils()
+    
+        self.project = Project(title="titleproj1", owner=self.user)
+        self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+        self.project.id = "11"
+        self.project.ldt_id = str(uuid.uuid1())
+        self.project.save()
+        
+        self.projectcopy = Project(title="the2ndproject")
+        self.projectcopy.id = "22"
+
+    def tearDown(self):
+        self.project.delete()
+        self.projectcopy.delete()
+        #self.cont1.delete()
+        #self.cont2.delete()
+
+    def test_generate_ldt(self):
+        self.cont1 = Content(iriurl="id1/iriurl1")
+        self.cont1.iri_id = "id1"
+        self.cont1.save()
+        
+        self.cont2 = Content(iriurl="id2/iriurl2")
+        self.cont2.iri_id = "id2"
+        self.cont2.save()
+        
+        self.project.contents.add(self.cont1, self.cont2)
+    
+        f = tempfile.TemporaryFile(mode='r+')
+        self.LU.generateLdt(Content.objects.all(), f)
+        f.seek(0)
+        ldoc = lxml.etree.parse(f)
+        self.assertEqual(ldoc.xpath("/iri/displays/display/content")[9].get("id"), self.cont2.iri_id)
+        self.assertEqual(ldoc.xpath("/iri/medias/media")[8].get("id"), self.cont1.iri_id)
+        f.close()
+
+    def test_generate_init(self):
+        self.cont3 = Content(iriurl="id3/iriurl1")
+        self.cont3.iri_id = "id3"
+        self.cont3.save()
+        
+        self.cont4 = Content(iriurl="id4/iriurl2")
+        self.cont4.iri_id = "id4"
+        self.cont4.save()
+        
+        self.project.contents.add(self.cont3, self.cont4)
+        ldoc = self.LU.generateInit(None, None)
+        self.assertEqual(ldoc.xpath("/iri/files/init")[0].tag, "init")
+        self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library")
+        self.assertEqual(ldoc.xpath("/iri/files/init/file")[0].get("video"), settings.STREAM_URL)
+
+    def test_create_ldt(self):
+        self.cont5 = Content(iriurl="id5/iriurl1")
+        self.cont5.iri_id = "id5"
+        self.cont5.save()
+        
+        self.cont6 = Content(iriurl="id6/iriurl2")
+        self.cont6.iri_id = "id6"
+        self.cont6.save()
+        
+        self.project.contents.add(self.cont5, self.cont6)
+        self.project.ldt = ""
+        create_ldt(self.project, self.user)
+        ldt = lxml.etree.fromstring(self.project.ldt)
+        self.assertEqual(ldt.xpath("/iri")[0].tag, "iri")
+        self.assertEqual(ldt.xpath("/iri/project")[0].get("title"), self.project.title)
+        self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.iri_url())
+        self.assertEqual(ldt.xpath("/iri/medias/media")[1].get("id"), self.cont6.iri_id)
+
+    def test_copy_ldt(self):
+        self.cont7 = Content(iriurl="id7/iriurl1")
+        self.cont7.iri_id = "id7"
+        self.cont7.save()
+        
+        self.cont8 = Content(iriurl="id8/iriurl2")
+        self.cont8.iri_id = "id8"
+        self.cont8.save()
+        
+        self.project.contents.add(self.cont7, self.cont8)
+        copy_ldt(self.project, self.projectcopy, self.user)
+        ldt1 = lxml.etree.fromstring(self.project.ldt)
+        ldt2 = lxml.etree.fromstring(self.projectcopy.ldt)
+        self.assertTrue(ldt1.xpath("/iri/project")[0].get("id") != ldt2.xpath("/iri/project")[0].get("id"))
+        self.assertEqual(ldt1.xpath("/iri/medias/media")[0].get("id"), ldt2.xpath("/iri/medias/media")[0].get("id"))
+        self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble")[0].get("title"), ldt2.xpath("/iri/annotations/content/ensemble")[0].get("title"))
+        self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"), ldt2.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"))
+        self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text, ldt2.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text.strip("\n\t"))
+
+    def test_create_empty_iri(self):
+        self.cont9 = Content(iriurl="id9/iriurl1")
+        self.cont9.iri_id = "id9"
+        self.cont9.save()
+        
+        self.cont10 = Content(iriurl="id10/iriurl2")
+        self.cont10.iri_id = "id10"
+        self.cont10.save()
+        
+        self.project.contents.add(self.cont9, self.cont10)
+        tmp = tempfile.TemporaryFile(mode='r+')
+        create_empty_iri(tmp, self.cont9, "admin")
+        tmp.seek(0)
+        ldoc = lxml.etree.parse(tmp)
+        self.assertEqual(ldoc.xpath("/iri/head/meta")[0].get("content"), self.cont9.iri_id)
+        self.assertEqual(ldoc.xpath("/iri/body/medias/media/video")[0].get("id"), self.cont9.iri_id)
+        tmp.close()
+    
+
+
+
+class ViewsTest(unittest.TestCase):
+    def setUp(self):
+        self.project = Project()
+        self.project.id = "121"
+        self.project.save()
+        self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>' 
+    
+        self.cont1 = Content(iriurl="/laurentcantet_entrelesmurs/iriurl1")
+        self.cont1.iri_id = 'laurentcantet_entrelesmurs'
+        self.cont1.save()
+    
+        self.cont2 = Content(iriurl="/content_notinldt/iriurl2")
+        self.cont2.iri_id = 'content_notinldt'
+        self.cont2.save()
+        
+        self.project.contents.add(self.cont1, self.cont2)
+
+    def tearDown(self):
+        self.project.delete()
+
--- a/src/ldt/ldt/ldt_utils/urls.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/urls.py	Mon May 16 20:00:36 2011 +0200
@@ -1,54 +1,54 @@
-from django.conf.urls.defaults import patterns, url
-from ldt.management import test_ldt
-
-# Uncomment the next two lines to enable the admin:
-# from django.contrib import admin
-# admin.autodiscover()
-
-urlpatterns = patterns('ldt.ldt_utils',
-    url(r'^searchInit/(?P<field>.*)/(?P<query>.*)$', 'views.searchInit'),
-    url(r'^searchForm/$', 'views.searchForm'),
-    url(r'^search/$', 'views.searchIndex'),
-    url(r'^search/(?P<field>.*)/(?P<query>.*)$', 'views.searchIndexGet'),
-    url(r'^searchLdt/(?P<field>.*)/(?P<query>.*)$', 'views.searchLdt'),
-    url(r'^searchSeg/(?P<field>.*)/(?P<query>.*)$', 'views.searchSegments'),
-    url(r'^index/(?P<url>.*)$', 'views.index'),
-    url(r'^init/(?P<method>.*)/(?P<url>.*)$', 'views.init', name='ldt_init'),
-    url(r'^ldt/(?P<url>.*)$', 'views.ldt'),
-    url(r'^search/loading/$', 'views.loading'),
-    url(r'^create/(?P<iri_id>.*)$', 'views.create_project'),
-    url(r'^copy/(?P<ldt_id>.*)$', 'views.copy_project'),
-    url(r'^update/(?P<ldt_id>.*)$', 'views.update_project'),
-    url(r'^cljson/id/(?P<id>.*)$', 'views.project_json_id'),
-    url(r'^cljson/externalid/(?P<id>.*)$', 'views.project_json_externalid'),
-    url(r'^rdf/id/(?P<ldt_id>.*)$', 'views.project_annotations_rdf'),
-    url(r'^/?$', "views.workspace", name="root-view"),
-    url(r'^filterprojects/_(?P<filter>[\w\%\_\-\+]*?)/(?P<is_owner>true|false)/(?P<status>\d)$', "views.projectsfilter",),
-    url(r'^filtercontents/_(?P<filter>[\w\%\_\-\+]*?)/$', "views.contentsfilter",),
-    (r'^embedpopup/?$', "views.popup_embed"),
-)
-
-urlpatterns += patterns('',
-    url('^jsi18n', 'django.views.i18n.javascript_catalog', name='jsi18n'),
-)
-
-
-if test_ldt():
-    urlpatterns += patterns('ldt.ldt_utils',
-        url(r'^space/content/$', 'views.list_content'),
-        url(r'^space/content/create/$', 'views.write_content'),
-        url(r'^space/content/update/(?P<iri_id>[\w-]+)$', 'views.write_content'),
-        url(r'^space/ldt/$', 'views.list_ldt'),
-        url(r'^space/ldt/indexproject/(?P<id>.*)$', 'views.indexProject'),
-        url(r'^space/ldt/indexprojectfull/(?P<id>.*)$', 'views.indexProjectFull'),
-        url(r'^space/ldt/init/(?P<method>.*)/(?P<url>.+)$', 'views.init', name='space_ldt_init'),
-        url(r'^space/ldt/project/(?P<id>.*)$', 'views.ldtProject'),
-        url(r'^space/ldt/create/$', 'views.create_ldt_view'),
-        url(r'^space/ldt/created_done/$', 'views.created_ldt'),
-        url(r'^space/ldt/save/$', 'views.save_ldtProject'),
-        url(r'^space/ldt/publish/(?P<id>[\w-]*)(?:/(?P<redirect>true|false))?$', 'views.publish'),
-        url(r'^space/ldt/unpublish/(?P<id>[\w-]*)(?:/(?P<redirect>true|false))?$', 'views.unpublish'),
-        url(r'^space/upload/$', 'views.upload'),
-        url(r'^space/removetempfile/$', 'views.removetempfile'),
-
-)
+from django.conf.urls.defaults import patterns, url
+from ldt.management import test_ldt
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('ldt.ldt_utils',
+    url(r'^searchInit/(?P<field>.*)/(?P<query>.*)$', 'views.searchInit'),
+    url(r'^searchForm/$', 'views.searchForm'),
+    url(r'^search/$', 'views.searchIndex'),
+    url(r'^search/(?P<field>.*)/(?P<query>.*)$', 'views.searchIndexGet'),
+    url(r'^searchLdt/(?P<field>.*)/(?P<query>.*)$', 'views.searchLdt'),
+    url(r'^searchSeg/(?P<field>.*)/(?P<query>.*)$', 'views.searchSegments'),
+    url(r'^index/(?P<url>.*)$', 'views.index'),
+    url(r'^init/(?P<method>.*)/(?P<url>.*)$', 'views.init', name='ldt_init'),
+    url(r'^ldt/(?P<url>.*)$', 'views.ldt'),
+    url(r'^search/loading/$', 'views.loading'),
+    url(r'^create/(?P<iri_id>.*)$', 'views.create_project'),
+    url(r'^copy/(?P<ldt_id>.*)$', 'views.copy_project'),
+    url(r'^update/(?P<ldt_id>.*)$', 'views.update_project'),
+    url(r'^cljson/id/(?P<id>.*)$', 'views.project_json_id'),
+    url(r'^cljson/externalid/(?P<id>.*)$', 'views.project_json_externalid'),
+    url(r'^rdf/id/(?P<ldt_id>.*)$', 'views.project_annotations_rdf'),
+    url(r'^/?$', "views.workspace", name="root-view"),
+    url(r'^filterprojects/_(?P<filter>[\w\%\_\-\+]*?)/(?P<is_owner>true|false)/(?P<status>\d)$', "views.projectsfilter",),
+    url(r'^filtercontents/_(?P<filter>[\w\%\_\-\+]*?)/$', "views.contentsfilter",),
+    (r'^embedpopup/?$', "views.popup_embed"),
+)
+
+urlpatterns += patterns('',
+    url('^jsi18n', 'django.views.i18n.javascript_catalog', name='jsi18n'),
+)
+
+
+if test_ldt():
+    urlpatterns += patterns('ldt.ldt_utils',
+        url(r'^space/content/$', 'views.list_content'),
+        url(r'^space/content/create/$', 'views.write_content'),
+        url(r'^space/content/update/(?P<iri_id>[\w-]+)$', 'views.write_content'),
+        url(r'^space/ldt/$', 'views.list_ldt'),
+        url(r'^space/ldt/indexproject/(?P<id>.*)$', 'views.indexProject'),
+        url(r'^space/ldt/indexprojectfull/(?P<id>.*)$', 'views.indexProjectFull'),
+        url(r'^space/ldt/init/(?P<method>.*)/(?P<url>.+)$', 'views.init', name='space_ldt_init'),
+        url(r'^space/ldt/project/(?P<id>.*)$', 'views.ldtProject'),
+        url(r'^space/ldt/create/$', 'views.create_ldt_view'),
+        url(r'^space/ldt/created_done/$', 'views.created_ldt'),
+        url(r'^space/ldt/save/$', 'views.save_ldtProject'),
+        url(r'^space/ldt/publish/(?P<id>[\w-]*)(?:/(?P<redirect>true|false))?$', 'views.publish'),
+        url(r'^space/ldt/unpublish/(?P<id>[\w-]*)(?:/(?P<redirect>true|false))?$', 'views.unpublish'),
+        url(r'^space/upload/$', 'views.upload'),
+        url(r'^space/removetempfile/$', 'views.removetempfile'),
+
+)
--- a/src/ldt/ldt/ldt_utils/views.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/ldt_utils/views.py	Mon May 16 20:00:36 2011 +0200
@@ -1,892 +1,901 @@
-from django.conf import settings
-from django.contrib.auth.decorators import login_required
-from django.core.urlresolvers import reverse
-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 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)
-from ldt.core.models import Owner
-from ldt.ldt_utils.models import Content
-from ldt.ldt_utils.utils import boolean_convert, LdtUtils, LdtSearch
-from lxml.html import fragment_fromstring
-from models import Media, Project
-from projectserializer import ProjectSerializer
-from urllib2 import urlparse
-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
-
-
-@login_required
-def workspace(request):
-
-    # list of contents
-    content_list = Content.objects.all() #@UndefinedVariable
-
-    # get list of projects
-    project_list = Project.objects.all() #@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))
-
-
-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.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.checkAccess(request.user, project):
-        return HttpResponseForbidden(_("You can not access this project"))
-
-    ps = ProjectSerializer(project, from_contents=False, from_display=True)
-    annotations = ps.getAnnotations(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 projectsfilter(request, filter, is_owner=False, status=0):
-
-    is_owner = boolean_convert(is_owner)
-    status = int(status)
-    query = Q()
-
-    if is_owner:
-        owner = None
-        try:
-            owner = Owner.objects.get(user=request.user) #@UndefinedVariable
-        except:
-            return HttpResponseServerError("<h1>User not found</h1>")
-        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)
-
-    project_list = Project.objects.filter(query) #@UndefinedVariable
-    
-    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-
-    return render_to_response("ldt/ldt_utils/partial/projectslist.html",
-                              {'projects': project_list, 'is_gecko': is_gecko},
-                              context_instance=RequestContext(request))
-
-
-
-@login_required
-def contentsfilter(request, filter):
-    if filter and len(filter) > 0 and filter[0] == '_':
-        filter = filter[1:]
-
-    if filter:
-        content_list = Content.objects.filter(title__icontains=filter) #@UndefinedVariable
-    else:
-        content_list = Content.objects.all() #@UndefinedVariable
-
-    return render_to_response("ldt/ldt_utils/partial/contentslist.html",
-                              {'contents': content_list},
-                              context_instance=RequestContext(request))
-
-
-def searchForm(request):
-    form = SearchForm()
-    return render_to_response('ldt/ldt_utils/search_form.html', {'form': form} , context_instance=RequestContext(request))    
-
-def searchIndex(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]
-    
-        url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.searchInit", args=[field, queryStr])
-        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))
-    else:
-        resp = HttpResponse()
-        resp.write("<html><head></head><body>Error : No result</body></html>");
-
-def searchIndexGet(request, field, query):
-
-    language_code = request.LANGUAGE_CODE[:2]
-    url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.searchInit", 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 searchInit(request, field, query):
-    
-    ldtgen = LdtUtils()
-    
-    doc = ldtgen.generateInit([field, query], 'ldt.ldt_utils.views.searchLdt', 'ldt.ldt_utils.views.searchSegments')
-    
-    resp = HttpResponse(mimetype="text/xml;charset=utf-8")
-    doc.write(resp, pretty_print=True)
-    return resp
-
-def searchLdt(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 = {}
-        
-        for result in searcher.query(field, queryStr):
-            ids[result["iri_id"]] = ""            
-
-        id_list = ids.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
-
-            
-    ldtgen = LdtUtils()
-    ldtgen.generateLdt(contentList, file=resp, title=u"Recherche : " + queryStr)
-    
-    return resp
-
-
-def searchSegments(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.objects.all() #@UndefinedVariable
-    try:
-        owner = Owner.objects.get(user=request.user) #@UndefinedVariable
-    except:
-        return HttpResponseRedirect(settings.LOGIN_URL)
-    ldtProjects = Project.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.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):
-    if request.method == "POST" :
-        form = LdtAddForm(request.POST)
-        if form.is_valid():
-            user = request.user
-            Project.create_project(title=form.cleaned_data['title'], user=user, contents=form.cleaned_data['contents'])
-            form_status = "saved"
-            contents = []
-    else:
-        form = LdtAddForm()
-        contents = Content.objects.all() #@UndefinedVariable
-        form_status = "none"
-            
-    return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form, 'form_status':form_status, 'create_project_action':reverse(create_ldt_view)}, context_instance=RequestContext(request))
-     
-def created_ldt(request):
-    return render_to_response('ldt/ldt_utils/save_done.html', context_instance=RequestContext(request))
-    
-def indexProject(request, id):
-
-    urlStr = settings.WEB_URL + reverse("space_ldt_init", args=['ldtProject', id])
-    posturl = settings.WEB_URL + reverse("ldt.ldt_utils.views.save_ldtProject")
-    language_code = request.LANGUAGE_CODE[:2]
-    
-    ldt = get_object_or_404(Project, ldt_id=id)
-    if ldt.state == 2: #published
-        readonly = 'true'
-    else:
-        readonly = 'false'
-    
-    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, 'posturl': posturl, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request))
-    
-def indexProjectFull(request, id):
-
-    urlStr = settings.WEB_URL + reverse("space_ldt_init", args=['ldtProject', id])
-    posturl = settings.WEB_URL + reverse("ldt.ldt_utils.views.save_ldtProject")
-    language_code = request.LANGUAGE_CODE[:2]
-    
-    ldt = get_object_or_404(Project, ldt_id=id)
-    if ldt.state == 2: #published
-        readonly = 'true'
-    else:
-        readonly = 'false'
-    
-    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': urlStr, 'posturl': posturl, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request))
-    
-def init(request, method, url):
-    ldtgen = LdtUtils()
-
-    doc = ldtgen.generateInit([url], 'ldt.ldt_utils.views.' + method, None)
-
-    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 ldtProject(request, id):
-    resp = HttpResponse(mimetype="text/xml")
-    resp['Cache-Control'] = 'no-cache, must-revalidate'
-    resp['Pragma'] = 'no-cache'
-    
-    project = Project.objects.get(ldt_id=id) #@UndefinedVariable
-    resp.write(project.ldt)
-    return resp
-
-
-def project_json_id(request, id):
-    
-    project = get_object_or_404(Project, ldt_id=id)
-
-    return project_json(request, project, False)
-
-
-def project_json_externalid(request, id):
-        
-    res_proj = get_list_or_404(Project.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):
-    
-    if not ldt_auth.checkAccess(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.objects.get(ldt_id=ldt_id); #@UndefinedVariable
-    
-    if not ldt_auth.checkAccess(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.getAnnotations(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"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
-    resp.write(u"<!DOCTYPE rdf:RDF PUBLIC \"-//DUBLIN CORE//DCMES DTD 2002/07/31//EN\" \"http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd\">\n")
-    
-    resp.write(lxml.etree.tostring(rdf_root, xml_declaration=False, encoding="utf-8", pretty_print=True))
-
-    return resp
-
-def save_ldtProject(request):
-    if request.method == "POST":
-        ldt = request.POST['ldt']
-        id = request.POST['id']
-        ldtproject = Project.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, ldt_id=id)
-    ldt.state = 2 #published
-    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, ldt_id=id)
-    ldt.state = 1 #edition
-    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.objects.filter(iri_id=url) #@UndefinedVariable
-
-    ldtgen = LdtUtils()
-    ldtgen.generateLdt(contentList, file=resp, title=contentList[0].title, startSegment=startSegment)
-
-    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, iri_id=iri_id)
-    contents = [ content, ]
-    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)
-            # Modal window is not used with firefox
-            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
-            if is_gecko :
-                return HttpResponseRedirect(reverse('ldt.ldt_utils.views.indexProjectFull', args=[project.ldt_id]))
-            else:
-                return HttpResponseRedirect(reverse('ldt.ldt_utils.views.indexProject', args=[project.ldt_id]))
-    else:
-        form = AddProjectForm()
-    # 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/create_ldt.html', {'form':form, 'contents':contents, 'create_project_action':reverse("ldt.ldt_utils.views.create_project", args=[iri_id]), 'target_parent':target_parent}, context_instance=RequestContext(request))
-
-@login_required
-def update_project(request, ldt_id):
-
-    project = get_object_or_404(Project, ldt_id=ldt_id)
-    contents = project.contents.all()
-    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 = 'saved'
-            form = AddProjectForm(request.POST)
-            if form.is_valid():
-                if project.title != form.cleaned_data['title']:
-                    project.title = form.cleaned_data['title']
-                    ldt = lxml.etree.fromstring(project.ldt.encode("utf-8"))
-                    res = ldt.xpath("/iri/project")
-                    res[0].set("title", project.title)
-                    project.ldt = lxml.etree.tostring(ldt, pretty_print=True)
-                    project.save()
-    else:
-        form = AddProjectForm({'title':unicode(project.title)})
-        form_status = 'none'
-        
-    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'ldt_id': ldt_id, 'contents':contents, '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):
-
-    project = get_object_or_404(Project, ldt_id=ldt_id)
-    if request.method == "POST" :
-        form = CopyProjectForm(request.POST)
-        if form.is_valid():
-            user = request.user
-            project = project.copy_project(title=request.POST['title'], user=user)
-            return HttpResponseRedirect(reverse('ldt.ldt_utils.views.indexProject', args=[project.ldt_id]))
-    else:
-        form = CopyProjectForm
-    return render_to_response('ldt/ldt_utils/copy_ldt.html', {'form':form, 'project':project}, context_instance=RequestContext(request))
-
-
-def write_content_base(request, iri_id=None):
-
-    if iri_id:        
-        instance_content = Content.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_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.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
-                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
-                    
-                media.save()
-            
-            
-            if form_status != "error":
-                #try:
-                content_defaults = {}
-                content_defaults.update(content_form.cleaned_data)
-                content_defaults['media_obj'] = media
-                del content_defaults["media_input_type"]
-                content, created = Content.objects.get_or_create(iri_id=content_form.cleaned_data['iri_id'], defaults=content_defaults) #@UndefinedVariable
-                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"}
-        
-        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) 
-
-    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:
-        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
-    
-    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, '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.objects.filter(iri_id=iri_id): #@UndefinedVariable
-            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.objects.filter(iri_id=iri_id).delete() #@UndefinedVariable
-
-
-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 removetempfile(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")
-    
+from django.conf import settings
+from django.contrib.auth.decorators import login_required
+from django.core.urlresolvers import reverse
+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 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)
+from ldt.core.models import Owner
+from ldt.ldt_utils.models import Content
+from ldt.ldt_utils.utils import boolean_convert, LdtUtils, LdtSearch
+from lxml.html import fragment_fromstring
+from models import Media, Project
+from projectserializer import ProjectSerializer
+from urllib2 import urlparse
+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
+
+
+@login_required
+def workspace(request):
+
+    # list of contents
+    content_list = Content.objects.all() #@UndefinedVariable
+
+    # get list of projects
+    project_list = Project.objects.all() #@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))
+
+
+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.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.checkAccess(request.user, project):
+        return HttpResponseForbidden(_("You can not access this project"))
+
+    ps = ProjectSerializer(project, from_contents=False, from_display=True)
+    annotations = ps.getAnnotations(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 projectsfilter(request, filter, is_owner=False, status=0):
+
+    is_owner = boolean_convert(is_owner)
+    status = int(status)
+    query = Q()
+
+    if is_owner:
+        owner = None
+        try:
+            owner = Owner.objects.get(user=request.user) #@UndefinedVariable
+        except:
+            return HttpResponseServerError("<h1>User not found</h1>")
+        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)
+
+    project_list = Project.objects.filter(query) #@UndefinedVariable
+    
+    is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
+
+    return render_to_response("ldt/ldt_utils/partial/projectslist.html",
+                              {'projects': project_list, 'is_gecko': is_gecko},
+                              context_instance=RequestContext(request))
+
+
+
+@login_required
+def contentsfilter(request, filter):
+    if filter and len(filter) > 0 and filter[0] == '_':
+        filter = filter[1:]
+
+    if filter:
+        content_list = Content.objects.filter(title__icontains=filter) #@UndefinedVariable
+    else:
+        content_list = Content.objects.all() #@UndefinedVariable
+
+    return render_to_response("ldt/ldt_utils/partial/contentslist.html",
+                              {'contents': content_list},
+                              context_instance=RequestContext(request))
+
+
+def searchForm(request):
+    form = SearchForm()
+    return render_to_response('ldt/ldt_utils/search_form.html', {'form': form} , context_instance=RequestContext(request))    
+
+def searchIndex(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]
+    
+        url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.searchInit", args=[field, queryStr])
+        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))
+    else:
+        resp = HttpResponse()
+        resp.write("<html><head></head><body>Error : No result</body></html>");
+
+def searchIndexGet(request, field, query):
+
+    language_code = request.LANGUAGE_CODE[:2]
+    url = settings.WEB_URL + django.core.urlresolvers.reverse("ldt.ldt_utils.views.searchInit", 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 searchInit(request, field, query):
+    
+    ldtgen = LdtUtils()
+    
+    doc = ldtgen.generateInit([field, query], 'ldt.ldt_utils.views.searchLdt', 'ldt.ldt_utils.views.searchSegments')
+    
+    resp = HttpResponse(mimetype="text/xml;charset=utf-8")
+    doc.write(resp, pretty_print=True)
+    return resp
+
+def searchLdt(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 = {}
+        
+        for result in searcher.query(field, queryStr):
+            ids[result["iri_id"]] = ""            
+
+        id_list = ids.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
+
+            
+    ldtgen = LdtUtils()
+    ldtgen.generateLdt(contentList, file=resp, title=u"Recherche : " + queryStr)
+    
+    return resp
+
+
+def searchSegments(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.objects.all() #@UndefinedVariable
+    try:
+        owner = Owner.objects.get(user=request.user) #@UndefinedVariable
+    except:
+        return HttpResponseRedirect(settings.LOGIN_URL)
+    ldtProjects = Project.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.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):
+    if request.method == "POST" :
+        form = LdtAddForm(request.POST)
+        if form.is_valid():
+            user = request.user
+            Project.create_project(title=form.cleaned_data['title'], user=user, contents=form.cleaned_data['contents'])
+            form_status = "saved"
+            contents = []
+    else:
+        form = LdtAddForm()
+        contents = Content.objects.all() #@UndefinedVariable
+        form_status = "none"
+            
+    return render_to_response('ldt/ldt_utils/create_ldt.html', {'contents': contents, 'form': form, 'form_status':form_status, 'create_project_action':reverse(create_ldt_view)}, 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):
+    pass
+
+def init_segment(request, project_id, content_id, cutting_id, ensemble_id, segment_id):
+    pass
+
+def ldt_segment(request, project_id, content_id, cutting_id, ensemble_id, segment_id):
+    pass
+    
+def indexProject(request, id):
+
+    urlStr = settings.WEB_URL + reverse("space_ldt_init", args=['ldtProject', id])
+    posturl = settings.WEB_URL + reverse("ldt.ldt_utils.views.save_ldtProject")
+    language_code = request.LANGUAGE_CODE[:2]
+    
+    ldt = get_object_or_404(Project, ldt_id=id)
+    if ldt.state == 2: #published
+        readonly = 'true'
+    else:
+        readonly = 'false'
+    
+    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, 'posturl': posturl, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request))
+    
+def indexProjectFull(request, id):
+
+    urlStr = settings.WEB_URL + reverse("space_ldt_init", args=['ldtProject', id])
+    posturl = settings.WEB_URL + reverse("ldt.ldt_utils.views.save_ldtProject")
+    language_code = request.LANGUAGE_CODE[:2]
+    
+    ldt = get_object_or_404(Project, ldt_id=id)
+    if ldt.state == 2: #published
+        readonly = 'true'
+    else:
+        readonly = 'false'
+    
+    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': urlStr, 'posturl': posturl, 'id': id, 'readonly': readonly}, context_instance=RequestContext(request))
+    
+def init(request, method, url):
+    ldtgen = LdtUtils()
+
+    doc = ldtgen.generateInit([url], 'ldt.ldt_utils.views.' + method, None)
+
+    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 ldtProject(request, id):
+    resp = HttpResponse(mimetype="text/xml")
+    resp['Cache-Control'] = 'no-cache, must-revalidate'
+    resp['Pragma'] = 'no-cache'
+    
+    project = Project.objects.get(ldt_id=id) #@UndefinedVariable
+    resp.write(project.ldt)
+    return resp
+
+
+def project_json_id(request, id):
+    
+    project = get_object_or_404(Project, ldt_id=id)
+
+    return project_json(request, project, False)
+
+
+def project_json_externalid(request, id):
+        
+    res_proj = get_list_or_404(Project.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):
+    
+    if not ldt_auth.checkAccess(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.objects.get(ldt_id=ldt_id); #@UndefinedVariable
+    
+    if not ldt_auth.checkAccess(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.getAnnotations(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"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
+    resp.write(u"<!DOCTYPE rdf:RDF PUBLIC \"-//DUBLIN CORE//DCMES DTD 2002/07/31//EN\" \"http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd\">\n")
+    
+    resp.write(lxml.etree.tostring(rdf_root, xml_declaration=False, encoding="utf-8", pretty_print=True))
+
+    return resp
+
+def save_ldtProject(request):
+    if request.method == "POST":
+        ldt = request.POST['ldt']
+        id = request.POST['id']
+        ldtproject = Project.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, ldt_id=id)
+    ldt.state = 2 #published
+    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, ldt_id=id)
+    ldt.state = 1 #edition
+    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.objects.filter(iri_id=url) #@UndefinedVariable
+
+    ldtgen = LdtUtils()
+    ldtgen.generateLdt(contentList, file=resp, title=contentList[0].title, startSegment=startSegment)
+
+    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, iri_id=iri_id)
+    contents = [ content, ]
+    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)
+            # Modal window is not used with firefox
+            is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
+            if is_gecko :
+                return HttpResponseRedirect(reverse('ldt.ldt_utils.views.indexProjectFull', args=[project.ldt_id]))
+            else:
+                return HttpResponseRedirect(reverse('ldt.ldt_utils.views.indexProject', args=[project.ldt_id]))
+    else:
+        form = AddProjectForm()
+    # 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/create_ldt.html', {'form':form, 'contents':contents, 'create_project_action':reverse("ldt.ldt_utils.views.create_project", args=[iri_id]), 'target_parent':target_parent}, context_instance=RequestContext(request))
+
+@login_required
+def update_project(request, ldt_id):
+
+    project = get_object_or_404(Project, ldt_id=ldt_id)
+    contents = project.contents.all()
+    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 = 'saved'
+            form = AddProjectForm(request.POST)
+            if form.is_valid():
+                if project.title != form.cleaned_data['title']:
+                    project.title = form.cleaned_data['title']
+                    ldt = lxml.etree.fromstring(project.ldt.encode("utf-8"))
+                    res = ldt.xpath("/iri/project")
+                    res[0].set("title", project.title)
+                    project.ldt = lxml.etree.tostring(ldt, pretty_print=True)
+                    project.save()
+    else:
+        form = AddProjectForm({'title':unicode(project.title)})
+        form_status = 'none'
+        
+    return render_to_response('ldt/ldt_utils/create_ldt.html', {'form':form, 'form_status':form_status, 'ldt_id': ldt_id, 'contents':contents, '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):
+
+    project = get_object_or_404(Project, ldt_id=ldt_id)
+    if request.method == "POST" :
+        form = CopyProjectForm(request.POST)
+        if form.is_valid():
+            user = request.user
+            project = project.copy_project(title=request.POST['title'], user=user)
+            return HttpResponseRedirect(reverse('ldt.ldt_utils.views.indexProject', args=[project.ldt_id]))
+    else:
+        form = CopyProjectForm
+    return render_to_response('ldt/ldt_utils/copy_ldt.html', {'form':form, 'project':project}, context_instance=RequestContext(request))
+
+
+def write_content_base(request, iri_id=None):
+
+    if iri_id:        
+        instance_content = Content.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_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.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
+                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
+                    
+                media.save()
+            
+            
+            if form_status != "error":
+                #try:
+                content_defaults = {}
+                content_defaults.update(content_form.cleaned_data)
+                content_defaults['media_obj'] = media
+                del content_defaults["media_input_type"]
+                content, created = Content.objects.get_or_create(iri_id=content_form.cleaned_data['iri_id'], defaults=content_defaults) #@UndefinedVariable
+                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"}
+        
+        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) 
+
+    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:
+        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
+    
+    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, '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.objects.filter(iri_id=iri_id): #@UndefinedVariable
+            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.objects.filter(iri_id=iri_id).delete() #@UndefinedVariable
+
+
+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 removetempfile(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")
+    
--- a/src/ldt/ldt/settings.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/settings.py	Mon May 16 20:00:36 2011 +0200
@@ -1,77 +1,77 @@
-import logging
-from django.conf import settings
-
-
-# EMAIL_HOST='smtp.gmail.com'
-# EMAIL_HOST_USER = 'wujingwen1112@gmail.com'
-# EMAIL_HOST_PASSWORD='jingwen1112'
-# EMAIL_PORT='587'
-# EMAIL_USE_TLS = True
-#DEFAULT_FROM_EMAIL = "admin@domain.com"
-#SERVER_EMAIL = "admin@domain.com"
-
-INSTALLED_APPS = (
-    'django_extensions',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.sites',
-    'django.contrib.messages',
-    'django.contrib.admin',
-    'registration',
-    'tagging',
-    'ldt',
-    'ldt.core',
-    'ldt.ldt_utils',
-    'ldt.text',
-    'ldt.user',
-    'ldt.management',
-    'oauth_provider',
-    'django_openid_consumer',
-    'piston',
-    'social_auth',
-)
-
-MIDDLEWARE_CLASSES = (
-    'django.middleware.common.CommonMiddleware',
-    'ldt.ldt_utils.middleware.swfupload.SWFUploadMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.middleware.locale.LocaleMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
-    'django_openid_consumer.middleware.OpenIDMiddleware',
-)
-
-
-
-WEB_URL = getattr(settings, 'WEB_URL', '')
-BASE_URL = getattr(settings, 'BASE_URL', '')
-STATIC_URL = getattr(settings, 'STATIC_URL', '')
-MEDIA_URL = getattr(settings, 'MEDIA_URL', '')
-MEDIA_ROOT = getattr(settings, 'MEDIA_ROOT', '')
-SITE_ID = getattr(settings, 'SITE_ID', 1)
-DEBUG = getattr(settings, 'DEBUG', True)
-MANAGERS = settings.MANAGERS
-INSTALLED_APPS = settings.INSTALLED_APPS
-LANGUAGES = settings.LANGUAGES
-DECOUPAGE_BLACKLIST = getattr(settings, 'DECOUPAGE_BLACKLIST', 'de_PPP')
-STREAM_URL = getattr(settings, 'STREAM_URL', '')
-STREAM_PATH = getattr(settings, 'STREAM_PATH', '')
-STREAM_SRC_PREFIX = getattr(settings, 'STREAM_SRC_PREFIX', '')
-LOG_FILE = getattr(settings, 'LOG_FILE', '')
-LOG_LEVEL = getattr(settings, 'LOG_LEVEL', logging.INFO)
-EMPTY_MEDIA_EXTERNALID = getattr(settings, 'EMPTY_MEDIA_EXTERNALID', None)
-
-GLOBAL_LOG_LEVEL = LOG_LEVEL
-GLOBAL_LOG_HANDLERS = [logging.FileHandler(LOG_FILE)]
-
-TEST_WEBSERVER_ADDRPORT = getattr(settings, 'TEST_WEBSERVER_ADDRPORT', '127.0.0.1:8000')
-
-ACCOUNT_ACTIVATION_DAYS = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', 7)
-LDT_MEDIA_PREFIX = getattr(settings, 'LDT_MEDIA_PREFIX', MEDIA_URL + 'ldt/')
-LDT_MAX_SEARCH_NUMBER = 50
-LDT_JSON_DEFAULT_INDENT = 2
-
-AUTO_INDEX_AFTER_SAVE = getattr(settings, 'AUTO_INDEX_AFTER_SAVE', True)
-
+import logging
+from django.conf import settings
+
+
+# EMAIL_HOST='smtp.gmail.com'
+# EMAIL_HOST_USER = 'wujingwen1112@gmail.com'
+# EMAIL_HOST_PASSWORD='jingwen1112'
+# EMAIL_PORT='587'
+# EMAIL_USE_TLS = True
+#DEFAULT_FROM_EMAIL = "admin@domain.com"
+#SERVER_EMAIL = "admin@domain.com"
+
+INSTALLED_APPS = (
+    'django_extensions',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.messages',
+    'django.contrib.admin',
+    'registration',
+    'tagging',
+    'ldt',
+    'ldt.core',
+    'ldt.ldt_utils',
+    'ldt.text',
+    'ldt.user',
+    'ldt.management',
+    'oauth_provider',
+    'django_openid_consumer',
+    'piston',
+    'social_auth',
+)
+
+MIDDLEWARE_CLASSES = (
+    'django.middleware.common.CommonMiddleware',
+    'ldt.ldt_utils.middleware.swfupload.SWFUploadMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.middleware.locale.LocaleMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django_openid_consumer.middleware.OpenIDMiddleware',
+)
+
+
+
+WEB_URL = getattr(settings, 'WEB_URL', '')
+BASE_URL = getattr(settings, 'BASE_URL', '')
+STATIC_URL = getattr(settings, 'STATIC_URL', '')
+MEDIA_URL = getattr(settings, 'MEDIA_URL', '')
+MEDIA_ROOT = getattr(settings, 'MEDIA_ROOT', '')
+SITE_ID = getattr(settings, 'SITE_ID', 1)
+DEBUG = getattr(settings, 'DEBUG', True)
+MANAGERS = settings.MANAGERS
+INSTALLED_APPS = settings.INSTALLED_APPS
+LANGUAGES = settings.LANGUAGES
+DECOUPAGE_BLACKLIST = getattr(settings, 'DECOUPAGE_BLACKLIST', 'de_PPP')
+STREAM_URL = getattr(settings, 'STREAM_URL', '')
+STREAM_PATH = getattr(settings, 'STREAM_PATH', '')
+STREAM_SRC_PREFIX = getattr(settings, 'STREAM_SRC_PREFIX', '')
+LOG_FILE = getattr(settings, 'LOG_FILE', '')
+LOG_LEVEL = getattr(settings, 'LOG_LEVEL', logging.INFO)
+EMPTY_MEDIA_EXTERNALID = getattr(settings, 'EMPTY_MEDIA_EXTERNALID', None)
+
+GLOBAL_LOG_LEVEL = LOG_LEVEL
+GLOBAL_LOG_HANDLERS = [logging.FileHandler(LOG_FILE)]
+
+TEST_WEBSERVER_ADDRPORT = getattr(settings, 'TEST_WEBSERVER_ADDRPORT', '127.0.0.1:8000')
+
+ACCOUNT_ACTIVATION_DAYS = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', 7)
+LDT_MEDIA_PREFIX = getattr(settings, 'LDT_MEDIA_PREFIX', MEDIA_URL + 'ldt/')
+LDT_MAX_SEARCH_NUMBER = 50
+LDT_JSON_DEFAULT_INDENT = 2
+
+AUTO_INDEX_AFTER_SAVE = getattr(settings, 'AUTO_INDEX_AFTER_SAVE', True)
+
--- a/src/ldt/ldt/static/ldt/css/LdtPlayer.css	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/css/LdtPlayer.css	Mon May 16 20:00:36 2011 +0200
@@ -1,165 +1,165 @@
-		#demo-frame > div.demo { padding: 5px !important; };
-		
-		button.ui-button-icon-only  {
-			height:1.5em;
-			width:1.5em;
-		}
-		
-		#Ldt-loader {
-			background:url(imgs/loader.gif) no-repeat;
-			width:20px;
-			height:16px;
-			float:left;
-		}
-		
-		#Ldt-controler {
-			font-size: 62.5%;
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-			background-color:#eeeeee;
-			height:35px;
-			padding:5px;
-		}
-		
-		.Ldt-iri-chapter{
-			padding-top:10px;
-			padding-bottom:5px;
-			border-left:solid 1px #000;
-			border-right:solid 1px #000;
-		}
-		
-		.tooltip {
-			display:none;
-			background:transparent url(imgs/white_arrow_mini.png);
-			font-size:12px;
-			height:55px;
-			width:180px;
-			padding:10px;
-			padding-left:15px;
-			padding-top:15px;
-			padding-right:15px;
-			color:#000;	
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-		}
-		#Ldt-Root{
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-		}
-		#Ldt-Hat{
-			height:3px;
-		}
-		#Ldt-Annotations{
-			padding-left:5px;
-			width:470px;
-			float:left;
-			font-size: 62.5%;
-		}
-		#Ldt-SaTitle{
-			padding-top:2px;
-			padding-bottom:5px;
-			font-size:18px;
-			height:22p;
-		}
-		#Ldt-SaDescription{
-			font-size:12px;	
-		}
-		#Ldt-Show-Arrow-container{
-			margin-left:60px;
-		}
-		#Ldt-Show-Arrow{
-			position:relative;
-			background:url(imgs/grey_arrow_Show.png);
-			width:27px;
-			height:13px;
-			margin-top:12px;
-			margin-left:-10px;
-		}
-
-		#Ldt-Show-Tags{
-			position:relative;
-			height:13px;
-			margin-top:-10px;
-			border: solid 1px #000;
-		}
-		#Ldt-ShowAnnotation-video{
-			position:absolute;
-			z-index: 999;
-			padding:5px;
-			background:url(imgs/transBlack.png);
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-			color:#FFF;	
-		}
-		#Ldt-ShowAnnotation-audio{
-			position:relative;
-			padding:5px;
-			background-color:#cfcfcf;
-			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
-			color:#4D4D4D;	
-		}
-		#Ldt-SaKeyword{
-			background-color:#b9b9b9;
-			color:#4D4D4D;
-			padding:5px;
-			font-weight:bold;
-			text-align:left;
-			float:left;
-			font-size:10px;
-		}
-		#Ldt-SaShareTools{
-			text-align:right;
-			float:right;
-		}
-		
-		
-		#Ldt-PlaceHolder{
-			position:absolue;
-			float:none;
-		}
-		
-		.Ldt-mode-radio{
-			visibility:hidden;
-			height:0px;
-			display:none
-		}
-		
-		.Ldt-Control1{
-			width:60px;
-			float:left;
-		}
-		.Ldt-Control2{
-			padding-left:10px;
-			width:60px;
-			float:left;
-		}
-		.Ldt-cleaner {
-			clear:both;
-		} 
-		.share {
-			background:url('imgs/widget20.png') no-repeat scroll 0 0 transparent ;
-			display:block;
-			height:16px;
-			line-height:16px !important;
-			overflow:hidden;
-			width:16px;
-			float:left;
-			cursor:pointer;
-			margin:2px;
-		}
-		.shareFacebook{
-			background-position:0 -704px;
-		}
-		.shareMySpace{
-			background-position:0 -736px;
-		}
-		.shareTwitter{
-			background-position:0 -1072px;
-		}
-		.shareGoogle{
-			background-position:0 -752px;
-		}
-		.shareDelicious{
-			background-position:0 -672px;
-		}
-		.shareJamesPot{
-			background-position:0 -1808px;
-		}
-		
+		#demo-frame > div.demo { padding: 5px !important; };
+		
+		button.ui-button-icon-only  {
+			height:1.5em;
+			width:1.5em;
+		}
+		
+		#Ldt-loader {
+			background:url(imgs/loader.gif) no-repeat;
+			width:20px;
+			height:16px;
+			float:left;
+		}
+		
+		#Ldt-controler {
+			font-size: 62.5%;
+			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+			background-color:#eeeeee;
+			height:35px;
+			padding:5px;
+		}
+		
+		.Ldt-iri-chapter{
+			padding-top:10px;
+			padding-bottom:5px;
+			border-left:solid 1px #000;
+			border-right:solid 1px #000;
+		}
+		
+		.tooltip {
+			display:none;
+			background:transparent url(imgs/white_arrow_mini.png);
+			font-size:12px;
+			height:55px;
+			width:180px;
+			padding:10px;
+			padding-left:15px;
+			padding-top:15px;
+			padding-right:15px;
+			color:#000;	
+			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+		}
+		#Ldt-Root{
+			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+		}
+		#Ldt-Hat{
+			height:3px;
+		}
+		#Ldt-Annotations{
+			padding-left:5px;
+			width:470px;
+			float:left;
+			font-size: 62.5%;
+		}
+		#Ldt-SaTitle{
+			padding-top:2px;
+			padding-bottom:5px;
+			font-size:18px;
+			height:22p;
+		}
+		#Ldt-SaDescription{
+			font-size:12px;	
+		}
+		#Ldt-Show-Arrow-container{
+			margin-left:60px;
+		}
+		#Ldt-Show-Arrow{
+			position:relative;
+			background:url(imgs/grey_arrow_Show.png);
+			width:27px;
+			height:13px;
+			margin-top:12px;
+			margin-left:-10px;
+		}
+
+		#Ldt-Show-Tags{
+			position:relative;
+			height:13px;
+			margin-top:-10px;
+			border: solid 1px #000;
+		}
+		#Ldt-ShowAnnotation-video{
+			position:absolute;
+			z-index: 999;
+			padding:5px;
+			background:url(imgs/transBlack.png);
+			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+			color:#FFF;	
+		}
+		#Ldt-ShowAnnotation-audio{
+			position:relative;
+			padding:5px;
+			background-color:#cfcfcf;
+			font-family: "Trebuchet MS", "Helvetica", "Arial",  "Verdana", "sans-serif";
+			color:#4D4D4D;	
+		}
+		#Ldt-SaKeyword{
+			background-color:#b9b9b9;
+			color:#4D4D4D;
+			padding:5px;
+			font-weight:bold;
+			text-align:left;
+			float:left;
+			font-size:10px;
+		}
+		#Ldt-SaShareTools{
+			text-align:right;
+			float:right;
+		}
+		
+		
+		#Ldt-PlaceHolder{
+			position:absolue;
+			float:none;
+		}
+		
+		.Ldt-mode-radio{
+			visibility:hidden;
+			height:0px;
+			display:none
+		}
+		
+		.Ldt-Control1{
+			width:60px;
+			float:left;
+		}
+		.Ldt-Control2{
+			padding-left:10px;
+			width:60px;
+			float:left;
+		}
+		.Ldt-cleaner {
+			clear:both;
+		} 
+		.share {
+			background:url('imgs/widget20.png') no-repeat scroll 0 0 transparent ;
+			display:block;
+			height:16px;
+			line-height:16px !important;
+			overflow:hidden;
+			width:16px;
+			float:left;
+			cursor:pointer;
+			margin:2px;
+		}
+		.shareFacebook{
+			background-position:0 -704px;
+		}
+		.shareMySpace{
+			background-position:0 -736px;
+		}
+		.shareTwitter{
+			background-position:0 -1072px;
+		}
+		.shareGoogle{
+			background-position:0 -752px;
+		}
+		.shareDelicious{
+			background-position:0 -672px;
+		}
+		.shareJamesPot{
+			background-position:0 -1808px;
+		}
+		
 		
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/css/blueprint/plugins/fancy-type/screen.css	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/css/blueprint/plugins/fancy-type/screen.css	Mon May 16 20:00:36 2011 +0200
@@ -1,71 +1,71 @@
-/* --------------------------------------------------------------
-
-   fancy-type.css
-   * Lots of pretty advanced classes for manipulating text.
-
-   See the Readme file in this folder for additional instructions.
-
--------------------------------------------------------------- */
-
-/* Indentation instead of line shifts for sibling paragraphs. */
-   p + p { text-indent:2em; margin-top:-1.5em; }
-   form p + p  { text-indent: 0; } /* Don't want this in forms. */
-
-
-/* For great looking type, use this code instead of asdf:
-   <span class="alt">asdf</span>
-   Best used on prepositions and ampersands. */
-
-.alt {
-  color: #666;
-  font-family: "Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif;
-  font-style: italic;
-  font-weight: normal;
-}
-
-
-/* For great looking quote marks in titles, replace "asdf" with:
-   <span class="dquo">&#8220;</span>asdf&#8221;
-   (That is, when the title starts with a quote mark).
-   (You may have to change this value depending on your font size). */
-
-.dquo { margin-left: -.5em; }
-
-
-/* Reduced size type with incremental leading
-   (http://www.markboulton.co.uk/journal/comments/incremental_leading/)
-
-   This could be used for side notes. For smaller type, you don't necessarily want to
-   follow the 1.5x vertical rhythm -- the line-height is too much.
-
-   Using this class, it reduces your font size and line-height so that for
-   every four lines of normal sized type, there is five lines of the sidenote. eg:
-
-   New type size in em's:
-     10px (wanted side note size) / 12px (existing base size) = 0.8333 (new type size in ems)
-
-   New line-height value:
-     12px x 1.5 = 18px (old line-height)
-     18px x 4 = 72px
-     72px / 5 = 14.4px (new line height)
-     14.4px / 10px = 1.44 (new line height in em's) */
-
-p.incr, .incr p {
-  font-size: 10px;
-  line-height: 1.44em;
-  margin-bottom: 1.5em;
-}
-
-
-/* Surround uppercase words and abbreviations with this class.
-   Based on work by Jørgen Arnor Gårdsø Lom [http://twistedintellect.com/] */
-
-.caps {
-  font-variant: small-caps;
-  letter-spacing: 1px;
-  text-transform: lowercase;
-  font-size:1.2em;
-  line-height:1%;
-  font-weight:bold;
-  padding:0 2px;
-}
+/* --------------------------------------------------------------
+
+   fancy-type.css
+   * Lots of pretty advanced classes for manipulating text.
+
+   See the Readme file in this folder for additional instructions.
+
+-------------------------------------------------------------- */
+
+/* Indentation instead of line shifts for sibling paragraphs. */
+   p + p { text-indent:2em; margin-top:-1.5em; }
+   form p + p  { text-indent: 0; } /* Don't want this in forms. */
+
+
+/* For great looking type, use this code instead of asdf:
+   <span class="alt">asdf</span>
+   Best used on prepositions and ampersands. */
+
+.alt {
+  color: #666;
+  font-family: "Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif;
+  font-style: italic;
+  font-weight: normal;
+}
+
+
+/* For great looking quote marks in titles, replace "asdf" with:
+   <span class="dquo">&#8220;</span>asdf&#8221;
+   (That is, when the title starts with a quote mark).
+   (You may have to change this value depending on your font size). */
+
+.dquo { margin-left: -.5em; }
+
+
+/* Reduced size type with incremental leading
+   (http://www.markboulton.co.uk/journal/comments/incremental_leading/)
+
+   This could be used for side notes. For smaller type, you don't necessarily want to
+   follow the 1.5x vertical rhythm -- the line-height is too much.
+
+   Using this class, it reduces your font size and line-height so that for
+   every four lines of normal sized type, there is five lines of the sidenote. eg:
+
+   New type size in em's:
+     10px (wanted side note size) / 12px (existing base size) = 0.8333 (new type size in ems)
+
+   New line-height value:
+     12px x 1.5 = 18px (old line-height)
+     18px x 4 = 72px
+     72px / 5 = 14.4px (new line height)
+     14.4px / 10px = 1.44 (new line height in em's) */
+
+p.incr, .incr p {
+  font-size: 10px;
+  line-height: 1.44em;
+  margin-bottom: 1.5em;
+}
+
+
+/* Surround uppercase words and abbreviations with this class.
+   Based on work by Jørgen Arnor Gårdsø Lom [http://twistedintellect.com/] */
+
+.caps {
+  font-variant: small-caps;
+  letter-spacing: 1px;
+  text-transform: lowercase;
+  font-size:1.2em;
+  line-height:1%;
+  font-weight:bold;
+  padding:0 2px;
+}
--- a/src/ldt/ldt/static/ldt/css/ldt.css	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/css/ldt.css	Mon May 16 20:00:36 2011 +0200
@@ -1,122 +1,122 @@
-#addldtform
-{
-    font-size: 16px;
-    background: #ffffff scroll repeat 0 0;
-    border: 1px solid #666666;
-    text-align: left;
-    width: 700px;
-}
-
-#addldtform .title
-{
-    color: #666666;
-    font-weight:bold !important;
-    font-size:16px;
-    position: relative;
-    padding:8px 12px;
-}
-
-#addldtform .title .closebutton
-{
-    float: right;
-    text-decoration: none;
-    color:#666666;
-}
-
-
-#addldtform .form-row
-{
-    border-bottom: 1px solid #eeeeee;
-    font-size: 15px;
-    padding: 8px 12px;
-}
-
-#addldtform label
-{
-    float: left;
-    padding: 3px 8px 0 0;
-    width:8em;
-    color: #333333 !important;
-    font-weight: bold !important;
-}
-#addldtform input
-{
-    font-size: 15px;
-    font-weight: normal;
-    padding:2px 3px;
-    vertical-align: middle;
-    margin : 2px 0;
-    background-color: #ffffff;
-    border: 1px solid #cccccc;
-}
-
-#addldtform  .checkbox
-{
-    padding: 6px 3px 3px 30px;
-}
-
-#addldtform .submit-row input
-{
-    color:black;
-    border-color:#DDDDDD #AAAAAA #AAAAAA #DDDDDD;
-    background:#dddddd;
-    padding: 3px;
-    margin:0 10px 10px 10px;
-}
-/*
-#ldtlist{
-    width:60%;
-    overflow:auto;
-    padding:1em;
-}
-*/
-#ldtlist table {
-    border-collapse: collapse;
-    border-color: #ccc;
-    width:100%;
-}
-#ldtlist table caption{
-    color:black;
-    font-size:15px;
-    font-weight:bold;
-    padding:5px;
-    text-align:left;
-    text-transform:uppercase;
-}
-#ldtlist td, th {
-    font-size: 11px;
-    line-height: 13px;
-    border-bottom: 1px solid #eee;
-    vertical-align: top;
-    padding: 5px;
-    font-family: "Lucida Grande", Verdana, Arial, sans-serif;
-}
-
-
-#ldtlist table thead {
-    color: #666;
-    padding: 2px 5px;
-    font-size: 13px;
-    background: #e1e1e1 url(../../admin/img/admin/nav-bg.gif) top left repeat-x;
-    border-left: 1px solid #ddd;
-    border-bottom: 1px solid #ddd;
-    white-space: nowrap;
-    vertical-align: middle;
-    font-weight: bold;
-    text-align: center;
-}
-
-#ldtlist table tbody td {
-    border-left: 1px solid #ddd;
-    text-align: center;
-}
-
-#ldtlist table tbody td:first-child {
-    border-left: 0;
-    border-right: 1px solid #ddd;
-    text-align: left;
-}
-
-#ldtlist table tfoot {
-    color: #666;
-}
+#addldtform
+{
+    font-size: 16px;
+    background: #ffffff scroll repeat 0 0;
+    border: 1px solid #666666;
+    text-align: left;
+    width: 700px;
+}
+
+#addldtform .title
+{
+    color: #666666;
+    font-weight:bold !important;
+    font-size:16px;
+    position: relative;
+    padding:8px 12px;
+}
+
+#addldtform .title .closebutton
+{
+    float: right;
+    text-decoration: none;
+    color:#666666;
+}
+
+
+#addldtform .form-row
+{
+    border-bottom: 1px solid #eeeeee;
+    font-size: 15px;
+    padding: 8px 12px;
+}
+
+#addldtform label
+{
+    float: left;
+    padding: 3px 8px 0 0;
+    width:8em;
+    color: #333333 !important;
+    font-weight: bold !important;
+}
+#addldtform input
+{
+    font-size: 15px;
+    font-weight: normal;
+    padding:2px 3px;
+    vertical-align: middle;
+    margin : 2px 0;
+    background-color: #ffffff;
+    border: 1px solid #cccccc;
+}
+
+#addldtform  .checkbox
+{
+    padding: 6px 3px 3px 30px;
+}
+
+#addldtform .submit-row input
+{
+    color:black;
+    border-color:#DDDDDD #AAAAAA #AAAAAA #DDDDDD;
+    background:#dddddd;
+    padding: 3px;
+    margin:0 10px 10px 10px;
+}
+/*
+#ldtlist{
+    width:60%;
+    overflow:auto;
+    padding:1em;
+}
+*/
+#ldtlist table {
+    border-collapse: collapse;
+    border-color: #ccc;
+    width:100%;
+}
+#ldtlist table caption{
+    color:black;
+    font-size:15px;
+    font-weight:bold;
+    padding:5px;
+    text-align:left;
+    text-transform:uppercase;
+}
+#ldtlist td, th {
+    font-size: 11px;
+    line-height: 13px;
+    border-bottom: 1px solid #eee;
+    vertical-align: top;
+    padding: 5px;
+    font-family: "Lucida Grande", Verdana, Arial, sans-serif;
+}
+
+
+#ldtlist table thead {
+    color: #666;
+    padding: 2px 5px;
+    font-size: 13px;
+    background: #e1e1e1 url(../../admin/img/admin/nav-bg.gif) top left repeat-x;
+    border-left: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    white-space: nowrap;
+    vertical-align: middle;
+    font-weight: bold;
+    text-align: center;
+}
+
+#ldtlist table tbody td {
+    border-left: 1px solid #ddd;
+    text-align: center;
+}
+
+#ldtlist table tbody td:first-child {
+    border-left: 0;
+    border-right: 1px solid #ddd;
+    text-align: left;
+}
+
+#ldtlist table tfoot {
+    color: #666;
+}
--- a/src/ldt/ldt/static/ldt/js/jquery.nyroModal-ie6.min.js	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/js/jquery.nyroModal-ie6.min.js	Mon May 16 20:00:36 2011 +0200
@@ -1,9 +1,9 @@
-/*
- * nyroModal v2.alpha
- * for IE6
- *
- */
-jQuery(function($,undefined){var $b=$('body'),$w=$(window),$h=$('html'),shown=0,zIndex=100;function isFullScreen(){return screen.height==$w.height()+58;};$b.append('<style type="text/css">'+'.nyroModalCloseButton{font-size: 1px}'+'.nyroModalLink .nyroModalPrev, .nyroModalDom .nyroModalPrev, .nyroModalForm .nyroModalPrev, .nyroModalFormFile .nyroModalPrev {left: -10px}'+'</style>');$.nmObj({_reposition:function(){var elts=this.elts.cont.find('.nmReposition');if(elts.length){var outer=this.getInternal()._getOuter($b),fs=isFullScreen();var space={top:-(fs?outer.h.border/2:0),left:-(fs?outer.w.border/2:0)};elts.each(function(){var me=$(this),offset=me.offset();me.css({top:offset.top-space.top,left:offset.left-space.left});});this.elts.cont.after(elts);}
-this.elts.cont.css('overflow','auto');}});$.nmInternal({_calculateFullSize:function(){var scrollHeight=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),offsetHeight=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),scrollWidth=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),offsetWidth=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);this.fullSize={wW:$w.width(),wH:$w.height()};this.fullSize.h=scrollHeight<offsetHeight?$w.height():scrollHeight;this.fullSize.w=scrollWidth<offsetWidth?$w.width():scrollWidth;this.fullSize.viewW=Math.min(this.fullSize.w,this.fullSize.wW);this.fullSize.viewH=Math.min(this.fullSize.h,this.fullSize.wH);}});$.nmAnims({basic:{resize:function(nm,clb){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter(nm.elts.cont);nm.elts.cont.css({width:nm.sizes.w,height:nm.sizes.h,top:space.top+(nm.getInternal().fullSize.viewH-outer.h.total-nm.sizes.h)/2,left:space.left+(nm.getInternal().fullSize.viewW-outer.w.total-nm.sizes.w)/2});clb();}},fade:{resize:function(nm,clb){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter(nm.elts.cont);nm.elts.cont.animate({width:nm.sizes.w,height:nm.sizes.h,top:space.top+(nm.getInternal().fullSize.viewH-outer.h.total-nm.sizes.h)/2,left:space.left+(nm.getInternal().fullSize.viewW-outer.w.total-nm.sizes.w)/2},clb);}}});$.nmFilters({ie6:{is:function(){return true;},initElts:function(nm){nm.store.ie6=true;if(shown==0){$h.css({overflow:'hidden'});var w=$b.width(),h=$b.outerHeight(true)+'px';if($w.height()>=$b.outerHeight(true)){h=$w.height()+'px';}else
-w+=20;w+='px';$b.css({width:w,height:h,position:'static',overflow:'hidden'});}},beforeShowBg:function(nm){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter($b);nm.elts.bg.css({position:'absolute',top:space.top,left:space.left,width:nm.getInternal().fullSize.viewW+200,height:nm.getInternal().fullSize.viewH+200});shown++;},afterHideBg:function(nm){if(nm.store.ie6){nm.store.ie6=false;shown--;}
+/*
+ * nyroModal v2.alpha
+ * for IE6
+ *
+ */
+jQuery(function($,undefined){var $b=$('body'),$w=$(window),$h=$('html'),shown=0,zIndex=100;function isFullScreen(){return screen.height==$w.height()+58;};$b.append('<style type="text/css">'+'.nyroModalCloseButton{font-size: 1px}'+'.nyroModalLink .nyroModalPrev, .nyroModalDom .nyroModalPrev, .nyroModalForm .nyroModalPrev, .nyroModalFormFile .nyroModalPrev {left: -10px}'+'</style>');$.nmObj({_reposition:function(){var elts=this.elts.cont.find('.nmReposition');if(elts.length){var outer=this.getInternal()._getOuter($b),fs=isFullScreen();var space={top:-(fs?outer.h.border/2:0),left:-(fs?outer.w.border/2:0)};elts.each(function(){var me=$(this),offset=me.offset();me.css({top:offset.top-space.top,left:offset.left-space.left});});this.elts.cont.after(elts);}
+this.elts.cont.css('overflow','auto');}});$.nmInternal({_calculateFullSize:function(){var scrollHeight=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),offsetHeight=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),scrollWidth=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),offsetWidth=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);this.fullSize={wW:$w.width(),wH:$w.height()};this.fullSize.h=scrollHeight<offsetHeight?$w.height():scrollHeight;this.fullSize.w=scrollWidth<offsetWidth?$w.width():scrollWidth;this.fullSize.viewW=Math.min(this.fullSize.w,this.fullSize.wW);this.fullSize.viewH=Math.min(this.fullSize.h,this.fullSize.wH);}});$.nmAnims({basic:{resize:function(nm,clb){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter(nm.elts.cont);nm.elts.cont.css({width:nm.sizes.w,height:nm.sizes.h,top:space.top+(nm.getInternal().fullSize.viewH-outer.h.total-nm.sizes.h)/2,left:space.left+(nm.getInternal().fullSize.viewW-outer.w.total-nm.sizes.w)/2});clb();}},fade:{resize:function(nm,clb){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter(nm.elts.cont);nm.elts.cont.animate({width:nm.sizes.w,height:nm.sizes.h,top:space.top+(nm.getInternal().fullSize.viewH-outer.h.total-nm.sizes.h)/2,left:space.left+(nm.getInternal().fullSize.viewW-outer.w.total-nm.sizes.w)/2},clb);}}});$.nmFilters({ie6:{is:function(){return true;},initElts:function(nm){nm.store.ie6=true;if(shown==0){$h.css({overflow:'hidden'});var w=$b.width(),h=$b.outerHeight(true)+'px';if($w.height()>=$b.outerHeight(true)){h=$w.height()+'px';}else
+w+=20;w+='px';$b.css({width:w,height:h,position:'static',overflow:'hidden'});}},beforeShowBg:function(nm){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter($b);nm.elts.bg.css({position:'absolute',top:space.top,left:space.left,width:nm.getInternal().fullSize.viewW+200,height:nm.getInternal().fullSize.viewH+200});shown++;},afterHideBg:function(nm){if(nm.store.ie6){nm.store.ie6=false;shown--;}
 if(shown==0){$h.css({overflow:''});$b.css({width:'',height:'',position:'',overflow:''});}},size:function(nm){if(!nm._hasFilter('image')&&!nm._hasFilter('swf')){if(nm.sizes.h<250)nm.sizes.h=250;if(nm.sizes.w<250)nm.sizes.w=250;else if(nm.sizes.w>1000)nm.sizes.w=1000;}},close:function(nm){if(nm.store.ie6){nm.store.ie6=false;shown--;}},beforeShowLoad:function(nm){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter(nm.elts.load);nm.elts.load.css({'z-index':zIndex++,position:'absolute',top:space.top+(nm.getInternal().fullSize.viewH-nm.elts.load.height()-outer.h.margin)/2,left:space.left+(nm.getInternal().fullSize.viewW-nm.elts.load.width()-outer.w.margin)/2});},beforeShowCont:function(nm){var space=nm.getInternal()._getSpaceReposition(),outer=nm.getInternal()._getOuter(nm.elts.cont);nm.elts.cont.css({'z-index':zIndex++,position:'absolute',top:space.top+(nm.getInternal().fullSize.viewH-outer.h.total-nm.sizes.h)/2,left:space.left+(nm.getInternal().fullSize.viewW-outer.w.total-nm.sizes.w)/2});}}});});
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/js/jquery.nyroModal.min.js	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/js/jquery.nyroModal.min.js	Mon May 16 20:00:36 2011 +0200
@@ -1,7 +1,7 @@
-/*
- * nyroModal v2.0.0
- * Core
- *
+/*
+ * nyroModal v2.0.0
+ * Core
+ *
  * 
  * Included parts:
  * - anims.fade
--- a/src/ldt/ldt/static/ldt/js/swfupload/swfupload.cookies.js	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/js/swfupload/swfupload.cookies.js	Mon May 16 20:00:36 2011 +0200
@@ -1,53 +1,53 @@
-/*
-	Cookie Plug-in
-	
-	This plug in automatically gets all the cookies for this site and adds them to the post_params.
-	Cookies are loaded only on initialization.  The refreshCookies function can be called to update the post_params.
-	The cookies will override any other post params with the same name.
-*/
-
-var SWFUpload;
-if (typeof(SWFUpload) === "function") {
-	SWFUpload.prototype.initSettings = function (oldInitSettings) {
-		return function () {
-			if (typeof(oldInitSettings) === "function") {
-				oldInitSettings.call(this);
-			}
-			
-			this.refreshCookies(false);	// The false parameter must be sent since SWFUpload has not initialzed at this point
-		};
-	}(SWFUpload.prototype.initSettings);
-	
-	// refreshes the post_params and updates SWFUpload.  The sendToFlash parameters is optional and defaults to True
-	SWFUpload.prototype.refreshCookies = function (sendToFlash) {
-		if (sendToFlash === undefined) {
-			sendToFlash = true;
-		}
-		sendToFlash = !!sendToFlash;
-		
-		// Get the post_params object
-		var postParams = this.settings.post_params;
-		
-		// Get the cookies
-		var i, cookieArray = document.cookie.split(';'), caLength = cookieArray.length, c, eqIndex, name, value;
-		for (i = 0; i < caLength; i++) {
-			c = cookieArray[i];
-			
-			// Left Trim spaces
-			while (c.charAt(0) === " ") {
-				c = c.substring(1, c.length);
-			}
-			eqIndex = c.indexOf("=");
-			if (eqIndex > 0) {
-				name = c.substring(0, eqIndex);
-				value = c.substring(eqIndex + 1);
-				postParams[name] = value;
-			}
-		}
-		
-		if (sendToFlash) {
-			this.setPostParams(postParams);
-		}
-	};
-
-}
+/*
+	Cookie Plug-in
+	
+	This plug in automatically gets all the cookies for this site and adds them to the post_params.
+	Cookies are loaded only on initialization.  The refreshCookies function can be called to update the post_params.
+	The cookies will override any other post params with the same name.
+*/
+
+var SWFUpload;
+if (typeof(SWFUpload) === "function") {
+	SWFUpload.prototype.initSettings = function (oldInitSettings) {
+		return function () {
+			if (typeof(oldInitSettings) === "function") {
+				oldInitSettings.call(this);
+			}
+			
+			this.refreshCookies(false);	// The false parameter must be sent since SWFUpload has not initialzed at this point
+		};
+	}(SWFUpload.prototype.initSettings);
+	
+	// refreshes the post_params and updates SWFUpload.  The sendToFlash parameters is optional and defaults to True
+	SWFUpload.prototype.refreshCookies = function (sendToFlash) {
+		if (sendToFlash === undefined) {
+			sendToFlash = true;
+		}
+		sendToFlash = !!sendToFlash;
+		
+		// Get the post_params object
+		var postParams = this.settings.post_params;
+		
+		// Get the cookies
+		var i, cookieArray = document.cookie.split(';'), caLength = cookieArray.length, c, eqIndex, name, value;
+		for (i = 0; i < caLength; i++) {
+			c = cookieArray[i];
+			
+			// Left Trim spaces
+			while (c.charAt(0) === " ") {
+				c = c.substring(1, c.length);
+			}
+			eqIndex = c.indexOf("=");
+			if (eqIndex > 0) {
+				name = c.substring(0, eqIndex);
+				value = c.substring(eqIndex + 1);
+				postParams[name] = value;
+			}
+		}
+		
+		if (sendToFlash) {
+			this.setPostParams(postParams);
+		}
+	};
+
+}
--- a/src/ldt/ldt/static/ldt/js/swfupload/swfupload.js	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/js/swfupload/swfupload.js	Mon May 16 20:00:36 2011 +0200
@@ -1,980 +1,980 @@
-/**
- * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
- *
- * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/,  http://www.vinterwebb.se/
- *
- * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
- * http://www.opensource.org/licenses/mit-license.php
- *
- * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
- * http://www.opensource.org/licenses/mit-license.php
- *
- */
-
-
-/* ******************* */
-/* Constructor & Init  */
-/* ******************* */
-var SWFUpload;
-
-if (SWFUpload == undefined) {
-	SWFUpload = function (settings) {
-		this.initSWFUpload(settings);
-	};
-}
-
-SWFUpload.prototype.initSWFUpload = function (settings) {
-	try {
-		this.customSettings = {};	// A container where developers can place their own settings associated with this instance.
-		this.settings = settings;
-		this.eventQueue = [];
-		this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
-		this.movieElement = null;
-
-
-		// Setup global control tracking
-		SWFUpload.instances[this.movieName] = this;
-
-		// Load the settings.  Load the Flash movie.
-		this.initSettings();
-		this.loadFlash();
-		this.displayDebugInfo();
-	} catch (ex) {
-		delete SWFUpload.instances[this.movieName];
-		throw ex;
-	}
-};
-
-/* *************** */
-/* Static Members  */
-/* *************** */
-SWFUpload.instances = {};
-SWFUpload.movieCount = 0;
-SWFUpload.version = "2.2.0 2009-03-25";
-SWFUpload.QUEUE_ERROR = {
-	QUEUE_LIMIT_EXCEEDED	  		: -100,
-	FILE_EXCEEDS_SIZE_LIMIT  		: -110,
-	ZERO_BYTE_FILE			  		: -120,
-	INVALID_FILETYPE		  		: -130
-};
-SWFUpload.UPLOAD_ERROR = {
-	HTTP_ERROR				  		: -200,
-	MISSING_UPLOAD_URL	      		: -210,
-	IO_ERROR				  		: -220,
-	SECURITY_ERROR			  		: -230,
-	UPLOAD_LIMIT_EXCEEDED	  		: -240,
-	UPLOAD_FAILED			  		: -250,
-	SPECIFIED_FILE_ID_NOT_FOUND		: -260,
-	FILE_VALIDATION_FAILED	  		: -270,
-	FILE_CANCELLED			  		: -280,
-	UPLOAD_STOPPED					: -290
-};
-SWFUpload.FILE_STATUS = {
-	QUEUED		 : -1,
-	IN_PROGRESS	 : -2,
-	ERROR		 : -3,
-	COMPLETE	 : -4,
-	CANCELLED	 : -5
-};
-SWFUpload.BUTTON_ACTION = {
-	SELECT_FILE  : -100,
-	SELECT_FILES : -110,
-	START_UPLOAD : -120
-};
-SWFUpload.CURSOR = {
-	ARROW : -1,
-	HAND : -2
-};
-SWFUpload.WINDOW_MODE = {
-	WINDOW : "window",
-	TRANSPARENT : "transparent",
-	OPAQUE : "opaque"
-};
-
-// Private: takes a URL, determines if it is relative and converts to an absolute URL
-// using the current site. Only processes the URL if it can, otherwise returns the URL untouched
-SWFUpload.completeURL = function(url) {
-	if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) {
-		return url;
-	}
-	
-	var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "");
-	
-	var indexSlash = window.location.pathname.lastIndexOf("/");
-	if (indexSlash <= 0) {
-		path = "/";
-	} else {
-		path = window.location.pathname.substr(0, indexSlash) + "/";
-	}
-	
-	return /*currentURL +*/ path + url;
-	
-};
-
-
-/* ******************** */
-/* Instance Members  */
-/* ******************** */
-
-// Private: initSettings ensures that all the
-// settings are set, getting a default value if one was not assigned.
-SWFUpload.prototype.initSettings = function () {
-	this.ensureDefault = function (settingName, defaultValue) {
-		this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
-	};
-	
-	// Upload backend settings
-	this.ensureDefault("upload_url", "");
-	this.ensureDefault("preserve_relative_urls", false);
-	this.ensureDefault("file_post_name", "Filedata");
-	this.ensureDefault("post_params", {});
-	this.ensureDefault("use_query_string", false);
-	this.ensureDefault("requeue_on_error", false);
-	this.ensureDefault("http_success", []);
-	this.ensureDefault("assume_success_timeout", 0);
-	
-	// File Settings
-	this.ensureDefault("file_types", "*.*");
-	this.ensureDefault("file_types_description", "All Files");
-	this.ensureDefault("file_size_limit", 0);	// Default zero means "unlimited"
-	this.ensureDefault("file_upload_limit", 0);
-	this.ensureDefault("file_queue_limit", 0);
-
-	// Flash Settings
-	this.ensureDefault("flash_url", "swfupload.swf");
-	this.ensureDefault("prevent_swf_caching", true);
-	
-	// Button Settings
-	this.ensureDefault("button_image_url", "");
-	this.ensureDefault("button_width", 1);
-	this.ensureDefault("button_height", 1);
-	this.ensureDefault("button_text", "");
-	this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
-	this.ensureDefault("button_text_top_padding", 0);
-	this.ensureDefault("button_text_left_padding", 0);
-	this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
-	this.ensureDefault("button_disabled", false);
-	this.ensureDefault("button_placeholder_id", "");
-	this.ensureDefault("button_placeholder", null);
-	this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
-	this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
-	
-	// Debug Settings
-	this.ensureDefault("debug", false);
-	this.settings.debug_enabled = this.settings.debug;	// Here to maintain v2 API
-	
-	// Event Handlers
-	this.settings.return_upload_start_handler = this.returnUploadStart;
-	this.ensureDefault("swfupload_loaded_handler", null);
-	this.ensureDefault("file_dialog_start_handler", null);
-	this.ensureDefault("file_queued_handler", null);
-	this.ensureDefault("file_queue_error_handler", null);
-	this.ensureDefault("file_dialog_complete_handler", null);
-	
-	this.ensureDefault("upload_start_handler", null);
-	this.ensureDefault("upload_progress_handler", null);
-	this.ensureDefault("upload_error_handler", null);
-	this.ensureDefault("upload_success_handler", null);
-	this.ensureDefault("upload_complete_handler", null);
-	
-	this.ensureDefault("debug_handler", this.debugMessage);
-
-	this.ensureDefault("custom_settings", {});
-
-	// Other settings
-	this.customSettings = this.settings.custom_settings;
-	
-	// Update the flash url if needed
-	if (!!this.settings.prevent_swf_caching) {
-		this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime();
-	}
-	
-	if (!this.settings.preserve_relative_urls) {
-		//this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url);	// Don't need to do this one since flash doesn't look at it
-		this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);
-		this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);
-	}
-	
-	delete this.ensureDefault;
-};
-
-// Private: loadFlash replaces the button_placeholder element with the flash movie.
-SWFUpload.prototype.loadFlash = function () {
-	var targetElement, tempParent;
-
-	// Make sure an element with the ID we are going to use doesn't already exist
-	if (document.getElementById(this.movieName) !== null) {
-		throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
-	}
-
-	// Get the element where we will be placing the flash movie
-	targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;
-
-	if (targetElement == undefined) {
-		throw "Could not find the placeholder element: " + this.settings.button_placeholder_id;
-	}
-
-	// Append the container and load the flash
-	tempParent = document.createElement("div");
-	tempParent.innerHTML = this.getFlashHTML();	// Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
-	targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);
-
-	// Fix IE Flash/Form bug
-	if (window[this.movieName] == undefined) {
-		window[this.movieName] = this.getMovieElement();
-	}
-	
-};
-
-// Private: getFlashHTML generates the object tag needed to embed the flash in to the document
-SWFUpload.prototype.getFlashHTML = function () {
-	// Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
-	return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
-				'<param name="wmode" value="', this.settings.button_window_mode, '" />',
-				'<param name="movie" value="', this.settings.flash_url, '" />',
-				'<param name="quality" value="high" />',
-				'<param name="menu" value="false" />',
-				'<param name="allowScriptAccess" value="always" />',
-				'<param name="flashvars" value="' + this.getFlashVars() + '" />',
-				'</object>'].join("");
-};
-
-// Private: getFlashVars builds the parameter string that will be passed
-// to flash in the flashvars param.
-SWFUpload.prototype.getFlashVars = function () {
-	// Build a string from the post param object
-	var paramString = this.buildParamString();
-	var httpSuccessString = this.settings.http_success.join(",");
-	
-	// Build the parameter string
-	return ["movieName=", encodeURIComponent(this.movieName),
-			"&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
-			"&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
-			"&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
-			"&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
-			"&amp;assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout),
-			"&amp;params=", encodeURIComponent(paramString),
-			"&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
-			"&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
-			"&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
-			"&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
-			"&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
-			"&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
-			"&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
-			"&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
-			"&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
-			"&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
-			"&amp;buttonText=", encodeURIComponent(this.settings.button_text),
-			"&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
-			"&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
-			"&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
-			"&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
-			"&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
-			"&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
-		].join("");
-};
-
-// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
-// The element is cached after the first lookup
-SWFUpload.prototype.getMovieElement = function () {
-	if (this.movieElement == undefined) {
-		this.movieElement = document.getElementById(this.movieName);
-	}
-
-	if (this.movieElement === null) {
-		throw "Could not find Flash element";
-	}
-	
-	return this.movieElement;
-};
-
-// Private: buildParamString takes the name/value pairs in the post_params setting object
-// and joins them up in to a string formatted "name=value&amp;name=value"
-SWFUpload.prototype.buildParamString = function () {
-	var postParams = this.settings.post_params; 
-	var paramStringPairs = [];
-
-	if (typeof(postParams) === "object") {
-		for (var name in postParams) {
-			if (postParams.hasOwnProperty(name)) {
-				paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
-			}
-		}
-	}
-
-	return paramStringPairs.join("&amp;");
-};
-
-// Public: Used to remove a SWFUpload instance from the page. This method strives to remove
-// all references to the SWF, and other objects so memory is properly freed.
-// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
-// Credits: Major improvements provided by steffen
-SWFUpload.prototype.destroy = function () {
-	try {
-		// Make sure Flash is done before we try to remove it
-		this.cancelUpload(null, false);
-		
-
-		// Remove the SWFUpload DOM nodes
-		var movieElement = null;
-		movieElement = this.getMovieElement();
-		
-		if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
-			// Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround)
-			for (var i in movieElement) {
-				try {
-					if (typeof(movieElement[i]) === "function") {
-						movieElement[i] = null;
-					}
-				} catch (ex1) {}
-			}
-
-			// Remove the Movie Element from the page
-			try {
-				movieElement.parentNode.removeChild(movieElement);
-			} catch (ex) {}
-		}
-		
-		// Remove IE form fix reference
-		window[this.movieName] = null;
-
-		// Destroy other references
-		SWFUpload.instances[this.movieName] = null;
-		delete SWFUpload.instances[this.movieName];
-
-		this.movieElement = null;
-		this.settings = null;
-		this.customSettings = null;
-		this.eventQueue = null;
-		this.movieName = null;
-		
-		
-		return true;
-	} catch (ex2) {
-		return false;
-	}
-};
-
-
-// Public: displayDebugInfo prints out settings and configuration
-// information about this SWFUpload instance.
-// This function (and any references to it) can be deleted when placing
-// SWFUpload in production.
-SWFUpload.prototype.displayDebugInfo = function () {
-	this.debug(
-		[
-			"---SWFUpload Instance Info---\n",
-			"Version: ", SWFUpload.version, "\n",
-			"Movie Name: ", this.movieName, "\n",
-			"Settings:\n",
-			"\t", "upload_url:               ", this.settings.upload_url, "\n",
-			"\t", "flash_url:                ", this.settings.flash_url, "\n",
-			"\t", "use_query_string:         ", this.settings.use_query_string.toString(), "\n",
-			"\t", "requeue_on_error:         ", this.settings.requeue_on_error.toString(), "\n",
-			"\t", "http_success:             ", this.settings.http_success.join(", "), "\n",
-			"\t", "assume_success_timeout:   ", this.settings.assume_success_timeout, "\n",
-			"\t", "file_post_name:           ", this.settings.file_post_name, "\n",
-			"\t", "post_params:              ", this.settings.post_params.toString(), "\n",
-			"\t", "file_types:               ", this.settings.file_types, "\n",
-			"\t", "file_types_description:   ", this.settings.file_types_description, "\n",
-			"\t", "file_size_limit:          ", this.settings.file_size_limit, "\n",
-			"\t", "file_upload_limit:        ", this.settings.file_upload_limit, "\n",
-			"\t", "file_queue_limit:         ", this.settings.file_queue_limit, "\n",
-			"\t", "debug:                    ", this.settings.debug.toString(), "\n",
-
-			"\t", "prevent_swf_caching:      ", this.settings.prevent_swf_caching.toString(), "\n",
-
-			"\t", "button_placeholder_id:    ", this.settings.button_placeholder_id.toString(), "\n",
-			"\t", "button_placeholder:       ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n",
-			"\t", "button_image_url:         ", this.settings.button_image_url.toString(), "\n",
-			"\t", "button_width:             ", this.settings.button_width.toString(), "\n",
-			"\t", "button_height:            ", this.settings.button_height.toString(), "\n",
-			"\t", "button_text:              ", this.settings.button_text.toString(), "\n",
-			"\t", "button_text_style:        ", this.settings.button_text_style.toString(), "\n",
-			"\t", "button_text_top_padding:  ", this.settings.button_text_top_padding.toString(), "\n",
-			"\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
-			"\t", "button_action:            ", this.settings.button_action.toString(), "\n",
-			"\t", "button_disabled:          ", this.settings.button_disabled.toString(), "\n",
-
-			"\t", "custom_settings:          ", this.settings.custom_settings.toString(), "\n",
-			"Event Handlers:\n",
-			"\t", "swfupload_loaded_handler assigned:  ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
-			"\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
-			"\t", "file_queued_handler assigned:       ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
-			"\t", "file_queue_error_handler assigned:  ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
-			"\t", "upload_start_handler assigned:      ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
-			"\t", "upload_progress_handler assigned:   ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
-			"\t", "upload_error_handler assigned:      ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
-			"\t", "upload_success_handler assigned:    ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
-			"\t", "upload_complete_handler assigned:   ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
-			"\t", "debug_handler assigned:             ", (typeof this.settings.debug_handler === "function").toString(), "\n"
-		].join("")
-	);
-};
-
-/* Note: addSetting and getSetting are no longer used by SWFUpload but are included
-	the maintain v2 API compatibility
-*/
-// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
-SWFUpload.prototype.addSetting = function (name, value, default_value) {
-    if (value == undefined) {
-        return (this.settings[name] = default_value);
-    } else {
-        return (this.settings[name] = value);
-	}
-};
-
-// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
-SWFUpload.prototype.getSetting = function (name) {
-    if (this.settings[name] != undefined) {
-        return this.settings[name];
-	}
-
-    return "";
-};
-
-
-
-// Private: callFlash handles function calls made to the Flash element.
-// Calls are made with a setTimeout for some functions to work around
-// bugs in the ExternalInterface library.
-SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
-	argumentArray = argumentArray || [];
-	
-	var movieElement = this.getMovieElement();
-	var returnValue, returnString;
-
-	// Flash's method if calling ExternalInterface methods (code adapted from MooTools).
-	try {
-		returnString = movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');
-		returnValue = eval(returnString);
-	} catch (ex) {
-		throw "Call to " + functionName + " failed";
-	}
-	
-	// Unescape file post param values
-	if (returnValue != undefined && typeof returnValue.post === "object") {
-		returnValue = this.unescapeFilePostParams(returnValue);
-	}
-
-	return returnValue;
-};
-
-/* *****************************
-	-- Flash control methods --
-	Your UI should use these
-	to operate SWFUpload
-   ***************************** */
-
-// WARNING: this function does not work in Flash Player 10
-// Public: selectFile causes a File Selection Dialog window to appear.  This
-// dialog only allows 1 file to be selected.
-SWFUpload.prototype.selectFile = function () {
-	this.callFlash("SelectFile");
-};
-
-// WARNING: this function does not work in Flash Player 10
-// Public: selectFiles causes a File Selection Dialog window to appear/ This
-// dialog allows the user to select any number of files
-// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
-// If the selection name length is too long the dialog will fail in an unpredictable manner.  There is no work-around
-// for this bug.
-SWFUpload.prototype.selectFiles = function () {
-	this.callFlash("SelectFiles");
-};
-
-
-// Public: startUpload starts uploading the first file in the queue unless
-// the optional parameter 'fileID' specifies the ID 
-SWFUpload.prototype.startUpload = function (fileID) {
-	this.callFlash("StartUpload", [fileID]);
-};
-
-// Public: cancelUpload cancels any queued file.  The fileID parameter may be the file ID or index.
-// If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
-// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
-SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
-	if (triggerErrorEvent !== false) {
-		triggerErrorEvent = true;
-	}
-	this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
-};
-
-// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
-// If nothing is currently uploading then nothing happens.
-SWFUpload.prototype.stopUpload = function () {
-	this.callFlash("StopUpload");
-};
-
-/* ************************
- * Settings methods
- *   These methods change the SWFUpload settings.
- *   SWFUpload settings should not be changed directly on the settings object
- *   since many of the settings need to be passed to Flash in order to take
- *   effect.
- * *********************** */
-
-// Public: getStats gets the file statistics object.
-SWFUpload.prototype.getStats = function () {
-	return this.callFlash("GetStats");
-};
-
-// Public: setStats changes the SWFUpload statistics.  You shouldn't need to 
-// change the statistics but you can.  Changing the statistics does not
-// affect SWFUpload accept for the successful_uploads count which is used
-// by the upload_limit setting to determine how many files the user may upload.
-SWFUpload.prototype.setStats = function (statsObject) {
-	this.callFlash("SetStats", [statsObject]);
-};
-
-// Public: getFile retrieves a File object by ID or Index.  If the file is
-// not found then 'null' is returned.
-SWFUpload.prototype.getFile = function (fileID) {
-	if (typeof(fileID) === "number") {
-		return this.callFlash("GetFileByIndex", [fileID]);
-	} else {
-		return this.callFlash("GetFile", [fileID]);
-	}
-};
-
-// Public: addFileParam sets a name/value pair that will be posted with the
-// file specified by the Files ID.  If the name already exists then the
-// exiting value will be overwritten.
-SWFUpload.prototype.addFileParam = function (fileID, name, value) {
-	return this.callFlash("AddFileParam", [fileID, name, value]);
-};
-
-// Public: removeFileParam removes a previously set (by addFileParam) name/value
-// pair from the specified file.
-SWFUpload.prototype.removeFileParam = function (fileID, name) {
-	this.callFlash("RemoveFileParam", [fileID, name]);
-};
-
-// Public: setUploadUrl changes the upload_url setting.
-SWFUpload.prototype.setUploadURL = function (url) {
-	this.settings.upload_url = url.toString();
-	this.callFlash("SetUploadURL", [url]);
-};
-
-// Public: setPostParams changes the post_params setting
-SWFUpload.prototype.setPostParams = function (paramsObject) {
-	this.settings.post_params = paramsObject;
-	this.callFlash("SetPostParams", [paramsObject]);
-};
-
-// Public: addPostParam adds post name/value pair.  Each name can have only one value.
-SWFUpload.prototype.addPostParam = function (name, value) {
-	this.settings.post_params[name] = value;
-	this.callFlash("SetPostParams", [this.settings.post_params]);
-};
-
-// Public: removePostParam deletes post name/value pair.
-SWFUpload.prototype.removePostParam = function (name) {
-	delete this.settings.post_params[name];
-	this.callFlash("SetPostParams", [this.settings.post_params]);
-};
-
-// Public: setFileTypes changes the file_types setting and the file_types_description setting
-SWFUpload.prototype.setFileTypes = function (types, description) {
-	this.settings.file_types = types;
-	this.settings.file_types_description = description;
-	this.callFlash("SetFileTypes", [types, description]);
-};
-
-// Public: setFileSizeLimit changes the file_size_limit setting
-SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
-	this.settings.file_size_limit = fileSizeLimit;
-	this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
-};
-
-// Public: setFileUploadLimit changes the file_upload_limit setting
-SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
-	this.settings.file_upload_limit = fileUploadLimit;
-	this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
-};
-
-// Public: setFileQueueLimit changes the file_queue_limit setting
-SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
-	this.settings.file_queue_limit = fileQueueLimit;
-	this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
-};
-
-// Public: setFilePostName changes the file_post_name setting
-SWFUpload.prototype.setFilePostName = function (filePostName) {
-	this.settings.file_post_name = filePostName;
-	this.callFlash("SetFilePostName", [filePostName]);
-};
-
-// Public: setUseQueryString changes the use_query_string setting
-SWFUpload.prototype.setUseQueryString = function (useQueryString) {
-	this.settings.use_query_string = useQueryString;
-	this.callFlash("SetUseQueryString", [useQueryString]);
-};
-
-// Public: setRequeueOnError changes the requeue_on_error setting
-SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
-	this.settings.requeue_on_error = requeueOnError;
-	this.callFlash("SetRequeueOnError", [requeueOnError]);
-};
-
-// Public: setHTTPSuccess changes the http_success setting
-SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
-	if (typeof http_status_codes === "string") {
-		http_status_codes = http_status_codes.replace(" ", "").split(",");
-	}
-	
-	this.settings.http_success = http_status_codes;
-	this.callFlash("SetHTTPSuccess", [http_status_codes]);
-};
-
-// Public: setHTTPSuccess changes the http_success setting
-SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {
-	this.settings.assume_success_timeout = timeout_seconds;
-	this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]);
-};
-
-// Public: setDebugEnabled changes the debug_enabled setting
-SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
-	this.settings.debug_enabled = debugEnabled;
-	this.callFlash("SetDebugEnabled", [debugEnabled]);
-};
-
-// Public: setButtonImageURL loads a button image sprite
-SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
-	if (buttonImageURL == undefined) {
-		buttonImageURL = "";
-	}
-	
-	this.settings.button_image_url = buttonImageURL;
-	this.callFlash("SetButtonImageURL", [buttonImageURL]);
-};
-
-// Public: setButtonDimensions resizes the Flash Movie and button
-SWFUpload.prototype.setButtonDimensions = function (width, height) {
-	this.settings.button_width = width;
-	this.settings.button_height = height;
-	
-	var movie = this.getMovieElement();
-	if (movie != undefined) {
-		movie.style.width = width + "px";
-		movie.style.height = height + "px";
-	}
-	
-	this.callFlash("SetButtonDimensions", [width, height]);
-};
-// Public: setButtonText Changes the text overlaid on the button
-SWFUpload.prototype.setButtonText = function (html) {
-	this.settings.button_text = html;
-	this.callFlash("SetButtonText", [html]);
-};
-// Public: setButtonTextPadding changes the top and left padding of the text overlay
-SWFUpload.prototype.setButtonTextPadding = function (left, top) {
-	this.settings.button_text_top_padding = top;
-	this.settings.button_text_left_padding = left;
-	this.callFlash("SetButtonTextPadding", [left, top]);
-};
-
-// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
-SWFUpload.prototype.setButtonTextStyle = function (css) {
-	this.settings.button_text_style = css;
-	this.callFlash("SetButtonTextStyle", [css]);
-};
-// Public: setButtonDisabled disables/enables the button
-SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
-	this.settings.button_disabled = isDisabled;
-	this.callFlash("SetButtonDisabled", [isDisabled]);
-};
-// Public: setButtonAction sets the action that occurs when the button is clicked
-SWFUpload.prototype.setButtonAction = function (buttonAction) {
-	this.settings.button_action = buttonAction;
-	this.callFlash("SetButtonAction", [buttonAction]);
-};
-
-// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
-SWFUpload.prototype.setButtonCursor = function (cursor) {
-	this.settings.button_cursor = cursor;
-	this.callFlash("SetButtonCursor", [cursor]);
-};
-
-/* *******************************
-	Flash Event Interfaces
-	These functions are used by Flash to trigger the various
-	events.
-	
-	All these functions a Private.
-	
-	Because the ExternalInterface library is buggy the event calls
-	are added to a queue and the queue then executed by a setTimeout.
-	This ensures that events are executed in a determinate order and that
-	the ExternalInterface bugs are avoided.
-******************************* */
-
-SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
-	// Warning: Don't call this.debug inside here or you'll create an infinite loop
-	
-	if (argumentArray == undefined) {
-		argumentArray = [];
-	} else if (!(argumentArray instanceof Array)) {
-		argumentArray = [argumentArray];
-	}
-	
-	var self = this;
-	if (typeof this.settings[handlerName] === "function") {
-		// Queue the event
-		this.eventQueue.push(function () {
-			this.settings[handlerName].apply(this, argumentArray);
-		});
-		
-		// Execute the next queued event
-		setTimeout(function () {
-			self.executeNextEvent();
-		}, 0);
-		
-	} else if (this.settings[handlerName] !== null) {
-		throw "Event handler " + handlerName + " is unknown or is not a function";
-	}
-};
-
-// Private: Causes the next event in the queue to be executed.  Since events are queued using a setTimeout
-// we must queue them in order to garentee that they are executed in order.
-SWFUpload.prototype.executeNextEvent = function () {
-	// Warning: Don't call this.debug inside here or you'll create an infinite loop
-
-	var  f = this.eventQueue ? this.eventQueue.shift() : null;
-	if (typeof(f) === "function") {
-		f.apply(this);
-	}
-};
-
-// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
-// properties that contain characters that are not valid for JavaScript identifiers. To work around this
-// the Flash Component escapes the parameter names and we must unescape again before passing them along.
-SWFUpload.prototype.unescapeFilePostParams = function (file) {
-	var reg = /[$]([0-9a-f]{4})/i;
-	var unescapedPost = {};
-	var uk;
-
-	if (file != undefined) {
-		for (var k in file.post) {
-			if (file.post.hasOwnProperty(k)) {
-				uk = k;
-				var match;
-				while ((match = reg.exec(uk)) !== null) {
-					uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
-				}
-				unescapedPost[uk] = file.post[k];
-			}
-		}
-
-		file.post = unescapedPost;
-	}
-
-	return file;
-};
-
-// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working)
-SWFUpload.prototype.testExternalInterface = function () {
-	try {
-		return this.callFlash("TestExternalInterface");
-	} catch (ex) {
-		return false;
-	}
-};
-
-// Private: This event is called by Flash when it has finished loading. Don't modify this.
-// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded.
-SWFUpload.prototype.flashReady = function () {
-	// Check that the movie element is loaded correctly with its ExternalInterface methods defined
-	var movieElement = this.getMovieElement();
-
-	if (!movieElement) {
-		this.debug("Flash called back ready but the flash movie can't be found.");
-		return;
-	}
-
-	this.cleanUp(movieElement);
-	
-	this.queueEvent("swfupload_loaded_handler");
-};
-
-// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE.
-// This function is called by Flash each time the ExternalInterface functions are created.
-SWFUpload.prototype.cleanUp = function (movieElement) {
-	// Pro-actively unhook all the Flash functions
-	try {
-		if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
-			this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
-			for (var key in movieElement) {
-				try {
-					if (typeof(movieElement[key]) === "function") {
-						movieElement[key] = null;
-					}
-				} catch (ex) {
-				}
-			}
-		}
-	} catch (ex1) {
-	
-	}
-
-	// Fix Flashes own cleanup code so if the SWFMovie was removed from the page
-	// it doesn't display errors.
-	window["__flash__removeCallback"] = function (instance, name) {
-		try {
-			if (instance) {
-				instance[name] = null;
-			}
-		} catch (flashEx) {
-		
-		}
-	};
-
-};
-
-
-/* This is a chance to do something before the browse window opens */
-SWFUpload.prototype.fileDialogStart = function () {
-	this.queueEvent("file_dialog_start_handler");
-};
-
-
-/* Called when a file is successfully added to the queue. */
-SWFUpload.prototype.fileQueued = function (file) {
-	file = this.unescapeFilePostParams(file);
-	this.queueEvent("file_queued_handler", file);
-};
-
-
-/* Handle errors that occur when an attempt to queue a file fails. */
-SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
-	file = this.unescapeFilePostParams(file);
-	this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
-};
-
-/* Called after the file dialog has closed and the selected files have been queued.
-	You could call startUpload here if you want the queued files to begin uploading immediately. */
-SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {
-	this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]);
-};
-
-SWFUpload.prototype.uploadStart = function (file) {
-	file = this.unescapeFilePostParams(file);
-	this.queueEvent("return_upload_start_handler", file);
-};
-
-SWFUpload.prototype.returnUploadStart = function (file) {
-	var returnValue;
-	if (typeof this.settings.upload_start_handler === "function") {
-		file = this.unescapeFilePostParams(file);
-		returnValue = this.settings.upload_start_handler.call(this, file);
-	} else if (this.settings.upload_start_handler != undefined) {
-		throw "upload_start_handler must be a function";
-	}
-
-	// Convert undefined to true so if nothing is returned from the upload_start_handler it is
-	// interpretted as 'true'.
-	if (returnValue === undefined) {
-		returnValue = true;
-	}
-	
-	returnValue = !!returnValue;
-	
-	this.callFlash("ReturnUploadStart", [returnValue]);
-};
-
-
-
-SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
-	file = this.unescapeFilePostParams(file);
-	this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
-};
-
-SWFUpload.prototype.uploadError = function (file, errorCode, message) {
-	file = this.unescapeFilePostParams(file);
-	this.queueEvent("upload_error_handler", [file, errorCode, message]);
-};
-
-SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {
-	file = this.unescapeFilePostParams(file);
-	this.queueEvent("upload_success_handler", [file, serverData, responseReceived]);
-};
-
-SWFUpload.prototype.uploadComplete = function (file) {
-	file = this.unescapeFilePostParams(file);
-	this.queueEvent("upload_complete_handler", file);
-};
-
-/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
-   internal debug console.  You can override this event and have messages written where you want. */
-SWFUpload.prototype.debug = function (message) {
-	this.queueEvent("debug_handler", message);
-};
-
-
-/* **********************************
-	Debug Console
-	The debug console is a self contained, in page location
-	for debug message to be sent.  The Debug Console adds
-	itself to the body if necessary.
-
-	The console is automatically scrolled as messages appear.
-	
-	If you are using your own debug handler or when you deploy to production and
-	have debug disabled you can remove these functions to reduce the file size
-	and complexity.
-********************************** */
-   
-// Private: debugMessage is the default debug_handler.  If you want to print debug messages
-// call the debug() function.  When overriding the function your own function should
-// check to see if the debug setting is true before outputting debug information.
-SWFUpload.prototype.debugMessage = function (message) {
-	if (this.settings.debug) {
-		var exceptionMessage, exceptionValues = [];
-
-		// Check for an exception object and print it nicely
-		if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
-			for (var key in message) {
-				if (message.hasOwnProperty(key)) {
-					exceptionValues.push(key + ": " + message[key]);
-				}
-			}
-			exceptionMessage = exceptionValues.join("\n") || "";
-			exceptionValues = exceptionMessage.split("\n");
-			exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
-			SWFUpload.Console.writeLine(exceptionMessage);
-		} else {
-			SWFUpload.Console.writeLine(message);
-		}
-	}
-};
-
-SWFUpload.Console = {};
-SWFUpload.Console.writeLine = function (message) {
-	var console, documentForm;
-
-	try {
-		console = document.getElementById("SWFUpload_Console");
-
-		if (!console) {
-			documentForm = document.createElement("form");
-			document.getElementsByTagName("body")[0].appendChild(documentForm);
-
-			console = document.createElement("textarea");
-			console.id = "SWFUpload_Console";
-			console.style.fontFamily = "monospace";
-			console.setAttribute("wrap", "off");
-			console.wrap = "off";
-			console.style.overflow = "auto";
-			console.style.width = "700px";
-			console.style.height = "350px";
-			console.style.margin = "5px";
-			documentForm.appendChild(console);
-		}
-
-		console.value += message + "\n";
-
-		console.scrollTop = console.scrollHeight - console.clientHeight;
-	} catch (ex) {
-		alert("Exception: " + ex.name + " Message: " + ex.message);
-	}
-};
+/**
+ * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
+ *
+ * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/,  http://www.vinterwebb.se/
+ *
+ * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz�n and Mammon Media and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ */
+
+
+/* ******************* */
+/* Constructor & Init  */
+/* ******************* */
+var SWFUpload;
+
+if (SWFUpload == undefined) {
+	SWFUpload = function (settings) {
+		this.initSWFUpload(settings);
+	};
+}
+
+SWFUpload.prototype.initSWFUpload = function (settings) {
+	try {
+		this.customSettings = {};	// A container where developers can place their own settings associated with this instance.
+		this.settings = settings;
+		this.eventQueue = [];
+		this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
+		this.movieElement = null;
+
+
+		// Setup global control tracking
+		SWFUpload.instances[this.movieName] = this;
+
+		// Load the settings.  Load the Flash movie.
+		this.initSettings();
+		this.loadFlash();
+		this.displayDebugInfo();
+	} catch (ex) {
+		delete SWFUpload.instances[this.movieName];
+		throw ex;
+	}
+};
+
+/* *************** */
+/* Static Members  */
+/* *************** */
+SWFUpload.instances = {};
+SWFUpload.movieCount = 0;
+SWFUpload.version = "2.2.0 2009-03-25";
+SWFUpload.QUEUE_ERROR = {
+	QUEUE_LIMIT_EXCEEDED	  		: -100,
+	FILE_EXCEEDS_SIZE_LIMIT  		: -110,
+	ZERO_BYTE_FILE			  		: -120,
+	INVALID_FILETYPE		  		: -130
+};
+SWFUpload.UPLOAD_ERROR = {
+	HTTP_ERROR				  		: -200,
+	MISSING_UPLOAD_URL	      		: -210,
+	IO_ERROR				  		: -220,
+	SECURITY_ERROR			  		: -230,
+	UPLOAD_LIMIT_EXCEEDED	  		: -240,
+	UPLOAD_FAILED			  		: -250,
+	SPECIFIED_FILE_ID_NOT_FOUND		: -260,
+	FILE_VALIDATION_FAILED	  		: -270,
+	FILE_CANCELLED			  		: -280,
+	UPLOAD_STOPPED					: -290
+};
+SWFUpload.FILE_STATUS = {
+	QUEUED		 : -1,
+	IN_PROGRESS	 : -2,
+	ERROR		 : -3,
+	COMPLETE	 : -4,
+	CANCELLED	 : -5
+};
+SWFUpload.BUTTON_ACTION = {
+	SELECT_FILE  : -100,
+	SELECT_FILES : -110,
+	START_UPLOAD : -120
+};
+SWFUpload.CURSOR = {
+	ARROW : -1,
+	HAND : -2
+};
+SWFUpload.WINDOW_MODE = {
+	WINDOW : "window",
+	TRANSPARENT : "transparent",
+	OPAQUE : "opaque"
+};
+
+// Private: takes a URL, determines if it is relative and converts to an absolute URL
+// using the current site. Only processes the URL if it can, otherwise returns the URL untouched
+SWFUpload.completeURL = function(url) {
+	if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) {
+		return url;
+	}
+	
+	var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "");
+	
+	var indexSlash = window.location.pathname.lastIndexOf("/");
+	if (indexSlash <= 0) {
+		path = "/";
+	} else {
+		path = window.location.pathname.substr(0, indexSlash) + "/";
+	}
+	
+	return /*currentURL +*/ path + url;
+	
+};
+
+
+/* ******************** */
+/* Instance Members  */
+/* ******************** */
+
+// Private: initSettings ensures that all the
+// settings are set, getting a default value if one was not assigned.
+SWFUpload.prototype.initSettings = function () {
+	this.ensureDefault = function (settingName, defaultValue) {
+		this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
+	};
+	
+	// Upload backend settings
+	this.ensureDefault("upload_url", "");
+	this.ensureDefault("preserve_relative_urls", false);
+	this.ensureDefault("file_post_name", "Filedata");
+	this.ensureDefault("post_params", {});
+	this.ensureDefault("use_query_string", false);
+	this.ensureDefault("requeue_on_error", false);
+	this.ensureDefault("http_success", []);
+	this.ensureDefault("assume_success_timeout", 0);
+	
+	// File Settings
+	this.ensureDefault("file_types", "*.*");
+	this.ensureDefault("file_types_description", "All Files");
+	this.ensureDefault("file_size_limit", 0);	// Default zero means "unlimited"
+	this.ensureDefault("file_upload_limit", 0);
+	this.ensureDefault("file_queue_limit", 0);
+
+	// Flash Settings
+	this.ensureDefault("flash_url", "swfupload.swf");
+	this.ensureDefault("prevent_swf_caching", true);
+	
+	// Button Settings
+	this.ensureDefault("button_image_url", "");
+	this.ensureDefault("button_width", 1);
+	this.ensureDefault("button_height", 1);
+	this.ensureDefault("button_text", "");
+	this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
+	this.ensureDefault("button_text_top_padding", 0);
+	this.ensureDefault("button_text_left_padding", 0);
+	this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
+	this.ensureDefault("button_disabled", false);
+	this.ensureDefault("button_placeholder_id", "");
+	this.ensureDefault("button_placeholder", null);
+	this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
+	this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
+	
+	// Debug Settings
+	this.ensureDefault("debug", false);
+	this.settings.debug_enabled = this.settings.debug;	// Here to maintain v2 API
+	
+	// Event Handlers
+	this.settings.return_upload_start_handler = this.returnUploadStart;
+	this.ensureDefault("swfupload_loaded_handler", null);
+	this.ensureDefault("file_dialog_start_handler", null);
+	this.ensureDefault("file_queued_handler", null);
+	this.ensureDefault("file_queue_error_handler", null);
+	this.ensureDefault("file_dialog_complete_handler", null);
+	
+	this.ensureDefault("upload_start_handler", null);
+	this.ensureDefault("upload_progress_handler", null);
+	this.ensureDefault("upload_error_handler", null);
+	this.ensureDefault("upload_success_handler", null);
+	this.ensureDefault("upload_complete_handler", null);
+	
+	this.ensureDefault("debug_handler", this.debugMessage);
+
+	this.ensureDefault("custom_settings", {});
+
+	// Other settings
+	this.customSettings = this.settings.custom_settings;
+	
+	// Update the flash url if needed
+	if (!!this.settings.prevent_swf_caching) {
+		this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime();
+	}
+	
+	if (!this.settings.preserve_relative_urls) {
+		//this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url);	// Don't need to do this one since flash doesn't look at it
+		this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);
+		this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);
+	}
+	
+	delete this.ensureDefault;
+};
+
+// Private: loadFlash replaces the button_placeholder element with the flash movie.
+SWFUpload.prototype.loadFlash = function () {
+	var targetElement, tempParent;
+
+	// Make sure an element with the ID we are going to use doesn't already exist
+	if (document.getElementById(this.movieName) !== null) {
+		throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
+	}
+
+	// Get the element where we will be placing the flash movie
+	targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;
+
+	if (targetElement == undefined) {
+		throw "Could not find the placeholder element: " + this.settings.button_placeholder_id;
+	}
+
+	// Append the container and load the flash
+	tempParent = document.createElement("div");
+	tempParent.innerHTML = this.getFlashHTML();	// Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
+	targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);
+
+	// Fix IE Flash/Form bug
+	if (window[this.movieName] == undefined) {
+		window[this.movieName] = this.getMovieElement();
+	}
+	
+};
+
+// Private: getFlashHTML generates the object tag needed to embed the flash in to the document
+SWFUpload.prototype.getFlashHTML = function () {
+	// Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
+	return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
+				'<param name="wmode" value="', this.settings.button_window_mode, '" />',
+				'<param name="movie" value="', this.settings.flash_url, '" />',
+				'<param name="quality" value="high" />',
+				'<param name="menu" value="false" />',
+				'<param name="allowScriptAccess" value="always" />',
+				'<param name="flashvars" value="' + this.getFlashVars() + '" />',
+				'</object>'].join("");
+};
+
+// Private: getFlashVars builds the parameter string that will be passed
+// to flash in the flashvars param.
+SWFUpload.prototype.getFlashVars = function () {
+	// Build a string from the post param object
+	var paramString = this.buildParamString();
+	var httpSuccessString = this.settings.http_success.join(",");
+	
+	// Build the parameter string
+	return ["movieName=", encodeURIComponent(this.movieName),
+			"&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
+			"&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
+			"&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
+			"&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
+			"&amp;assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout),
+			"&amp;params=", encodeURIComponent(paramString),
+			"&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
+			"&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
+			"&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
+			"&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
+			"&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
+			"&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
+			"&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
+			"&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
+			"&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
+			"&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
+			"&amp;buttonText=", encodeURIComponent(this.settings.button_text),
+			"&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
+			"&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
+			"&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
+			"&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
+			"&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
+			"&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
+		].join("");
+};
+
+// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
+// The element is cached after the first lookup
+SWFUpload.prototype.getMovieElement = function () {
+	if (this.movieElement == undefined) {
+		this.movieElement = document.getElementById(this.movieName);
+	}
+
+	if (this.movieElement === null) {
+		throw "Could not find Flash element";
+	}
+	
+	return this.movieElement;
+};
+
+// Private: buildParamString takes the name/value pairs in the post_params setting object
+// and joins them up in to a string formatted "name=value&amp;name=value"
+SWFUpload.prototype.buildParamString = function () {
+	var postParams = this.settings.post_params; 
+	var paramStringPairs = [];
+
+	if (typeof(postParams) === "object") {
+		for (var name in postParams) {
+			if (postParams.hasOwnProperty(name)) {
+				paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
+			}
+		}
+	}
+
+	return paramStringPairs.join("&amp;");
+};
+
+// Public: Used to remove a SWFUpload instance from the page. This method strives to remove
+// all references to the SWF, and other objects so memory is properly freed.
+// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
+// Credits: Major improvements provided by steffen
+SWFUpload.prototype.destroy = function () {
+	try {
+		// Make sure Flash is done before we try to remove it
+		this.cancelUpload(null, false);
+		
+
+		// Remove the SWFUpload DOM nodes
+		var movieElement = null;
+		movieElement = this.getMovieElement();
+		
+		if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
+			// Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround)
+			for (var i in movieElement) {
+				try {
+					if (typeof(movieElement[i]) === "function") {
+						movieElement[i] = null;
+					}
+				} catch (ex1) {}
+			}
+
+			// Remove the Movie Element from the page
+			try {
+				movieElement.parentNode.removeChild(movieElement);
+			} catch (ex) {}
+		}
+		
+		// Remove IE form fix reference
+		window[this.movieName] = null;
+
+		// Destroy other references
+		SWFUpload.instances[this.movieName] = null;
+		delete SWFUpload.instances[this.movieName];
+
+		this.movieElement = null;
+		this.settings = null;
+		this.customSettings = null;
+		this.eventQueue = null;
+		this.movieName = null;
+		
+		
+		return true;
+	} catch (ex2) {
+		return false;
+	}
+};
+
+
+// Public: displayDebugInfo prints out settings and configuration
+// information about this SWFUpload instance.
+// This function (and any references to it) can be deleted when placing
+// SWFUpload in production.
+SWFUpload.prototype.displayDebugInfo = function () {
+	this.debug(
+		[
+			"---SWFUpload Instance Info---\n",
+			"Version: ", SWFUpload.version, "\n",
+			"Movie Name: ", this.movieName, "\n",
+			"Settings:\n",
+			"\t", "upload_url:               ", this.settings.upload_url, "\n",
+			"\t", "flash_url:                ", this.settings.flash_url, "\n",
+			"\t", "use_query_string:         ", this.settings.use_query_string.toString(), "\n",
+			"\t", "requeue_on_error:         ", this.settings.requeue_on_error.toString(), "\n",
+			"\t", "http_success:             ", this.settings.http_success.join(", "), "\n",
+			"\t", "assume_success_timeout:   ", this.settings.assume_success_timeout, "\n",
+			"\t", "file_post_name:           ", this.settings.file_post_name, "\n",
+			"\t", "post_params:              ", this.settings.post_params.toString(), "\n",
+			"\t", "file_types:               ", this.settings.file_types, "\n",
+			"\t", "file_types_description:   ", this.settings.file_types_description, "\n",
+			"\t", "file_size_limit:          ", this.settings.file_size_limit, "\n",
+			"\t", "file_upload_limit:        ", this.settings.file_upload_limit, "\n",
+			"\t", "file_queue_limit:         ", this.settings.file_queue_limit, "\n",
+			"\t", "debug:                    ", this.settings.debug.toString(), "\n",
+
+			"\t", "prevent_swf_caching:      ", this.settings.prevent_swf_caching.toString(), "\n",
+
+			"\t", "button_placeholder_id:    ", this.settings.button_placeholder_id.toString(), "\n",
+			"\t", "button_placeholder:       ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n",
+			"\t", "button_image_url:         ", this.settings.button_image_url.toString(), "\n",
+			"\t", "button_width:             ", this.settings.button_width.toString(), "\n",
+			"\t", "button_height:            ", this.settings.button_height.toString(), "\n",
+			"\t", "button_text:              ", this.settings.button_text.toString(), "\n",
+			"\t", "button_text_style:        ", this.settings.button_text_style.toString(), "\n",
+			"\t", "button_text_top_padding:  ", this.settings.button_text_top_padding.toString(), "\n",
+			"\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
+			"\t", "button_action:            ", this.settings.button_action.toString(), "\n",
+			"\t", "button_disabled:          ", this.settings.button_disabled.toString(), "\n",
+
+			"\t", "custom_settings:          ", this.settings.custom_settings.toString(), "\n",
+			"Event Handlers:\n",
+			"\t", "swfupload_loaded_handler assigned:  ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
+			"\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
+			"\t", "file_queued_handler assigned:       ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
+			"\t", "file_queue_error_handler assigned:  ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
+			"\t", "upload_start_handler assigned:      ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
+			"\t", "upload_progress_handler assigned:   ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
+			"\t", "upload_error_handler assigned:      ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
+			"\t", "upload_success_handler assigned:    ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
+			"\t", "upload_complete_handler assigned:   ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
+			"\t", "debug_handler assigned:             ", (typeof this.settings.debug_handler === "function").toString(), "\n"
+		].join("")
+	);
+};
+
+/* Note: addSetting and getSetting are no longer used by SWFUpload but are included
+	the maintain v2 API compatibility
+*/
+// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
+SWFUpload.prototype.addSetting = function (name, value, default_value) {
+    if (value == undefined) {
+        return (this.settings[name] = default_value);
+    } else {
+        return (this.settings[name] = value);
+	}
+};
+
+// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
+SWFUpload.prototype.getSetting = function (name) {
+    if (this.settings[name] != undefined) {
+        return this.settings[name];
+	}
+
+    return "";
+};
+
+
+
+// Private: callFlash handles function calls made to the Flash element.
+// Calls are made with a setTimeout for some functions to work around
+// bugs in the ExternalInterface library.
+SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
+	argumentArray = argumentArray || [];
+	
+	var movieElement = this.getMovieElement();
+	var returnValue, returnString;
+
+	// Flash's method if calling ExternalInterface methods (code adapted from MooTools).
+	try {
+		returnString = movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');
+		returnValue = eval(returnString);
+	} catch (ex) {
+		throw "Call to " + functionName + " failed";
+	}
+	
+	// Unescape file post param values
+	if (returnValue != undefined && typeof returnValue.post === "object") {
+		returnValue = this.unescapeFilePostParams(returnValue);
+	}
+
+	return returnValue;
+};
+
+/* *****************************
+	-- Flash control methods --
+	Your UI should use these
+	to operate SWFUpload
+   ***************************** */
+
+// WARNING: this function does not work in Flash Player 10
+// Public: selectFile causes a File Selection Dialog window to appear.  This
+// dialog only allows 1 file to be selected.
+SWFUpload.prototype.selectFile = function () {
+	this.callFlash("SelectFile");
+};
+
+// WARNING: this function does not work in Flash Player 10
+// Public: selectFiles causes a File Selection Dialog window to appear/ This
+// dialog allows the user to select any number of files
+// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
+// If the selection name length is too long the dialog will fail in an unpredictable manner.  There is no work-around
+// for this bug.
+SWFUpload.prototype.selectFiles = function () {
+	this.callFlash("SelectFiles");
+};
+
+
+// Public: startUpload starts uploading the first file in the queue unless
+// the optional parameter 'fileID' specifies the ID 
+SWFUpload.prototype.startUpload = function (fileID) {
+	this.callFlash("StartUpload", [fileID]);
+};
+
+// Public: cancelUpload cancels any queued file.  The fileID parameter may be the file ID or index.
+// If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
+// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
+SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
+	if (triggerErrorEvent !== false) {
+		triggerErrorEvent = true;
+	}
+	this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
+};
+
+// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
+// If nothing is currently uploading then nothing happens.
+SWFUpload.prototype.stopUpload = function () {
+	this.callFlash("StopUpload");
+};
+
+/* ************************
+ * Settings methods
+ *   These methods change the SWFUpload settings.
+ *   SWFUpload settings should not be changed directly on the settings object
+ *   since many of the settings need to be passed to Flash in order to take
+ *   effect.
+ * *********************** */
+
+// Public: getStats gets the file statistics object.
+SWFUpload.prototype.getStats = function () {
+	return this.callFlash("GetStats");
+};
+
+// Public: setStats changes the SWFUpload statistics.  You shouldn't need to 
+// change the statistics but you can.  Changing the statistics does not
+// affect SWFUpload accept for the successful_uploads count which is used
+// by the upload_limit setting to determine how many files the user may upload.
+SWFUpload.prototype.setStats = function (statsObject) {
+	this.callFlash("SetStats", [statsObject]);
+};
+
+// Public: getFile retrieves a File object by ID or Index.  If the file is
+// not found then 'null' is returned.
+SWFUpload.prototype.getFile = function (fileID) {
+	if (typeof(fileID) === "number") {
+		return this.callFlash("GetFileByIndex", [fileID]);
+	} else {
+		return this.callFlash("GetFile", [fileID]);
+	}
+};
+
+// Public: addFileParam sets a name/value pair that will be posted with the
+// file specified by the Files ID.  If the name already exists then the
+// exiting value will be overwritten.
+SWFUpload.prototype.addFileParam = function (fileID, name, value) {
+	return this.callFlash("AddFileParam", [fileID, name, value]);
+};
+
+// Public: removeFileParam removes a previously set (by addFileParam) name/value
+// pair from the specified file.
+SWFUpload.prototype.removeFileParam = function (fileID, name) {
+	this.callFlash("RemoveFileParam", [fileID, name]);
+};
+
+// Public: setUploadUrl changes the upload_url setting.
+SWFUpload.prototype.setUploadURL = function (url) {
+	this.settings.upload_url = url.toString();
+	this.callFlash("SetUploadURL", [url]);
+};
+
+// Public: setPostParams changes the post_params setting
+SWFUpload.prototype.setPostParams = function (paramsObject) {
+	this.settings.post_params = paramsObject;
+	this.callFlash("SetPostParams", [paramsObject]);
+};
+
+// Public: addPostParam adds post name/value pair.  Each name can have only one value.
+SWFUpload.prototype.addPostParam = function (name, value) {
+	this.settings.post_params[name] = value;
+	this.callFlash("SetPostParams", [this.settings.post_params]);
+};
+
+// Public: removePostParam deletes post name/value pair.
+SWFUpload.prototype.removePostParam = function (name) {
+	delete this.settings.post_params[name];
+	this.callFlash("SetPostParams", [this.settings.post_params]);
+};
+
+// Public: setFileTypes changes the file_types setting and the file_types_description setting
+SWFUpload.prototype.setFileTypes = function (types, description) {
+	this.settings.file_types = types;
+	this.settings.file_types_description = description;
+	this.callFlash("SetFileTypes", [types, description]);
+};
+
+// Public: setFileSizeLimit changes the file_size_limit setting
+SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
+	this.settings.file_size_limit = fileSizeLimit;
+	this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
+};
+
+// Public: setFileUploadLimit changes the file_upload_limit setting
+SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
+	this.settings.file_upload_limit = fileUploadLimit;
+	this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
+};
+
+// Public: setFileQueueLimit changes the file_queue_limit setting
+SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
+	this.settings.file_queue_limit = fileQueueLimit;
+	this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
+};
+
+// Public: setFilePostName changes the file_post_name setting
+SWFUpload.prototype.setFilePostName = function (filePostName) {
+	this.settings.file_post_name = filePostName;
+	this.callFlash("SetFilePostName", [filePostName]);
+};
+
+// Public: setUseQueryString changes the use_query_string setting
+SWFUpload.prototype.setUseQueryString = function (useQueryString) {
+	this.settings.use_query_string = useQueryString;
+	this.callFlash("SetUseQueryString", [useQueryString]);
+};
+
+// Public: setRequeueOnError changes the requeue_on_error setting
+SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
+	this.settings.requeue_on_error = requeueOnError;
+	this.callFlash("SetRequeueOnError", [requeueOnError]);
+};
+
+// Public: setHTTPSuccess changes the http_success setting
+SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
+	if (typeof http_status_codes === "string") {
+		http_status_codes = http_status_codes.replace(" ", "").split(",");
+	}
+	
+	this.settings.http_success = http_status_codes;
+	this.callFlash("SetHTTPSuccess", [http_status_codes]);
+};
+
+// Public: setHTTPSuccess changes the http_success setting
+SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {
+	this.settings.assume_success_timeout = timeout_seconds;
+	this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]);
+};
+
+// Public: setDebugEnabled changes the debug_enabled setting
+SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
+	this.settings.debug_enabled = debugEnabled;
+	this.callFlash("SetDebugEnabled", [debugEnabled]);
+};
+
+// Public: setButtonImageURL loads a button image sprite
+SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
+	if (buttonImageURL == undefined) {
+		buttonImageURL = "";
+	}
+	
+	this.settings.button_image_url = buttonImageURL;
+	this.callFlash("SetButtonImageURL", [buttonImageURL]);
+};
+
+// Public: setButtonDimensions resizes the Flash Movie and button
+SWFUpload.prototype.setButtonDimensions = function (width, height) {
+	this.settings.button_width = width;
+	this.settings.button_height = height;
+	
+	var movie = this.getMovieElement();
+	if (movie != undefined) {
+		movie.style.width = width + "px";
+		movie.style.height = height + "px";
+	}
+	
+	this.callFlash("SetButtonDimensions", [width, height]);
+};
+// Public: setButtonText Changes the text overlaid on the button
+SWFUpload.prototype.setButtonText = function (html) {
+	this.settings.button_text = html;
+	this.callFlash("SetButtonText", [html]);
+};
+// Public: setButtonTextPadding changes the top and left padding of the text overlay
+SWFUpload.prototype.setButtonTextPadding = function (left, top) {
+	this.settings.button_text_top_padding = top;
+	this.settings.button_text_left_padding = left;
+	this.callFlash("SetButtonTextPadding", [left, top]);
+};
+
+// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
+SWFUpload.prototype.setButtonTextStyle = function (css) {
+	this.settings.button_text_style = css;
+	this.callFlash("SetButtonTextStyle", [css]);
+};
+// Public: setButtonDisabled disables/enables the button
+SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
+	this.settings.button_disabled = isDisabled;
+	this.callFlash("SetButtonDisabled", [isDisabled]);
+};
+// Public: setButtonAction sets the action that occurs when the button is clicked
+SWFUpload.prototype.setButtonAction = function (buttonAction) {
+	this.settings.button_action = buttonAction;
+	this.callFlash("SetButtonAction", [buttonAction]);
+};
+
+// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
+SWFUpload.prototype.setButtonCursor = function (cursor) {
+	this.settings.button_cursor = cursor;
+	this.callFlash("SetButtonCursor", [cursor]);
+};
+
+/* *******************************
+	Flash Event Interfaces
+	These functions are used by Flash to trigger the various
+	events.
+	
+	All these functions a Private.
+	
+	Because the ExternalInterface library is buggy the event calls
+	are added to a queue and the queue then executed by a setTimeout.
+	This ensures that events are executed in a determinate order and that
+	the ExternalInterface bugs are avoided.
+******************************* */
+
+SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
+	// Warning: Don't call this.debug inside here or you'll create an infinite loop
+	
+	if (argumentArray == undefined) {
+		argumentArray = [];
+	} else if (!(argumentArray instanceof Array)) {
+		argumentArray = [argumentArray];
+	}
+	
+	var self = this;
+	if (typeof this.settings[handlerName] === "function") {
+		// Queue the event
+		this.eventQueue.push(function () {
+			this.settings[handlerName].apply(this, argumentArray);
+		});
+		
+		// Execute the next queued event
+		setTimeout(function () {
+			self.executeNextEvent();
+		}, 0);
+		
+	} else if (this.settings[handlerName] !== null) {
+		throw "Event handler " + handlerName + " is unknown or is not a function";
+	}
+};
+
+// Private: Causes the next event in the queue to be executed.  Since events are queued using a setTimeout
+// we must queue them in order to garentee that they are executed in order.
+SWFUpload.prototype.executeNextEvent = function () {
+	// Warning: Don't call this.debug inside here or you'll create an infinite loop
+
+	var  f = this.eventQueue ? this.eventQueue.shift() : null;
+	if (typeof(f) === "function") {
+		f.apply(this);
+	}
+};
+
+// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
+// properties that contain characters that are not valid for JavaScript identifiers. To work around this
+// the Flash Component escapes the parameter names and we must unescape again before passing them along.
+SWFUpload.prototype.unescapeFilePostParams = function (file) {
+	var reg = /[$]([0-9a-f]{4})/i;
+	var unescapedPost = {};
+	var uk;
+
+	if (file != undefined) {
+		for (var k in file.post) {
+			if (file.post.hasOwnProperty(k)) {
+				uk = k;
+				var match;
+				while ((match = reg.exec(uk)) !== null) {
+					uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
+				}
+				unescapedPost[uk] = file.post[k];
+			}
+		}
+
+		file.post = unescapedPost;
+	}
+
+	return file;
+};
+
+// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working)
+SWFUpload.prototype.testExternalInterface = function () {
+	try {
+		return this.callFlash("TestExternalInterface");
+	} catch (ex) {
+		return false;
+	}
+};
+
+// Private: This event is called by Flash when it has finished loading. Don't modify this.
+// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded.
+SWFUpload.prototype.flashReady = function () {
+	// Check that the movie element is loaded correctly with its ExternalInterface methods defined
+	var movieElement = this.getMovieElement();
+
+	if (!movieElement) {
+		this.debug("Flash called back ready but the flash movie can't be found.");
+		return;
+	}
+
+	this.cleanUp(movieElement);
+	
+	this.queueEvent("swfupload_loaded_handler");
+};
+
+// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE.
+// This function is called by Flash each time the ExternalInterface functions are created.
+SWFUpload.prototype.cleanUp = function (movieElement) {
+	// Pro-actively unhook all the Flash functions
+	try {
+		if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
+			this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
+			for (var key in movieElement) {
+				try {
+					if (typeof(movieElement[key]) === "function") {
+						movieElement[key] = null;
+					}
+				} catch (ex) {
+				}
+			}
+		}
+	} catch (ex1) {
+	
+	}
+
+	// Fix Flashes own cleanup code so if the SWFMovie was removed from the page
+	// it doesn't display errors.
+	window["__flash__removeCallback"] = function (instance, name) {
+		try {
+			if (instance) {
+				instance[name] = null;
+			}
+		} catch (flashEx) {
+		
+		}
+	};
+
+};
+
+
+/* This is a chance to do something before the browse window opens */
+SWFUpload.prototype.fileDialogStart = function () {
+	this.queueEvent("file_dialog_start_handler");
+};
+
+
+/* Called when a file is successfully added to the queue. */
+SWFUpload.prototype.fileQueued = function (file) {
+	file = this.unescapeFilePostParams(file);
+	this.queueEvent("file_queued_handler", file);
+};
+
+
+/* Handle errors that occur when an attempt to queue a file fails. */
+SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
+	file = this.unescapeFilePostParams(file);
+	this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
+};
+
+/* Called after the file dialog has closed and the selected files have been queued.
+	You could call startUpload here if you want the queued files to begin uploading immediately. */
+SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {
+	this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]);
+};
+
+SWFUpload.prototype.uploadStart = function (file) {
+	file = this.unescapeFilePostParams(file);
+	this.queueEvent("return_upload_start_handler", file);
+};
+
+SWFUpload.prototype.returnUploadStart = function (file) {
+	var returnValue;
+	if (typeof this.settings.upload_start_handler === "function") {
+		file = this.unescapeFilePostParams(file);
+		returnValue = this.settings.upload_start_handler.call(this, file);
+	} else if (this.settings.upload_start_handler != undefined) {
+		throw "upload_start_handler must be a function";
+	}
+
+	// Convert undefined to true so if nothing is returned from the upload_start_handler it is
+	// interpretted as 'true'.
+	if (returnValue === undefined) {
+		returnValue = true;
+	}
+	
+	returnValue = !!returnValue;
+	
+	this.callFlash("ReturnUploadStart", [returnValue]);
+};
+
+
+
+SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
+	file = this.unescapeFilePostParams(file);
+	this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
+};
+
+SWFUpload.prototype.uploadError = function (file, errorCode, message) {
+	file = this.unescapeFilePostParams(file);
+	this.queueEvent("upload_error_handler", [file, errorCode, message]);
+};
+
+SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {
+	file = this.unescapeFilePostParams(file);
+	this.queueEvent("upload_success_handler", [file, serverData, responseReceived]);
+};
+
+SWFUpload.prototype.uploadComplete = function (file) {
+	file = this.unescapeFilePostParams(file);
+	this.queueEvent("upload_complete_handler", file);
+};
+
+/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
+   internal debug console.  You can override this event and have messages written where you want. */
+SWFUpload.prototype.debug = function (message) {
+	this.queueEvent("debug_handler", message);
+};
+
+
+/* **********************************
+	Debug Console
+	The debug console is a self contained, in page location
+	for debug message to be sent.  The Debug Console adds
+	itself to the body if necessary.
+
+	The console is automatically scrolled as messages appear.
+	
+	If you are using your own debug handler or when you deploy to production and
+	have debug disabled you can remove these functions to reduce the file size
+	and complexity.
+********************************** */
+   
+// Private: debugMessage is the default debug_handler.  If you want to print debug messages
+// call the debug() function.  When overriding the function your own function should
+// check to see if the debug setting is true before outputting debug information.
+SWFUpload.prototype.debugMessage = function (message) {
+	if (this.settings.debug) {
+		var exceptionMessage, exceptionValues = [];
+
+		// Check for an exception object and print it nicely
+		if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
+			for (var key in message) {
+				if (message.hasOwnProperty(key)) {
+					exceptionValues.push(key + ": " + message[key]);
+				}
+			}
+			exceptionMessage = exceptionValues.join("\n") || "";
+			exceptionValues = exceptionMessage.split("\n");
+			exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
+			SWFUpload.Console.writeLine(exceptionMessage);
+		} else {
+			SWFUpload.Console.writeLine(message);
+		}
+	}
+};
+
+SWFUpload.Console = {};
+SWFUpload.Console.writeLine = function (message) {
+	var console, documentForm;
+
+	try {
+		console = document.getElementById("SWFUpload_Console");
+
+		if (!console) {
+			documentForm = document.createElement("form");
+			document.getElementsByTagName("body")[0].appendChild(documentForm);
+
+			console = document.createElement("textarea");
+			console.id = "SWFUpload_Console";
+			console.style.fontFamily = "monospace";
+			console.setAttribute("wrap", "off");
+			console.wrap = "off";
+			console.style.overflow = "auto";
+			console.style.width = "700px";
+			console.style.height = "350px";
+			console.style.margin = "5px";
+			documentForm.appendChild(console);
+		}
+
+		console.value += message + "\n";
+
+		console.scrollTop = console.scrollHeight - console.clientHeight;
+	} catch (ex) {
+		alert("Exception: " + ex.name + " Message: " + ex.message);
+	}
+};
--- a/src/ldt/ldt/static/ldt/js/swfupload/swfupload.queue.js	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/js/swfupload/swfupload.queue.js	Mon May 16 20:00:36 2011 +0200
@@ -1,98 +1,98 @@
-/*
-	Queue Plug-in
-	
-	Features:
-		*Adds a cancelQueue() method for cancelling the entire queue.
-		*All queued files are uploaded when startUpload() is called.
-		*If false is returned from uploadComplete then the queue upload is stopped.
-		 If false is not returned (strict comparison) then the queue upload is continued.
-		*Adds a QueueComplete event that is fired when all the queued files have finished uploading.
-		 Set the event handler with the queue_complete_handler setting.
-		
-	*/
-
-var SWFUpload;
-if (typeof(SWFUpload) === "function") {
-	SWFUpload.queue = {};
-	
-	SWFUpload.prototype.initSettings = (function (oldInitSettings) {
-		return function () {
-			if (typeof(oldInitSettings) === "function") {
-				oldInitSettings.call(this);
-			}
-			
-			this.queueSettings = {};
-			
-			this.queueSettings.queue_cancelled_flag = false;
-			this.queueSettings.queue_upload_count = 0;
-			
-			this.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler;
-			this.queueSettings.user_upload_start_handler = this.settings.upload_start_handler;
-			this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler;
-			this.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler;
-			
-			this.settings.queue_complete_handler = this.settings.queue_complete_handler || null;
-		};
-	})(SWFUpload.prototype.initSettings);
-
-	SWFUpload.prototype.startUpload = function (fileID) {
-		this.queueSettings.queue_cancelled_flag = false;
-		this.callFlash("StartUpload", [fileID]);
-	};
-
-	SWFUpload.prototype.cancelQueue = function () {
-		this.queueSettings.queue_cancelled_flag = true;
-		this.stopUpload();
-		
-		var stats = this.getStats();
-		while (stats.files_queued > 0) {
-			this.cancelUpload();
-			stats = this.getStats();
-		}
-	};
-	
-	SWFUpload.queue.uploadStartHandler = function (file) {
-		var returnValue;
-		if (typeof(this.queueSettings.user_upload_start_handler) === "function") {
-			returnValue = this.queueSettings.user_upload_start_handler.call(this, file);
-		}
-		
-		// To prevent upload a real "FALSE" value must be returned, otherwise default to a real "TRUE" value.
-		returnValue = (returnValue === false) ? false : true;
-		
-		this.queueSettings.queue_cancelled_flag = !returnValue;
-
-		return returnValue;
-	};
-	
-	SWFUpload.queue.uploadCompleteHandler = function (file) {
-		var user_upload_complete_handler = this.queueSettings.user_upload_complete_handler;
-		var continueUpload;
-		
-		if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) {
-			this.queueSettings.queue_upload_count++;
-		}
-
-		if (typeof(user_upload_complete_handler) === "function") {
-			continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true;
-		} else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) {
-			// If the file was stopped and re-queued don't restart the upload
-			continueUpload = false;
-		} else {
-			continueUpload = true;
-		}
-		
-		if (continueUpload) {
-			var stats = this.getStats();
-			if (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) {
-				this.startUpload();
-			} else if (this.queueSettings.queue_cancelled_flag === false) {
-				this.queueEvent("queue_complete_handler", [this.queueSettings.queue_upload_count]);
-				this.queueSettings.queue_upload_count = 0;
-			} else {
-				this.queueSettings.queue_cancelled_flag = false;
-				this.queueSettings.queue_upload_count = 0;
-			}
-		}
-	};
+/*
+	Queue Plug-in
+	
+	Features:
+		*Adds a cancelQueue() method for cancelling the entire queue.
+		*All queued files are uploaded when startUpload() is called.
+		*If false is returned from uploadComplete then the queue upload is stopped.
+		 If false is not returned (strict comparison) then the queue upload is continued.
+		*Adds a QueueComplete event that is fired when all the queued files have finished uploading.
+		 Set the event handler with the queue_complete_handler setting.
+		
+	*/
+
+var SWFUpload;
+if (typeof(SWFUpload) === "function") {
+	SWFUpload.queue = {};
+	
+	SWFUpload.prototype.initSettings = (function (oldInitSettings) {
+		return function () {
+			if (typeof(oldInitSettings) === "function") {
+				oldInitSettings.call(this);
+			}
+			
+			this.queueSettings = {};
+			
+			this.queueSettings.queue_cancelled_flag = false;
+			this.queueSettings.queue_upload_count = 0;
+			
+			this.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler;
+			this.queueSettings.user_upload_start_handler = this.settings.upload_start_handler;
+			this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler;
+			this.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler;
+			
+			this.settings.queue_complete_handler = this.settings.queue_complete_handler || null;
+		};
+	})(SWFUpload.prototype.initSettings);
+
+	SWFUpload.prototype.startUpload = function (fileID) {
+		this.queueSettings.queue_cancelled_flag = false;
+		this.callFlash("StartUpload", [fileID]);
+	};
+
+	SWFUpload.prototype.cancelQueue = function () {
+		this.queueSettings.queue_cancelled_flag = true;
+		this.stopUpload();
+		
+		var stats = this.getStats();
+		while (stats.files_queued > 0) {
+			this.cancelUpload();
+			stats = this.getStats();
+		}
+	};
+	
+	SWFUpload.queue.uploadStartHandler = function (file) {
+		var returnValue;
+		if (typeof(this.queueSettings.user_upload_start_handler) === "function") {
+			returnValue = this.queueSettings.user_upload_start_handler.call(this, file);
+		}
+		
+		// To prevent upload a real "FALSE" value must be returned, otherwise default to a real "TRUE" value.
+		returnValue = (returnValue === false) ? false : true;
+		
+		this.queueSettings.queue_cancelled_flag = !returnValue;
+
+		return returnValue;
+	};
+	
+	SWFUpload.queue.uploadCompleteHandler = function (file) {
+		var user_upload_complete_handler = this.queueSettings.user_upload_complete_handler;
+		var continueUpload;
+		
+		if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) {
+			this.queueSettings.queue_upload_count++;
+		}
+
+		if (typeof(user_upload_complete_handler) === "function") {
+			continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true;
+		} else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) {
+			// If the file was stopped and re-queued don't restart the upload
+			continueUpload = false;
+		} else {
+			continueUpload = true;
+		}
+		
+		if (continueUpload) {
+			var stats = this.getStats();
+			if (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) {
+				this.startUpload();
+			} else if (this.queueSettings.queue_cancelled_flag === false) {
+				this.queueEvent("queue_complete_handler", [this.queueSettings.queue_upload_count]);
+				this.queueSettings.queue_upload_count = 0;
+			} else {
+				this.queueSettings.queue_cancelled_flag = false;
+				this.queueSettings.queue_upload_count = 0;
+			}
+		}
+	};
 }
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/js/swfupload/swfupload.speed.js	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/js/swfupload/swfupload.speed.js	Mon May 16 20:00:36 2011 +0200
@@ -1,342 +1,342 @@
-/*
-	Speed Plug-in
-	
-	Features:
-		*Adds several properties to the 'file' object indicated upload speed, time left, upload time, etc.
-			- currentSpeed -- String indicating the upload speed, bytes per second
-			- averageSpeed -- Overall average upload speed, bytes per second
-			- movingAverageSpeed -- Speed over averaged over the last several measurements, bytes per second
-			- timeRemaining -- Estimated remaining upload time in seconds
-			- timeElapsed -- Number of seconds passed for this upload
-			- percentUploaded -- Percentage of the file uploaded (0 to 100)
-			- sizeUploaded -- Formatted size uploaded so far, bytes
-		
-		*Adds setting 'moving_average_history_size' for defining the window size used to calculate the moving average speed.
-		
-		*Adds several Formatting functions for formatting that values provided on the file object.
-			- SWFUpload.speed.formatBPS(bps) -- outputs string formatted in the best units (Gbps, Mbps, Kbps, bps)
-			- SWFUpload.speed.formatTime(seconds) -- outputs string formatted in the best units (x Hr y M z S)
-			- SWFUpload.speed.formatSize(bytes) -- outputs string formatted in the best units (w GB x MB y KB z B )
-			- SWFUpload.speed.formatPercent(percent) -- outputs string formatted with a percent sign (x.xx %)
-			- SWFUpload.speed.formatUnits(baseNumber, divisionArray, unitLabelArray, fractionalBoolean)
-				- Formats a number using the division array to determine how to apply the labels in the Label Array
-				- factionalBoolean indicates whether the number should be returned as a single fractional number with a unit (speed)
-				    or as several numbers labeled with units (time)
-	*/
-
-var SWFUpload;
-if (typeof(SWFUpload) === "function") {
-	SWFUpload.speed = {};
-	
-	SWFUpload.prototype.initSettings = (function (oldInitSettings) {
-		return function () {
-			if (typeof(oldInitSettings) === "function") {
-				oldInitSettings.call(this);
-			}
-			
-			this.ensureDefault = function (settingName, defaultValue) {
-				this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
-			};
-
-			// List used to keep the speed stats for the files we are tracking
-			this.fileSpeedStats = {};
-			this.speedSettings = {};
-
-			this.ensureDefault("moving_average_history_size", "10");
-			
-			this.speedSettings.user_file_queued_handler = this.settings.file_queued_handler;
-			this.speedSettings.user_file_queue_error_handler = this.settings.file_queue_error_handler;
-			this.speedSettings.user_upload_start_handler = this.settings.upload_start_handler;
-			this.speedSettings.user_upload_error_handler = this.settings.upload_error_handler;
-			this.speedSettings.user_upload_progress_handler = this.settings.upload_progress_handler;
-			this.speedSettings.user_upload_success_handler = this.settings.upload_success_handler;
-			this.speedSettings.user_upload_complete_handler = this.settings.upload_complete_handler;
-			
-			this.settings.file_queued_handler = SWFUpload.speed.fileQueuedHandler;
-			this.settings.file_queue_error_handler = SWFUpload.speed.fileQueueErrorHandler;
-			this.settings.upload_start_handler = SWFUpload.speed.uploadStartHandler;
-			this.settings.upload_error_handler = SWFUpload.speed.uploadErrorHandler;
-			this.settings.upload_progress_handler = SWFUpload.speed.uploadProgressHandler;
-			this.settings.upload_success_handler = SWFUpload.speed.uploadSuccessHandler;
-			this.settings.upload_complete_handler = SWFUpload.speed.uploadCompleteHandler;
-			
-			delete this.ensureDefault;
-		};
-	})(SWFUpload.prototype.initSettings);
-
-	
-	SWFUpload.speed.fileQueuedHandler = function (file) {
-		if (typeof this.speedSettings.user_file_queued_handler === "function") {
-			file = SWFUpload.speed.extendFile(file);
-			
-			return this.speedSettings.user_file_queued_handler.call(this, file);
-		}
-	};
-	
-	SWFUpload.speed.fileQueueErrorHandler = function (file, errorCode, message) {
-		if (typeof this.speedSettings.user_file_queue_error_handler === "function") {
-			file = SWFUpload.speed.extendFile(file);
-			
-			return this.speedSettings.user_file_queue_error_handler.call(this, file, errorCode, message);
-		}
-	};
-
-	SWFUpload.speed.uploadStartHandler = function (file) {
-		if (typeof this.speedSettings.user_upload_start_handler === "function") {
-			file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
-			return this.speedSettings.user_upload_start_handler.call(this, file);
-		}
-	};
-	
-	SWFUpload.speed.uploadErrorHandler = function (file, errorCode, message) {
-		file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
-		SWFUpload.speed.removeTracking(file, this.fileSpeedStats);
-
-		if (typeof this.speedSettings.user_upload_error_handler === "function") {
-			return this.speedSettings.user_upload_error_handler.call(this, file, errorCode, message);
-		}
-	};
-	SWFUpload.speed.uploadProgressHandler = function (file, bytesComplete, bytesTotal) {
-		this.updateTracking(file, bytesComplete);
-		file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
-
-		if (typeof this.speedSettings.user_upload_progress_handler === "function") {
-			return this.speedSettings.user_upload_progress_handler.call(this, file, bytesComplete, bytesTotal);
-		}
-	};
-	
-	SWFUpload.speed.uploadSuccessHandler = function (file, serverData) {
-		if (typeof this.speedSettings.user_upload_success_handler === "function") {
-			file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
-			return this.speedSettings.user_upload_success_handler.call(this, file, serverData);
-		}
-	};
-	SWFUpload.speed.uploadCompleteHandler = function (file) {
-		file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
-		SWFUpload.speed.removeTracking(file, this.fileSpeedStats);
-
-		if (typeof this.speedSettings.user_upload_complete_handler === "function") {
-			return this.speedSettings.user_upload_complete_handler.call(this, file);
-		}
-	};
-	
-	// Private: extends the file object with the speed plugin values
-	SWFUpload.speed.extendFile = function (file, trackingList) {
-		var tracking;
-		
-		if (trackingList) {
-			tracking = trackingList[file.id];
-		}
-		
-		if (tracking) {
-			file.currentSpeed = tracking.currentSpeed;
-			file.averageSpeed = tracking.averageSpeed;
-			file.movingAverageSpeed = tracking.movingAverageSpeed;
-			file.timeRemaining = tracking.timeRemaining;
-			file.timeElapsed = tracking.timeElapsed;
-			file.percentUploaded = tracking.percentUploaded;
-			file.sizeUploaded = tracking.bytesUploaded;
-
-		} else {
-			file.currentSpeed = 0;
-			file.averageSpeed = 0;
-			file.movingAverageSpeed = 0;
-			file.timeRemaining = 0;
-			file.timeElapsed = 0;
-			file.percentUploaded = 0;
-			file.sizeUploaded = 0;
-		}
-		
-		return file;
-	};
-	
-	// Private: Updates the speed tracking object, or creates it if necessary
-	SWFUpload.prototype.updateTracking = function (file, bytesUploaded) {
-		var tracking = this.fileSpeedStats[file.id];
-		if (!tracking) {
-			this.fileSpeedStats[file.id] = tracking = {};
-		}
-		
-		// Sanity check inputs
-		bytesUploaded = bytesUploaded || tracking.bytesUploaded || 0;
-		if (bytesUploaded < 0) {
-			bytesUploaded = 0;
-		}
-		if (bytesUploaded > file.size) {
-			bytesUploaded = file.size;
-		}
-		
-		var tickTime = (new Date()).getTime();
-		if (!tracking.startTime) {
-			tracking.startTime = (new Date()).getTime();
-			tracking.lastTime = tracking.startTime;
-			tracking.currentSpeed = 0;
-			tracking.averageSpeed = 0;
-			tracking.movingAverageSpeed = 0;
-			tracking.movingAverageHistory = [];
-			tracking.timeRemaining = 0;
-			tracking.timeElapsed = 0;
-			tracking.percentUploaded = bytesUploaded / file.size;
-			tracking.bytesUploaded = bytesUploaded;
-		} else if (tracking.startTime > tickTime) {
-			this.debug("When backwards in time");
-		} else {
-			// Get time and deltas
-			var now = (new Date()).getTime();
-			var lastTime = tracking.lastTime;
-			var deltaTime = now - lastTime;
-			var deltaBytes = bytesUploaded - tracking.bytesUploaded;
-			
-			if (deltaBytes === 0 || deltaTime === 0) {
-				return tracking;
-			}
-			
-			// Update tracking object
-			tracking.lastTime = now;
-			tracking.bytesUploaded = bytesUploaded;
-			
-			// Calculate speeds
-			tracking.currentSpeed = (deltaBytes * 8 ) / (deltaTime / 1000);
-			tracking.averageSpeed = (tracking.bytesUploaded * 8) / ((now - tracking.startTime) / 1000);
-
-			// Calculate moving average
-			tracking.movingAverageHistory.push(tracking.currentSpeed);
-			if (tracking.movingAverageHistory.length > this.settings.moving_average_history_size) {
-				tracking.movingAverageHistory.shift();
-			}
-			
-			tracking.movingAverageSpeed = SWFUpload.speed.calculateMovingAverage(tracking.movingAverageHistory);
-			
-			// Update times
-			tracking.timeRemaining = (file.size - tracking.bytesUploaded) * 8 / tracking.movingAverageSpeed;
-			tracking.timeElapsed = (now - tracking.startTime) / 1000;
-			
-			// Update percent
-			tracking.percentUploaded = (tracking.bytesUploaded / file.size * 100);
-		}
-		
-		return tracking;
-	};
-	SWFUpload.speed.removeTracking = function (file, trackingList) {
-		try {
-			trackingList[file.id] = null;
-			delete trackingList[file.id];
-		} catch (ex) {
-		}
-	};
-	
-	SWFUpload.speed.formatUnits = function (baseNumber, unitDivisors, unitLabels, singleFractional) {
-		var i, unit, unitDivisor, unitLabel;
-
-		if (baseNumber === 0) {
-			return "0 " + unitLabels[unitLabels.length - 1];
-		}
-		
-		if (singleFractional) {
-			unit = baseNumber;
-			unitLabel = unitLabels.length >= unitDivisors.length ? unitLabels[unitDivisors.length - 1] : "";
-			for (i = 0; i < unitDivisors.length; i++) {
-				if (baseNumber >= unitDivisors[i]) {
-					unit = (baseNumber / unitDivisors[i]).toFixed(2);
-					unitLabel = unitLabels.length >= i ? " " + unitLabels[i] : "";
-					break;
-				}
-			}
-			
-			return unit + unitLabel;
-		} else {
-			var formattedStrings = [];
-			var remainder = baseNumber;
-			
-			for (i = 0; i < unitDivisors.length; i++) {
-				unitDivisor = unitDivisors[i];
-				unitLabel = unitLabels.length > i ? " " + unitLabels[i] : "";
-				
-				unit = remainder / unitDivisor;
-				if (i < unitDivisors.length -1) {
-					unit = Math.floor(unit);
-				} else {
-					unit = unit.toFixed(2);
-				}
-				if (unit > 0) {
-					remainder = remainder % unitDivisor;
-					
-					formattedStrings.push(unit + unitLabel);
-				}
-			}
-			
-			return formattedStrings.join(" ");
-		}
-	};
-	
-	SWFUpload.speed.formatBPS = function (baseNumber) {
-		var bpsUnits = [1073741824, 1048576, 1024, 1], bpsUnitLabels = ["Gbps", "Mbps", "Kbps", "bps"];
-		return SWFUpload.speed.formatUnits(baseNumber, bpsUnits, bpsUnitLabels, true);
-	
-	};
-	SWFUpload.speed.formatTime = function (baseNumber) {
-		var timeUnits = [86400, 3600, 60, 1], timeUnitLabels = ["d", "h", "m", "s"];
-		return SWFUpload.speed.formatUnits(baseNumber, timeUnits, timeUnitLabels, false);
-	
-	};
-	SWFUpload.speed.formatBytes = function (baseNumber) {
-		var sizeUnits = [1073741824, 1048576, 1024, 1], sizeUnitLabels = ["GB", "MB", "KB", "bytes"];
-		return SWFUpload.speed.formatUnits(baseNumber, sizeUnits, sizeUnitLabels, true);
-	
-	};
-	SWFUpload.speed.formatPercent = function (baseNumber) {
-		return baseNumber.toFixed(2) + " %";
-	};
-	
-	SWFUpload.speed.calculateMovingAverage = function (history) {
-		var vals = [], size, sum = 0.0, mean = 0.0, varianceTemp = 0.0, variance = 0.0, standardDev = 0.0;
-		var i;
-		var mSum = 0, mCount = 0;
-		
-		size = history.length;
-		
-		// Check for sufficient data
-		if (size >= 8) {
-			// Clone the array and Calculate sum of the values 
-			for (i = 0; i < size; i++) {
-				vals[i] = history[i];
-				sum += vals[i];
-			}
-
-			mean = sum / size;
-
-			// Calculate variance for the set
-			for (i = 0; i < size; i++) {
-				varianceTemp += Math.pow((vals[i] - mean), 2);
-			}
-
-			variance = varianceTemp / size;
-			standardDev = Math.sqrt(variance);
-			
-			//Standardize the Data
-			for (i = 0; i < size; i++) {
-				vals[i] = (vals[i] - mean) / standardDev;
-			}
-
-			// Calculate the average excluding outliers
-			var deviationRange = 2.0;
-			for (i = 0; i < size; i++) {
-				
-				if (vals[i] <= deviationRange && vals[i] >= -deviationRange) {
-					mCount++;
-					mSum += history[i];
-				}
-			}
-			
-		} else {
-			// Calculate the average (not enough data points to remove outliers)
-			mCount = size;
-			for (i = 0; i < size; i++) {
-				mSum += history[i];
-			}
-		}
-
-		return mSum / mCount;
-	};
-	
+/*
+	Speed Plug-in
+	
+	Features:
+		*Adds several properties to the 'file' object indicated upload speed, time left, upload time, etc.
+			- currentSpeed -- String indicating the upload speed, bytes per second
+			- averageSpeed -- Overall average upload speed, bytes per second
+			- movingAverageSpeed -- Speed over averaged over the last several measurements, bytes per second
+			- timeRemaining -- Estimated remaining upload time in seconds
+			- timeElapsed -- Number of seconds passed for this upload
+			- percentUploaded -- Percentage of the file uploaded (0 to 100)
+			- sizeUploaded -- Formatted size uploaded so far, bytes
+		
+		*Adds setting 'moving_average_history_size' for defining the window size used to calculate the moving average speed.
+		
+		*Adds several Formatting functions for formatting that values provided on the file object.
+			- SWFUpload.speed.formatBPS(bps) -- outputs string formatted in the best units (Gbps, Mbps, Kbps, bps)
+			- SWFUpload.speed.formatTime(seconds) -- outputs string formatted in the best units (x Hr y M z S)
+			- SWFUpload.speed.formatSize(bytes) -- outputs string formatted in the best units (w GB x MB y KB z B )
+			- SWFUpload.speed.formatPercent(percent) -- outputs string formatted with a percent sign (x.xx %)
+			- SWFUpload.speed.formatUnits(baseNumber, divisionArray, unitLabelArray, fractionalBoolean)
+				- Formats a number using the division array to determine how to apply the labels in the Label Array
+				- factionalBoolean indicates whether the number should be returned as a single fractional number with a unit (speed)
+				    or as several numbers labeled with units (time)
+	*/
+
+var SWFUpload;
+if (typeof(SWFUpload) === "function") {
+	SWFUpload.speed = {};
+	
+	SWFUpload.prototype.initSettings = (function (oldInitSettings) {
+		return function () {
+			if (typeof(oldInitSettings) === "function") {
+				oldInitSettings.call(this);
+			}
+			
+			this.ensureDefault = function (settingName, defaultValue) {
+				this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
+			};
+
+			// List used to keep the speed stats for the files we are tracking
+			this.fileSpeedStats = {};
+			this.speedSettings = {};
+
+			this.ensureDefault("moving_average_history_size", "10");
+			
+			this.speedSettings.user_file_queued_handler = this.settings.file_queued_handler;
+			this.speedSettings.user_file_queue_error_handler = this.settings.file_queue_error_handler;
+			this.speedSettings.user_upload_start_handler = this.settings.upload_start_handler;
+			this.speedSettings.user_upload_error_handler = this.settings.upload_error_handler;
+			this.speedSettings.user_upload_progress_handler = this.settings.upload_progress_handler;
+			this.speedSettings.user_upload_success_handler = this.settings.upload_success_handler;
+			this.speedSettings.user_upload_complete_handler = this.settings.upload_complete_handler;
+			
+			this.settings.file_queued_handler = SWFUpload.speed.fileQueuedHandler;
+			this.settings.file_queue_error_handler = SWFUpload.speed.fileQueueErrorHandler;
+			this.settings.upload_start_handler = SWFUpload.speed.uploadStartHandler;
+			this.settings.upload_error_handler = SWFUpload.speed.uploadErrorHandler;
+			this.settings.upload_progress_handler = SWFUpload.speed.uploadProgressHandler;
+			this.settings.upload_success_handler = SWFUpload.speed.uploadSuccessHandler;
+			this.settings.upload_complete_handler = SWFUpload.speed.uploadCompleteHandler;
+			
+			delete this.ensureDefault;
+		};
+	})(SWFUpload.prototype.initSettings);
+
+	
+	SWFUpload.speed.fileQueuedHandler = function (file) {
+		if (typeof this.speedSettings.user_file_queued_handler === "function") {
+			file = SWFUpload.speed.extendFile(file);
+			
+			return this.speedSettings.user_file_queued_handler.call(this, file);
+		}
+	};
+	
+	SWFUpload.speed.fileQueueErrorHandler = function (file, errorCode, message) {
+		if (typeof this.speedSettings.user_file_queue_error_handler === "function") {
+			file = SWFUpload.speed.extendFile(file);
+			
+			return this.speedSettings.user_file_queue_error_handler.call(this, file, errorCode, message);
+		}
+	};
+
+	SWFUpload.speed.uploadStartHandler = function (file) {
+		if (typeof this.speedSettings.user_upload_start_handler === "function") {
+			file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
+			return this.speedSettings.user_upload_start_handler.call(this, file);
+		}
+	};
+	
+	SWFUpload.speed.uploadErrorHandler = function (file, errorCode, message) {
+		file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
+		SWFUpload.speed.removeTracking(file, this.fileSpeedStats);
+
+		if (typeof this.speedSettings.user_upload_error_handler === "function") {
+			return this.speedSettings.user_upload_error_handler.call(this, file, errorCode, message);
+		}
+	};
+	SWFUpload.speed.uploadProgressHandler = function (file, bytesComplete, bytesTotal) {
+		this.updateTracking(file, bytesComplete);
+		file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
+
+		if (typeof this.speedSettings.user_upload_progress_handler === "function") {
+			return this.speedSettings.user_upload_progress_handler.call(this, file, bytesComplete, bytesTotal);
+		}
+	};
+	
+	SWFUpload.speed.uploadSuccessHandler = function (file, serverData) {
+		if (typeof this.speedSettings.user_upload_success_handler === "function") {
+			file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
+			return this.speedSettings.user_upload_success_handler.call(this, file, serverData);
+		}
+	};
+	SWFUpload.speed.uploadCompleteHandler = function (file) {
+		file = SWFUpload.speed.extendFile(file, this.fileSpeedStats);
+		SWFUpload.speed.removeTracking(file, this.fileSpeedStats);
+
+		if (typeof this.speedSettings.user_upload_complete_handler === "function") {
+			return this.speedSettings.user_upload_complete_handler.call(this, file);
+		}
+	};
+	
+	// Private: extends the file object with the speed plugin values
+	SWFUpload.speed.extendFile = function (file, trackingList) {
+		var tracking;
+		
+		if (trackingList) {
+			tracking = trackingList[file.id];
+		}
+		
+		if (tracking) {
+			file.currentSpeed = tracking.currentSpeed;
+			file.averageSpeed = tracking.averageSpeed;
+			file.movingAverageSpeed = tracking.movingAverageSpeed;
+			file.timeRemaining = tracking.timeRemaining;
+			file.timeElapsed = tracking.timeElapsed;
+			file.percentUploaded = tracking.percentUploaded;
+			file.sizeUploaded = tracking.bytesUploaded;
+
+		} else {
+			file.currentSpeed = 0;
+			file.averageSpeed = 0;
+			file.movingAverageSpeed = 0;
+			file.timeRemaining = 0;
+			file.timeElapsed = 0;
+			file.percentUploaded = 0;
+			file.sizeUploaded = 0;
+		}
+		
+		return file;
+	};
+	
+	// Private: Updates the speed tracking object, or creates it if necessary
+	SWFUpload.prototype.updateTracking = function (file, bytesUploaded) {
+		var tracking = this.fileSpeedStats[file.id];
+		if (!tracking) {
+			this.fileSpeedStats[file.id] = tracking = {};
+		}
+		
+		// Sanity check inputs
+		bytesUploaded = bytesUploaded || tracking.bytesUploaded || 0;
+		if (bytesUploaded < 0) {
+			bytesUploaded = 0;
+		}
+		if (bytesUploaded > file.size) {
+			bytesUploaded = file.size;
+		}
+		
+		var tickTime = (new Date()).getTime();
+		if (!tracking.startTime) {
+			tracking.startTime = (new Date()).getTime();
+			tracking.lastTime = tracking.startTime;
+			tracking.currentSpeed = 0;
+			tracking.averageSpeed = 0;
+			tracking.movingAverageSpeed = 0;
+			tracking.movingAverageHistory = [];
+			tracking.timeRemaining = 0;
+			tracking.timeElapsed = 0;
+			tracking.percentUploaded = bytesUploaded / file.size;
+			tracking.bytesUploaded = bytesUploaded;
+		} else if (tracking.startTime > tickTime) {
+			this.debug("When backwards in time");
+		} else {
+			// Get time and deltas
+			var now = (new Date()).getTime();
+			var lastTime = tracking.lastTime;
+			var deltaTime = now - lastTime;
+			var deltaBytes = bytesUploaded - tracking.bytesUploaded;
+			
+			if (deltaBytes === 0 || deltaTime === 0) {
+				return tracking;
+			}
+			
+			// Update tracking object
+			tracking.lastTime = now;
+			tracking.bytesUploaded = bytesUploaded;
+			
+			// Calculate speeds
+			tracking.currentSpeed = (deltaBytes * 8 ) / (deltaTime / 1000);
+			tracking.averageSpeed = (tracking.bytesUploaded * 8) / ((now - tracking.startTime) / 1000);
+
+			// Calculate moving average
+			tracking.movingAverageHistory.push(tracking.currentSpeed);
+			if (tracking.movingAverageHistory.length > this.settings.moving_average_history_size) {
+				tracking.movingAverageHistory.shift();
+			}
+			
+			tracking.movingAverageSpeed = SWFUpload.speed.calculateMovingAverage(tracking.movingAverageHistory);
+			
+			// Update times
+			tracking.timeRemaining = (file.size - tracking.bytesUploaded) * 8 / tracking.movingAverageSpeed;
+			tracking.timeElapsed = (now - tracking.startTime) / 1000;
+			
+			// Update percent
+			tracking.percentUploaded = (tracking.bytesUploaded / file.size * 100);
+		}
+		
+		return tracking;
+	};
+	SWFUpload.speed.removeTracking = function (file, trackingList) {
+		try {
+			trackingList[file.id] = null;
+			delete trackingList[file.id];
+		} catch (ex) {
+		}
+	};
+	
+	SWFUpload.speed.formatUnits = function (baseNumber, unitDivisors, unitLabels, singleFractional) {
+		var i, unit, unitDivisor, unitLabel;
+
+		if (baseNumber === 0) {
+			return "0 " + unitLabels[unitLabels.length - 1];
+		}
+		
+		if (singleFractional) {
+			unit = baseNumber;
+			unitLabel = unitLabels.length >= unitDivisors.length ? unitLabels[unitDivisors.length - 1] : "";
+			for (i = 0; i < unitDivisors.length; i++) {
+				if (baseNumber >= unitDivisors[i]) {
+					unit = (baseNumber / unitDivisors[i]).toFixed(2);
+					unitLabel = unitLabels.length >= i ? " " + unitLabels[i] : "";
+					break;
+				}
+			}
+			
+			return unit + unitLabel;
+		} else {
+			var formattedStrings = [];
+			var remainder = baseNumber;
+			
+			for (i = 0; i < unitDivisors.length; i++) {
+				unitDivisor = unitDivisors[i];
+				unitLabel = unitLabels.length > i ? " " + unitLabels[i] : "";
+				
+				unit = remainder / unitDivisor;
+				if (i < unitDivisors.length -1) {
+					unit = Math.floor(unit);
+				} else {
+					unit = unit.toFixed(2);
+				}
+				if (unit > 0) {
+					remainder = remainder % unitDivisor;
+					
+					formattedStrings.push(unit + unitLabel);
+				}
+			}
+			
+			return formattedStrings.join(" ");
+		}
+	};
+	
+	SWFUpload.speed.formatBPS = function (baseNumber) {
+		var bpsUnits = [1073741824, 1048576, 1024, 1], bpsUnitLabels = ["Gbps", "Mbps", "Kbps", "bps"];
+		return SWFUpload.speed.formatUnits(baseNumber, bpsUnits, bpsUnitLabels, true);
+	
+	};
+	SWFUpload.speed.formatTime = function (baseNumber) {
+		var timeUnits = [86400, 3600, 60, 1], timeUnitLabels = ["d", "h", "m", "s"];
+		return SWFUpload.speed.formatUnits(baseNumber, timeUnits, timeUnitLabels, false);
+	
+	};
+	SWFUpload.speed.formatBytes = function (baseNumber) {
+		var sizeUnits = [1073741824, 1048576, 1024, 1], sizeUnitLabels = ["GB", "MB", "KB", "bytes"];
+		return SWFUpload.speed.formatUnits(baseNumber, sizeUnits, sizeUnitLabels, true);
+	
+	};
+	SWFUpload.speed.formatPercent = function (baseNumber) {
+		return baseNumber.toFixed(2) + " %";
+	};
+	
+	SWFUpload.speed.calculateMovingAverage = function (history) {
+		var vals = [], size, sum = 0.0, mean = 0.0, varianceTemp = 0.0, variance = 0.0, standardDev = 0.0;
+		var i;
+		var mSum = 0, mCount = 0;
+		
+		size = history.length;
+		
+		// Check for sufficient data
+		if (size >= 8) {
+			// Clone the array and Calculate sum of the values 
+			for (i = 0; i < size; i++) {
+				vals[i] = history[i];
+				sum += vals[i];
+			}
+
+			mean = sum / size;
+
+			// Calculate variance for the set
+			for (i = 0; i < size; i++) {
+				varianceTemp += Math.pow((vals[i] - mean), 2);
+			}
+
+			variance = varianceTemp / size;
+			standardDev = Math.sqrt(variance);
+			
+			//Standardize the Data
+			for (i = 0; i < size; i++) {
+				vals[i] = (vals[i] - mean) / standardDev;
+			}
+
+			// Calculate the average excluding outliers
+			var deviationRange = 2.0;
+			for (i = 0; i < size; i++) {
+				
+				if (vals[i] <= deviationRange && vals[i] >= -deviationRange) {
+					mCount++;
+					mSum += history[i];
+				}
+			}
+			
+		} else {
+			// Calculate the average (not enough data points to remove outliers)
+			mCount = size;
+			for (i = 0; i < size; i++) {
+				mSum += history[i];
+			}
+		}
+
+		return mSum / mCount;
+	};
+	
 }
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/js/swfupload/swfupload.swfobject.js	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/static/ldt/js/swfupload/swfupload.swfobject.js	Mon May 16 20:00:36 2011 +0200
@@ -1,111 +1,111 @@
-/*
-	SWFUpload.SWFObject Plugin
-
-	Summary:
-		This plugin uses SWFObject to embed SWFUpload dynamically in the page.  SWFObject provides accurate Flash Player detection and DOM Ready loading.
-		This plugin replaces the Graceful Degradation plugin.
-
-	Features:
-		* swfupload_load_failed_hander event
-		* swfupload_pre_load_handler event
-		* minimum_flash_version setting (default: "9.0.28")
-		* SWFUpload.onload event for early loading
-
-	Usage:
-		Provide handlers and settings as needed.  When using the SWFUpload.SWFObject plugin you should initialize SWFUploading
-		in SWFUpload.onload rather than in window.onload.  When initialized this way SWFUpload can load earlier preventing the UI flicker
-		that was seen using the Graceful Degradation plugin.
-
-		<script type="text/javascript">
-			var swfu;
-			SWFUpload.onload = function () {
-				swfu = new SWFUpload({
-					minimum_flash_version: "9.0.28",
-					swfupload_pre_load_handler: swfuploadPreLoad,
-					swfupload_load_failed_handler: swfuploadLoadFailed
-				});
-			};
-		</script>
-		
-	Notes:
-		You must provide set minimum_flash_version setting to "8" if you are using SWFUpload for Flash Player 8.
-		The swfuploadLoadFailed event is only fired if the minimum version of Flash Player is not met.  Other issues such as missing SWF files, browser bugs
-		 or corrupt Flash Player installations will not trigger this event.
-		The swfuploadPreLoad event is fired as soon as the minimum version of Flash Player is found.  It does not wait for SWFUpload to load and can
-		 be used to prepare the SWFUploadUI and hide alternate content.
-		swfobject's onDomReady event is cross-browser safe but will default to the window.onload event when DOMReady is not supported by the browser.
-		 Early DOM Loading is supported in major modern browsers but cannot be guaranteed for every browser ever made.
-*/
-
-
-/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
-	Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
-	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
-*/
-var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();
-
-
-	
-var SWFUpload;
-if (typeof(SWFUpload) === "function") {
-	SWFUpload.onload = function () {};
-	
-	swfobject.addDomLoadEvent(function () {
-		if (typeof(SWFUpload.onload) === "function") {
-			SWFUpload.onload.call(window);
-		}
-	});
-	
-	SWFUpload.prototype.initSettings = (function (oldInitSettings) {
-		return function () {
-			if (typeof(oldInitSettings) === "function") {
-				oldInitSettings.call(this);
-			}
-
-			this.ensureDefault = function (settingName, defaultValue) {
-				this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
-			};
-
-			this.ensureDefault("minimum_flash_version", "9.0.28");
-			this.ensureDefault("swfupload_pre_load_handler", null);
-			this.ensureDefault("swfupload_load_failed_handler", null);
-
-			delete this.ensureDefault;
-
-		};
-	})(SWFUpload.prototype.initSettings);
-
-
-	SWFUpload.prototype.loadFlash = function (oldLoadFlash) {
-		return function () {
-			var hasFlash = swfobject.hasFlashPlayerVersion(this.settings.minimum_flash_version);
-			
-			if (hasFlash) {
-				this.queueEvent("swfupload_pre_load_handler");
-				if (typeof(oldLoadFlash) === "function") {
-					oldLoadFlash.call(this);
-				}
-			} else {
-				this.queueEvent("swfupload_load_failed_handler");
-			}
-		};
-		
-	}(SWFUpload.prototype.loadFlash);
-			
-	SWFUpload.prototype.displayDebugInfo = function (oldDisplayDebugInfo) {
-		return function () {
-			if (typeof(oldDisplayDebugInfo) === "function") {
-				oldDisplayDebugInfo.call(this);
-			}
-			
-			this.debug(
-				[
-					"SWFUpload.SWFObject Plugin settings:", "\n",
-					"\t", "minimum_flash_version:                      ", this.settings.minimum_flash_version, "\n",
-					"\t", "swfupload_pre_load_handler assigned:     ", (typeof(this.settings.swfupload_pre_load_handler) === "function").toString(), "\n",
-					"\t", "swfupload_load_failed_handler assigned:     ", (typeof(this.settings.swfupload_load_failed_handler) === "function").toString(), "\n",
-				].join("")
-			);
-		};	
-	}(SWFUpload.prototype.displayDebugInfo);
-}
+/*
+	SWFUpload.SWFObject Plugin
+
+	Summary:
+		This plugin uses SWFObject to embed SWFUpload dynamically in the page.  SWFObject provides accurate Flash Player detection and DOM Ready loading.
+		This plugin replaces the Graceful Degradation plugin.
+
+	Features:
+		* swfupload_load_failed_hander event
+		* swfupload_pre_load_handler event
+		* minimum_flash_version setting (default: "9.0.28")
+		* SWFUpload.onload event for early loading
+
+	Usage:
+		Provide handlers and settings as needed.  When using the SWFUpload.SWFObject plugin you should initialize SWFUploading
+		in SWFUpload.onload rather than in window.onload.  When initialized this way SWFUpload can load earlier preventing the UI flicker
+		that was seen using the Graceful Degradation plugin.
+
+		<script type="text/javascript">
+			var swfu;
+			SWFUpload.onload = function () {
+				swfu = new SWFUpload({
+					minimum_flash_version: "9.0.28",
+					swfupload_pre_load_handler: swfuploadPreLoad,
+					swfupload_load_failed_handler: swfuploadLoadFailed
+				});
+			};
+		</script>
+		
+	Notes:
+		You must provide set minimum_flash_version setting to "8" if you are using SWFUpload for Flash Player 8.
+		The swfuploadLoadFailed event is only fired if the minimum version of Flash Player is not met.  Other issues such as missing SWF files, browser bugs
+		 or corrupt Flash Player installations will not trigger this event.
+		The swfuploadPreLoad event is fired as soon as the minimum version of Flash Player is found.  It does not wait for SWFUpload to load and can
+		 be used to prepare the SWFUploadUI and hide alternate content.
+		swfobject's onDomReady event is cross-browser safe but will default to the window.onload event when DOMReady is not supported by the browser.
+		 Early DOM Loading is supported in major modern browsers but cannot be guaranteed for every browser ever made.
+*/
+
+
+/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
+	Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
+	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
+*/
+var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();
+
+
+	
+var SWFUpload;
+if (typeof(SWFUpload) === "function") {
+	SWFUpload.onload = function () {};
+	
+	swfobject.addDomLoadEvent(function () {
+		if (typeof(SWFUpload.onload) === "function") {
+			SWFUpload.onload.call(window);
+		}
+	});
+	
+	SWFUpload.prototype.initSettings = (function (oldInitSettings) {
+		return function () {
+			if (typeof(oldInitSettings) === "function") {
+				oldInitSettings.call(this);
+			}
+
+			this.ensureDefault = function (settingName, defaultValue) {
+				this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
+			};
+
+			this.ensureDefault("minimum_flash_version", "9.0.28");
+			this.ensureDefault("swfupload_pre_load_handler", null);
+			this.ensureDefault("swfupload_load_failed_handler", null);
+
+			delete this.ensureDefault;
+
+		};
+	})(SWFUpload.prototype.initSettings);
+
+
+	SWFUpload.prototype.loadFlash = function (oldLoadFlash) {
+		return function () {
+			var hasFlash = swfobject.hasFlashPlayerVersion(this.settings.minimum_flash_version);
+			
+			if (hasFlash) {
+				this.queueEvent("swfupload_pre_load_handler");
+				if (typeof(oldLoadFlash) === "function") {
+					oldLoadFlash.call(this);
+				}
+			} else {
+				this.queueEvent("swfupload_load_failed_handler");
+			}
+		};
+		
+	}(SWFUpload.prototype.loadFlash);
+			
+	SWFUpload.prototype.displayDebugInfo = function (oldDisplayDebugInfo) {
+		return function () {
+			if (typeof(oldDisplayDebugInfo) === "function") {
+				oldDisplayDebugInfo.call(this);
+			}
+			
+			this.debug(
+				[
+					"SWFUpload.SWFObject Plugin settings:", "\n",
+					"\t", "minimum_flash_version:                      ", this.settings.minimum_flash_version, "\n",
+					"\t", "swfupload_pre_load_handler assigned:     ", (typeof(this.settings.swfupload_pre_load_handler) === "function").toString(), "\n",
+					"\t", "swfupload_load_failed_handler assigned:     ", (typeof(this.settings.swfupload_load_failed_handler) === "function").toString(), "\n",
+				].join("")
+			);
+		};	
+	}(SWFUpload.prototype.displayDebugInfo);
+}
--- a/src/ldt/ldt/templates/base.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/templates/base.html	Mon May 16 20:00:36 2011 +0200
@@ -1,48 +1,48 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
-{% block html_declare %}
-<html lang="en">
-{% endblock %}
-
-<head>
-    <title>{% if user.is_authenticated %}Hello {{ user }}{% else %}Please login{% endif %}</title>
-    <link rel="stylesheet" type="text/css" media="screen"  href="{{ MEDIA_URL }}css/socialauth.css" />
-    {% block extra_head %}
-    {% endblock %}
-</head>
-
-<body>
-    <h1>social-auth</h1>
-        {% if FACEBOOK_APP_ID %}
-          <div id="fb-root"></div>
-          <script>
-          window.fbAsyncInit = function() {
-            FB.init({appId: '{{ FACEBOOK_APP_ID }}', status: true, cookie: true, xfbml: true});
-            FB.Event.subscribe('auth.sessionChange', function(response) {
-              if (response.session) {
-                  window.location = '{% url socialauth_facebook_login_done %}';
-              } else {
-                  //window.location = '{% url socialauth_social_logout %}';
-              }
-            });
-          };
-          (function() {
-            var e = document.createElement('script');
-            e.type = 'text/javascript';
-            e.src = document.location.protocol +
-              '//connect.facebook.net/en_US/all.js';
-            e.async = true;
-            document.getElementById('fb-root').appendChild(e);
-          }());
-          </script>    
-        {% endif %}    
-    {% block extra_body %}
-    {% endblock %}
-    
-    {% block main_content %}
-    {% endblock %}
-    
-    {% block content %}
-    {% endblock %}
-    <!-- Insert your content here -->
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+{% block html_declare %}
+<html lang="en">
+{% endblock %}
+
+<head>
+    <title>{% if user.is_authenticated %}Hello {{ user }}{% else %}Please login{% endif %}</title>
+    <link rel="stylesheet" type="text/css" media="screen"  href="{{ MEDIA_URL }}css/socialauth.css" />
+    {% block extra_head %}
+    {% endblock %}
+</head>
+
+<body>
+    <h1>social-auth</h1>
+        {% if FACEBOOK_APP_ID %}
+          <div id="fb-root"></div>
+          <script>
+          window.fbAsyncInit = function() {
+            FB.init({appId: '{{ FACEBOOK_APP_ID }}', status: true, cookie: true, xfbml: true});
+            FB.Event.subscribe('auth.sessionChange', function(response) {
+              if (response.session) {
+                  window.location = '{% url socialauth_facebook_login_done %}';
+              } else {
+                  //window.location = '{% url socialauth_social_logout %}';
+              }
+            });
+          };
+          (function() {
+            var e = document.createElement('script');
+            e.type = 'text/javascript';
+            e.src = document.location.protocol +
+              '//connect.facebook.net/en_US/all.js';
+            e.async = true;
+            document.getElementById('fb-root').appendChild(e);
+          }());
+          </script>    
+        {% endif %}    
+    {% block extra_body %}
+    {% endblock %}
+    
+    {% block main_content %}
+    {% endblock %}
+    
+    {% block content %}
+    {% endblock %}
+    <!-- Insert your content here -->
+</body>
+</html>
--- a/src/ldt/ldt/templates/socialauth/createprofile.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/templates/socialauth/createprofile.html	Mon May 16 20:00:36 2011 +0200
@@ -1,13 +1,13 @@
-{% extends 'socialauth/socialauth_base.html' %}
-
-{% block content %}
-
-<form action="." method="post"> {% csrf_token %}
-    <table>
-    {{ create_form }}
-    </table>
-    <input type="submit" name="create profile" value="create profile" />
-    <input type="submit" name="cancel" value="cancel" />
-</form>
-
+{% extends 'socialauth/socialauth_base.html' %}
+
+{% block content %}
+
+<form action="." method="post"> {% csrf_token %}
+    <table>
+    {{ create_form }}
+    </table>
+    <input type="submit" name="create profile" value="create profile" />
+    <input type="submit" name="cancel" value="cancel" />
+</form>
+
 {% endblock %}
\ No newline at end of file
--- a/src/ldt/ldt/text/annotindexer.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/text/annotindexer.py	Mon May 16 20:00:36 2011 +0200
@@ -1,41 +1,41 @@
-import lucene
-
-
-class AnnotIndexer(object):
-    
-    def __init__(self, annotList, writer):
-        self.__annotList = annotList
-        self.__writer = writer
-        
-    
-    def index_all(self):
-        for annot in self.__annotList:
-            self.index_annotation(annot)
-    
-    
-    def index_annotation(self, annotation):
-        
-        doc = lucene.Document()
-        
-        doc.add(lucene.Field("annotation_id", annotation.external_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))              
-        
-        annottags = annotation.get_tag_list()
-        tags = ""
-        
-        if annottags is None or len(annottags) == 0:
-            tags = ""
-        else:
-            for tag in annottags:
-                tags += tag + ";" 
-        
-        doc.add(lucene.Field("type_doc", "text-annotation", lucene.Field.Store.NO, lucene.Field.Index.NOT_ANALYZED))              
-        doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-        doc.add(lucene.Field("title", annotation.title, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-        doc.add(lucene.Field("abstract", annotation.description, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-        doc.add(lucene.Field("text", annotation.text, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-        doc.add(lucene.Field("all", " ".join([tags, annotation.title, annotation.description, annotation.text]), lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
-
-        self.__writer.addDocument(doc)
-            
-        self.__writer.close()
-        
+import lucene
+
+
+class AnnotIndexer(object):
+    
+    def __init__(self, annotList, writer):
+        self.__annotList = annotList
+        self.__writer = writer
+        
+    
+    def index_all(self):
+        for annot in self.__annotList:
+            self.index_annotation(annot)
+    
+    
+    def index_annotation(self, annotation):
+        
+        doc = lucene.Document()
+        
+        doc.add(lucene.Field("annotation_id", annotation.external_id, lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))              
+        
+        annottags = annotation.get_tag_list()
+        tags = ""
+        
+        if annottags is None or len(annottags) == 0:
+            tags = ""
+        else:
+            for tag in annottags:
+                tags += tag + ";" 
+        
+        doc.add(lucene.Field("type_doc", "text-annotation", lucene.Field.Store.NO, lucene.Field.Index.NOT_ANALYZED))              
+        doc.add(lucene.Field("tags", tags, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+        doc.add(lucene.Field("title", annotation.title, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+        doc.add(lucene.Field("abstract", annotation.description, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+        doc.add(lucene.Field("text", annotation.text, lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+        doc.add(lucene.Field("all", " ".join([tags, annotation.title, annotation.description, annotation.text]), lucene.Field.Store.NO, lucene.Field.Index.ANALYZED))
+
+        self.__writer.addDocument(doc)
+            
+        self.__writer.close()
+        
--- a/src/ldt/ldt/text/models.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/text/models.py	Mon May 16 20:00:36 2011 +0200
@@ -1,148 +1,154 @@
-from annotindexer import AnnotIndexer
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from tagging.models import Tag
-from utils import generate_uuid
-import ldt.indexation
-import lucene
-import lxml
-import tagging.fields
-#from django.core.management.validation import max_length
-
-def Property(func):
-    return property(**func()) 
-
-
-class Annotation(models.Model):
-    external_id = models.CharField(max_length=1024, null=False, unique=True, default=generate_uuid, verbose_name=_('annotation.external_id'))
-    uri = models.CharField(max_length=1024, verbose_name=_('annotation.uri'))
-    tags_field = tagging.fields.TagField(max_length=2048, null=True, blank=True, verbose_name=_('annotation.tags'))
-    title = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('annotation.title'))
-    description = models.TextField(null=True, blank=True, verbose_name=_('annotation.description'))
-    text = models.TextField(null=True, blank=True, verbose_name=_('annotation.text'))
-    color = models.CharField(max_length=1024, verbose_name=_('annotation.color'))
-    creator = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('creator.title'))
-    contributor = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('contributor.title'))
-    creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('annotation.creation_date'))
-    update_date = models.DateTimeField(auto_now=True, verbose_name=_('annotation.update_date'))
-    
-    @Property
-    def tags(): #@NoSelf
-        
-        def fget(self):
-            return ",".join(self.tag_list)
-        
-        def fset(self, value):
-            values = None
-            if isinstance(value, (list, tuple)):
-                values = list(value)
-            elif value is not None:
-                values = [v.lower().strip() for v in unicode(value).split(",")]
-            
-            if values is not None:
-                self.tags_field = ",".join(values) + ","
-            else:
-                self.tags_field = None
-
-        return locals()
-    
-    @Property
-    def tag_list(): #@NoSelf
-        def fget(self):
-            return [t.name for t in Tag.objects.get_for_object(self)]
-        
-        return locals()
-        
-    
-    def get_tag_list(self):
-        tags = []
-        if self.tags:
-            tags_list = unicode(self.tags)
-            for t in tags_list.split(","):
-                tags.append(t.strip()) 
-        return tags
-        #return self.tags
-
-
-    def __unicode__(self):
-        return unicode(self.external_id) + u": " + unicode(self.title)
-
-    def serialize(self, root_element=None):
-        
-        if root_element is not None:
-            iri = root_element
-        else :
-            iri = lxml.etree.Element('iri')
-            doc = lxml.etree.ElementTree(iri)
-        
-        
-        textannotation = lxml.etree.SubElement(iri, 'text-annotation')
-        id = lxml.etree.SubElement(textannotation, 'id')
-        id.text = self.external_id
-        uri = lxml.etree.SubElement(textannotation, 'uri')
-        uri.text = self.uri
-        
-        if self.tags:
-            tags = lxml.etree.SubElement(textannotation, 'tags')
-            for t in self.get_tag_list():
-                tag = lxml.etree.SubElement(tags, 'tag')
-                tag.text = t
-        
-        content = lxml.etree.SubElement(textannotation, 'content')
-        color = lxml.etree.SubElement(content, 'color')
-        color.text = self.color
-        description = lxml.etree.SubElement(content, 'description')
-        description.text = self.description
-        title = lxml.etree.SubElement(content, 'title')
-        title.text = self.title
-        text = lxml.etree.SubElement(content, 'text')
-        text.text = self.text
-        
-        meta = lxml.etree.SubElement(textannotation, 'meta')
-        contributor = lxml.etree.SubElement(meta, "contributor")
-        contributor.text = self.contributor
-        creator = lxml.etree.SubElement(meta, "creator")
-        creator.text = self.creator
-        creationdate = lxml.etree.SubElement(meta, "created")
-        creationdate.text = str(self.creation_date)
-        updatedate = lxml.etree.SubElement(meta, "modified")
-        updatedate.text = str(self.update_date)
-
-        if root_element is not None:
-            return root_element
-        else:        
-            return doc
-
-
-    @staticmethod
-    def create_annotation(external_id, uri=None, tags=None, title=None, description=None, text=None, color=None, creator=None, contributor=None, creation_date=None, update_date=None):
-        annotation = Annotation(external_id=external_id, uri=uri, tags=tags, title=title, description=description, text=text, color=color, creator=creator, contributor=contributor, creation_date=creation_date, update_date=update_date)
-        annotation.save()
-        annotation.index_annot()
-        
-        return annotation
-
-
-    def delete(self):
-        super(Annotation, self).delete()
-        lucene.getVMEnv().attachCurrentThread()
-        writer = ldt.indexation.get_writer()
-        writer.deleteDocuments(lucene.Term("external_id", self.external_id))
-        writer.close()
-
-    def index_annot(self):
-        lucene.getVMEnv().attachCurrentThread()
-        writer = ldt.indexation.get_writer()
-        annotl = [self, ]
-        indexer = AnnotIndexer(annotl, writer)
-        indexer.index_all()
-        writer.close()
-
-    def update_index(self):
-        lucene.getVMEnv().attachCurrentThread()
-        writer = ldt.indexation.get_writer()
-        writer.deleteDocuments(lucene.Term("external_id", self.external_id))
-        writer.close()
-        self.index_annot()
-        
-        
+from annotindexer import AnnotIndexer
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from tagging.models import Tag
+from utils import generate_uuid
+import ldt.indexation
+import lucene
+import lxml
+import tagging.fields
+#from django.core.management.validation import max_length
+
+def Property(func):
+    return property(**func()) 
+
+
+class Annotation(models.Model):
+    external_id = models.CharField(max_length=1024, null=False, unique=True, default=generate_uuid, verbose_name=_('annotation.external_id'))
+    uri = models.CharField(max_length=1024, verbose_name=_('annotation.uri'))
+    tags_field = tagging.fields.TagField(max_length=2048, null=True, blank=True, verbose_name=_('annotation.tags'))
+    title = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('annotation.title'))
+    description = models.TextField(null=True, blank=True, verbose_name=_('annotation.description'))
+    text = models.TextField(null=True, blank=True, verbose_name=_('annotation.text'))
+    color = models.CharField(max_length=1024, verbose_name=_('annotation.color'))
+    creator = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('creator.title'))
+    contributor = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('contributor.title'))
+    creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('annotation.creation_date'))
+    update_date = models.DateTimeField(auto_now=True, verbose_name=_('annotation.update_date'))
+    
+    @Property
+    def tags(): #@NoSelf
+        
+        def fget(self):
+            return ",".join(self.tag_list)
+        
+        def fset(self, value):
+            values = None
+            if isinstance(value, (list, tuple)):
+                values = list(value)
+            elif value is not None:
+                values = [v.lower().strip() for v in unicode(value).split(",")]
+            
+            if values is not None:
+                self.tags_field = ",".join(values) + ","
+            else:
+                self.tags_field = None
+
+        return locals()
+    
+    @Property
+    def tag_list(): #@NoSelf
+        def fget(self):
+            return [t.name for t in Tag.objects.get_for_object(self)]
+        
+        return locals()
+        
+    
+    def get_tag_list(self):
+        tags = []
+        if self.tags:
+            tags_list = unicode(self.tags)
+            for t in tags_list.split(","):
+                tags.append(t.strip()) 
+        return tags
+        #return self.tags
+
+
+    def __unicode__(self):
+        return unicode(self.external_id) + u": " + unicode(self.title)
+
+    def serialize(self, root_element=None):
+        
+        if root_element is not None:
+            iri = root_element
+        else :
+            iri = lxml.etree.Element('iri')
+            doc = lxml.etree.ElementTree(iri)
+        
+        
+        textannotation = lxml.etree.SubElement(iri, 'text-annotation')
+        id = lxml.etree.SubElement(textannotation, 'id')
+        id.text = self.external_id
+        uri = lxml.etree.SubElement(textannotation, 'uri')
+        uri.text = self.uri
+        
+        if self.tags:
+            tags = lxml.etree.SubElement(textannotation, 'tags')
+            for t in self.get_tag_list():
+                tag = lxml.etree.SubElement(tags, 'tag')
+                tag.text = t
+        
+        content = lxml.etree.SubElement(textannotation, 'content')
+        color = lxml.etree.SubElement(content, 'color')
+        color.text = self.color
+        description = lxml.etree.SubElement(content, 'description')
+        description.text = self.description
+        title = lxml.etree.SubElement(content, 'title')
+        title.text = self.title
+        text = lxml.etree.SubElement(content, 'text')
+        text.text = self.text
+        
+        meta = lxml.etree.SubElement(textannotation, 'meta')
+        contributor = lxml.etree.SubElement(meta, "contributor")
+        contributor.text = self.contributor
+        creator = lxml.etree.SubElement(meta, "creator")
+        creator.text = self.creator
+        creationdate = lxml.etree.SubElement(meta, "created")
+        creationdate.text = str(self.creation_date)
+        updatedate = lxml.etree.SubElement(meta, "modified")
+        updatedate.text = str(self.update_date)
+
+        if root_element is not None:
+            return root_element
+        else:        
+            return doc
+
+
+    @staticmethod
+    def create_annotation(external_id, uri=None, tags=None, title=None, description=None, text=None, color=None, creator=None, contributor=None, creation_date=None, update_date=None):
+        annotation = Annotation(external_id=external_id, uri=uri, tags=tags, title=title, description=description, text=text, color=color, creator=creator, contributor=contributor, creation_date=creation_date, update_date=update_date)
+        annotation.save()
+        annotation.index_annot()
+        
+        return annotation
+
+
+    def delete(self):
+        super(Annotation, self).delete()
+        lucene.getVMEnv().attachCurrentThread()
+        writer = ldt.indexation.get_writer()
+        try:
+            writer.deleteDocuments(lucene.Term("external_id", self.external_id))
+        finally:
+            writer.close()
+
+    def index_annot(self):
+        lucene.getVMEnv().attachCurrentThread()
+        writer = ldt.indexation.get_writer()
+        try:
+            annotl = [self, ]
+            indexer = AnnotIndexer(annotl, writer)
+            indexer.index_all()
+        finally:
+            writer.close()
+
+    def update_index(self):
+        lucene.getVMEnv().attachCurrentThread()
+        writer = ldt.indexation.get_writer()
+        try:
+            writer.deleteDocuments(lucene.Term("external_id", self.external_id))
+        finally:
+            writer.close()
+        self.index_annot()
+        
+        
--- a/src/ldt/ldt/text/urls.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/text/urls.py	Mon May 16 20:00:36 2011 +0200
@@ -1,13 +1,13 @@
-from django.conf.urls.defaults import patterns, url
-
-# Uncomment the next two lines to enable the admin:
-# from django.contrib import admin
-# admin.autodiscover()
-
-urlpatterns = patterns('ldt.text',
-    url(r'^create/$', 'views.create_annotation'),
-    url(r'^filter/$', 'views.filter_annotation'),
-    url(r'^get/(?P<id>.*)$', 'views.get_annotation'),
-    url(r'^delete/(?P<id>.*)$', 'views.delete_annotation'),
-    url(r'^update/(?P<id>.*)$', 'views.update_annotation'),
-)
+from django.conf.urls.defaults import patterns, url
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('ldt.text',
+    url(r'^create/$', 'views.create_annotation'),
+    url(r'^filter/$', 'views.filter_annotation'),
+    url(r'^get/(?P<id>.*)$', 'views.get_annotation'),
+    url(r'^delete/(?P<id>.*)$', 'views.delete_annotation'),
+    url(r'^update/(?P<id>.*)$', 'views.update_annotation'),
+)
--- a/src/ldt/ldt/text/views.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/text/views.py	Mon May 16 20:00:36 2011 +0200
@@ -1,199 +1,199 @@
-from django.db import IntegrityError
-from django.db.models import Q
-from django.http import HttpResponse, Http404
-from django.views.decorators.csrf import csrf_exempt
-from ldt.text.models import Annotation
-from ldt.text.utils import TextSearch, generate_uuid
-from oauth_provider.decorators import oauth_required
-from urllib2 import urlparse
-import lxml
-
-
-## Filters the annotation depending on the request parameters
-## Returns an xml containing the resulting annotations
-def filter_annotation(request, uri=None, filter=None, limit=None, creator=None):
-    query = Q()    
-    
-    if request.GET.get('uri'):
-        query &= Q(uri=request.GET.get('uri'))
-    if request.GET.get('creator'):
-        query &= Q(creator=request.GET.get('creator'))
-
-    annotlist = Annotation.objects.filter(query)
-    
-    if request.GET.get('filter') and len(request.GET.get('filter')) > 0:
-        search = TextSearch()
-        res = search.query("text", request.GET.get('filter'))        
-        for r in res:
-            annotlist.append(r)
-    
-    if request.GET.get('limit'):
-        nb = request.GET.get('limit')[0]
-        offset = request.GET.get('limit')[2]
-        annotlist = annotlist[offset:]
-        annotlist = annotlist[:nb]
-
-    #create xml
-    iri = lxml.etree.Element('iri')
-    doc = lxml.etree.ElementTree(iri)
-    
-    for annot in annotlist:
-        annot.serialize(iri)
-        
-    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8")
-
-
-## Creates an annotation from a urlencoded xml content
-## Returns an xml-structured annotation
-@oauth_required
-@csrf_exempt
-def create_annotation(request):
-    cont = request.POST["content"]
-    doc = lxml.etree.fromstring(cont)
-    
-    id_nodes = doc.xpath("/iri/text-annotation/id/text()")
-    if id_nodes:
-        id = unicode(id_nodes[0])
-    else:
-        id = generate_uuid()
-        
-    uri = unicode(doc.xpath("/iri/text-annotation/uri/text()")[0])
-
-    ltags = list(set([unicode(tag.text).lower().strip() for tag in doc.xpath("/iri/text-annotation/tags/tag")]))
-    tags = ",".join(ltags)
-    if len(ltags) == 1:
-        tags += ","
-    
-    
-    title_nodes = doc.xpath("/iri/text-annotation/content/title/text()")
-    if title_nodes:
-        title = unicode(title_nodes[0])
-    else:
-        title = None
-    desc_nodes = doc.xpath("/iri/text-annotation/content/description/text()")
-    if desc_nodes:
-        desc = unicode(desc_nodes[0])
-    else:
-        desc = None
-    text_nodes = doc.xpath("/iri/text-annotation/content/text/text()")
-    if text_nodes:
-        text = unicode(text_nodes[0])
-    else:
-        text = None
-    color_nodes = doc.xpath("/iri/text-annotation/content/color/text()")
-    if color_nodes:
-        color = unicode(color_nodes[0])
-    else:
-        color = None
-    
-    creator_nodes = doc.xpath("/iri/text-annotation/meta/creator/text()")
-    if creator_nodes:
-        creator = unicode(creator_nodes[0])
-    else:
-        creator = None
-    contributor_nodes = doc.xpath("/iri/text-annotation/meta/contributor/text()")
-    if contributor_nodes:
-        contributor = unicode(contributor_nodes[0])
-    else:
-        contributor = None
-
-    try:
-        annotation = Annotation.create_annotation(external_id=id, uri=uri, tags=tags, title=title, description=desc, text=text, color=color, creator=creator, contributor=contributor)
-        annotation.save()
-        return HttpResponse(lxml.etree.tostring(annotation.serialize(), pretty_print=True), mimetype="text/xml;charset=utf-8")
-    except IntegrityError:
-        return HttpResponse(status=409)
-
-    
-    
-## Gets an annotation from its id
-## Returns the xml-structured annotation
-def get_annotation(request, id):
-    try:
-        annot = Annotation.objects.get(external_id=id)
-    except Annotation.DoesNotExist:
-        raise Http404
-
-    doc = annot.serialize()
-
-    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8")
-
-
-## Deletes an annotation (from its id)
-## Returns an empty xml-structured annotation
-@oauth_required
-@csrf_exempt
-def delete_annotation(request, id):
-    try:
-        annot = Annotation.objects.get(external_id=id)
-        annot.delete()
-    except Annotation.DoesNotExist:
-        raise Http404
-    
-    return HttpResponse("")
-
-
-## Updates the content of an annotation
-## Returns the xml-structured updated annotation
-@oauth_required
-@csrf_exempt
-def update_annotation(request, id):
-    
-    put_data = {}
-    if request.GET != {}:
-        put_data = request.GET.copy()
-    elif request.raw_post_data is not None:
-        for k, v in urlparse.parse_qs(request.raw_post_data).iteritems():
-            if len(v) > 1:
-                for item in v:
-                    put_data[k] = item
-            else:
-                put_data[k] = v[0]
-    
-    try:
-        annot = Annotation.objects.get(external_id=id)
-    except Annotation.DoesNotExist:
-        raise Http404
-    
-    cont = put_data['content']
-    doc = lxml.etree.fromstring(cont)
-    
-    uri = doc.xpath("/iri/text-annotation/uri/text()")
-    if uri != [] and annot.uri != uri[0]:
-        annot.uri = unicode(uri[0])
-    
-    tags_nodes = doc.xpath("/iri/text-annotation/tags")
-    
-    if len(tags_nodes) > 0:
-        tags = list(set([unicode(tag.text).lower().strip() for tag in doc.xpath("/iri/text-annotation/tags/tag")]))
-        tags_str = ",".join(tags)
-        if len(tags) == 1:
-            tags_str += ","
-        annot.tags = tags_str
-                    
-    title = doc.xpath("/iri/text-annotation/content/title/text()")
-    if title and annot.title != title[0]:
-        annot.title = unicode(title[0])
-    desc = doc.xpath("/iri/text-annotation/content/description/text()")
-    if desc and annot.description != desc[0]:
-        annot.description = unicode(desc[0])
-    text = doc.xpath("/iri/text-annotation/content/text/text()")
-    if text and annot.text != text[0]:
-        annot.text = unicode(text[0])
-    color = doc.xpath("/iri/text-annotation/content/color/text()")
-    if color and annot.color != color[0]:
-        annot.color = unicode(color[0])
-    
-    contributor = doc.xpath("/iri/text-annotation/meta/contributor/text()")
-    if contributor and annot.contributor != contributor[0]:
-        annot.contributor = unicode(contributor[0])
-    update_date = doc.xpath("/iri/text-annotation/meta/modified/text()")
-    if update_date and annot.update_date != update_date[0]:
-        annot.update_date = unicode(update_date[0])
-
-    annot.save()
-    annot.update_index()
-
-    return HttpResponse(lxml.etree.tostring(annot.serialize(), pretty_print=True), mimetype="text/xml;charset=utf-8")
-
-    
+from django.db import IntegrityError
+from django.db.models import Q
+from django.http import HttpResponse, Http404
+from django.views.decorators.csrf import csrf_exempt
+from ldt.text.models import Annotation
+from ldt.text.utils import TextSearch, generate_uuid
+from oauth_provider.decorators import oauth_required
+from urllib2 import urlparse
+import lxml
+
+
+## Filters the annotation depending on the request parameters
+## Returns an xml containing the resulting annotations
+def filter_annotation(request, uri=None, filter=None, limit=None, creator=None):
+    query = Q()    
+    
+    if request.GET.get('uri'):
+        query &= Q(uri=request.GET.get('uri'))
+    if request.GET.get('creator'):
+        query &= Q(creator=request.GET.get('creator'))
+
+    annotlist = Annotation.objects.filter(query)
+    
+    if request.GET.get('filter') and len(request.GET.get('filter')) > 0:
+        search = TextSearch()
+        res = search.query("text", request.GET.get('filter'))        
+        for r in res:
+            annotlist.append(r)
+    
+    if request.GET.get('limit'):
+        nb = request.GET.get('limit')[0]
+        offset = request.GET.get('limit')[2]
+        annotlist = annotlist[offset:]
+        annotlist = annotlist[:nb]
+
+    #create xml
+    iri = lxml.etree.Element('iri')
+    doc = lxml.etree.ElementTree(iri)
+    
+    for annot in annotlist:
+        annot.serialize(iri)
+        
+    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8")
+
+
+## Creates an annotation from a urlencoded xml content
+## Returns an xml-structured annotation
+@oauth_required
+@csrf_exempt
+def create_annotation(request):
+    cont = request.POST["content"]
+    doc = lxml.etree.fromstring(cont)
+    
+    id_nodes = doc.xpath("/iri/text-annotation/id/text()")
+    if id_nodes:
+        id = unicode(id_nodes[0])
+    else:
+        id = generate_uuid()
+        
+    uri = unicode(doc.xpath("/iri/text-annotation/uri/text()")[0])
+
+    ltags = list(set([unicode(tag.text).lower().strip() for tag in doc.xpath("/iri/text-annotation/tags/tag")]))
+    tags = ",".join(ltags)
+    if len(ltags) == 1:
+        tags += ","
+    
+    
+    title_nodes = doc.xpath("/iri/text-annotation/content/title/text()")
+    if title_nodes:
+        title = unicode(title_nodes[0])
+    else:
+        title = None
+    desc_nodes = doc.xpath("/iri/text-annotation/content/description/text()")
+    if desc_nodes:
+        desc = unicode(desc_nodes[0])
+    else:
+        desc = None
+    text_nodes = doc.xpath("/iri/text-annotation/content/text/text()")
+    if text_nodes:
+        text = unicode(text_nodes[0])
+    else:
+        text = None
+    color_nodes = doc.xpath("/iri/text-annotation/content/color/text()")
+    if color_nodes:
+        color = unicode(color_nodes[0])
+    else:
+        color = None
+    
+    creator_nodes = doc.xpath("/iri/text-annotation/meta/creator/text()")
+    if creator_nodes:
+        creator = unicode(creator_nodes[0])
+    else:
+        creator = None
+    contributor_nodes = doc.xpath("/iri/text-annotation/meta/contributor/text()")
+    if contributor_nodes:
+        contributor = unicode(contributor_nodes[0])
+    else:
+        contributor = None
+
+    try:
+        annotation = Annotation.create_annotation(external_id=id, uri=uri, tags=tags, title=title, description=desc, text=text, color=color, creator=creator, contributor=contributor)
+        annotation.save()
+        return HttpResponse(lxml.etree.tostring(annotation.serialize(), pretty_print=True), mimetype="text/xml;charset=utf-8")
+    except IntegrityError:
+        return HttpResponse(status=409)
+
+    
+    
+## Gets an annotation from its id
+## Returns the xml-structured annotation
+def get_annotation(request, id):
+    try:
+        annot = Annotation.objects.get(external_id=id)
+    except Annotation.DoesNotExist:
+        raise Http404
+
+    doc = annot.serialize()
+
+    return HttpResponse(lxml.etree.tostring(doc, pretty_print=True), mimetype="text/xml;charset=utf-8")
+
+
+## Deletes an annotation (from its id)
+## Returns an empty xml-structured annotation
+@oauth_required
+@csrf_exempt
+def delete_annotation(request, id):
+    try:
+        annot = Annotation.objects.get(external_id=id)
+        annot.delete()
+    except Annotation.DoesNotExist:
+        raise Http404
+    
+    return HttpResponse("")
+
+
+## Updates the content of an annotation
+## Returns the xml-structured updated annotation
+@oauth_required
+@csrf_exempt
+def update_annotation(request, id):
+    
+    put_data = {}
+    if request.GET != {}:
+        put_data = request.GET.copy()
+    elif request.raw_post_data is not None:
+        for k, v in urlparse.parse_qs(request.raw_post_data).iteritems():
+            if len(v) > 1:
+                for item in v:
+                    put_data[k] = item
+            else:
+                put_data[k] = v[0]
+    
+    try:
+        annot = Annotation.objects.get(external_id=id)
+    except Annotation.DoesNotExist:
+        raise Http404
+    
+    cont = put_data['content']
+    doc = lxml.etree.fromstring(cont)
+    
+    uri = doc.xpath("/iri/text-annotation/uri/text()")
+    if uri != [] and annot.uri != uri[0]:
+        annot.uri = unicode(uri[0])
+    
+    tags_nodes = doc.xpath("/iri/text-annotation/tags")
+    
+    if len(tags_nodes) > 0:
+        tags = list(set([unicode(tag.text).lower().strip() for tag in doc.xpath("/iri/text-annotation/tags/tag")]))
+        tags_str = ",".join(tags)
+        if len(tags) == 1:
+            tags_str += ","
+        annot.tags = tags_str
+                    
+    title = doc.xpath("/iri/text-annotation/content/title/text()")
+    if title and annot.title != title[0]:
+        annot.title = unicode(title[0])
+    desc = doc.xpath("/iri/text-annotation/content/description/text()")
+    if desc and annot.description != desc[0]:
+        annot.description = unicode(desc[0])
+    text = doc.xpath("/iri/text-annotation/content/text/text()")
+    if text and annot.text != text[0]:
+        annot.text = unicode(text[0])
+    color = doc.xpath("/iri/text-annotation/content/color/text()")
+    if color and annot.color != color[0]:
+        annot.color = unicode(color[0])
+    
+    contributor = doc.xpath("/iri/text-annotation/meta/contributor/text()")
+    if contributor and annot.contributor != contributor[0]:
+        annot.contributor = unicode(contributor[0])
+    update_date = doc.xpath("/iri/text-annotation/meta/modified/text()")
+    if update_date and annot.update_date != update_date[0]:
+        annot.update_date = unicode(update_date[0])
+
+    annot.save()
+    annot.update_index()
+
+    return HttpResponse(lxml.etree.tostring(annot.serialize(), pretty_print=True), mimetype="text/xml;charset=utf-8")
+
+    
--- a/src/ldt/ldt/user/admin.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/admin.py	Mon May 16 20:00:36 2011 +0200
@@ -1,40 +1,40 @@
-from copy import deepcopy #@UnresolvedImport
-from django.contrib import admin
-from django.contrib.auth.admin import UserAdmin
-from django.utils.translation import ugettext as _
-from forms import ldtForm, IriGroupForm
-from models import ldt, IriGroup
-
-class ldtAdmin(UserAdmin):    
-    list_display = ('username', 'email', 'first_name', 'last_name')
-    
-    fieldsets = [
-        (None, {'fields': ('username', ('password1', 'password2'))}),
-        (_('User details'), {'fields': (('first_name', 'last_name'), 'email')}),
-        (_('Groups'), {'fields': ('groups',)}),
-        (_('Permissions'), {'fields': ('is_staff', 'user_permissions')}),
-    ]    
-    form = ldtForm
-    model = ldt
-    filter_horizontal = ('user_permissions',)
-    
-    def get_fieldsets(self, request, obj=None): 
-        fieldsets = deepcopy(self.fieldsets)
-        if not '/add' in request.path:
-            fieldsets[0] = (None, {'fields': ('username',)})
-            fieldsets.append((_('Password'), {'fields': ('password1', 'password2'), 'classes': ('collapse',)}))
-        return fieldsets
-        
-    def add_view(self, request):
-        return super(UserAdmin, self).add_view(request)               
-        
-admin.site.unregister(ldt)
-admin.site.register(ldt, ldtAdmin)
-
-class IriGroupAdmin(admin.ModelAdmin):
-    form = IriGroupForm
-    model = IriGroup
-    filter_horizontal = ('permissions',)
-    
-admin.site.unregister(IriGroup)
-admin.site.register(IriGroup, IriGroupAdmin)
+from copy import deepcopy #@UnresolvedImport
+from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin
+from django.utils.translation import ugettext as _
+from forms import ldtForm, IriGroupForm
+from models import ldt, IriGroup
+
+class ldtAdmin(UserAdmin):    
+    list_display = ('username', 'email', 'first_name', 'last_name')
+    
+    fieldsets = [
+        (None, {'fields': ('username', ('password1', 'password2'))}),
+        (_('User details'), {'fields': (('first_name', 'last_name'), 'email')}),
+        (_('Groups'), {'fields': ('groups',)}),
+        (_('Permissions'), {'fields': ('is_staff', 'user_permissions')}),
+    ]    
+    form = ldtForm
+    model = ldt
+    filter_horizontal = ('user_permissions',)
+    
+    def get_fieldsets(self, request, obj=None): 
+        fieldsets = deepcopy(self.fieldsets)
+        if not '/add' in request.path:
+            fieldsets[0] = (None, {'fields': ('username',)})
+            fieldsets.append((_('Password'), {'fields': ('password1', 'password2'), 'classes': ('collapse',)}))
+        return fieldsets
+        
+    def add_view(self, request):
+        return super(UserAdmin, self).add_view(request)               
+        
+admin.site.unregister(ldt)
+admin.site.register(ldt, ldtAdmin)
+
+class IriGroupAdmin(admin.ModelAdmin):
+    form = IriGroupForm
+    model = IriGroup
+    filter_horizontal = ('permissions',)
+    
+admin.site.unregister(IriGroup)
+admin.site.register(IriGroup, IriGroupAdmin)
--- a/src/ldt/ldt/user/forms.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/forms.py	Mon May 16 20:00:36 2011 +0200
@@ -1,98 +1,98 @@
-from django import forms
-from django.contrib.auth.forms import UserCreationForm
-from django.contrib.auth.models import Permission
-from django.forms.util import ErrorList
-from django.utils.translation import gettext as _
-from ldt.management import get_content_type_list
-from models import ldt, IriGroup
-
-
-class ldtForm(UserCreationForm):
-        
-    class Meta:
-        model = ldt
-        
-    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
-                 initial=None, error_class=ErrorList, label_suffix=':',
-                 empty_permitted=False, instance=None):
-                 
-        if instance:
-            initial = initial or {}           
-        
-        super(ldtForm, self).__init__(data, files, auto_id, prefix,
-            initial, error_class, label_suffix, empty_permitted, instance)
-            
-        # filtre les permissions necessaires
-        content_type_list = get_content_type_list()
-        self.fields['user_permissions'].queryset = Permission.objects.filter(content_type__in=content_type_list)
-        
-        if instance:
-            self.fields['password1'].required = False
-            self.fields['password1'].label = _('New password')
-            self.fields['password2'].required = False
-            self.fields['password2'].label = _('New password confirmation')
-        
-        self._password_change = True
-        
-    def clean_username(self):
-        if self.instance:
-            return self.cleaned_data['username']
-        return super(ldtForm, self).clean_username()
-    
-    def clean_password2(self): 
-        if self.instance and self.cleaned_data['password1'] == '' and self.cleaned_data['password2'] == '':
-            self._password_change = False
-            return u''
-        return super(ldtForm, self).clean_password2()
-    
-   
-    def save(self, commit=True):
-        Super = self._password_change and ldtForm  or UserCreationForm  
-        user = super(Super, self).save(commit=False)
-        # if user.pk != None:
-            # self.save_m2m()
-        
-        if commit:
-            user.save()
-        
-        return user
-        
-class IriGroupForm(forms.ModelForm):
-    class meta:
-        model = IriGroup
-        
-    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
-                 initial=None, error_class=ErrorList, label_suffix=':',
-                 empty_permitted=False, instance=None):
-        if instance:
-            initial = initial or {}                               
-        
-        super(IriGroupForm, self).__init__(data, files, auto_id, prefix,
-            initial, error_class, label_suffix, empty_permitted, instance)
-            
-        # filtre les permissions necessaires
-        content_type_list = get_content_type_list()
-        self.fields['permissions'].queryset = Permission.objects.filter(content_type__in=content_type_list)
-        
-class EmailChangeForm(forms.Form):
-    email1 = forms.EmailField(label=_("E-mail"), max_length=75)
-    email2 = forms.EmailField(label=_("E-mail"), max_length=75)
-    
-    def __init__(self, user=None, *args, **kwargs):
-        self.user = user
-        super(EmailChangeForm, self).__init__(*args, **kwargs)
-        
-    def clean_email2(self):
-        email1 = self.cleaned_data.get('email1')
-        email2 = self.cleaned_data.get('email2')
-        if email1 and email2:
-            if email1 != email2:
-                raise forms.ValidationError(_("The two emails didn't match."))
-        return email2
-
-    
-    def save(self):
-        self.user.email = self.cleaned_data['email1']
-        self.user.save()
-        return self.user
-
+from django import forms
+from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.models import Permission
+from django.forms.util import ErrorList
+from django.utils.translation import gettext as _
+from ldt.management import get_content_type_list
+from models import ldt, IriGroup
+
+
+class ldtForm(UserCreationForm):
+        
+    class Meta:
+        model = ldt
+        
+    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
+                 initial=None, error_class=ErrorList, label_suffix=':',
+                 empty_permitted=False, instance=None):
+                 
+        if instance:
+            initial = initial or {}           
+        
+        super(ldtForm, self).__init__(data, files, auto_id, prefix,
+            initial, error_class, label_suffix, empty_permitted, instance)
+            
+        # filtre les permissions necessaires
+        content_type_list = get_content_type_list()
+        self.fields['user_permissions'].queryset = Permission.objects.filter(content_type__in=content_type_list)
+        
+        if instance:
+            self.fields['password1'].required = False
+            self.fields['password1'].label = _('New password')
+            self.fields['password2'].required = False
+            self.fields['password2'].label = _('New password confirmation')
+        
+        self._password_change = True
+        
+    def clean_username(self):
+        if self.instance:
+            return self.cleaned_data['username']
+        return super(ldtForm, self).clean_username()
+    
+    def clean_password2(self): 
+        if self.instance and self.cleaned_data['password1'] == '' and self.cleaned_data['password2'] == '':
+            self._password_change = False
+            return u''
+        return super(ldtForm, self).clean_password2()
+    
+   
+    def save(self, commit=True):
+        Super = self._password_change and ldtForm  or UserCreationForm  
+        user = super(Super, self).save(commit=False)
+        # if user.pk != None:
+            # self.save_m2m()
+        
+        if commit:
+            user.save()
+        
+        return user
+        
+class IriGroupForm(forms.ModelForm):
+    class meta:
+        model = IriGroup
+        
+    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
+                 initial=None, error_class=ErrorList, label_suffix=':',
+                 empty_permitted=False, instance=None):
+        if instance:
+            initial = initial or {}                               
+        
+        super(IriGroupForm, self).__init__(data, files, auto_id, prefix,
+            initial, error_class, label_suffix, empty_permitted, instance)
+            
+        # filtre les permissions necessaires
+        content_type_list = get_content_type_list()
+        self.fields['permissions'].queryset = Permission.objects.filter(content_type__in=content_type_list)
+        
+class EmailChangeForm(forms.Form):
+    email1 = forms.EmailField(label=_("E-mail"), max_length=75)
+    email2 = forms.EmailField(label=_("E-mail"), max_length=75)
+    
+    def __init__(self, user=None, *args, **kwargs):
+        self.user = user
+        super(EmailChangeForm, self).__init__(*args, **kwargs)
+        
+    def clean_email2(self):
+        email1 = self.cleaned_data.get('email1')
+        email2 = self.cleaned_data.get('email2')
+        if email1 and email2:
+            if email1 != email2:
+                raise forms.ValidationError(_("The two emails didn't match."))
+        return email2
+
+    
+    def save(self):
+        self.user.email = self.cleaned_data['email1']
+        self.user.save()
+        return self.user
+
--- a/src/ldt/ldt/user/models.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/models.py	Mon May 16 20:00:36 2011 +0200
@@ -1,41 +1,41 @@
-from django.contrib import admin
-from django.contrib.auth.models import User, Group, UserManager
-from django.db import models
-import datetime
-
-
-class IriGroup(Group):
-    description = models.TextField(null=True, blank=True)
-    
-    def __unicode__(self):
-        return self.name
-
-            
-class ldt(User):
-    irigroups = models.ManyToManyField(IriGroup, blank=True)
-    
-    class Meta:
-        verbose_name = 'iri user'
-        verbose_name_plural = 'iri users'
-    
-    def __unicode__(self):
-        return self.username
-        
-
-class ldtManager(UserManager):
-    def create_user(self, username, email, password=None):
-        "Creates and saves a User with the given username, e-mail and password."
-        now = datetime.datetime.now()
-        user = ldt(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
-        if password:
-            user.set_password(password)
-        else:
-            user.set_unusable_password()
-        user.save()
-        return user   
-
-User.objects = ldtManager()
-User.objects.contribute_to_class(User, "objects")
-
-admin.site.register(ldt)
-admin.site.register(IriGroup)
+from django.contrib import admin
+from django.contrib.auth.models import User, Group, UserManager
+from django.db import models
+import datetime
+
+
+class IriGroup(Group):
+    description = models.TextField(null=True, blank=True)
+    
+    def __unicode__(self):
+        return self.name
+
+            
+class ldt(User):
+    irigroups = models.ManyToManyField(IriGroup, blank=True)
+    
+    class Meta:
+        verbose_name = 'iri user'
+        verbose_name_plural = 'iri users'
+    
+    def __unicode__(self):
+        return self.username
+        
+
+class ldtManager(UserManager):
+    def create_user(self, username, email, password=None):
+        "Creates and saves a User with the given username, e-mail and password."
+        now = datetime.datetime.now()
+        user = ldt(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
+        if password:
+            user.set_password(password)
+        else:
+            user.set_unusable_password()
+        user.save()
+        return user   
+
+User.objects = ldtManager()
+User.objects.contribute_to_class(User, "objects")
+
+admin.site.register(ldt)
+admin.site.register(IriGroup)
--- a/src/ldt/ldt/user/templates/ldt/user/change_email.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templates/ldt/user/change_email.html	Mon May 16 20:00:36 2011 +0200
@@ -1,51 +1,51 @@
-{% extends "ldt/user/user_base.html" %}
-{# form of email address's change #}
-{% load i18n %}
-{% block breadcrumb %}
-    <li></li>
-    <li><a href="{% url ldt.user.views.profile %}">{% trans "Profiles" %}</a></li>
-    <li>{% trans "Modification de l'adresse émail" %}</li>
-{% endblock %}
-
-{% block content_title %}{% trans "Modification de l'adresse émail" %}{% endblock %}
-{% block js_declaration %}{{ block.super }}
-    <script type="text/javascript">
-        $(document).ready(function() {
-            $("#change_email").validate();
-        });
-    </script>
-{% endblock %}
-{% block css_import %}
-{{ block.super }}
-    <style type="text/css">
-        label.error { float: none; color: red; padding-left: .5em; vertical-align: middle; }
-    </style>
-{% endblock %}
-
-{% block iricontent %}
-<p>{% trans "Please enter your new e-mail twice so we can verify you typed it in correctly." %}</p>
-<form action="" method="POST" id="change_email">
-{% csrf_token %}
-    <table>
-       <tr>
-            <td>
-                <label for="id_email1">{% trans "email" %}:</label>
-            </td>
-            <td>
-                <input id="id_email1" type="text" maxlength="75" name="email1" class="required email"/>
-            </td>
-            <td>{{form.email1.errors}}</td>
-        <tr>
-        </tr>
-            <td>
-                <label for="id_email2">{% trans "Confirmation de l'adresse émail" %}:</label>
-            </td>
-            <td>
-                 <input id="id_email2" type="text" maxlength="75" name="email2" class="required email"/>
-            </td>
-            <td>{{form.email1.errors}}</td>
-        </tr>
-        <tr><th></th><td><input type="submit" class="button" name="submit" value="{% trans 'change my e-mail' %}" /></td></tr>
-    </table>
-</form>
-{% endblock%}
+{% extends "ldt/user/user_base.html" %}
+{# form of email address's change #}
+{% load i18n %}
+{% block breadcrumb %}
+    <li></li>
+    <li><a href="{% url ldt.user.views.profile %}">{% trans "Profiles" %}</a></li>
+    <li>{% trans "Modification de l'adresse émail" %}</li>
+{% endblock %}
+
+{% block content_title %}{% trans "Modification de l'adresse émail" %}{% endblock %}
+{% block js_declaration %}{{ block.super }}
+    <script type="text/javascript">
+        $(document).ready(function() {
+            $("#change_email").validate();
+        });
+    </script>
+{% endblock %}
+{% block css_import %}
+{{ block.super }}
+    <style type="text/css">
+        label.error { float: none; color: red; padding-left: .5em; vertical-align: middle; }
+    </style>
+{% endblock %}
+
+{% block iricontent %}
+<p>{% trans "Please enter your new e-mail twice so we can verify you typed it in correctly." %}</p>
+<form action="" method="POST" id="change_email">
+{% csrf_token %}
+    <table>
+       <tr>
+            <td>
+                <label for="id_email1">{% trans "email" %}:</label>
+            </td>
+            <td>
+                <input id="id_email1" type="text" maxlength="75" name="email1" class="required email"/>
+            </td>
+            <td>{{form.email1.errors}}</td>
+        <tr>
+        </tr>
+            <td>
+                <label for="id_email2">{% trans "Confirmation de l'adresse émail" %}:</label>
+            </td>
+            <td>
+                 <input id="id_email2" type="text" maxlength="75" name="email2" class="required email"/>
+            </td>
+            <td>{{form.email1.errors}}</td>
+        </tr>
+        <tr><th></th><td><input type="submit" class="button" name="submit" value="{% trans 'change my e-mail' %}" /></td></tr>
+    </table>
+</form>
+{% endblock%}
--- a/src/ldt/ldt/user/templates/ldt/user/change_email_done.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templates/ldt/user/change_email_done.html	Mon May 16 20:00:36 2011 +0200
@@ -1,14 +1,14 @@
-{% extends "ldt/user/user_base.html" %}
-{# if email is changed successfully, retrun this page #}
-{% load i18n %}
-{% block breadcrumb %}
-    <li></li>
-    <li><a href="{% url ldt.user.views.profile %}">{% trans "Profiles" %}</a></li>
-    <li>{% trans "email change" %}</li>
-{% endblock %}
-
-{% block content_title %}{% trans "email change" %}{% endblock %}
-{% block iricontent %}
-<p> {% trans "email changed" %}</p>
-<a href="{% url ldt.user.views.profile %}">{% trans "back to profile" %}</a>
-{% endblock %}
+{% extends "ldt/user/user_base.html" %}
+{# if email is changed successfully, retrun this page #}
+{% load i18n %}
+{% block breadcrumb %}
+    <li></li>
+    <li><a href="{% url ldt.user.views.profile %}">{% trans "Profiles" %}</a></li>
+    <li>{% trans "email change" %}</li>
+{% endblock %}
+
+{% block content_title %}{% trans "email change" %}{% endblock %}
+{% block iricontent %}
+<p> {% trans "email changed" %}</p>
+<a href="{% url ldt.user.views.profile %}">{% trans "back to profile" %}</a>
+{% endblock %}
--- a/src/ldt/ldt/user/templates/ldt/user/home.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templates/ldt/user/home.html	Mon May 16 20:00:36 2011 +0200
@@ -1,14 +1,14 @@
-{% extends "ldt/ldt_base.html" %}
-{% load i18n %}
-
-{% block title %}Home{% endblock %}
-
-{% block content_base %}
-
-<p>Welcome</p>
-<li><a href="{% url django.contrib.auth.views.login  %}" >{% trans "Se connecter" %}</a></li>
-<li><a href="{% url registration.views.register  %}" >{% trans "Créer un compte" %}</a></li>
-<li><a href="{% url django.contrib.auth.views.password_reset  %}" >{% trans "récupérer mot de passe" %}</a></li>
-
-{% endblock %} 
-
+{% extends "ldt/ldt_base.html" %}
+{% load i18n %}
+
+{% block title %}Home{% endblock %}
+
+{% block content_base %}
+
+<p>Welcome</p>
+<li><a href="{% url django.contrib.auth.views.login  %}" >{% trans "Se connecter" %}</a></li>
+<li><a href="{% url registration.views.register  %}" >{% trans "Créer un compte" %}</a></li>
+<li><a href="{% url django.contrib.auth.views.password_reset  %}" >{% trans "récupérer mot de passe" %}</a></li>
+
+{% endblock %} 
+
--- a/src/ldt/ldt/user/templates/ldt/user/login_form.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templates/ldt/user/login_form.html	Mon May 16 20:00:36 2011 +0200
@@ -1,75 +1,75 @@
-{% load i18n %}
-{# print user's state and form of login #}
-{% block js_import %}
-{{block.super}}
-
-    <script language="javascript">
-    var url_login_ajax='{{WEB_URL}}{% url ldt.user.views.loginAjax %}';
-    {% if reload %}    
-        var reload=true;    
-    {% else %}
-        var reload=false;  
-    {% endif %}
-
-    $(document).ready(function(){
-        $('.login_link').nyroModal({
-        	   sizes: {
-        		   minH: 235,
-        		   minW: 430
-        	   }
-        });
-    });
-
-    </script>
-{% endblock %}
-{% block css_import %}
-{{block.super}}
-{% endblock %}
-<div id="loginstate" class="block span-24 last">
-    <ul class="usertool">
-        {% if user.is_authenticated %}    
-            <li id="user">{{user.username}}</li>
-            <li><a href="{% url ldt.user.views.profile  %}" >{% trans "Profiles" %}</a> </li>
-            <li><a href="{% url ldt.user.views.space %}">{% trans "Space" %}</a></li>
-            <li><a href="{% url ldt.user.views.logout_view %}" >{% trans "Log out" %}</a></li>  
-        
-        {% else %}     
-            <li><a href="#inlineContent" class="login_link">{% trans "Log in" %}</li>
-        {% endif %}
-    </ul>
-</div>
-<div id="inlineContent" style="display: none;">
-    <div id="loginform">
-            <div class="title">
-                <a href="#" class="nyroModalClose">X</a>
-                <div>{% trans "Log in" %}</div>             
-            </div>
-            <div id="msg"></div>
-            <div id="login_form" style="padding: 8px;" method="POST" action="">
-                <div style="float: right; padding-bottom: 8px;">
-                    <a href="{% url registration.views.register  %}" >{% trans "create account" %}</a>
-                </div>
-                <dl style="clear: both;">
-                    
-                    <dt><label for="username">{% trans "Pseudo" %}:</label></dt>
-                    <dd>
-                        <input class= "inputbox" type="text" style="width:148px" name="username" value="" id="username">
-                        <div id="login_form_username_error" class="ajaxform_error">{% trans "this field is compulsory" %}</div>
-                    </dd>
-               
-                
-                    <dt><label for="password">{% trans "Password" %}: </label></dt>
-                    <dd>
-                        <input class= "inputbox" type="password" style="width:148px" name="password" value="" id="password" >
-                        <div id="login_form_password_error" class="ajaxform_error">{% trans "this field is compulsory" %}</div>
-                    </dd>
-                    <dt/>
-                    <dd>
-                        <a href="{% url django.contrib.auth.views.password_reset  %}" >{% trans "reset password" %}</a>
-                    </dd>
-                </dl>
-                <input class="button" id="submit" type="submit" value="{% trans 'Connection' %}"/>  
-            </div>
-
-        </div>
-</div>
+{% load i18n %}
+{# print user's state and form of login #}
+{% block js_import %}
+{{block.super}}
+
+    <script language="javascript">
+    var url_login_ajax='{{WEB_URL}}{% url ldt.user.views.loginAjax %}';
+    {% if reload %}    
+        var reload=true;    
+    {% else %}
+        var reload=false;  
+    {% endif %}
+
+    $(document).ready(function(){
+        $('.login_link').nyroModal({
+        	   sizes: {
+        		   minH: 235,
+        		   minW: 430
+        	   }
+        });
+    });
+
+    </script>
+{% endblock %}
+{% block css_import %}
+{{block.super}}
+{% endblock %}
+<div id="loginstate" class="block span-24 last">
+    <ul class="usertool">
+        {% if user.is_authenticated %}    
+            <li id="user">{{user.username}}</li>
+            <li><a href="{% url ldt.user.views.profile  %}" >{% trans "Profiles" %}</a> </li>
+            <li><a href="{% url ldt.user.views.space %}">{% trans "Space" %}</a></li>
+            <li><a href="{% url ldt.user.views.logout_view %}" >{% trans "Log out" %}</a></li>  
+        
+        {% else %}     
+            <li><a href="#inlineContent" class="login_link">{% trans "Log in" %}</li>
+        {% endif %}
+    </ul>
+</div>
+<div id="inlineContent" style="display: none;">
+    <div id="loginform">
+            <div class="title">
+                <a href="#" class="nyroModalClose">X</a>
+                <div>{% trans "Log in" %}</div>             
+            </div>
+            <div id="msg"></div>
+            <div id="login_form" style="padding: 8px;" method="POST" action="">
+                <div style="float: right; padding-bottom: 8px;">
+                    <a href="{% url registration.views.register  %}" >{% trans "create account" %}</a>
+                </div>
+                <dl style="clear: both;">
+                    
+                    <dt><label for="username">{% trans "Pseudo" %}:</label></dt>
+                    <dd>
+                        <input class= "inputbox" type="text" style="width:148px" name="username" value="" id="username">
+                        <div id="login_form_username_error" class="ajaxform_error">{% trans "this field is compulsory" %}</div>
+                    </dd>
+               
+                
+                    <dt><label for="password">{% trans "Password" %}: </label></dt>
+                    <dd>
+                        <input class= "inputbox" type="password" style="width:148px" name="password" value="" id="password" >
+                        <div id="login_form_password_error" class="ajaxform_error">{% trans "this field is compulsory" %}</div>
+                    </dd>
+                    <dt/>
+                    <dd>
+                        <a href="{% url django.contrib.auth.views.password_reset  %}" >{% trans "reset password" %}</a>
+                    </dd>
+                </dl>
+                <input class="button" id="submit" type="submit" value="{% trans 'Connection' %}"/>  
+            </div>
+
+        </div>
+</div>
--- a/src/ldt/ldt/user/templates/ldt/user/space.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templates/ldt/user/space.html	Mon May 16 20:00:36 2011 +0200
@@ -1,19 +1,19 @@
-{% extends "ldt/user/user_base.html" %}
-{# user's space (edit page or project lignes de temps) #}
-{% load i18n %}
-{% block breadcrumb %}
-    <li></li>
-    <li>{% trans "Space" %}</li>    
-{% endblock %}
-
-{% block content_title %}{% trans "Space" %}{% endblock %}
-{% block iricontent%}
-<ul>
-{% if cms %}
-    <li><a href="{% url admin:page %}">{% trans "Page" %}</a></li>
-{% endif %}
-{% if ldt %}
-    <li><a href="{% url ldt.ldt_utils.views.list_ldt %}">{% trans "Projets Lignes de temps" %}</a></li>
-{% endif %}
-</ul>      
-{% endblock %}
+{% extends "ldt/user/user_base.html" %}
+{# user's space (edit page or project lignes de temps) #}
+{% load i18n %}
+{% block breadcrumb %}
+    <li></li>
+    <li>{% trans "Space" %}</li>    
+{% endblock %}
+
+{% block content_title %}{% trans "Space" %}{% endblock %}
+{% block iricontent%}
+<ul>
+{% if cms %}
+    <li><a href="{% url admin:page %}">{% trans "Page" %}</a></li>
+{% endif %}
+{% if ldt %}
+    <li><a href="{% url ldt.ldt_utils.views.list_ldt %}">{% trans "Projets Lignes de temps" %}</a></li>
+{% endif %}
+</ul>      
+{% endblock %}
--- a/src/ldt/ldt/user/templates/registration/activation_complete.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templates/registration/activation_complete.html	Mon May 16 20:00:36 2011 +0200
@@ -1,8 +1,8 @@
-{% extends "registration/base.html" %}
-{% load i18n %}
-
-{% block content_title %}{% trans 'Sign up successfully' %}{% endblock %}
-{% block iricontent %}
-<p> {% trans "activation completed" %}</p>
-
-{% endblock%}
+{% extends "registration/base.html" %}
+{% load i18n %}
+
+{% block content_title %}{% trans 'Sign up successfully' %}{% endblock %}
+{% block iricontent %}
+<p> {% trans "activation completed" %}</p>
+
+{% endblock%}
--- a/src/ldt/ldt/user/templates/registration/registration_complete.html	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templates/registration/registration_complete.html	Mon May 16 20:00:36 2011 +0200
@@ -1,12 +1,12 @@
-{% extends "registration/base.html" %}
-{% load i18n %}
-
-{% block breadcrumb %}
-    <li></li>
-    <li>{% trans 'Sign up' %}</li>
-{% endblock %}
-{% block content_title %}{% trans 'Sign up successfully' %}{% endblock %}
-{% block iricontent %}
-<p> {% trans "We've e-mailed you instructions for activate your account to the e-mail address you submitted. You should be receiving it shortly." %}</p>
-
+{% extends "registration/base.html" %}
+{% load i18n %}
+
+{% block breadcrumb %}
+    <li></li>
+    <li>{% trans 'Sign up' %}</li>
+{% endblock %}
+{% block content_title %}{% trans 'Sign up successfully' %}{% endblock %}
+{% block iricontent %}
+<p> {% trans "We've e-mailed you instructions for activate your account to the e-mail address you submitted. You should be receiving it shortly." %}</p>
+
 {% endblock%}
\ No newline at end of file
--- a/src/ldt/ldt/user/templatetags/logintag.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/templatetags/logintag.py	Mon May 16 20:00:36 2011 +0200
@@ -1,8 +1,8 @@
-from django import template
-
-register = template.Library() 
-
-def loginAjax(user, reload=None):
-    return {'user': user, 'reload': reload}
-    
-register.inclusion_tag('ldt/user/login_form.html')(loginAjax)
+from django import template
+
+register = template.Library() 
+
+def loginAjax(user, reload=None):
+    return {'user': user, 'reload': reload}
+    
+register.inclusion_tag('ldt/user/login_form.html')(loginAjax)
--- a/src/ldt/ldt/user/tests.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/tests.py	Mon May 16 20:00:36 2011 +0200
@@ -1,23 +1,23 @@
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
-
-Replace these with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-class SimpleTest(TestCase):
-    def test_basic_addition(self):
-        """
-        Tests that 1 + 1 always equals 2.
-        """
-        self.failUnlessEqual(1 + 1, 2)
-
-__test__ = {"doctest": """
-Another way to test that 1 + 1 is equal to 2.
-
->>> 1 + 1 == 2
-True
-"""}
-
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
--- a/src/ldt/ldt/user/urls.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/urls.py	Mon May 16 20:00:36 2011 +0200
@@ -1,19 +1,19 @@
-from django.conf.urls.defaults import patterns, url
-
-urlpatterns = patterns('',
-    url(r'^loginAjax/$', 'ldt.user.views.loginAjax'),
-    url(r'^profile/', 'ldt.user.views.profile'),
-    url(r'^logout/', 'ldt.user.views.logout_view'),
-    url(r'^space/$', 'ldt.user.views.space'),
-    url(r'^emailchange/$', 'ldt.user.views.change_email'),
-    url(r'^emailchange/done/$', 'ldt.user.views.change_email_done'),
-#    url(r'^space/ldt/$', 'ldt.ldt_utils.views.list_ldt'),
-#    url(r'^space/ldt/indexproject/(?P<id>.*)$', 'ldt.ldt_utils.views.indexProject'),
-#    url(r'^space/ldt/init/(?P<method>.*)/(?P<url>.*)$', 'ldt.ldt_utils.views.init'),
-#    url(r'^space/ldt/project/(?P<id>.*)$', 'ldt.ldt_utils.views.ldtProject'),
-#    url(r'^space/ldt/create/$', 'ldt.ldt_utils.views.create_ldt_view'),
-#    url(r'^space/ldt/created_done/$', 'ldt.ldt_utils.views.created_ldt'),
-#    url(r'^space/ldt/save/$', 'ldt.ldt_utils.views.save_ldtProject'),
-#    url(r'^space/ldt/publish/(?P<id>.*)$', 'ldt.ldt_utils.views.publish'),
-#    url(r'^space/ldt/unpublish/(?P<id>.*)$', 'ldt.ldt_utils.views.unpublish'),
-)
+from django.conf.urls.defaults import patterns, url
+
+urlpatterns = patterns('',
+    url(r'^loginAjax/$', 'ldt.user.views.loginAjax'),
+    url(r'^profile/', 'ldt.user.views.profile'),
+    url(r'^logout/', 'ldt.user.views.logout_view'),
+    url(r'^space/$', 'ldt.user.views.space'),
+    url(r'^emailchange/$', 'ldt.user.views.change_email'),
+    url(r'^emailchange/done/$', 'ldt.user.views.change_email_done'),
+#    url(r'^space/ldt/$', 'ldt.ldt_utils.views.list_ldt'),
+#    url(r'^space/ldt/indexproject/(?P<id>.*)$', 'ldt.ldt_utils.views.indexProject'),
+#    url(r'^space/ldt/init/(?P<method>.*)/(?P<url>.*)$', 'ldt.ldt_utils.views.init'),
+#    url(r'^space/ldt/project/(?P<id>.*)$', 'ldt.ldt_utils.views.ldtProject'),
+#    url(r'^space/ldt/create/$', 'ldt.ldt_utils.views.create_ldt_view'),
+#    url(r'^space/ldt/created_done/$', 'ldt.ldt_utils.views.created_ldt'),
+#    url(r'^space/ldt/save/$', 'ldt.ldt_utils.views.save_ldtProject'),
+#    url(r'^space/ldt/publish/(?P<id>.*)$', 'ldt.ldt_utils.views.publish'),
+#    url(r'^space/ldt/unpublish/(?P<id>.*)$', 'ldt.ldt_utils.views.unpublish'),
+)
--- a/src/ldt/ldt/user/views.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/user/views.py	Mon May 16 20:00:36 2011 +0200
@@ -1,74 +1,74 @@
-from django.contrib.auth import authenticate, login, logout
-from django.contrib.auth.decorators import login_required
-from django.core.urlresolvers import reverse
-from django.http import HttpResponse, HttpResponseRedirect
-from django.shortcuts import render_to_response
-from django.template import RequestContext, loader
-from django.utils import simplejson
-from django.utils.translation import ugettext as _
-from forms import EmailChangeForm
-from ldt.management import test_cms, test_ldt
-# from django.contrib.sites.models import Site, RequestSite
-
-
-def home(request):
-    return render_to_response('ldt/user/home.html', context_instance=RequestContext(request))
-    
-@login_required   
-def profile(request):
-    return render_to_response('ldt/user/profile.html', context_instance=RequestContext(request))
-
-@login_required     
-def space(request, page_id=None, slug=None):
-    cms = test_cms()
-    ldt = test_ldt()
-    context = {
-        'cms': cms,
-        'ldt': ldt
-    }
-    return render_to_response('ldt/user/space.html', context, context_instance=RequestContext(request))
-    
-
-    
-def logout_view(request):
-    logout(request)
-    return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
-    #return HttpResponseRedirect(settings.LOGOUT_URL)
-
-    
-def loginAjax(request, loginstate_template_name='ldt/user/login_form.html'):
-    if request.method == "POST":
-        username = request.POST["username"]
-        password = request.POST["password"]
-        user = authenticate(username=username, password=password)
-        error_message = _(u"Sorry, that's not a valid username or password.")
-        if user is not None:
-            if user.is_active:
-                login(request, user)
-                context = RequestContext(request, { 'username': user.username, })
-                template = loader.get_template(loginstate_template_name)
-                html = template.render(context)
-                return HttpResponse(simplejson.dumps({'message': u'successful', 'username': user.username, 'html': html, 'reload': request.POST["reload"], }))               
-            else:
-                return HttpResponse(simplejson.dumps({'message': error_message, }))
-        else:
-            return HttpResponse(simplejson.dumps({'message': error_message, }))
-    return render_to_response('ldt/user/login_ajax.html', context_instance=RequestContext(request))
-            
-@login_required              
-def change_email(request, post_change_redirect=None):
-    if post_change_redirect is None:
-        post_change_redirect = reverse('ldt.user.views.change_email_done')
-    if request.method == "POST":
-        form = EmailChangeForm(request.user, request.POST)
-        if form.is_valid():
-            form.save()
-            return HttpResponseRedirect(post_change_redirect)
-    else:
-        form = EmailChangeForm(request.user)
-    return render_to_response('ldt/user/change_email.html', {'form': form, }, context_instance=RequestContext(request))
-    
-@login_required    
-def change_email_done(request, template_name='ldt/user/change_email_done.html'):
-    return render_to_response(template_name, context_instance=RequestContext(request))
-
+from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.decorators import login_required
+from django.core.urlresolvers import reverse
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render_to_response
+from django.template import RequestContext, loader
+from django.utils import simplejson
+from django.utils.translation import ugettext as _
+from forms import EmailChangeForm
+from ldt.management import test_cms, test_ldt
+# from django.contrib.sites.models import Site, RequestSite
+
+
+def home(request):
+    return render_to_response('ldt/user/home.html', context_instance=RequestContext(request))
+    
+@login_required   
+def profile(request):
+    return render_to_response('ldt/user/profile.html', context_instance=RequestContext(request))
+
+@login_required     
+def space(request, page_id=None, slug=None):
+    cms = test_cms()
+    ldt = test_ldt()
+    context = {
+        'cms': cms,
+        'ldt': ldt
+    }
+    return render_to_response('ldt/user/space.html', context, context_instance=RequestContext(request))
+    
+
+    
+def logout_view(request):
+    logout(request)
+    return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
+    #return HttpResponseRedirect(settings.LOGOUT_URL)
+
+    
+def loginAjax(request, loginstate_template_name='ldt/user/login_form.html'):
+    if request.method == "POST":
+        username = request.POST["username"]
+        password = request.POST["password"]
+        user = authenticate(username=username, password=password)
+        error_message = _(u"Sorry, that's not a valid username or password.")
+        if user is not None:
+            if user.is_active:
+                login(request, user)
+                context = RequestContext(request, { 'username': user.username, })
+                template = loader.get_template(loginstate_template_name)
+                html = template.render(context)
+                return HttpResponse(simplejson.dumps({'message': u'successful', 'username': user.username, 'html': html, 'reload': request.POST["reload"], }))               
+            else:
+                return HttpResponse(simplejson.dumps({'message': error_message, }))
+        else:
+            return HttpResponse(simplejson.dumps({'message': error_message, }))
+    return render_to_response('ldt/user/login_ajax.html', context_instance=RequestContext(request))
+            
+@login_required              
+def change_email(request, post_change_redirect=None):
+    if post_change_redirect is None:
+        post_change_redirect = reverse('ldt.user.views.change_email_done')
+    if request.method == "POST":
+        form = EmailChangeForm(request.user, request.POST)
+        if form.is_valid():
+            form.save()
+            return HttpResponseRedirect(post_change_redirect)
+    else:
+        form = EmailChangeForm(request.user)
+    return render_to_response('ldt/user/change_email.html', {'form': form, }, context_instance=RequestContext(request))
+    
+@login_required    
+def change_email_done(request, template_name='ldt/user/change_email_done.html'):
+    return render_to_response(template_name, context_instance=RequestContext(request))
+
--- a/src/ldt/ldt/utils/__init__.py	Mon May 16 17:43:34 2011 +0200
+++ b/src/ldt/ldt/utils/__init__.py	Mon May 16 20:00:36 2011 +0200
@@ -1,4 +1,4 @@
-
-def Property(func):
-    return property(**func())
-    
+
+def Property(func):
+    return property(**func())
+