1 from itertools import islice
5 from django.contrib.auth.decorators import login_required
6 from django.core.exceptions import PermissionDenied
7 from django.http import JsonResponse, StreamingHttpResponse
8 from django.shortcuts import get_object_or_404
9 from django.template.defaultfilters import filesizeformat
10 from django.utils.formats import date_format
11 from django.views.decorators.http import require_POST
12 from django.views.generic import View
14 from filex.forms import HostPathNameForm, RenameForm, FavoriteForm, HostPathForm, ExtractForm, HostItemsForm, \
16 from filex.ftp import FTPOperation, FTPError
17 from filex.models import Favorite
18 from filex.uploadhandler import with_ftp_upload_handler
23 form_class = HostPathForm
26 def as_view(cls, **initkwargs):
27 def process(self, request):
28 if not request.user.is_authenticated():
29 raise PermissionDenied("Login required!")
30 if not request.session['proxy']:
31 raise PermissionDenied("No proxy found!")
33 form = self.form_class(request.POST if self.method == 'post' else request.GET)
35 if not form.is_valid():
36 return JsonResponse({'error': form.errors}, status=400)
39 return self.handle(FTPOperation(request.session['proxy']), form.cleaned_data)
42 if 'No such file or directory' in e.message:
44 elif 'Permission denied' in e.message:
47 return JsonResponse({'error': e.message}, status=status)
49 setattr(cls, cls.method, process)
51 return super(FTPView, cls).as_view(**initkwargs)
53 def handle(self, ftp, params):
54 raise NotImplementedError
57 class ListView(FTPView):
58 def handle(self, ftp, params):
59 listing = ftp.listing(make_url(params, 'path'))
62 # ignore . and .. from beginning of the listing
63 for item in islice(listing, 2, None):
64 item['size'] = filesizeformat(item['size'])
65 item['date'] = date_format(item['date'], 'CUSTOM_DATETIME_FORMAT')
69 return JsonResponse(data, safe=False)
72 class DownloadView(FTPView):
73 def handle(self, ftp, params):
74 data = ftp.get(make_url(params, 'path'))
76 name = os.path.basename(params['path'])
77 mime_type, encoding = mimetypes.guess_type(name)
79 response = StreamingHttpResponse(data, content_type=mime_type or 'application/octet-stream')
80 response['Content-Disposition'] = u'attachment; filename={}'.format(name)
81 # TODO Content-Length (?)
84 response['Content-Encoding'] = encoding
89 class InfoView(FTPView):
90 def handle(self, ftp, params):
91 return JsonResponse(ftp.info(make_url(params, 'path')))
94 class DeleteView(FTPView):
96 form_class = HostItemsForm
98 def handle(self, ftp, params):
99 url = make_url(params)
102 for path in params['dirs']:
104 ftp.rmdir(url + path)
105 except FTPError as e:
106 fail[path] = e.message
110 for path in params['files']:
112 ftp.delete(url + path)
113 except FTPError as e:
114 fail[path] = e.message
118 return JsonResponse({'done': done, 'fail': fail})
121 class MkdirView(FTPView):
123 form_class = HostPathNameForm
125 def handle(self, ftp, params):
126 ftp.mkdir(make_url(params, 'path', 'name'))
128 return JsonResponse({'success': True})
131 class MoveView(FTPView):
133 form_class = RenameForm
135 def handle(self, ftp, params):
136 ftp.move(make_url(params, 'src'), make_url(params, 'dst'))
138 return JsonResponse({'success': True})
141 class CompressView(FTPView):
143 form_class = CompressForm
145 def handle(self, ftp, params):
147 # consume generator with command output
148 list(ftp.compress(make_url(params), params['path'], params['files'], params['archive']))
149 except ValueError as e:
150 return JsonResponse({'error': e.message}, status=400)
152 return JsonResponse({'success': True})
155 class ExtractView(FTPView):
157 form_class = ExtractForm
159 def handle(self, ftp, params):
161 # consume generator with command output
162 list(ftp.extract(make_url(params), params['path'], params['dst']))
163 except ValueError as e:
164 return JsonResponse({'error': e.message}, status=400)
166 return JsonResponse({'success': True})
169 def make_url(params, *parts):
170 return 'gsiftp://{}/{}'.format(params['host'], os.path.join(*[params[part] for part in parts]) if parts else '')
174 @with_ftp_upload_handler
176 return JsonResponse({'success': True})
181 def fav_add(request):
182 data = request.POST.copy()
183 data['owner'] = request.user.id
185 form = FavoriteForm(data)
187 # TODO check if path exists
189 instance = form.save()
191 return JsonResponse({'group': 'usr', 'host': instance.host, 'path': instance.path,
192 'value': instance.host + '/' + instance.path})
194 return JsonResponse({'error': form.errors}, status=400)
199 def fav_delete(request):
200 fav = get_object_or_404(Favorite, owner=request.user, host=request.POST['host'], path=request.POST['path'])
203 return JsonResponse({'success': True})