diff options
Diffstat (limited to 'lib/filebrowser/views.py')
-rw-r--r-- | lib/filebrowser/views.py | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/lib/filebrowser/views.py b/lib/filebrowser/views.py new file mode 100644 index 0000000..eece2b2 --- /dev/null +++ b/lib/filebrowser/views.py @@ -0,0 +1,494 @@ +# coding: utf-8 + +# general imports +import itertools, os, re +from time import gmtime, strftime + +# django imports +from django.shortcuts import render_to_response, HttpResponse +from django.template import RequestContext as Context +from django.http import HttpResponseRedirect +from django.contrib.admin.views.decorators import staff_member_required +from django.views.decorators.cache import never_cache +from django.utils.translation import ugettext as _ +from django.conf import settings +from django import forms +from django.core.urlresolvers import reverse +from django.core.exceptions import ImproperlyConfigured +from django.dispatch import Signal +from django.core.paginator import Paginator, InvalidPage, EmptyPage +from django.utils.encoding import smart_str + +try: + # django SVN + from django.views.decorators.csrf import csrf_exempt +except: + # django 1.1 + from django.contrib.csrf.middleware import csrf_exempt + +# filebrowser imports +from filebrowser.settings import * +from filebrowser.functions import path_to_url, sort_by_attr, get_path, get_file, get_version_path, get_breadcrumbs, get_filterdate, get_settings_var, handle_file_upload, convert_filename +from filebrowser.templatetags.fb_tags import query_helper +from filebrowser.base import FileObject +from filebrowser.decorators import flash_login_required + +# Precompile regular expressions +filter_re = [] +for exp in EXCLUDE: + filter_re.append(re.compile(exp)) +for k,v in VERSIONS.iteritems(): + exp = (r'_%s.(%s)') % (k, '|'.join(EXTENSION_LIST)) + filter_re.append(re.compile(exp)) + + +def browse(request): + """ + Browse Files/Directories. + """ + + # QUERY / PATH CHECK + query = request.GET.copy() + path = get_path(query.get('dir', '')) + directory = get_path('') + q = request.GET.get('q') + + if path is None: + msg = _('The requested Folder does not exist.') + request.user.message_set.create(message=msg) + if directory is None: + # The DIRECTORY does not exist, raise an error to prevent eternal redirecting. + raise ImproperlyConfigured, _("Error finding Upload-Folder (MEDIA_ROOT + FILEBROWSER_DIRECTORY). Maybe it does not exist?") + redirect_url = reverse("fb_browse") + query_helper(query, "", "dir") + return HttpResponseRedirect(redirect_url) + abs_path = u'%s' % os.path.join(MEDIA_ROOT, DIRECTORY, path) + + # INITIAL VARIABLES + results_var = {'results_total': 0, 'results_current': 0, 'delete_total': 0, 'images_total': 0, 'select_total': 0 } + counter = {} + for k,v in EXTENSIONS.iteritems(): + counter[k] = 0 + + if q: + m_root = os.path.normpath(MEDIA_ROOT) + dirs = [] + for root, _subdirs, filenames in os.walk(abs_path): + dirs_2 = [] + items = _subdirs + filenames + for f in items: + dirs_2.append((os.path.normpath(root)[len(m_root)+1:], f)) + # append result of every iteration to dirs + dirs.append(dirs_2) + dir_list = itertools.chain(*dirs) + else: + root = os.path.join(DIRECTORY, path) + dir_list = ((root, f) for f in os.listdir(abs_path)) + + files = [] + for file_dir, file in dir_list: + # EXCLUDE FILES MATCHING VERSIONS_PREFIX OR ANY OF THE EXCLUDE PATTERNS + filtered = file.startswith('.') + for re_prefix in filter_re: + if re_prefix.search(file): + filtered = True + if filtered: + continue + results_var['results_total'] += 1 + + # CREATE FILEOBJECT + fileobject = FileObject(os.path.join(file_dir, file)) + + # FILTER / SEARCH + append = False + if fileobject.filetype == request.GET.get('filter_type', fileobject.filetype) and get_filterdate(request.GET.get('filter_date', ''), fileobject.date or 0): + append = True + if q and not re.compile(q.lower(), re.M).search(file.lower()): + append = False + + # APPEND FILE_LIST + if append: + try: + # COUNTER/RESULTS + if fileobject.filetype == 'Image': + results_var['images_total'] += 1 + if fileobject.filetype != 'Folder': + results_var['delete_total'] += 1 + elif fileobject.filetype == 'Folder' and fileobject.is_empty: + results_var['delete_total'] += 1 + if query.get('type') and query.get('type') in SELECT_FORMATS and fileobject.filetype in SELECT_FORMATS[query.get('type')]: + results_var['select_total'] += 1 + elif not query.get('type'): + results_var['select_total'] += 1 + except OSError: + # Ignore items that have problems + continue + else: + files.append(fileobject) + results_var['results_current'] += 1 + + # COUNTER/RESULTS + if fileobject.filetype: + counter[fileobject.filetype] += 1 + + # SORTING + query['o'] = request.GET.get('o', DEFAULT_SORTING_BY) + query['ot'] = request.GET.get('ot', DEFAULT_SORTING_ORDER) + files = sort_by_attr(files, request.GET.get('o', DEFAULT_SORTING_BY)) + if not request.GET.get('ot') and DEFAULT_SORTING_ORDER == "desc" or request.GET.get('ot') == "desc": + files.reverse() + + p = Paginator(files, LIST_PER_PAGE) + try: + page_nr = request.GET.get('p', '1') + except: + page_nr = 1 + try: + page = p.page(page_nr) + except (EmptyPage, InvalidPage): + page = p.page(p.num_pages) + + return render_to_response('filebrowser/index.html', { + 'dir': path, + 'p': p, + 'q': q, + 'page': page, + 'results_var': results_var, + 'counter': counter, + 'query': query, + 'title': _(u'FileBrowser'), + 'settings_var': get_settings_var(), + 'breadcrumbs': get_breadcrumbs(query, path), + 'breadcrumbs_title': "" + }, context_instance=Context(request)) +browse = staff_member_required(never_cache(browse)) + + +# mkdir signals +filebrowser_pre_createdir = Signal(providing_args=["path", "dirname"]) +filebrowser_post_createdir = Signal(providing_args=["path", "dirname"]) + +def mkdir(request): + """ + Make Directory. + """ + + from filebrowser.forms import MakeDirForm + + # QUERY / PATH CHECK + query = request.GET + path = get_path(query.get('dir', '')) + if path is None: + msg = _('The requested Folder does not exist.') + request.user.message_set.create(message=msg) + return HttpResponseRedirect(reverse("fb_browse")) + abs_path = u'%s' % os.path.join(MEDIA_ROOT, DIRECTORY, path) + + if request.method == 'POST': + form = MakeDirForm(abs_path, request.POST) + if form.is_valid(): + server_path = os.path.join(abs_path, form.cleaned_data['dir_name']) + try: + # PRE CREATE SIGNAL + filebrowser_pre_createdir.send(sender=request, path=path, dirname=form.cleaned_data['dir_name']) + # CREATE FOLDER + os.mkdir(server_path) + os.chmod(server_path, 0775) + # POST CREATE SIGNAL + filebrowser_post_createdir.send(sender=request, path=path, dirname=form.cleaned_data['dir_name']) + # MESSAGE & REDIRECT + msg = _('The Folder %s was successfully created.') % (form.cleaned_data['dir_name']) + request.user.message_set.create(message=msg) + # on redirect, sort by date desc to see the new directory on top of the list + # remove filter in order to actually _see_ the new folder + # remove pagination + redirect_url = reverse("fb_browse") + query_helper(query, "ot=desc,o=date", "ot,o,filter_type,filter_date,q,p") + return HttpResponseRedirect(redirect_url) + except OSError, (errno, strerror): + if errno == 13: + form.errors['dir_name'] = forms.util.ErrorList([_('Permission denied.')]) + else: + form.errors['dir_name'] = forms.util.ErrorList([_('Error creating folder.')]) + else: + form = MakeDirForm(abs_path) + + return render_to_response('filebrowser/makedir.html', { + 'form': form, + 'query': query, + 'title': _(u'New Folder'), + 'settings_var': get_settings_var(), + 'breadcrumbs': get_breadcrumbs(query, path), + 'breadcrumbs_title': _(u'New Folder') + }, context_instance=Context(request)) +mkdir = staff_member_required(never_cache(mkdir)) + + +def upload(request): + """ + Multipe File Upload. + """ + + from django.http import parse_cookie + + # QUERY / PATH CHECK + query = request.GET + path = get_path(query.get('dir', '')) + if path is None: + msg = _('The requested Folder does not exist.') + request.user.message_set.create(message=msg) + return HttpResponseRedirect(reverse("fb_browse")) + abs_path = u'%s' % os.path.join(MEDIA_ROOT, DIRECTORY, path) + + # SESSION (used for flash-uploading) + cookie_dict = parse_cookie(request.META.get('HTTP_COOKIE', '')) + engine = __import__(settings.SESSION_ENGINE, {}, {}, ['']) + session_key = cookie_dict.get(settings.SESSION_COOKIE_NAME, None) + + return render_to_response('filebrowser/upload.html', { + 'query': query, + 'title': _(u'Select files to upload'), + 'settings_var': get_settings_var(), + 'session_key': session_key, + 'breadcrumbs': get_breadcrumbs(query, path), + 'breadcrumbs_title': _(u'Upload') + }, context_instance=Context(request)) +upload = staff_member_required(never_cache(upload)) + + +@csrf_exempt +def _check_file(request): + """ + Check if file already exists on the server. + """ + + from django.utils import simplejson + + folder = request.POST.get('folder') + fb_uploadurl_re = re.compile(r'^.*(%s)' % reverse("fb_upload")) + folder = fb_uploadurl_re.sub('', folder) + + fileArray = {} + if request.method == 'POST': + for k,v in request.POST.items(): + if k != "folder": + v = convert_filename(v) + if os.path.isfile(smart_str(os.path.join(MEDIA_ROOT, DIRECTORY, folder, v))): + fileArray[k] = v + + return HttpResponse(simplejson.dumps(fileArray)) + + +# upload signals +filebrowser_pre_upload = Signal(providing_args=["path", "file"]) +filebrowser_post_upload = Signal(providing_args=["path", "file"]) + +@csrf_exempt +@flash_login_required +def _upload_file(request): + """ + Upload file to the server. + """ + + from django.core.files.move import file_move_safe + + if request.method == 'POST': + folder = request.POST.get('folder') + fb_uploadurl_re = re.compile(r'^.*(%s)' % reverse("fb_upload")) + folder = fb_uploadurl_re.sub('', folder) + abs_path = os.path.join(MEDIA_ROOT, DIRECTORY, folder) + if request.FILES: + filedata = request.FILES['Filedata'] + filedata.name = convert_filename(filedata.name) + # PRE UPLOAD SIGNAL + filebrowser_pre_upload.send(sender=request, path=request.POST.get('folder'), file=filedata) + # HANDLE UPLOAD + uploadedfile = handle_file_upload(abs_path, filedata) + # MOVE UPLOADED FILE + # if file already exists + if os.path.isfile(smart_str(os.path.join(MEDIA_ROOT, DIRECTORY, folder, filedata.name))): + old_file = smart_str(os.path.join(abs_path, filedata.name)) + new_file = smart_str(os.path.join(abs_path, uploadedfile)) + file_move_safe(new_file, old_file, allow_overwrite=True) + # POST UPLOAD SIGNAL + filebrowser_post_upload.send(sender=request, path=request.POST.get('folder'), file=FileObject(smart_str(os.path.join(DIRECTORY, folder, filedata.name)))) + return HttpResponse('True') +#_upload_file = flash_login_required(_upload_file) + + +# delete signals +filebrowser_pre_delete = Signal(providing_args=["path", "filename"]) +filebrowser_post_delete = Signal(providing_args=["path", "filename"]) + +def delete(request): + """ + Delete existing File/Directory. + + When trying to delete a Directory, the Directory has to be empty. + """ + + # QUERY / PATH CHECK + query = request.GET + path = get_path(query.get('dir', '')) + filename = get_file(query.get('dir', ''), query.get('filename', '')) + if path is None or filename is None: + if path is None: + msg = _('The requested Folder does not exist.') + else: + msg = _('The requested File does not exist.') + request.user.message_set.create(message=msg) + return HttpResponseRedirect(reverse("fb_browse")) + abs_path = u'%s' % os.path.join(MEDIA_ROOT, DIRECTORY, path) + + msg = "" + if request.GET: + if request.GET.get('filetype') != "Folder": + relative_server_path = os.path.join(DIRECTORY, path, filename) + try: + # PRE DELETE SIGNAL + filebrowser_pre_delete.send(sender=request, path=path, filename=filename) + # DELETE IMAGE VERSIONS/THUMBNAILS + for version in VERSIONS: + try: + os.unlink(os.path.join(MEDIA_ROOT, get_version_path(relative_server_path, version))) + except: + pass + # DELETE FILE + os.unlink(smart_str(os.path.join(abs_path, filename))) + # POST DELETE SIGNAL + filebrowser_post_delete.send(sender=request, path=path, filename=filename) + # MESSAGE & REDIRECT + msg = _('The file %s was successfully deleted.') % (filename.lower()) + request.user.message_set.create(message=msg) + redirect_url = reverse("fb_browse") + query_helper(query, "", "filename,filetype") + return HttpResponseRedirect(redirect_url) + except OSError: + # todo: define error message + msg = OSError + else: + try: + # PRE DELETE SIGNAL + filebrowser_pre_delete.send(sender=request, path=path, filename=filename) + # DELETE FOLDER + os.rmdir(os.path.join(abs_path, filename)) + # POST DELETE SIGNAL + filebrowser_post_delete.send(sender=request, path=path, filename=filename) + # MESSAGE & REDIRECT + msg = _('The folder %s was successfully deleted.') % (filename.lower()) + request.user.message_set.create(message=msg) + redirect_url = reverse("fb_browse") + query_helper(query, "", "filename,filetype") + return HttpResponseRedirect(redirect_url) + except OSError: + # todo: define error message + msg = OSError + + if msg: + request.user.message_set.create(message=msg) + + return render_to_response('filebrowser/index.html', { + 'dir': dir_name, + 'file': request.GET.get('filename', ''), + 'query': query, + 'settings_var': get_settings_var(), + 'breadcrumbs': get_breadcrumbs(query, dir_name), + 'breadcrumbs_title': "" + }, context_instance=Context(request)) +delete = staff_member_required(never_cache(delete)) + + +# rename signals +filebrowser_pre_rename = Signal(providing_args=["path", "filename", "new_filename"]) +filebrowser_post_rename = Signal(providing_args=["path", "filename", "new_filename"]) + +def rename(request): + """ + Rename existing File/Directory. + + Includes renaming existing Image Versions/Thumbnails. + """ + + from filebrowser.forms import RenameForm + + # QUERY / PATH CHECK + query = request.GET + path = get_path(query.get('dir', '')) + filename = get_file(query.get('dir', ''), query.get('filename', '')) + if path is None or filename is None: + if path is None: + msg = _('The requested Folder does not exist.') + else: + msg = _('The requested File does not exist.') + request.user.message_set.create(message=msg) + return HttpResponseRedirect(reverse("fb_browse")) + abs_path = u'%s' % os.path.join(MEDIA_ROOT, DIRECTORY, path) + file_extension = os.path.splitext(filename)[1].lower() + + if request.method == 'POST': + form = RenameForm(abs_path, file_extension, request.POST) + if form.is_valid(): + relative_server_path = os.path.join(DIRECTORY, path, filename) + new_filename = form.cleaned_data['name'] + file_extension + new_relative_server_path = os.path.join(DIRECTORY, path, new_filename) + try: + # PRE RENAME SIGNAL + filebrowser_pre_rename.send(sender=request, path=path, filename=filename, new_filename=new_filename) + # DELETE IMAGE VERSIONS/THUMBNAILS + # regenerating versions/thumbs will be done automatically + for version in VERSIONS: + try: + os.unlink(os.path.join(MEDIA_ROOT, get_version_path(relative_server_path, version))) + except: + pass + # RENAME ORIGINAL + os.rename(os.path.join(MEDIA_ROOT, relative_server_path), os.path.join(MEDIA_ROOT, new_relative_server_path)) + # POST RENAME SIGNAL + filebrowser_post_rename.send(sender=request, path=path, filename=filename, new_filename=new_filename) + # MESSAGE & REDIRECT + msg = _('Renaming was successful.') + request.user.message_set.create(message=msg) + redirect_url = reverse("fb_browse") + query_helper(query, "", "filename") + return HttpResponseRedirect(redirect_url) + except OSError, (errno, strerror): + form.errors['name'] = forms.util.ErrorList([_('Error.')]) + else: + form = RenameForm(abs_path, file_extension) + + return render_to_response('filebrowser/rename.html', { + 'form': form, + 'query': query, + 'file_extension': file_extension, + 'title': _(u'Rename "%s"') % filename, + 'settings_var': get_settings_var(), + 'breadcrumbs': get_breadcrumbs(query, path), + 'breadcrumbs_title': _(u'Rename') + }, context_instance=Context(request)) +rename = staff_member_required(never_cache(rename)) + + +def versions(request): + """ + Show all Versions for an Image according to ADMIN_VERSIONS. + """ + + # QUERY / PATH CHECK + query = request.GET + path = get_path(query.get('dir', '')) + filename = get_file(query.get('dir', ''), query.get('filename', '')) + if path is None or filename is None: + if path is None: + msg = _('The requested Folder does not exist.') + else: + msg = _('The requested File does not exist.') + request.user.message_set.create(message=msg) + return HttpResponseRedirect(reverse("fb_browse")) + abs_path = u'%s' % os.path.join(MEDIA_ROOT, DIRECTORY, path) + + return render_to_response('filebrowser/versions.html', { + 'original': path_to_url(os.path.join(DIRECTORY, path, filename)), + 'query': query, + 'title': _(u'Versions for "%s"') % filename, + 'settings_var': get_settings_var(), + 'breadcrumbs': get_breadcrumbs(query, path), + 'breadcrumbs_title': _(u'Versions for "%s"') % filename + }, context_instance=Context(request)) +versions = staff_member_required(never_cache(versions)) + + |