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, render
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.utils import with_ftp_upload_handler, parse_ftp_error
23 form_class = HostPathForm
27 def as_view(cls, **initkwargs):
28 def process(self, request):
29 if not request.user.is_authenticated():
30 raise PermissionDenied("Login required!")
31 if not request.session['proxy']:
32 raise PermissionDenied("No proxy found!")
34 form = self.form_class(request.POST if self.method == 'post' else request.GET)
36 if not form.is_valid():
37 return JsonResponse({'error': form.errors}, status=400)
39 self.request = request
41 return self.handle(FTPOperation(request.session['proxy']), form.cleaned_data)
43 msg, status = parse_ftp_error(e)
45 return JsonResponse({'error': msg}, status=status)
47 setattr(cls, cls.method, process)
49 return super(FTPView, cls).as_view(**initkwargs)
51 def handle(self, ftp, params):
52 raise NotImplementedError
55 class ListView(FTPView):
56 def handle(self, ftp, params):
57 listing = ftp.listing(make_url(params, 'path'))
60 # ignore . and .. from beginning of the listing
61 for item in islice(listing, 2, None):
62 item['size'] = filesizeformat(item['size'])
63 item['date'] = date_format(item['date'], 'CUSTOM_DATETIME_FORMAT')
67 return JsonResponse(data, safe=False)
70 class DownloadView(FTPView):
71 def handle(self, ftp, params):
72 url = make_url(params, 'path')
77 msg, status = parse_ftp_error(e)
79 return render(self.request, 'qcg/download_error.html', {'msg': msg, 'url': url}, status=status)
83 name = os.path.basename(params['path'])
84 mime_type, encoding = mimetypes.guess_type(name)
86 response = StreamingHttpResponse(data, content_type=mime_type or 'application/octet-stream')
87 response['Content-Disposition'] = u'attachment; filename={}'.format(name)
88 response['Content-Length'] = stats['size']
91 response['Content-Encoding'] = encoding
96 class InfoView(FTPView):
97 def handle(self, ftp, params):
98 return JsonResponse(ftp.info(make_url(params, 'path')))
101 class DeleteView(FTPView):
103 form_class = HostItemsForm
105 def handle(self, ftp, params):
106 url = make_url(params)
109 for path in params['dirs']:
111 ftp.rmdir(url + path)
112 except FTPError as e:
113 fail[path] = e.message
117 for path in params['files']:
119 ftp.delete(url + path)
120 except FTPError as e:
121 fail[path] = e.message
125 return JsonResponse({'done': done, 'fail': fail})
128 class MkdirView(FTPView):
130 form_class = HostPathNameForm
132 def handle(self, ftp, params):
133 ftp.mkdir(make_url(params, 'path', 'name'))
135 return JsonResponse({'success': True})
138 class MoveView(FTPView):
140 form_class = RenameForm
142 def handle(self, ftp, params):
143 ftp.move(make_url(params, 'src'), make_url(params, 'dst'))
145 return JsonResponse({'success': True})
148 class CompressView(FTPView):
150 form_class = CompressForm
152 def handle(self, ftp, params):
154 # consume generator with command output
155 list(ftp.compress(make_url(params), params['path'], params['files'], params['archive']))
156 except ValueError as e:
157 return JsonResponse({'error': e.message}, status=400)
159 return JsonResponse({'success': True})
162 class ExtractView(FTPView):
164 form_class = ExtractForm
166 def handle(self, ftp, params):
168 # consume generator with command output
169 list(ftp.extract(make_url(params), params['path'], params['dst']))
170 except ValueError as e:
171 return JsonResponse({'error': e.message}, status=400)
173 return JsonResponse({'success': True})
176 def make_url(params, *parts):
177 return 'gsiftp://{}/{}'.format(params['host'], os.path.join(*[params[part] for part in parts]) if parts else '')
181 @with_ftp_upload_handler
183 return JsonResponse({'success': True})
188 def fav_add(request):
189 data = request.POST.copy()
190 data['owner'] = request.user.id
192 form = FavoriteForm(data)
194 if not form.is_valid():
195 return JsonResponse({'error': form.errors}, status=400)
198 FTPOperation(request.session['proxy']).info(make_url(form.cleaned_data, 'path'))
199 except FTPError as e:
200 msg, status = parse_ftp_error(e)
202 return JsonResponse({'error': msg}, status=status)
204 instance = form.save()
206 return JsonResponse({'group': 'usr', 'host': instance.host, 'path': instance.path,
207 'value': instance.host + '/' + instance.path})
212 def fav_delete(request):
213 fav = get_object_or_404(Favorite, owner=request.user, host=request.POST['host'], path=request.POST['path'])
216 return JsonResponse({'success': True})