Unicode errors in filebrowser. Refs #372.
authorŁukasz Rekucki <lrekucki@gmail.com>
Wed, 3 Mar 2010 08:15:32 +0000 (09:15 +0100)
committerŁukasz Rekucki <lrekucki@gmail.com>
Wed, 3 Mar 2010 08:15:32 +0000 (09:15 +0100)
apps/filebrowser/base.py
apps/filebrowser/functions.py
apps/filebrowser/templates/filebrowser/include/filelisting.html
apps/filebrowser/templatetags/fb_tags.py
apps/filebrowser/templatetags/fb_versions.py
apps/filebrowser/views.py
platforma/settings.py
platforma/templates/registration/head_login.html
platforma/urls.py

index e72b9ff..da53d91 100644 (file)
@@ -1,8 +1,11 @@
 # coding: utf-8
 
+import locale
+
 import os, re, datetime
 from time import gmtime, strftime
 from django.conf import settings
+import urllib
 
 # filebrowser imports
 from filebrowser.fb_settings import *
@@ -16,7 +19,12 @@ else:
         from PIL import Image
     except ImportError:
         import Image
-    
+
+
+def filesystem_encoding(ucode):
+    ucode = ucode.encode('utf-8')
+    ucode = urllib.quote(ucode)
+    return ucode
 
 class FileObject(object):
     """
@@ -24,14 +32,14 @@ class FileObject(object):
     
     PATH has to be relative to MEDIA_ROOT.
     """
-    
+
     def __init__(self, path):
-        self.path = path
+        self.path = unicode(path)
         self.head = os.path.split(path)[0]
         self.filename = os.path.split(path)[1]
         self.filename_lower = self.filename.lower() # important for sorting
         self.filetype = _get_file_type(self.filename)
-    
+
     def _filesize(self):
         """
         Filesize.
@@ -40,30 +48,31 @@ class FileObject(object):
             return os.path.getsize(os.path.join(MEDIA_ROOT, self.path))
         return ""
     filesize = property(_filesize)
-        
+
     def _date(self):
         """
         Date.
         """
         if os.path.isfile(os.path.join(MEDIA_ROOT, self.path)) or os.path.isdir(os.path.join(MEDIA_ROOT, self.path)):
             return os.path.getmtime(os.path.join(MEDIA_ROOT, self.path))
-        return ""
+        # IMHO this should raise an exception
+        return None
     date = property(_date)
-    
+
     def _datetime(self):
         """
         Datetime Object.
         """
         return datetime.datetime.fromtimestamp(self.date)
     datetime = property(_datetime)
-    
+
     def _extension(self):
         """
         Extension.
         """
         return u"%s" % os.path.splitext(self.filename)[1]
     extension = property(_extension)
-    
+
     def _filetype_checked(self):
         if self.filetype == "Folder" and os.path.isdir(self.path_full):
             return self.filetype
@@ -72,18 +81,18 @@ class FileObject(object):
         else:
             return ""
     filetype_checked = property(_filetype_checked)
-    
+
     def _path_full(self):
         """
         Full server PATH including MEDIA_ROOT.
         """
         return u"%s" % os.path.join(MEDIA_ROOT, self.path)
     path_full = property(_path_full)
-    
+
     def _path_relative(self):
         return self.path
     path_relative = property(_path_relative)
-    
+
     def _path_relative_directory(self):
         """
         Path relative to initial directory.
@@ -92,18 +101,19 @@ class FileObject(object):
         value = directory_re.sub('', self.path)
         return u"%s" % value
     path_relative_directory = property(_path_relative_directory)
-    
+
     def _url_relative(self):
         return self.path
     url_relative = property(_url_relative)
-    
+
     def _url_full(self):
         """
         Full URL including MEDIA_URL.
         """
-        return u"%s" % _url_join(MEDIA_URL, self.path)
+        return filesystem_encoding(u"%s" % _url_join(MEDIA_URL, self.path))
+
     url_full = property(_url_full)
