extracting archive in gridftp
[qcg-portal.git] / filex / views.py
1 import mimetypes
2
3 from django.core.exceptions import PermissionDenied, SuspiciousOperation
4 from django.http import JsonResponse, StreamingHttpResponse
5 from django.template.defaultfilters import filesizeformat
6 from django.utils.formats import date_format
7 from django.views.decorators.http import require_POST
8 from filex.forms import NewDirForm, RenameForm
9
10 from filex.ftp import FTPOperation, FTPException
11 from filex.uploadhandler import with_ftp_upload_handler
12
13
14 def check_auth(request):
15     if not request.user.is_authenticated():
16         raise PermissionDenied("Login required!")
17     if not request.session['proxy']:
18         raise PermissionDenied("No proxy found!")
19
20
21 def list_content(request):
22     check_auth(request)
23
24     # TODO data validation
25     host = request.GET.get('host')
26     path = request.GET.get('path')
27     if not host or not path:
28         raise SuspiciousOperation("No path or host given!")
29
30     url = 'gsiftp://' + host + path
31
32     try:
33         listing = FTPOperation(request.session['proxy']).listing(url)
34     except FTPException as e:
35         return JsonResponse({'msg': e.message}, status=400)
36
37     data = []
38     for item in listing:
39         item['size'] = filesizeformat(item['size'])
40         item['date'] = date_format(item['date'], 'CUSTOM_DATETIME_FORMAT')
41
42         data.append(item)
43
44     return JsonResponse(data, safe=False)
45
46
47 def download(request):
48     check_auth(request)
49
50     # TODO data validation
51     host = request.GET.get('host')
52     path = request.GET.get('path')
53     name = request.GET.get('name')
54     if not host or not path or not name:
55         raise SuspiciousOperation("No path or host or name given!")
56
57     url = 'gsiftp://' + host + path + '/' + name
58
59     mime_type, encoding = mimetypes.guess_type(name)
60
61     response = StreamingHttpResponse(FTPOperation(request.session['proxy']).get(url),
62                                      content_type=mime_type or 'application/octet-stream')
63     response['Content-Disposition'] = 'attachment; filename={}'.format(name)
64     # TODO Content-Length (?)
65
66     if encoding:
67         response['Content-Encoding'] = encoding
68
69     return response
70
71
72 @with_ftp_upload_handler
73 def upload(request):
74     # TODO error handling
75     return JsonResponse({'success': True})
76
77
78 def info(request):
79     check_auth(request)
80
81     # TODO data validation
82     host = request.GET.get('host')
83     path = request.GET.get('path')
84     if not host or not path:
85         raise SuspiciousOperation("No path or host given!")
86
87     url = 'gsiftp://' + host + path
88
89     try:
90         return JsonResponse(FTPOperation(request.session['proxy']).info(url))
91     except FTPException as e:
92         status = 400
93         if 'No such file or directory' in e.message:
94             status = 404
95         elif 'Permission denied' in e.message:
96             status = 403
97
98         return JsonResponse({'msg': e.message}, status=status)
99
100
101 @require_POST
102 def delete(request):
103     check_auth(request)
104
105     # TODO data validation
106     host = request.POST.get('host')
107     path = request.POST.get('path')
108     dirs = request.POST.getlist('dirs')
109     files = request.POST.getlist('files')
110     if not host or not path or not (files or dirs):
111         raise SuspiciousOperation("No path or host or files given!")
112
113     url = 'gsiftp://' + host + path + '/'
114     ftp = FTPOperation(request.session['proxy'])
115
116     done, fail = [], {}
117
118     for name in dirs:
119         try:
120             ftp.rmdir(url + name)
121         except FTPException as e:
122             fail[name] = e.message
123         else:
124             done.append(name)
125
126     for name in files:
127         try:
128             ftp.delete(url + name)
129         except FTPException as e:
130             fail[name] = e.message
131         else:
132             done.append(name)
133
134     return JsonResponse({'done': done, 'fail': fail})
135
136
137 @require_POST
138 def mkdir(request):
139     check_auth(request)
140
141     # TODO actual data validation
142     form = NewDirForm(request.POST)
143
144     if form.is_valid():
145         host = form.cleaned_data['host']
146         path = form.cleaned_data['path']
147         name = form.cleaned_data['name']
148
149         url = 'gsiftp://' + host + path + '/' + name
150
151         try:
152             FTPOperation(request.session['proxy']).mkdir(url)
153         except FTPException as e:
154             msg = e.message
155         else:
156             return JsonResponse({'success': True})
157     else:
158         msg = form.errors
159
160     return JsonResponse({'msg': msg}, status=400)
161
162
163 @require_POST
164 def move(request):
165     check_auth(request)
166
167     # TODO actual data validation
168     form = RenameForm(request.POST)
169
170     if form.is_valid():
171         host = form.cleaned_data['host']
172         path = form.cleaned_data['path']
173         src = form.cleaned_data['src']
174         dst = form.cleaned_data['dst']
175
176         src_url = 'gsiftp://' + host + path + '/' + src
177         dst_url = 'gsiftp://' + host + path + '/' + dst
178
179         try:
180             FTPOperation(request.session['proxy']).move(src_url, dst_url)
181         except FTPException as e:
182             msg = e.message
183         else:
184             return JsonResponse({'success': True})
185     else:
186         msg = form.errors
187
188     return JsonResponse({'msg': msg}, status=400)
189
190
191 @require_POST
192 def compress(request):
193     check_auth(request)
194
195     # TODO data validation
196     host = request.POST.get('host')
197     path = request.POST.get('path')
198     files = request.POST.getlist('files')
199     archive = request.POST.get('archive')
200     if not host or not path or not files or not archive:
201         raise SuspiciousOperation("No path or host or files or archive given!")
202
203     server = 'gsiftp://' + host
204
205     try:
206         # consume generator with command output
207         list(FTPOperation(request.session['proxy']).compress(server, path, files, archive))
208     except FTPException as e:
209         return JsonResponse({'msg': e.message}, status=400)
210     else:
211         return JsonResponse({'success': True})
212
213
214 @require_POST
215 def extract(request):
216     check_auth(request)
217
218     # TODO data validation
219     host = request.POST.get('host')
220     archive = request.POST.get('archive')
221     dst = request.POST.get('dst')
222     if not host or not archive or not dst:
223         raise SuspiciousOperation("No path or host or files or archive given!")
224
225     server = 'gsiftp://' + host
226
227     try:
228         # consume generator with command output
229         list(FTPOperation(request.session['proxy']).extract(server, archive, dst))
230     except FTPException as e:
231         return JsonResponse({'msg': e.message}, status=400)
232     else:
233         return JsonResponse({'success': True})