From 4daecd17f0930daecae009a2b6bebef80c4dab3d Mon Sep 17 00:00:00 2001 From: Tim Graham <timograham@gmail.com> Date: Thu, 13 Mar 2014 09:32:44 -0400 Subject: [PATCH 1/9] Added file extension validation to AJAX uploader, fixed #216. --- docs/changelog.rst | 3 ++- .../static/filebrowser/js/fileuploader.js | 4 ++-- filebrowser/templates/filebrowser/upload.html | 1 + filebrowser/templatetags/fb_tags.py | 11 ++++++++++- filebrowser/tests/test_templatetags.py | 16 ++++++++++++++++ 5 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 filebrowser/tests/test_templatetags.py diff --git a/docs/changelog.rst b/docs/changelog.rst index 740d4f5..3f21f94 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -14,6 +14,7 @@ Changelog * Improved tests with convert/normalize (removed special chars from test filename). * Fixed file selection after using search box (CKEditor). * Removed encoding of file URIs with CKEditor. +* Added client-side (JavaScript) file extension validation to the AJAX uploader. 3.5.4 (February 21st, 2014) --------------------------- @@ -108,4 +109,4 @@ Changelog 3.4.0 (15/11/2011) ------------------ -* Final release of 3.4, see :ref:`releasenotes` \ No newline at end of file +* Final release of 3.4, see :ref:`releasenotes` diff --git a/filebrowser/static/filebrowser/js/fileuploader.js b/filebrowser/static/filebrowser/js/fileuploader.js index d813cfb..7afbb68 100644 --- a/filebrowser/static/filebrowser/js/fileuploader.js +++ b/filebrowser/static/filebrowser/js/fileuploader.js @@ -447,7 +447,7 @@ qq.FileUploaderBasic.prototype = { return name; }, _isAllowedExtension: function(fileName){ - var ext = (-1 !== fileName.indexOf('.')) ? fileName.replace(/.*[.]/, '').toLowerCase() : ''; + var ext = (-1 !== fileName.indexOf('.')) ? fileName.substr(fileName.lastIndexOf('.')).toLowerCase() : ''; var allowed = this._options.allowedExtensions; if (!allowed.length){return true;} @@ -1247,4 +1247,4 @@ qq.extend(qq.UploadHandlerXhr.prototype, { this._xhrs[id] = null; } } -}); \ No newline at end of file +}); diff --git a/filebrowser/templates/filebrowser/upload.html b/filebrowser/templates/filebrowser/upload.html index f0e8a99..8998813 100644 --- a/filebrowser/templates/filebrowser/upload.html +++ b/filebrowser/templates/filebrowser/upload.html @@ -58,6 +58,7 @@ 'csrf_xname': 'X-CSRFToken', 'folder': '{{ query.dir|escapejs }}', }, + allowedExtensions: {% get_file_extensions_for_file_type request.GET.type %}, sizeLimit: {{ settings_var.MAX_UPLOAD_SIZE|unlocalize }}, minSizeLimit: 0, debug: false, diff --git a/filebrowser/templatetags/fb_tags.py b/filebrowser/templatetags/fb_tags.py index 524b812..1f3de7b 100644 --- a/filebrowser/templatetags/fb_tags.py +++ b/filebrowser/templatetags/fb_tags.py @@ -5,7 +5,7 @@ from django.utils.http import urlquote # FILEBROWSER IMPORTS -from filebrowser.settings import SELECT_FORMATS +from filebrowser.settings import EXTENSIONS, SELECT_FORMATS register = template.Library() @@ -141,3 +141,12 @@ def selectable(parser, token): return SelectableNode(filetype, format) register.tag(selectable) + + +def get_file_extensions_for_file_type(query_format): + extensions = [] + for format in SELECT_FORMATS.get(query_format, []): + extensions.extend(EXTENSIONS[format]) + return extensions + +register.simple_tag(get_file_extensions_for_file_type) diff --git a/filebrowser/tests/test_templatetags.py b/filebrowser/tests/test_templatetags.py new file mode 100644 index 0000000..533697d --- /dev/null +++ b/filebrowser/tests/test_templatetags.py @@ -0,0 +1,16 @@ +# coding: utf-8 + +# DJANGO IMPORTS +from django.test import TestCase + +# FILEBROWSER IMPORTS +from filebrowser.templatetags.fb_tags import get_file_extensions_for_file_type + + +class TemplateTagsTests(TestCase): + def test_get_file_extensions_for_file_type(self): + self.assertEqual(get_file_extensions_for_file_type(''), []) + self.assertEqual( + get_file_extensions_for_file_type('image'), + ['.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff'] + ) From 39d2607a50e190ce8aa7857cfa03bcf4a90d644e Mon Sep 17 00:00:00 2001 From: Tim Graham <timograham@gmail.com> Date: Thu, 13 Mar 2014 10:01:12 -0400 Subject: [PATCH 2/9] Added experimental support for Python 3.3. --- docs/changelog.rst | 3 ++- filebrowser/base.py | 16 +++++++--------- filebrowser/decorators.py | 2 +- filebrowser/fields.py | 4 ++-- .../management/commands/fb_version_generate.py | 5 +++-- .../management/commands/fb_version_remove.py | 7 ++++--- filebrowser/settings.py | 2 +- filebrowser/sites.py | 17 +++++++++-------- filebrowser/templatetags/fb_tags.py | 4 ++-- filebrowser/templatetags/fb_versions.py | 8 ++++---- filebrowser/tests/test_base.py | 6 +++--- filebrowser/tests/test_commands.py | 4 ++-- filebrowser/tests/test_sites.py | 12 ++++++------ filebrowser/utils.py | 5 ++++- setup.py | 3 +-- 15 files changed, 51 insertions(+), 47 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 3f21f94..49e2940 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -15,6 +15,7 @@ Changelog * Fixed file selection after using search box (CKEditor). * Removed encoding of file URIs with CKEditor. * Added client-side (JavaScript) file extension validation to the AJAX uploader. +* Added experimental Python 3.3 support. 3.5.4 (February 21st, 2014) --------------------------- @@ -88,7 +89,7 @@ Changelog ----------------- * Fixed security bug: added staff_member_required decorator to the upload-function. -* Fixed a XSS vulnerability with fb_tags. +* Fixed a XSS vulnerability with fb_tags. 3.4.1 (7.3.2012) ---------------- diff --git a/filebrowser/base.py b/filebrowser/base.py index e2ed09b..7b92b89 100644 --- a/filebrowser/base.py +++ b/filebrowser/base.py @@ -15,7 +15,7 @@ # FILEBROWSER IMPORTS from filebrowser.settings import EXTENSIONS, VERSIONS, ADMIN_VERSIONS, VERSIONS_BASEDIR, VERSION_QUALITY, PLACEHOLDER, FORCE_PLACEHOLDER, SHOW_PLACEHOLDER, STRICT_PIL, IMAGE_MAXBLOCK from filebrowser.utils import path_strip, scale_and_crop -from django.utils.encoding import smart_str, smart_text +from django.utils.encoding import python_2_unicode_compatible, smart_str # PIL import if STRICT_PIL: @@ -86,7 +86,7 @@ def sort_by_attr(self, seq, attr): # only to provide stable sorting, but mainly to eliminate comparison of objects # (which can be expensive or prohibited) in case of equal attribute values. intermed = sorted(zip(map(getattr, seq, (attr,)*len(seq)), range(len(seq)), seq)) - return map(operator.getitem, intermed, (-1,) * len(intermed)) + return list(map(operator.getitem, intermed, (-1,) * len(intermed))) _is_folder_stored = None @property @@ -165,7 +165,7 @@ def files_walk_total(self): def files_listing_filtered(self): "Returns FileObjects for filtered files in listing" if self.filter_func: - listing = filter(self.filter_func, self.files_listing_total()) + listing = list(filter(self.filter_func, self.files_listing_total())) else: listing = self.files_listing_total() self._results_listing_filtered = len(listing) @@ -174,7 +174,7 @@ def files_listing_filtered(self): def files_walk_filtered(self): "Returns FileObjects for filtered files in walk" if self.filter_func: - listing = filter(self.filter_func, self.files_walk_total()) + listing = list(filter(self.filter_func, self.files_walk_total())) else: listing = self.files_walk_total() self._results_walk_filtered = len(listing) @@ -205,6 +205,7 @@ def results_walk_filtered(self): return len(self.files_walk_filtered()) +@python_2_unicode_compatible class FileObject(): """ The FileObject represents a file (or directory) on the server. @@ -235,9 +236,6 @@ def __init__(self, path, site=None): def __str__(self): return smart_str(self.path) - def __unicode__(self): - return smart_text(self.path) - @property def name(self): return self.path @@ -254,7 +252,7 @@ def __len__(self): def _get_file_type(self): "Get file type as defined in EXTENSIONS." file_type = '' - for k, v in EXTENSIONS.iteritems(): + for k, v in EXTENSIONS.items(): for extension in v: if self.extension.lower() == extension.lower(): file_type = k @@ -482,7 +480,7 @@ def versions(self): "List of versions (not checking if they actually exist)" version_list = [] if self.filetype == "Image" and not self.is_version: - for version in VERSIONS: + for version in sorted(VERSIONS): version_list.append(os.path.join(self.versions_basedir, self.dirname, self.version_name(version))) return version_list diff --git a/filebrowser/decorators.py b/filebrowser/decorators.py index fa28639..5ed1a2c 100644 --- a/filebrowser/decorators.py +++ b/filebrowser/decorators.py @@ -36,7 +36,7 @@ def path_exists(site, function): def decorator(request, *args, **kwargs): if get_path('', site=site) is None: # The storage location does not exist, raise an error to prevent eternal redirecting. - raise ImproperlyConfigured, _("Error finding Upload-Folder (site.storage.location + site.directory). Maybe it does not exist?") + raise ImproperlyConfigured(_("Error finding Upload-Folder (site.storage.location + site.directory). Maybe it does not exist?")) if get_path(request.GET.get('dir', ''), site=site) is None: msg = _('The requested Folder does not exist.') messages.add_message(request, messages.ERROR, msg) diff --git a/filebrowser/fields.py b/filebrowser/fields.py index f920c00..49d86aa 100644 --- a/filebrowser/fields.py +++ b/filebrowser/fields.py @@ -10,6 +10,7 @@ from django import forms from django.forms.widgets import Input from django.template.loader import render_to_string +from django.utils.six import with_metaclass from django.utils.translation import ugettext_lazy as _ # FILEBROWSER IMPORTS @@ -83,9 +84,8 @@ def clean(self, value): return value -class FileBrowseField(CharField): +class FileBrowseField(with_metaclass(models.SubfieldBase, CharField)): description = "FileBrowseField" - __metaclass__ = models.SubfieldBase def __init__(self, *args, **kwargs): self.site = kwargs.pop('filebrowser_site', site) diff --git a/filebrowser/management/commands/fb_version_generate.py b/filebrowser/management/commands/fb_version_generate.py index 264eacb..da15c73 100644 --- a/filebrowser/management/commands/fb_version_generate.py +++ b/filebrowser/management/commands/fb_version_generate.py @@ -7,6 +7,7 @@ # DJANGO IMPORTS from django.core.management.base import BaseCommand, CommandError from django.conf import settings +from django.utils.six.moves import input # FILEBROWSER IMPORTS from filebrowser.settings import EXTENSION_LIST, EXCLUDE, DIRECTORY, VERSIONS, EXTENSIONS @@ -16,7 +17,7 @@ filter_re = [] for exp in EXCLUDE: filter_re.append(re.compile(exp)) -for k, v in VERSIONS.iteritems(): +for k, v in VERSIONS.items(): exp = (r'_%s(%s)') % (k, '|'.join(EXTENSION_LIST)) filter_re.append(re.compile(exp)) @@ -43,7 +44,7 @@ def handle(self, *args, **options): for version in VERSIONS: self.stdout.write(' * %s\n' % version) - version_name = raw_input('(leave blank to generate all versions): ') + version_name = input('(leave blank to generate all versions): ') if version_name == "": selected_version = None diff --git a/filebrowser/management/commands/fb_version_remove.py b/filebrowser/management/commands/fb_version_remove.py index 879509f..2c737f9 100644 --- a/filebrowser/management/commands/fb_version_remove.py +++ b/filebrowser/management/commands/fb_version_remove.py @@ -7,6 +7,7 @@ # DJANGO IMPORTS from django.core.management.base import BaseCommand, CommandError from django.conf import settings +from django.utils.six.moves import input # FILEBROWSER IMPORTS from filebrowser.settings import EXTENSION_LIST, EXCLUDE, DIRECTORY, VERSIONS, EXTENSIONS @@ -36,7 +37,7 @@ def handle(self, *args, **options): while 1: self.stdout.write('\nOlder versions of the FileBrowser used to prefix the filename with the version name.\n') self.stdout.write('Current version of the FileBrowser adds the version name as suffix.\n') - prefix_or_suffix = raw_input('"p" for prefix or "s" for suffix (leave blank for "%s"): ' % default_prefix_or_suffix) + prefix_or_suffix = input('"p" for prefix or "s" for suffix (leave blank for "%s"): ' % default_prefix_or_suffix) if default_prefix_or_suffix and prefix_or_suffix == '': prefix_or_suffix = default_prefix_or_suffix @@ -48,7 +49,7 @@ def handle(self, *args, **options): # get version name while 1: - version_name = raw_input('\nversion name as defined with VERSIONS: ') + version_name = input('\nversion name as defined with VERSIONS: ') if version_name == "": self.stderr.write('Error: You have to enter a version name.\n') @@ -84,7 +85,7 @@ def handle(self, *args, **options): # ask to make sure do_remove = "" self.stdout.write('Are Sure you want to delete these files?\n') - do_remove = raw_input('"y" for Yes or "n" for No (leave blank for "n"): ') + do_remove = input('"y" for Yes or "n" for No (leave blank for "n"): ') # if "yes" we delete. any different case we finish without removing anything if do_remove == "y": diff --git a/filebrowser/settings.py b/filebrowser/settings.py index 640047f..1994d2c 100644 --- a/filebrowser/settings.py +++ b/filebrowser/settings.py @@ -100,7 +100,7 @@ # Traverse directories when searching SEARCH_TRAVERSE = getattr(settings, "FILEBROWSER_SEARCH_TRAVERSE", False) # Default Upload and Version Permissions -DEFAULT_PERMISSIONS = getattr(settings, "FILEBROWSER_DEFAULT_PERMISSIONS", 0755) +DEFAULT_PERMISSIONS = getattr(settings, "FILEBROWSER_DEFAULT_PERMISSIONS", 0o755) # Overwrite existing files on upload OVERWRITE_EXISTING = getattr(settings, "FILEBROWSER_OVERWRITE_EXISTING", True) diff --git a/filebrowser/sites.py b/filebrowser/sites.py index f5ae844..71a3584 100644 --- a/filebrowser/sites.py +++ b/filebrowser/sites.py @@ -67,7 +67,7 @@ def get_site_dict(app_name='filebrowser'): # Get names of all deployed filebrowser sites with a give app_name deployed = get_resolver(get_urlconf()).app_dict[app_name] # Get the deployed subset from the cache - return dict((k, v) for k, v in _sites_cache[app_name].iteritems() if k in deployed) + return dict((k, v) for k, v in _sites_cache[app_name].items() if k in deployed) def register_site(app_name, site_name, site): @@ -165,7 +165,7 @@ def handle_file_upload(path, file, site): try: file_path = os.path.join(path, file.name) uploadedfile = site.storage.save(file_path, file) - except Exception, inst: + except Exception as inst: raise inst return uploadedfile @@ -269,7 +269,7 @@ def actions(self): Get all the enabled actions as a list of (name, func). The list is sorted alphabetically by actions names """ - res = self._actions.items() + res = list(self._actions.items()) res.sort(key=lambda name_func: name_func[0]) return res @@ -283,7 +283,7 @@ def browse(self, request): filter_re = [] for exp in EXCLUDE: filter_re.append(re.compile(exp)) - for k, v in VERSIONS.iteritems(): + for k, v in VERSIONS.items(): exp = (r'_%s(%s)$') % (k, '|'.join(EXTENSION_LIST)) filter_re.append(re.compile(exp, re.IGNORECASE)) @@ -372,7 +372,8 @@ def createdir(self, request): messages.add_message(request, messages.SUCCESS, _('The Folder %s was successfully created.') % form.cleaned_data['name']) redirect_url = reverse("filebrowser:fb_browse", current_app=self.name) + query_helper(query, "ot=desc,o=date", "ot,o,filter_type,filter_date,q,p") return HttpResponseRedirect(redirect_url) - except OSError, (errno, strerror): + except OSError as e: + errno = e.args[0] if errno == 13: form.errors['name'] = forms.util.ErrorList([_('Permission denied.')]) else: @@ -449,7 +450,7 @@ def delete(self, request): fileobject.delete() signals.filebrowser_post_delete.send(sender=request, path=fileobject.path, name=fileobject.filename, site=self) messages.add_message(request, messages.SUCCESS, _('Successfully deleted %s') % fileobject.filename) - except OSError, (errno, strerror): + except OSError: # TODO: define error-message pass redirect_url = reverse("filebrowser:fb_browse", current_app=self.name) + query_helper(query, "", "filename,filetype") @@ -493,7 +494,7 @@ def detail(self, request): else: redirect_url = reverse("filebrowser:fb_browse", current_app=self.name) + query_helper(query, "", "filename") return HttpResponseRedirect(redirect_url) - except OSError, (errno, strerror): + except OSError: form.errors['name'] = forms.util.ErrorList([_('Error.')]) else: form = ChangeForm(initial={"name": fileobject.filename}, path=path, fileobject=fileobject, filebrowser_site=self) @@ -537,7 +538,7 @@ def _upload_file(self, request): if len(request.FILES) > 1: return HttpResponseBadRequest('Invalid request! Multiple files included.') - filedata = request.FILES.values()[0] + filedata = list(request.FILES.values())[0] fb_uploadurl_re = re.compile(r'^.*(%s)' % reverse("filebrowser:fb_upload", current_app=self.name)) folder = fb_uploadurl_re.sub('', folder) diff --git a/filebrowser/templatetags/fb_tags.py b/filebrowser/templatetags/fb_tags.py index 1f3de7b..2259d25 100644 --- a/filebrowser/templatetags/fb_tags.py +++ b/filebrowser/templatetags/fb_tags.py @@ -52,7 +52,7 @@ def get_query_string(p, new_params=None, remove=None): if remove is None: remove = [] for r in remove: - for k in p.keys(): + for k in list(p): #if k.startswith(r): if k == r: del p[k] @@ -136,7 +136,7 @@ def selectable(parser, token): try: tag, filetype, format = token.split_contents() except: - raise TemplateSyntaxError, "%s tag requires 2 arguments" % token.contents.split()[0] + raise TemplateSyntaxError("%s tag requires 2 arguments" % token.contents.split()[0]) return SelectableNode(filetype, format) diff --git a/filebrowser/templatetags/fb_versions.py b/filebrowser/templatetags/fb_versions.py index 78c41a0..624d617 100644 --- a/filebrowser/templatetags/fb_versions.py +++ b/filebrowser/templatetags/fb_versions.py @@ -44,7 +44,7 @@ def render(self, context): try: version = fileobject.version_generate(version_suffix) return version.url - except Exception, e: + except Exception as e: if settings.TEMPLATE_DEBUG: raise e return "" @@ -93,7 +93,7 @@ def render(self, context): try: version = fileobject.version_generate(version_suffix) context[self.var_name] = version - except Exception, e: + except Exception as e: if settings.TEMPLATE_DEBUG: raise e context[self.var_name] = "" @@ -146,9 +146,9 @@ def version_setting(parser, token): try: tag, version_suffix = token.split_contents() except: - raise TemplateSyntaxError, "%s tag requires 1 argument" % token.contents.split()[0] + raise TemplateSyntaxError("%s tag requires 1 argument" % token.contents.split()[0]) if (version_suffix[0] == version_suffix[-1] and version_suffix[0] in ('"', "'")) and version_suffix.lower()[1:-1] not in VERSIONS: - raise TemplateSyntaxError, "%s tag received bad version_suffix %s" % (tag, version_suffix) + raise TemplateSyntaxError("%s tag received bad version_suffix %s" % (tag, version_suffix)) return VersionSettingNode(version_suffix) diff --git a/filebrowser/tests/test_base.py b/filebrowser/tests/test_base.py index 97af575..5c739cc 100644 --- a/filebrowser/tests/test_base.py +++ b/filebrowser/tests/test_base.py @@ -301,7 +301,7 @@ def test_version_attributes_1(self): } filebrowser.base.ADMIN_VERSIONS = ['large'] # expected test results - version_list = ['fb_test_directory/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg', 'fb_test_directory/fb_tmp_dir/fb_tmp_dir_sub/testimage_admin_thumbnail.jpg'] + version_list = ['fb_test_directory/fb_tmp_dir/fb_tmp_dir_sub/testimage_admin_thumbnail.jpg', 'fb_test_directory/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg',] admin_version_list = ['fb_test_directory/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg'] self.assertEqual(self.f_image.is_version, False) @@ -346,7 +346,7 @@ def test_version_attributes_2(self): } filebrowser.base.ADMIN_VERSIONS = ['large'] # expected test results - version_list = ['fb_test_directory/_versions/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg', 'fb_test_directory/_versions/fb_tmp_dir/fb_tmp_dir_sub/testimage_admin_thumbnail.jpg'] + version_list = ['fb_test_directory/_versions/fb_tmp_dir/fb_tmp_dir_sub/testimage_admin_thumbnail.jpg', 'fb_test_directory/_versions/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg'] admin_version_list = ['fb_test_directory/_versions/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg'] self.assertEqual(self.f_image.is_version, False) @@ -392,7 +392,7 @@ def test_version_attributes_3(self): } filebrowser.base.ADMIN_VERSIONS = ['large'] # expected test results - version_list = ['_versionstestdirectory/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg', '_versionstestdirectory/fb_tmp_dir/fb_tmp_dir_sub/testimage_admin_thumbnail.jpg'] + version_list = ['_versionstestdirectory/fb_tmp_dir/fb_tmp_dir_sub/testimage_admin_thumbnail.jpg', '_versionstestdirectory/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg'] admin_version_list = ['_versionstestdirectory/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg'] self.assertEqual(self.f_image.is_version, False) diff --git a/filebrowser/tests/test_commands.py b/filebrowser/tests/test_commands.py index 51d7778..5ecaf12 100644 --- a/filebrowser/tests/test_commands.py +++ b/filebrowser/tests/test_commands.py @@ -6,7 +6,6 @@ import posixpath import shutil import sys -import StringIO # DJANGO IMPORTS from django.conf import settings @@ -15,6 +14,7 @@ from django.utils.encoding import filepath_to_uri from django.template import Context, Template, TemplateSyntaxError from django.core.management import call_command +from django.utils.six import StringIO # FILEBROWSER IMPORTS import filebrowser @@ -100,7 +100,7 @@ def test_fb_version_generate(self): # no versions self.assertEqual(os.path.exists(os.path.join(settings.MEDIA_ROOT, "fb_test_directory/_versions/fb_tmp_dir/fb_tmp_dir_sub/testimage_large.jpg")), False) - sys.stdin = StringIO.StringIO("large") + sys.stdin = StringIO("large") call_command('fb_version_generate', 'fb_test_directory') # versions diff --git a/filebrowser/tests/test_sites.py b/filebrowser/tests/test_sites.py index a2172de..b7fb44e 100644 --- a/filebrowser/tests/test_sites.py +++ b/filebrowser/tests/test_sites.py @@ -13,7 +13,6 @@ import os import sys import shutil -from urllib import urlencode from types import MethodType # DJANGO IMPORTS @@ -22,6 +21,7 @@ from django.core.urlresolvers import get_resolver, get_urlconf, resolve, reverse from django.contrib.admin.templatetags.admin_static import static from django.test.utils import override_settings +from django.utils.six.moves.urllib.parse import urlencode # FILEBROWSER IMPORTS import filebrowser.settings @@ -388,7 +388,7 @@ def setUp(self): def tearDown(self): # Delete a left-over tmp directories, if there's any if hasattr(self, 'tmpdir') and self.tmpdir: - print "Removing left-over tmp dir:", self.tmpdir.path + print("Removing left-over tmp dir:", self.tmpdir.path) self.site.storage.rmtree(self.tmpdir.path) @@ -417,13 +417,13 @@ def runTest(self): ## Create a test class for each deployed filebrowser site for site in all_sites: - print 'Creating Test for the FileBrowser site:', site + print('Creating Test for the FileBrowser site:', site) # Create a subclass of TestCase testcase_class = type('TestSite_' + site, (TestCase,), {'site_name': site, 'c': Client(), 'tmpdirs': None}) # Add setUp, tearDown, and runTest methods - setattr(testcase_class, 'setUp', MethodType(setUp, None, testcase_class)) - setattr(testcase_class, 'tearDown', MethodType(tearDown, None, testcase_class)) - setattr(testcase_class, 'runTest', MethodType(runTest, None, testcase_class)) + setattr(testcase_class, 'setUp', setUp) + setattr(testcase_class, 'tearDown', tearDown) + setattr(testcase_class, 'runTest', runTest) # Add the test case class to this module setattr(this_module, 'TestSite_' + site, testcase_class) diff --git a/filebrowser/utils.py b/filebrowser/utils.py index f1f9008..dd805e9 100644 --- a/filebrowser/utils.py +++ b/filebrowser/utils.py @@ -5,6 +5,9 @@ import os import unicodedata +# DJANGO IMPORTS +from django.utils import six + # FILEBROWSER IMPORTS from filebrowser.settings import STRICT_PIL, NORMALIZE_FILENAME, CONVERT_FILENAME @@ -27,7 +30,7 @@ def convert_filename(value): chunks = value.split(os.extsep) normalized = [] for v in chunks: - v = unicodedata.normalize('NFKD', unicode(v)).encode('ascii', 'ignore') + v = unicodedata.normalize('NFKD', six.text_type(v)).encode('ascii', 'ignore').decode('ascii') v = re.sub(r'[^\w\s-]', '', v).strip() normalized.append(v) diff --git a/setup.py b/setup.py index 3719c3f..ad92c85 100644 --- a/setup.py +++ b/setup.py @@ -28,5 +28,4 @@ def read(fname): install_requires = [ 'django-grappelli>=2.4,<2.5.99', ], - use_2to3=True, -) \ No newline at end of file +) From 8527e881e7e5ffedbcc1e3113593d8d604e70269 Mon Sep 17 00:00:00 2001 From: Patrick Kranzlmueller <sehmaschine@gmail.com> Date: Sat, 29 Mar 2014 11:34:52 +0100 Subject: [PATCH 3/9] better client-side ajax validation, #218 --- docs/admin.rst | 2 +- filebrowser/templates/filebrowser/upload.html | 2 +- filebrowser/templatetags/fb_tags.py | 13 +++++++++---- filebrowser/tests/test_templatetags.py | 12 ++++++++---- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/docs/admin.rst b/docs/admin.rst index 4e4dcde..fa4f804 100644 --- a/docs/admin.rst +++ b/docs/admin.rst @@ -182,7 +182,7 @@ All views use the ``staff_member_requird`` and ``path_exists`` decorator in orde * Upload, ``fb_upload`` Multiple upload. - * Optional query string args: ``dir`` + * Optional query string args: ``dir``, ``type`` * Signals: `filebrowser_pre_upload`, `filebrowser_post_upload` * Edit, ``fb_edit`` diff --git a/filebrowser/templates/filebrowser/upload.html b/filebrowser/templates/filebrowser/upload.html index 8998813..03c0390 100644 --- a/filebrowser/templates/filebrowser/upload.html +++ b/filebrowser/templates/filebrowser/upload.html @@ -58,7 +58,7 @@ 'csrf_xname': 'X-CSRFToken', 'folder': '{{ query.dir|escapejs }}', }, - allowedExtensions: {% get_file_extensions_for_file_type request.GET.type %}, + allowedExtensions: {% get_file_extensions request.GET %}, sizeLimit: {{ settings_var.MAX_UPLOAD_SIZE|unlocalize }}, minSizeLimit: 0, debug: false, diff --git a/filebrowser/templatetags/fb_tags.py b/filebrowser/templatetags/fb_tags.py index 2259d25..47a8757 100644 --- a/filebrowser/templatetags/fb_tags.py +++ b/filebrowser/templatetags/fb_tags.py @@ -143,10 +143,15 @@ def selectable(parser, token): register.tag(selectable) -def get_file_extensions_for_file_type(query_format): +def get_file_extensions(qs): extensions = [] - for format in SELECT_FORMATS.get(query_format, []): - extensions.extend(EXTENSIONS[format]) + if "type" in qs and qs.get("type") in SELECT_FORMATS: + for format in SELECT_FORMATS.get(qs.get("type"), []): + extensions.extend(EXTENSIONS[format]) + else: + for k, v in EXTENSIONS.items(): + for item in v: + if item: extensions.append(item) return extensions -register.simple_tag(get_file_extensions_for_file_type) +register.simple_tag(get_file_extensions) diff --git a/filebrowser/tests/test_templatetags.py b/filebrowser/tests/test_templatetags.py index 533697d..0db4a84 100644 --- a/filebrowser/tests/test_templatetags.py +++ b/filebrowser/tests/test_templatetags.py @@ -2,15 +2,19 @@ # DJANGO IMPORTS from django.test import TestCase +from django.http import QueryDict # FILEBROWSER IMPORTS -from filebrowser.templatetags.fb_tags import get_file_extensions_for_file_type +from filebrowser.templatetags.fb_tags import get_file_extensions class TemplateTagsTests(TestCase): - def test_get_file_extensions_for_file_type(self): - self.assertEqual(get_file_extensions_for_file_type(''), []) + def test_get_file_extensions(self): + self.assertEqual(get_file_extensions(''), + ['.pdf', '.doc', '.rtf', '.txt', '.xls', '.csv', '.docx', '.mov', \ + '.wmv', '.mpeg', '.mpg', '.avi', '.rm', '.jpg', '.jpeg', '.gif', '.png', \ + '.tif', '.tiff', '.mp3', '.mp4', '.wav', '.aiff', '.midi', '.m4p']) self.assertEqual( - get_file_extensions_for_file_type('image'), + get_file_extensions(QueryDict('type=image')), ['.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff'] ) From c5b4162038d792f0de8833f7c0e0b20d69954f71 Mon Sep 17 00:00:00 2001 From: Patrick Kranzlmueller <sehmaschine@gmail.com> Date: Sat, 29 Mar 2014 14:31:10 +0100 Subject: [PATCH 4/9] finally fixed convert/normalize tests, #213 #209 --- docs/changelog.rst | 10 +-- ...{TEST IMAGE ***.jpg => TEST IMAGE 000.jpg} | Bin filebrowser/tests/test_sites.py | 78 ++++++++++-------- 3 files changed, 48 insertions(+), 40 deletions(-) rename filebrowser/static/filebrowser/img/{TEST IMAGE ***.jpg => TEST IMAGE 000.jpg} (100%) diff --git a/docs/changelog.rst b/docs/changelog.rst index 49e2940..b424904 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -11,11 +11,11 @@ Changelog 3.5.5 (not yet released) ------------------------ -* Improved tests with convert/normalize (removed special chars from test filename). -* Fixed file selection after using search box (CKEditor). -* Removed encoding of file URIs with CKEditor. -* Added client-side (JavaScript) file extension validation to the AJAX uploader. -* Added experimental Python 3.3 support. +* New: Added client-side (JavaScript) file extension validation to the AJAX uploader. +* New: Added experimental Python 3.3 support. +* Improved: Tests with convert/normalize (removed special chars from test filename). +* Fixed: File selection after using search box (CKEditor). +* Fixed: Removed encoding of file URIs with CKEditor. 3.5.4 (February 21st, 2014) --------------------------- diff --git a/filebrowser/static/filebrowser/img/TEST IMAGE ***.jpg b/filebrowser/static/filebrowser/img/TEST IMAGE 000.jpg similarity index 100% rename from filebrowser/static/filebrowser/img/TEST IMAGE ***.jpg rename to filebrowser/static/filebrowser/img/TEST IMAGE 000.jpg diff --git a/filebrowser/tests/test_sites.py b/filebrowser/tests/test_sites.py index b7fb44e..6d9a91a 100644 --- a/filebrowser/tests/test_sites.py +++ b/filebrowser/tests/test_sites.py @@ -185,8 +185,8 @@ def test_convert_normalize(test): """ url = reverse('%s:fb_do_upload' % test.site_name) - url = '?'.join([url, urlencode({'folder': test.tmpdir.path_relative_directory, 'qqfile': 'TEST IMAGE ***.jpg'})]) - f = open(os.path.join(FILEBROWSER_PATH, u'static/filebrowser/img/TEST IMAGE ***.jpg'), "rb") + url = '?'.join([url, urlencode({'folder': test.tmpdir.path_relative_directory, 'qqfile': 'TEST IMAGE 000.jpg'})]) + f = open(os.path.join(FILEBROWSER_PATH, u'static/filebrowser/img/TEST IMAGE 000.jpg'), "rb") # Save settings oe = filebrowser.sites.OVERWRITE_EXISTING @@ -198,84 +198,92 @@ def test_convert_normalize(test): filebrowser.sites.NORMALIZE_FILENAME = False filebrowser.utils.CONVERT_FILENAME = False filebrowser.utils.NORMALIZE_FILENAME = False - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'TEST IMAGE ***.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'TEST IMAGE 000.jpg') test.assertTrue(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'testimage.jpg', u'testimage_1.jpg']) # OVERWRITE true filebrowser.sites.OVERWRITE_EXISTING = True - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'TEST IMAGE ***.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'TEST IMAGE 000.jpg') test.assertTrue(test.site.storage.exists(path)) - path = os.path.join(test.tmpdir.path, 'TEST IMAGE ***_1.jpg') + path = os.path.join(test.tmpdir.path, 'TEST IMAGE 000_1.jpg') test.assertFalse(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'testimage.jpg', u'testimage_1.jpg']) # OVERWRITE false filebrowser.sites.OVERWRITE_EXISTING = False - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'TEST IMAGE ***.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'TEST IMAGE 000.jpg') test.assertTrue(test.site.storage.exists(path)) - path = os.path.join(test.tmpdir.path, 'TEST IMAGE ***_1.jpg') + path = os.path.join(test.tmpdir.path, 'TEST IMAGE 000_1.jpg') test.assertTrue(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'TEST IMAGE ***_1.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'TEST IMAGE 000_1.jpg', u'testimage.jpg', u'testimage_1.jpg']) # Set CONVERT_FILENAME, NORMALIZE_FILENAME filebrowser.sites.CONVERT_FILENAME = True filebrowser.sites.NORMALIZE_FILENAME = False filebrowser.utils.CONVERT_FILENAME = True filebrowser.utils.NORMALIZE_FILENAME = False - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'test_image_***.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'test_image_000.jpg') test.assertTrue(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'TEST IMAGE ***_1.jpg', u'test_image_***.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'TEST IMAGE 000_1.jpg', u'test_image_000.jpg', u'testimage.jpg', u'testimage_1.jpg']) # OVERWRITE true filebrowser.sites.OVERWRITE_EXISTING = True - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'test_image_***.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'test_image_000.jpg') test.assertTrue(test.site.storage.exists(path)) - path = os.path.join(test.tmpdir.path, 'test_image_***_1.jpg') + path = os.path.join(test.tmpdir.path, 'test_image_000_1.jpg') test.assertFalse(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'TEST IMAGE ***_1.jpg', u'test_image_***.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'TEST IMAGE 000_1.jpg', u'test_image_000.jpg', u'testimage.jpg', u'testimage_1.jpg']) # OVERWRITE false filebrowser.sites.OVERWRITE_EXISTING = False - response = test.c.post(url, data={'qqfile': 'TTEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'test_image_***.jpg') + response = test.c.post(url, data={'qqfile': 'TTEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'test_image_000.jpg') test.assertTrue(test.site.storage.exists(path)) - path = os.path.join(test.tmpdir.path, 'test_image_***_1.jpg') + path = os.path.join(test.tmpdir.path, 'test_image_000_1.jpg') test.assertTrue(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'TEST IMAGE ***_1.jpg', u'test_image_***.jpg', u'test_image_***_1.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'TEST IMAGE 000_1.jpg', u'test_image_000.jpg', u'test_image_000_1.jpg', u'testimage.jpg', u'testimage_1.jpg']) # Set CONVERT_FILENAME, NORMALIZE_FILENAME filebrowser.sites.CONVERT_FILENAME = True filebrowser.sites.NORMALIZE_FILENAME = True filebrowser.utils.CONVERT_FILENAME = True filebrowser.utils.NORMALIZE_FILENAME = True - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'test_image.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'test_image_000.jpg') test.assertTrue(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'TEST IMAGE ***_1.jpg', u'test_image.jpg', u'test_image_***.jpg', u'test_image_***_1.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'TEST IMAGE 000_1.jpg', u'test_image_000.jpg', u'test_image_000_1.jpg', u'test_image_000_2.jpg', u'testimage.jpg', u'testimage_1.jpg']) # OVERWRITE true filebrowser.sites.OVERWRITE_EXISTING = True - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'test_image.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'test_image_000.jpg') test.assertTrue(test.site.storage.exists(path)) - path = os.path.join(test.tmpdir.path, 'test_image_1.jpg') + path = os.path.join(test.tmpdir.path, 'test_image_000_1.jpg') + test.assertTrue(test.site.storage.exists(path)) + path = os.path.join(test.tmpdir.path, 'test_image_000_2.jpg') + test.assertTrue(test.site.storage.exists(path)) + path = os.path.join(test.tmpdir.path, 'test_image_000_3.jpg') test.assertFalse(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'TEST IMAGE ***_1.jpg', u'test_image.jpg', u'test_image_***.jpg', u'test_image_***_1.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'TEST IMAGE 000_1.jpg', u'test_image_000.jpg', u'test_image_000_1.jpg', u'test_image_000_2.jpg', u'testimage.jpg', u'testimage_1.jpg']) # OVERWRITE false filebrowser.sites.OVERWRITE_EXISTING = False - response = test.c.post(url, data={'qqfile': 'TEST IMAGE ***.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - path = os.path.join(test.tmpdir.path, 'test_image.jpg') + response = test.c.post(url, data={'qqfile': 'TEST IMAGE 000.jpg', 'file': f}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + path = os.path.join(test.tmpdir.path, 'test_image_000.jpg') + test.assertTrue(test.site.storage.exists(path)) + path = os.path.join(test.tmpdir.path, 'test_image_000_1.jpg') + test.assertTrue(test.site.storage.exists(path)) + path = os.path.join(test.tmpdir.path, 'test_image_000_2.jpg') test.assertTrue(test.site.storage.exists(path)) - path = os.path.join(test.tmpdir.path, 'test_image_1.jpg') + path = os.path.join(test.tmpdir.path, 'test_image_000_3.jpg') test.assertTrue(test.site.storage.exists(path)) - test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE ***.jpg', u'TEST IMAGE ***_1.jpg', u'test_image.jpg', u'test_image_***.jpg', u'test_image_***_1.jpg', u'test_image_1.jpg', u'testimage.jpg', u'testimage_1.jpg']) + test.assertEqual(sorted(test.site.storage.listdir(test.tmpdir)[1]), [u'TEST IMAGE 000.jpg', u'TEST IMAGE 000_1.jpg', u'test_image_000.jpg', u'test_image_000_1.jpg', u'test_image_000_2.jpg', u'test_image_000_3.jpg', u'testimage.jpg', u'testimage_1.jpg']) # Reset settings filebrowser.sites.CONVERT_FILENAME = cf From 24ccf66bc84919b0afd6270590a7ef20528f860d Mon Sep 17 00:00:00 2001 From: Tim Graham <timograham@gmail.com> Date: Thu, 3 Apr 2014 12:36:24 -0400 Subject: [PATCH 5/9] Fixed test_get_file_extensions() on Python 3. (removed dependency on dictionary iteration order) --- filebrowser/tests/test_templatetags.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/filebrowser/tests/test_templatetags.py b/filebrowser/tests/test_templatetags.py index 0db4a84..2dfb70c 100644 --- a/filebrowser/tests/test_templatetags.py +++ b/filebrowser/tests/test_templatetags.py @@ -10,10 +10,10 @@ class TemplateTagsTests(TestCase): def test_get_file_extensions(self): - self.assertEqual(get_file_extensions(''), - ['.pdf', '.doc', '.rtf', '.txt', '.xls', '.csv', '.docx', '.mov', \ - '.wmv', '.mpeg', '.mpg', '.avi', '.rm', '.jpg', '.jpeg', '.gif', '.png', \ - '.tif', '.tiff', '.mp3', '.mp4', '.wav', '.aiff', '.midi', '.m4p']) + self.assertEqual(sorted(get_file_extensions('')), + sorted(['.pdf', '.doc', '.rtf', '.txt', '.xls', '.csv', '.docx', '.mov', + '.wmv', '.mpeg', '.mpg', '.avi', '.rm', '.jpg', '.jpeg', '.gif', '.png', + '.tif', '.tiff', '.mp3', '.mp4', '.wav', '.aiff', '.midi', '.m4p'])) self.assertEqual( get_file_extensions(QueryDict('type=image')), ['.jpg', '.jpeg', '.gif', '.png', '.tif', '.tiff'] From 8faf0a99d86b3870bd2f279d678b0c4cea8defab Mon Sep 17 00:00:00 2001 From: Jason Liu <jxnl@users.noreply.github.com> Date: Sun, 13 Apr 2014 00:43:12 -0700 Subject: [PATCH 6/9] Corrected Typos Fixed a spelling error and removed a double `import` --- docs/admin.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/admin.rst b/docs/admin.rst index fa4f804..cb02258 100644 --- a/docs/admin.rst +++ b/docs/admin.rst @@ -22,7 +22,7 @@ FileBrowser Site .. py:class:: FileBrowserSite(name=None, app_name='filebrowser', storage=default_storage) - Respresens the FileBrowser admin application (similar to Django's admin site). + Respresents the FileBrowser admin application (similar to Django's admin site). :param name: A name for the site, defaults to None. :param app_name: Defaults to 'filebrowser'. @@ -41,7 +41,7 @@ Now you are able to browse the location defined with the storage engine associat .. code-block:: python from django.core.files.storage import DefaultStorage - from filebrowser.sites import import FileBrowserSite + from filebrowser.sites import FileBrowserSite # Default FileBrowser site site = FileBrowserSite(name='filebrowser', storage=DefaultStorage()) @@ -285,4 +285,4 @@ Here's a small example for using the above Signals:: print "Filesize:", kwargs['file'].filesize print "Orientation:", kwargs['file'].orientation print "Extension:", kwargs['file'].extension - signals.filebrowser_post_upload.connect(post_upload_callback) \ No newline at end of file + signals.filebrowser_post_upload.connect(post_upload_callback) From 943024195798edcaf696230a67c1e4731bfe78f8 Mon Sep 17 00:00:00 2001 From: Patrick Kranzlmueller <sehmaschine@gmail.com> Date: Sun, 13 Apr 2014 13:10:26 +0200 Subject: [PATCH 7/9] compatibility with tests and older django versions (1.4.) --- filebrowser/tests/test_sites.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/filebrowser/tests/test_sites.py b/filebrowser/tests/test_sites.py index 6d9a91a..9611c1b 100644 --- a/filebrowser/tests/test_sites.py +++ b/filebrowser/tests/test_sites.py @@ -21,7 +21,10 @@ from django.core.urlresolvers import get_resolver, get_urlconf, resolve, reverse from django.contrib.admin.templatetags.admin_static import static from django.test.utils import override_settings -from django.utils.six.moves.urllib.parse import urlencode +try: + from django.utils.six.moves.urllib.parse import urlencode +except: + from django.utils.http import urlencode # FILEBROWSER IMPORTS import filebrowser.settings From 04920154abb1ab15176ee47a98c67094344f5fba Mon Sep 17 00:00:00 2001 From: Patrick Kranzlmueller <sehmaschine@gmail.com> Date: Sun, 13 Apr 2014 13:14:52 +0200 Subject: [PATCH 8/9] final docs update for 3.5.5 --- docs/changelog.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index b424904..a5d6a46 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,7 +8,10 @@ Changelog ========= -3.5.5 (not yet released) +3.5.6 (not yet released) +------------------------ + +3.5.5 (April 13th, 2014) ------------------------ * New: Added client-side (JavaScript) file extension validation to the AJAX uploader. From 5147880804ec161c37516739d7dc0af433abd4a8 Mon Sep 17 00:00:00 2001 From: Patrick Kranzlmueller <sehmaschine@gmail.com> Date: Sun, 13 Apr 2014 13:18:57 +0200 Subject: [PATCH 9/9] final version update (3.5.5) --- README.rst | 4 ++-- docs/index.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index e5b1a42..3656afa 100644 --- a/README.rst +++ b/README.rst @@ -31,7 +31,7 @@ https://www.transifex.com/projects/p/django-filebrowser/ Releases -------- -* FileBrowser 3.5.5 (Development Version, not yet released, see Branch Stable/3.5.x) -* FileBrowser 3.5.4 (February 21st, 2014): Compatible with Django 1.4/1.5/1.6 +* FileBrowser 3.5.6 (Development Version, not yet released, see Branch Stable/3.5.x) +* FileBrowser 3.5.5 (April 13th, 2014): Compatible with Django 1.4/1.5/1.6 Older versions are availabe at GitHub, but are not supported anymore. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 57c9d14..81e1b91 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -90,7 +90,7 @@ Use the `FileBrowser Google Group <http://groups.google.com/group/django-filebro Versions and Compatibility -------------------------- -* FileBrowser 3.5.5 (Development Version, not yet released, see Branch Stable/3.5.x) -* FileBrowser 3.5.4 (February 21st, 2014): Compatible with Django 1.4/1.5/1.6 +* FileBrowser 3.5.6 (Development Version, not yet released, see Branch Stable/3.5.x) +* FileBrowser 3.5.5 (April 13th, 2014): Compatible with Django 1.4/1.5/1.6 Older versions are availabe at GitHub, but are not supported anymore. \ No newline at end of file