-    
+
     def _url_save(self):
         """
         URL used for the filebrowsefield.
@@ -111,27 +121,27 @@ class FileObject(object):
         if SAVE_FULL_URL:
             return self.url_full
         else:
-            return self.path
+            return filesystem_encoding(self.path)
     url_save = property(_url_save)
-    
+
     def _url_thumbnail(self):
         """
         Thumbnail URL.
         """
         if self.filetype == "Image":
-            return u"%s" % _url_join(MEDIA_URL, _get_version_path(self.path, 'fb_thumb'))
+            return filesystem_encoding(u"%s" % _url_join(MEDIA_URL, _get_version_path(self.path, u'fb_thumb')))
         else:
             return ""
     url_thumbnail = property(_url_thumbnail)
-    
+
     def url_admin(self):
         if self.filetype_checked == "Folder":
             directory_re = re.compile(r'^(%s)' % (DIRECTORY))
             value = directory_re.sub('', self.path)
-            return u"%s" % value
+            return filesystem_encoding(u"%s" % value)
         else:
-            return u"%s" % _url_join(MEDIA_URL, self.path)
-    
+            return filesystem_encoding(u"%s" % _url_join(MEDIA_URL, self.path))
+
     def _dimensions(self):
         """
         Image Dimensions.
@@ -145,21 +155,21 @@ class FileObject(object):
         else:
             return False
     dimensions = property(_dimensions)
-    
+
     def _width(self):
         """
         Image Width.
         """
         return self.dimensions[0]
     width = property(_width)
-    
+
     def _height(self):
         """
         Image Height.
         """
         return self.dimensions[1]
     height = property(_height)
-    
+
     def _orientation(self):
         """
         Image Orientation.
@@ -172,7 +182,7 @@ class FileObject(object):
         else:
             return None
     orientation = property(_orientation)
-    
+
     def _is_empty(self):
         """
         True if Folder is empty, False if not.
@@ -185,15 +195,15 @@ class FileObject(object):
         else:
             return None
     is_empty = property(_is_empty)
-    
+
     def __repr__(self):
         return u"%s" % self.url_save
-    
+
     def __str__(self):
         return u"%s" % self.url_save
-    
+
     def __unicode__(self):
         return u"%s" % self.url_save
-    
+
 
 
index 5f7f98f..afcdffd 100755 (executable)
@@ -28,8 +28,9 @@ def _url_to_path(value):
     
     Returns a PATH relative to MEDIA_ROOT.
     """
+    print "URL2PATH", repr(value)
     mediaurl_re = re.compile(r'^(%s)' % (MEDIA_URL))
-    value = mediaurl_re.sub('', value)
+    value = mediaurl_re.sub(u'', value)
     return value
 
 
@@ -70,26 +71,26 @@ def _get_version_path(value, version_prefix):
     if os.path.isfile(os.path.join(MEDIA_ROOT, value)):
         path, filename = os.path.split(value)
         filename, ext = os.path.splitext(filename)
-        version_filename = filename + "_" + version_prefix + ext
+        version_filename = filename + u"_" + version_prefix + ext
         return os.path.join(VERSIONS_BASEDIR, path, version_filename)
     else:
         return None
 
 
 def _url_join(*args):
-    if args[0].startswith("http://"):
-        url = "http://"
+    if args[0].startswith(u"http://"):
+        url = u"http://"
     else:
-        url = "/"
+        url = u"/"
     for arg in args:
-        arg = str(arg).replace("\\", "/")
-        arg_split = arg.split("/")
+        arg = unicode(arg).replace(u"\\", u"/")
+        arg_split = arg.split(u"/")
         for elem in arg_split:
-            if elem != "" and elem != "http:":
-                url = url + elem + "/"
+            if elem != u"" and elem != u"http:":
+                url = url + elem + u"/"
     # remove trailing slash for filenames
     if os.path.splitext(args[-1])[1]:
-        url = url.rstrip("/")
+        url = url.rstrip(u"/")
     return url
 
 
@@ -192,14 +193,11 @@ def _get_file_type(filename):
     """
     Get file type as defined in EXTENSIONS.
     """
-
     file_extension = os.path.splitext(filename)[1].lower()
-    file_type = ''
-    for k, v in EXTENSIONS.iteritems():
-        for extension in v:
-            if file_extension == extension.lower():
-                file_type = k
-    return file_type
+    for ftype, ext_list in EXTENSIONS.iteritems():
+        if file_extension in map(str.lower, ext_list):
+            return ftype
+    return u''
 
 
 def _is_selectable(filename, selecttype):
index 6b3b762..f652612 100644 (file)
@@ -1,6 +1,5 @@
 {% load i18n adminmedia fb_tags fb_versions %}
-<tr class="{% cycle 'row1' 'row2' %}">
-    
+<tr class="{% cycle 'row1' 'row2' %}">    
     <!-- FILESELECT FOR FILEBROWSEFIELD -->
     {% ifequal query.pop '1' %}
     {% if results_var.select_total %}
@@ -64,7 +63,7 @@
     
     <!-- FILENAME/DIMENSIONS -->
     {% ifequal file.filetype 'Folder' %}
-    <td><b><a href="{% url fb_browse %}{% query_string "" "dir" %}&amp;dir={{ file.path_relative_directory|urlencode }}">{{ file.filename }}</a></b></td>
+    <td><b><a href="{% url fb_browse %}{% query_string '' 'dir' %}&amp;dir={{ file.path_relative_directory|urlencode }}">{{ file.filename }}</a></b></td>
     {% else %}
     <td><b><a href="{{ file.url_full }}">{{ file.filename }}</a></b>{% if file.dimensions %}<br /><span class="tiny">{{ file.dimensions.0 }} x {{ file.dimensions.1 }} px</span>{% endif %}</td>
     {% endifequal %}
index f1e968d..3733485 100644 (file)
@@ -8,8 +8,8 @@ from filebrowser.fb_settings import SELECT_FORMATS
 
 register = template.Library()
 
-@register.inclusion_tag('filebrowser/include/_response.html', takes_context=True)
-def query_string(context, add=None, remove=None):
+@register.inclusion_tag('filebrowser/include/_response.html', takes_context = True)
+def query_string(context, add = None, remove = None):
     """
     Allows the addition and removal of query string parameters.
     
