X-Git-Url: http://mmka.chem.univ.gda.pl/gitweb/?a=blobdiff_plain;f=filex%2Fviews.py;h=108f7c3435e4d56001b55161490dc70818974b0e;hb=HEAD;hp=f5aabb80d3d4b00ecde10db47132ce51d9e9e4f2;hpb=6d6c248706a2b7a388ab37bc12a38d1b3806ba63;p=qcg-portal.git diff --git a/filex/views.py b/filex/views.py index f5aabb8..108f7c3 100644 --- a/filex/views.py +++ b/filex/views.py @@ -1,13 +1,14 @@ -from itertools import islice +import logging import mimetypes import os from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied from django.http import JsonResponse, StreamingHttpResponse -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, render from django.template.defaultfilters import filesizeformat from django.utils.formats import date_format +from django.utils.http import urlquote from django.views.decorators.http import require_POST from django.views.generic import View @@ -15,12 +16,13 @@ from filex.forms import HostPathNameForm, RenameForm, FavoriteForm, HostPathForm CompressForm from filex.ftp import FTPOperation, FTPError from filex.models import Favorite -from filex.uploadhandler import with_ftp_upload_handler +from filex.utils import with_ftp_upload_handler, parse_ftp_error class FTPView(View): method = 'get' form_class = HostPathForm + request = None @classmethod def as_view(cls, **initkwargs): @@ -35,16 +37,16 @@ class FTPView(View): if not form.is_valid(): return JsonResponse({'error': form.errors}, status=400) + self.request = request try: return self.handle(FTPOperation(request.session['proxy']), form.cleaned_data) except FTPError as e: - status = 400 - if 'No such file or directory' in e.message: - status = 404 - elif 'Permission denied' in e.message: - status = 403 + msg, status = parse_ftp_error(e) - return JsonResponse({'error': e.message}, status=status) + logger = logging.getLogger('gridftp') + logger.error(e.verbose, extra={'user': request.user, 'path': request.path, 'params': form.cleaned_data}) + + return JsonResponse({'error': msg}, status=status) setattr(cls, cls.method, process) @@ -59,26 +61,35 @@ class ListView(FTPView): listing = ftp.listing(make_url(params, 'path')) data = [] - # ignore . and .. from beginning of the listing - for item in islice(listing, 2, None): - item['size'] = filesizeformat(item['size']) - item['date'] = date_format(item['date'], 'CUSTOM_DATETIME_FORMAT') + for item in listing: + if item['name'] not in ['.', '..']: + item['size'] = filesizeformat(item['size']) + item['date'] = date_format(item['date'], 'CUSTOM_DATETIME_FORMAT') - data.append(item) + data.append(item) return JsonResponse(data, safe=False) class DownloadView(FTPView): def handle(self, ftp, params): - data = ftp.get(make_url(params, 'path')) + url = make_url(params, 'path') + + try: + stats = ftp.info(url) + except FTPError as e: + msg, status = parse_ftp_error(e) + + return render(self.request, 'qcg/download_error.html', {'msg': msg, 'url': url}, status=status) + + data = ftp.get(url) name = os.path.basename(params['path']) mime_type, encoding = mimetypes.guess_type(name) response = StreamingHttpResponse(data, content_type=mime_type or 'application/octet-stream') - response['Content-Disposition'] = u'attachment; filename={}'.format(name) - # TODO Content-Length (?) + response['Content-Disposition'] = 'attachment; filename*={}'.format(urlquote(name)) + response['Content-Length'] = stats['size'] if encoding: response['Content-Encoding'] = encoding @@ -101,7 +112,7 @@ class DeleteView(FTPView): for path in params['dirs']: try: - ftp.rmdir(url + path) + ftp.rmdir(url + urlquote(path)) except FTPError as e: fail[path] = e.message else: @@ -109,7 +120,7 @@ class DeleteView(FTPView): for path in params['files']: try: - ftp.delete(url + path) + ftp.delete(url + urlquote(path)) except FTPError as e: fail[path] = e.message else: @@ -167,7 +178,8 @@ class ExtractView(FTPView): def make_url(params, *parts): - return 'gsiftp://{}/{}'.format(params['host'], os.path.join(*[params[part] for part in parts]) if parts else '') + return 'gsiftp://{}/{}'.format(params['host'], + urlquote(os.path.join(*[params[part] for part in parts]), safe='/~') if parts else '') @require_POST @@ -184,14 +196,20 @@ def fav_add(request): form = FavoriteForm(data) - # TODO check if path exists - if form.is_valid(): - instance = form.save() + if not form.is_valid(): + return JsonResponse({'error': form.errors}, status=400) + + try: + FTPOperation(request.session['proxy']).info(make_url(form.cleaned_data, 'path')) + except FTPError as e: + msg, status = parse_ftp_error(e) + + return JsonResponse({'error': msg}, status=status) - return JsonResponse({'group': 'usr', 'host': instance.host, 'path': instance.path, - 'value': instance.host + '/' + instance.path}) + instance = form.save() - return JsonResponse({'error': form.errors}, status=400) + return JsonResponse({'group': 'usr', 'host': instance.host, 'path': instance.path, + 'value': instance.host + '/' + instance.path}) @require_POST