From 49e1a0fdfaa15ac3cccb84fd993d68a72cc2a0b9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Rekucki?= Date: Wed, 3 Mar 2010 09:15:32 +0100 Subject: [PATCH 1/1] Unicode errors in filebrowser. Refs #372. --- apps/filebrowser/base.py | 72 +++++++++++-------- apps/filebrowser/functions.py | 32 ++++----- .../filebrowser/include/filelisting.html | 5 +- apps/filebrowser/templatetags/fb_tags.py | 30 ++++---- apps/filebrowser/templatetags/fb_versions.py | 39 +++++----- apps/filebrowser/views.py | 7 +- platforma/settings.py | 1 + .../templates/registration/head_login.html | 4 +- platforma/urls.py | 26 ++----- 9 files changed, 111 insertions(+), 105 deletions(-) diff --git a/apps/filebrowser/base.py b/apps/filebrowser/base.py index e72b9ff0..da53d91f 100644 --- a/apps/filebrowser/base.py +++ b/apps/filebrowser/base.py @@ -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 - + diff --git a/apps/filebrowser/functions.py b/apps/filebrowser/functions.py index 5f7f98f8..afcdffd8 100755 --- a/apps/filebrowser/functions.py +++ b/apps/filebrowser/functions.py @@ -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): diff --git a/apps/filebrowser/templates/filebrowser/include/filelisting.html b/apps/filebrowser/templates/filebrowser/include/filelisting.html index 6b3b7622..f652612a 100644 --- a/apps/filebrowser/templates/filebrowser/include/filelisting.html +++ b/apps/filebrowser/templates/filebrowser/include/filelisting.html @@ -1,6 +1,5 @@ {% load i18n adminmedia fb_tags fb_versions %} - - + {% ifequal query.pop '1' %} {% if results_var.select_total %} @@ -64,7 +63,7 @@ {% ifequal file.filetype 'Folder' %} - {{ file.filename }} + {{ file.filename }} {% else %} {{ file.filename }}{% if file.dimensions %}
{{ file.dimensions.0 }} x {{ file.dimensions.1 }} px{% endif %} {% endifequal %} diff --git a/apps/filebrowser/templatetags/fb_tags.py b/apps/filebrowser/templatetags/fb_tags.py index f1e968d0..3733485f 100644 --- a/apps/filebrowser/templatetags/fb_tags.py +++ b/apps/filebrowser/templatetags/fb_tags.py @@ -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) diff --git a/apps/filebrowser/templatetags/fb_versions.py b/apps/filebrowser/templatetags/fb_versions.py index 887fd9ea..cdb05194 100644 --- a/apps/filebrowser/templatetags/fb_versions.py +++ b/apps/filebrowser/templatetags/fb_versions.py @@ -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) diff --git a/apps/filebrowser/views.py b/apps/filebrowser/views.py index 3dcba4a3..b507a75f 100644 --- a/apps/filebrowser/views.py +++ b/apps/filebrowser/views.py @@ -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: diff --git a/platforma/settings.py b/platforma/settings.py index 414c7130..9e4fd8f5 100755 --- a/platforma/settings.py +++ b/platforma/settings.py @@ -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 diff --git a/platforma/templates/registration/head_login.html b/platforma/templates/registration/head_login.html index 560ae728..ca2c4e1f 100644 --- a/platforma/templates/registration/head_login.html +++ b/platforma/templates/registration/head_login.html @@ -2,10 +2,10 @@ {% if user.is_authenticated %} {{ user.username }} | -{% trans "Log Out" %} +{% trans "Log Out" %} {% else %} {% url login as login_url %} {% ifnotequal login_url request.path %} - {% trans "Log In" %} + {% trans "Log In" %} {% endifnotequal %} {% endif %} diff --git a/platforma/urls.py b/platforma/urls.py index cfa23001..1abc8992 100755 --- a/platforma/urls.py +++ b/platforma/urls.py @@ -5,30 +5,20 @@ from django.contrib import admin from django.conf import settings admin.autodiscover() -PATH_SEC = r"(?P[^/]+)" -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[^/]+)$', '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[^/]+)$', 'wiki.views.document_detail'), - ) - -- 2.20.1