@@ -25,10 +25,10 @@ def query_string(context, add=None, remove=None):
     remove = string_to_list(remove)
     params = context['query'].copy()
     response = get_query_string(params, add, remove)
-    return {'response': response }
-    
+    return {'response': smart_unicode(response) }
+
 
-def query_helper(query, add=None, remove=None):
+def query_helper(query, add = None, remove = None):
     """
     Helper Function for use within views.
     """
@@ -36,9 +36,9 @@ def query_helper(query, add=None, remove=None):
     remove = string_to_list(remove)
     params = query.copy()
     return get_query_string(params, add, remove)
-    
 
-def get_query_string(p, new_params=None, remove=None):
+
+def get_query_string(p, new_params = None, remove = None):
     """
     Add and remove query parameters. From `django.contrib.admin`.
     """
@@ -54,7 +54,7 @@ def get_query_string(p, new_params=None, remove=None):
         elif v is not None:
             p[k] = v
     return mark_safe('?' + '&'.join([u'%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20'))
-    
+
 
 def string_to_dict(string):
     """
@@ -76,7 +76,7 @@ def string_to_dict(string):
             kw, val = arg.split('=', 1)
             kwargs[kw] = val
     return kwargs
-    
+
 
 def string_to_list(string):
     """
@@ -95,13 +95,13 @@ def string_to_list(string):
             if arg == '': continue
             args.append(arg)
     return args
-    
+
 
 class SelectableNode(template.Node):
     def __init__(self, filetype, format):
         self.filetype = template.Variable(filetype)
         self.format = template.Variable(format)
-    
+
     def render(self, context):
         try:
             filetype = self.filetype.resolve(context)
@@ -119,15 +119,15 @@ class SelectableNode(template.Node):
             selectable = True
         context['selectable'] = selectable
         return ''
-    
+
 
 def selectable(parser, token):
-    
+
     try:
         tag, filetype, format = token.split_contents()
     except:
         raise TemplateSyntaxError, "%s tag requires 2 arguments" % token.contents.split()[0]
-        
+
     return SelectableNode(filetype, format)
-    
+
 register.tag(selectable)
index 887fd9e..cdb0519 100644 (file)
@@ -5,6 +5,7 @@ from time import gmtime
 from django.template import Library, Node, Variable, VariableDoesNotExist, TemplateSyntaxError
 from django.conf import settings
 from django.utils.encoding import force_unicode
+import urllib
 
 # filebrowser imports
 from filebrowser.fb_settings import MEDIA_ROOT, MEDIA_URL, VERSIONS
@@ -21,12 +22,13 @@ class VersionNode(Node):
         else:
             self.version_prefix = None
             self.version_prefix_var = Variable(version_prefix)
-        
+
     def render(self, context):
         try:
             source = self.src.resolve(context)
         except VariableDoesNotExist:
             return None
+
         if self.version_prefix:
             version_prefix = self.version_prefix
         else:
@@ -34,6 +36,7 @@ class VersionNode(Node):
                 version_prefix = self.version_prefix_var.resolve(context)
             except VariableDoesNotExist:
                 return None
+
         try:
             version_path = _get_version_path(_url_to_path(str(source)), version_prefix)
             if not os.path.isfile(os.path.join(MEDIA_ROOT, version_path)):
@@ -41,11 +44,15 @@ class VersionNode(Node):
                 version_path = _version_generator(_url_to_path(str(source)), version_prefix)
             elif os.path.getmtime(os.path.join(MEDIA_ROOT, _url_to_path(str(source)))) > os.path.getmtime(os.path.join(MEDIA_ROOT, version_path)):
                 # recreate version if original image was updated
-                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force=True)
+                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force = True)
             return _path_to_url(version_path)
