self.wait()
- def compress(self, server, path, files, archive):
- def match_ext(*extensions):
- for ext in extensions:
- if archive.endswith(ext):
- return True
- return False
+ @staticmethod
+ def match_ext(archive, *extensions):
+ for ext in extensions:
+ if archive.endswith(ext):
+ return True
+ return False
- if match_ext('.tar.gz', '.tgz'):
+ def compress(self, server, path, files, archive):
+ if self.match_ext(archive, '.tar.gz', '.tgz'):
cmd, args = 'tar', ['cvzf', os.path.join(path, archive), '-C', path] + files
- elif match_ext('.tar.bz2', '.tbz'):
+ elif self.match_ext(archive, '.tar.bz2', '.tbz'):
cmd, args = 'tar', ['cvjf', os.path.join(path, archive), '-C', path] + files
- elif match_ext('.zip'):
+ elif self.match_ext(archive, '.zip'):
cmd, args = 'zip', ['-r', os.path.join(path, archive)] + [os.path.join(path, f) for f in files]
else:
raise ValueError('Unknown archive type: {}'.format(archive))
self.op_attr.set_disk_stack('#'.join(["popen:argv=", cmd] + args))
return self.get(server)
+
+ def extract(self, server, archive, dst):
+ if self.match_ext(archive, '.tar.gz', '.tgz'):
+ cmd, args = 'tar', ['xvzf', archive, '-C', dst]
+ elif self.match_ext(archive, '.tar.bz2', '.tbz'):
+ cmd, args = 'tar', ['xvjf', archive, '-C', dst]
+ elif self.match_ext(archive, '.zip'):
+ cmd, args = 'unzip', [archive, '-d', dst]
+ else:
+ raise ValueError('Unknown archive type: {}'.format(archive))
+
+ # FIXME handling filename with #
+ self.op_attr.set_disk_stack('#'.join(["popen:argv=", cmd] + args))
+
+ return self.get(server)
url(r'^mkdir/$', views.mkdir, name='mkdir'),
url(r'^move/$', views.move, name='move'),
url(r'^compress/$', views.compress, name='compress'),
+ url(r'^extract/$', views.extract, name='extract'),
)
path = request.POST.get('path')
files = request.POST.getlist('files')
archive = request.POST.get('archive')
- if not host or not path or not files:
+ if not host or not path or not files or not archive:
raise SuspiciousOperation("No path or host or files or archive given!")
server = 'gsiftp://' + host
return JsonResponse({'msg': e.message}, status=400)
else:
return JsonResponse({'success': True})
+
+
+@require_POST
+def extract(request):
+ check_auth(request)
+
+ # TODO data validation
+ host = request.POST.get('host')
+ archive = request.POST.get('archive')
+ dst = request.POST.get('dst')
+ if not host or not archive or not dst:
+ raise SuspiciousOperation("No path or host or files or archive given!")
+
+ server = 'gsiftp://' + host
+
+ try:
+ # consume generator with command output
+ list(FTPOperation(request.session['proxy']).extract(server, archive, dst))
+ except FTPException as e:
+ return JsonResponse({'msg': e.message}, status=400)
+ else:
+ return JsonResponse({'success': True})
$(function () {
var statusTimeout;
+ String.prototype.endsWith = function(suffix) {
+ return this.indexOf(suffix, this.length - suffix.length) !== -1;
+ };
+
function status(msg) {
clearTimeout(statusTimeout);
statusTimeout = setTimeout(function() {
$('#status').text(msg);
}
- function fail(xhr) {
- status('Wystąpił błąd: ' + ((xhr.responseJSON || {}).msg || "Server error"));
- console.error(xhr);
+ function fail() {
+ status('Wystąpił błąd.');
+ console.error(arguments);
filex.idle();
}
$('#btn-rename').toggleClass('disabled', selected != 1);
$('#btn-delete').toggleClass('disabled', selected == 0);
$('#btn-compress').toggleClass('disabled', selected == 0);
- $('#btn-extract').toggleClass('disabled', selected != 1);
+
+ if (selected == 1) {
+ var filename = filex.selectedFiles()[0].get('name'),
+ is_archive = _.some(['.zip', '.tar.gz', '.tgz', '.tar.bz2', 'tbz'], function(ext) {
+ return filename.endsWith(ext);
+ });
+
+ $('#btn-extract').toggleClass('disabled', !is_archive);
+ }
+ else {
+ $('#btn-extract').toggleClass('disabled', true);
+ }
});
$('#btn-upload').on('click', function() {
$this.find('#id_host').val(filex.host);
$this.find('#id_path').val(filex.path.full());
- $.post($this.attr('action'), $this.serialize(), function(response) {
+ $.post($this.attr('action'), $this.serialize(), function() {
status('Katalog utworzono pomyślnie');
filex.reloadFiles();
}, 'json').fail(fail);
filex.busy();
$this.modal('hide');
- $.post($this.attr('action'), $this.serialize(), function(response) {
+ $.post($this.attr('action'), $this.serialize(), function() {
status('Nazwę zmieniono pomyślnie');
filex.reloadFiles();
}, 'json').fail(fail);
var $this = $(this),
name = $this.find('#id_name').val(),
type = $this.find('#id_type').val(),
- archive = name + (name.indexOf(type, name.length - type.length) === -1 ? type : ''),
+ archive = name + (name.endsWith(type) ? '' : type),
data = {
host: filex.host,
path: filex.path.full(),
filex.busy();
$this.modal('hide');
- $.post($this.attr('action'), data, function(response) {
+ $.post($this.attr('action'), data, function() {
status('Archiwum utworzono pomyślnie');
filex.reloadFiles();
}, 'json').fail(fail);
});
+
+ $('#btn-extract').on('click', function() {
+ filex.busy();
+
+ var data = {
+ host: filex.host,
+ archive: filex.path.full() + '/' + filex.selectedFiles()[0].get('name'),
+ dst: filex.path.full()
+ };
+
+ $.post('{% url 'filex:extract' %}', data, function() {
+ status('Archiwum rozpakowano pomyślnie');
+ filex.reloadFiles();
+ }, 'json').fail(fail);
+ });
})
</script>
{% endblock extra_js %}