From 7931c7efe9fd2deb08a635948a5546bf259d0930 Mon Sep 17 00:00:00 2001 From: Stefano Alberto Russo <stefano.russo@gmail.com> Date: Mon, 29 Mar 2021 19:36:49 +0200 Subject: [PATCH] Added the mkdir. Fixes and imporvements (form ls to stat). --- services/webapp/code/rosetta/core_app/api.py | 122 +++++++++++++++---- 1 file changed, 96 insertions(+), 26 deletions(-) diff --git a/services/webapp/code/rosetta/core_app/api.py b/services/webapp/code/rosetta/core_app/api.py index f8452c3..e7afc3f 100644 --- a/services/webapp/code/rosetta/core_app/api.py +++ b/services/webapp/code/rosetta/core_app/api.py @@ -416,7 +416,7 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): raise Exception('No computing user?!') # Command - command = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} {}'.format(user_keys.private_key_file, computing_user, computing_host, command) + command = 'ssh -o LogLevel=ERROR -i {} -4 -o StrictHostKeyChecking=no {}@{} "{}"'.format(user_keys.private_key_file, computing_user, computing_host, command) return command @@ -426,6 +426,12 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): path = re.sub(cleaner,'/',path) return path + @staticmethod + def sanitize_shell_path(path): + path = path.replace(' ', '\ ') + cleaner = re.compile('(?:\\\)+') + path = re.sub(cleaner,r"\\",path) + return path def get_computing(self, path, request): # Get the computing based on the folder name # TODO: this is very weak.. @@ -458,13 +464,22 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): # Data container data = [] + path = self.sanitize_shell_path(path) + # Prepare command - command = self.ssh_command('ls -al {}'.format(path), user, computing) + # https://askubuntu.com/questions/1116634/ls-command-show-time-only-in-iso-format + # https://www.howtogeek.com/451022/how-to-use-the-stat-command-on-linux/ + command = self.ssh_command('cd {} && stat --printf=\'%F/%n/%s/%Y\\n\' * .*'.format(path), user, computing) # Execute_command out = os_shell(command, capture=True) if out.exit_code != 0: - raise Exception(out.stderr) + + # Did we just get a "cannot stat - No such file or directory error? + if 'No such file or directory' in out.stderr: + pass + else: + raise Exception(out.stderr) # Log #logger.debug('Shell exec output: "{}"'.format(out)) @@ -472,16 +487,17 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): out_lines = out.stdout.split('\n') for line in out_lines: - - # Skip total files summary line at the end - if line.startswith('total'): - continue + # Example line: directory/My folder/68/1617030350 + # Set name - name = line.split(' ')[-1] + line_pieces = line.split('/') + type = line_pieces[0] + name = line_pieces[1] + size = line_pieces[2] + timestamp = line_pieces[3] - # Check against binds if set - + # Check against binds if set if binds: if not path == '/': full_path = path + '/' + name @@ -499,11 +515,10 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): # Define and clean listing path: listing_path = '/{}/{}/{}/'.format(computing.name, path, name) listing_path = self.clean_path(listing_path) - # File or directory? - if line.startswith('d'): - if line.split(' ')[-1] not in ['.', '..']: + if type == 'directory': + if name not in ['.', '..']: data.append({ 'id': listing_path, 'type': 'folder', @@ -537,7 +552,9 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): def delete(self, path, user, computing): - + + path = self.sanitize_shell_path(path) + # Prepare command command = self.ssh_command('rm -rf {}'.format(path), user, computing) @@ -548,8 +565,24 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): return out.stdout + def mkdir(self, path, user, computing): + + path = self.sanitize_shell_path(path) + + # Prepare command + command = self.ssh_command('mkdir {}'.format(path), user, computing) + + # Execute_command + out = os_shell(command, capture=True) + if out.exit_code != 0: + raise Exception(out.stderr) + return out.stdout + + def cat(self, path, user, computing): + path = self.sanitize_shell_path(path) + # Prepare command command = self.ssh_command('cat {}'.format(path), user, computing) @@ -562,12 +595,13 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): def rename(self, old, new, user, computing): - old = old.replace(' ', '\ ') - new = new.replace(' ', '\ ') + old = self.sanitize_shell_path(old) + new = self.sanitize_shell_path(new) - # Prepare command - command = self.ssh_command('mv \'{}\' \'{}\''.format(old, new), user, computing) + command = self.ssh_command('mv {} {}'.format(old, new), user, computing) + + logger.critical(command) # Execute_command out = os_shell(command, capture=True) @@ -577,11 +611,12 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): def copy(self, source, target, user, computing): - source = source.replace(' ', '\ ') - target = target.replace(' ', '\ ') + + source = self.sanitize_shell_path(source) + target = self.sanitize_shell_path(target) # Prepare command - command = self.ssh_command('cp -a \'{}\' \'{}\''.format(source, target), user, computing) + command = self.ssh_command('cp -a {} {}'.format(source, target), user, computing) # Execute_command out = os_shell(command, capture=True) @@ -590,13 +625,13 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): return out.stdout - def scp(self, source_path, target_path, user, computing, mode='get'): + def scp(self, source, target, user, computing, mode='get'): + + source = self.sanitize_shell_path(source) + target = self.sanitize_shell_path(target) - source_path = source_path.replace(' ', '\ ') - target_path = target_path.replace(' ', '\ ') - # Prepare command - command = self.scp_command(source_path, target_path, user, computing, mode) + command = self.scp_command(source, target, user, computing, mode) # Execute_command out = os_shell(command, capture=True) @@ -761,6 +796,41 @@ class FileManagerAPI(PrivateGETAPI, PrivatePOSTAPI): return Response(data, status=status.HTTP_200_OK) + elif mode == 'addfolder': + logger.debug('Deleting "{}"'.format(path)) + + name = request.GET.get('name', None) + if not name: + raise ValueError('No folder name set') + + # Set support vars + computing = self.get_computing(path, request) + path = '/'+'/'.join(path.split('/')[2:]) + name + + # Get file contents + data = self.mkdir(path, request.user, computing) + + # Response data + data = { 'data': { + 'id': '/{}{}'.format(computing.name, path), + 'type': 'folder', + 'attributes':{ + #'created': 1616415170, + #'modified': 1616415170, + 'name': name, + 'readable': 1, + #'timestamp': 1616415170, + 'writable': 1, + 'path': '/{}{}'.format(computing.name, path) + } + } + } + + + # Return file contents + return Response(data, status=status.HTTP_200_OK) + + elif mode == 'rename': logger.debug('Renaming "{}"'.format(path)) -- GitLab