-        except:
-            return ""
-    
+        except Exception, e:
+            import traceback, sys
+            print "FB VERSION ERROR"
+            traceback.print_exc(file = sys.stdout)
+            return u""
+
+
 
 def version(parser, token):
     """
@@ -57,7 +64,7 @@ def version(parser, token):
     
     version_prefix can be a string or a variable. if version_prefix is a string, use quotes.
     """
-    
+
     try:
         tag, src, version_prefix = token.split_contents()
     except:
@@ -65,7 +72,7 @@ def version(parser, token):
     if (version_prefix[0] == version_prefix[-1] and version_prefix[0] in ('"', "'")) and version_prefix.lower()[1:-1] not in VERSIONS:
         raise TemplateSyntaxError, "%s tag received bad version_prefix %s" % (tag, version_prefix)
     return VersionNode(src, version_prefix)
-    
+
 
 class VersionObjectNode(Node):
     def __init__(self, src, version_prefix, var_name):
@@ -76,7 +83,7 @@ class VersionObjectNode(Node):
         else:
             self.version_prefix = None
             self.version_prefix_var = Variable(version_prefix)
-    
+
     def render(self, context):
         try:
             source = self.src.resolve(context)
@@ -96,12 +103,12 @@ class VersionObjectNode(Node):
                 version_path = _version_generator(_url_to_path(str(source)), version_prefix)
             elif os.path.getmtime(os.path.join(MEDIA_ROOT, _url_to_path(str(source)))) > os.path.getmtime(os.path.join(MEDIA_ROOT, version_path)):
                 # recreate version if original image was updated
-                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force=True)
+                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force = True)
             context[self.var_name] = FileObject(version_path)
         except:
             context[self.var_name] = ""
         return ''
-        
+
 
 def version_object(parser, token):
     """
@@ -115,7 +122,7 @@ def version_object(parser, token):
     
     version_prefix can be a string or a variable. if version_prefix is a string, use quotes.
     """
-    
+
     try:
         #tag, src, version_prefix = token.split_contents()
         tag, arg = token.contents.split(None, 1)
@@ -128,7 +135,7 @@ def version_object(parser, token):
     if (version_prefix[0] == version_prefix[-1] and version_prefix[0] in ('"', "'")) and version_prefix.lower()[1:-1] not in VERSIONS:
         raise TemplateSyntaxError, "%s tag received bad version_prefix %s" % (tag, version_prefix)
     return VersionObjectNode(src, version_prefix, var_name)
-    
+
 
 class VersionSettingNode(Node):
     def __init__(self, version_prefix):
@@ -137,7 +144,7 @@ class VersionSettingNode(Node):
         else:
             self.version_prefix = None
             self.version_prefix_var = Variable(version_prefix)
-    
+
     def render(self, context):
         if self.version_prefix:
             version_prefix = self.version_prefix
@@ -148,13 +155,13 @@ class VersionSettingNode(Node):
                 return None
         context['version_setting'] = VERSIONS[version_prefix]
         return ''
-        
+
 
 def version_setting(parser, token):
     """
     Get Information about a version setting.
     """
-    
+
     try:
         tag, version_prefix = token.split_contents()
     except:
@@ -162,7 +169,7 @@ def version_setting(parser, token):
     if (version_prefix[0] == version_prefix[-1] and version_prefix[0] in ('"', "'")) and version_prefix.lower()[1:-1] not in VERSIONS:
         raise TemplateSyntaxError, "%s tag received bad version_prefix %s" % (tag, version_prefix)
     return VersionSettingNode(version_prefix)
-    
+
 
 register.tag(version)
 register.tag(version_object)
index 3dcba4a..b507a75 100644 (file)
@@ -1,7 +1,7 @@
 # coding: utf-8
 
 # general imports
-import os, re
+import os, re, locale
 from time import gmtime, strftime
 
 # django imports
@@ -17,6 +17,8 @@ from django.core.urlresolvers import reverse
 from django.core.exceptions import ImproperlyConfigured
 from django.dispatch import Signal
 
+from django.utils.encoding import smart_unicode
+
 # filebrowser imports
 from filebrowser.fb_settings import *
 from filebrowser.functions import _url_to_path, _path_to_url, _get_path, _get_file, _get_version_path, _get_breadcrumbs, _get_filterdate, _get_settings_var, _handle_file_upload, _get_file_type, _url_join, _convert_filename
@@ -61,8 +63,9 @@ def browse(request):
 
     dir_list = os.listdir(abs_path)
     files = []
+    print "LISTING FILES: ", dir_list
     for file in dir_list:
-
+        print repr(file)
         # EXCLUDE FILES MATCHING VERSIONS_PREFIX OR ANY OF THE EXCLUDE PATTERNS
         filtered = file.startswith('.')
         for re_prefix in filter_re:
index 414c713..9e4fd8f 100755 (executable)
@@ -159,6 +159,7 @@ log.addHandler(ch)
 # Import localsettings file, which may override settings defined here
 try:
     from localsettings import *
+    INSTALLED_APPS += EXTRA_INSTALLED_APPS
 except ImportError:
     pass
 
index 560ae72..ca2c4e1 100644 (file)
@@ -2,10 +2,10 @@
 
 {% if user.is_authenticated %}
 <span class="user_name">{{ user.username }}</span> | 
-<a href='{% url logout %}?next={{request.get_full_path}}'>{% trans "Log Out" %}</a>
+<a href='{% url logout %}?next={{request.get_full_path|urlencode}}'>{% trans "Log Out" %}</a>
 {% else %}
 {% url login as login_url %}
 {% ifnotequal login_url request.path %}
-    <a href='{{ login_url }}?next={{request.get_full_path}}'>{% trans "Log In" %}</a>
+    <a href='{{ login_url }}?next={{request.get_full_path|urlencode}}'>{% trans "Log In" %}</a>
 {% endifnotequal %}
 {% endif %}
index cfa2300..1abc899 100755 (executable)
@@ -5,30 +5,20 @@ from django.contrib import admin
 from django.conf import settings
 
 admin.autodiscover()
-PATH_SEC = r"(?P<path>[^/]+)"
-PATH_END = PATH_SEC + "/$"
-
-
-
-urlpatterns = patterns('')
 
 if 'cas_consumer' in settings.INSTALLED_APPS:
-    urlpatterns += patterns('',
-        # django-cas-consumer
-        url(r'^accounts/login/$', 'cas_consumer.views.login', name = 'login'),
-        url(r'^accounts/logout/$', 'cas_consumer.views.logout', name = 'logout'),
-    )
+    auth_views = 'cas_consumer.views'
 else:
-    urlpatterns += patterns('',
-        # Django auth
-        url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'redirect_field_name': 'next'}, name = 'login'),
-        url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}, name = 'logout'),
-    )
+    auth_views = 'django.contrib.auth.views'
 
-urlpatterns += patterns('',
+urlpatterns = patterns('',
     url(r'^$', 'wiki.views.document_list'),
     url(r'^gallery/(?P<directory>[^/]+)$', 'wiki.views.document_gallery'),
 
+    # Auth
+    url(r'^accounts/login/$', auth_views + '.login', name = 'login'),
+    url(r'^accounts/logout/$', auth_views + '.logout', name = 'logout'),
+
     # Admin panel
     (r'^admin/filebrowser/', include('filebrowser.urls')),
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
@@ -43,6 +33,4 @@ urlpatterns += patterns('',
         {'document_root': settings.STATIC_ROOT, 'show_indexes': True}),
 
     url(r'^(?P<name>[^/]+)$', 'wiki.views.document_detail'),
-
 )
-