def edit_paper_url(url): from vimbox.remote.paper_backend import StorageBackEnd, DOC_REGEX title, did, doc_id = DOC_REGEX.match(url).groups() paper_token = local.load_config()['DROPBOX_TOKEN'] client = StorageBackEnd(paper_token) response = client.file_download(url) local_folder = local.get_local_file('.paper/') if not os.path.isdir(local_folder): os.mkdir(local_folder) local_file = "%s/%s--%s-%s.md" % (local_folder, title, did, doc_id) content = local.local_edit(local_file, response['content']) # Update remote if there are changes if content != response['content']: response = client.files_upload(content, url, response['revision']) if response['status'] == 'api-error': print(response['alert']) os.remove(local_file)
def reset_folder(folder_path, delete=False): # Local local_unit_test_folder = local.get_local_file(REMOTE_UNIT_TEST_FOLDER) unit_test_name = os.path.basename(local_unit_test_folder[:-1]) assert unit_test_name == '.vimbox_unit_test', \ "unit-test folder changed name. Aborting just in case." # Remote # NOTE: This assumes these operations pass the unit test! client = VimboxClient() ret = client.client.file_type(REMOTE_UNIT_TEST_FOLDER[:-1]) if ret['status'] == 'online' and ret['content'] == 'dir': client.client.files_delete(REMOTE_UNIT_TEST_FOLDER[:-1]) print("Removed %s" % REMOTE_UNIT_TEST_FOLDER) if os.path.isdir(local_unit_test_folder): shutil.rmtree(local_unit_test_folder) if not delete: client.client.make_directory(REMOTE_UNIT_TEST_FOLDER[:-1]) os.mkdir(local_unit_test_folder)
def test_main(backend_name): # Creation tmp_file = '%sfolder1/plain' % REMOTE_UNIT_TEST_FOLDER assert main(['-f', tmp_file, 'This is some text']) # Check a local copy was created (if intended) assert os.path.isfile(get_local_file(tmp_file)), \ "Creation of local file %s failed" % tmp_file tmp_file = '%sfolder1/encrypted' % REMOTE_UNIT_TEST_FOLDER worked = main( ['-e', tmp_file, 'This is some encrypted text'], password='******' ) assert not worked, "Should not be able to create encrypted file offline" assert not main(['rm', tmp_file]), \ "Should not be able to remove files offline" assert not main(['cp', tmp_file, tmp_file + '2']), \ "Should not be able to copy files offline" tmp_folder = '%sfolder1/folder2/' % REMOTE_UNIT_TEST_FOLDER assert not main(['mkdir', tmp_folder]), \ "Should not be able to make folder offline"
def make_directory(self, remote_target): if remote_target[-1] != '/': raise VimboxClientError("Folder paths must end in / ") file_type, is_encripted, status = self.file_type(remote_target) if status != 'online': raise VimboxOfflineError("Connection error") if file_type is None: response = self.client.make_directory(remote_target[:-1]) if response['status'] == 'online': # Local file os.mkdir(local.get_local_file(remote_target)) # Cache self.register_file(remote_target, False) elif file_type == 'dir': raise VimboxClientError("%s already exists" % remote_target) elif is_encripted: raise VimboxClientError("%s already exists as an encrypted file" % remote_target) else: raise VimboxClientError("%s already exists as a file" % remote_target) return {'status': status, 'content': None, 'alert': None}
def list_folders(self, remote_folder): """ list folder content in remote """ # Try first remote if remote_folder and remote_folder[-1] == '/': response = self.client.list_folders(remote_folder[:-1]) else: response = self.client.list_folders(remote_folder) entries = response['content']['entries'] is_files = response['content']['is_files'] status = response['status'] message = response['alerts'] # Second try to see if there is an ecrypted file # TODO: entries is None is used to signal a this is a file not a # folder. This is an obscure way of dealing with this. is_encrypted = False if status == 'online' and entries is False: enc_remote_folder = crypto.get_path_hash(remote_folder) response = self.client.list_folders(enc_remote_folder) entries = response['content']['entries'] is_files = response['content']['is_files'] status = response['status'] message = response['alerts'] is_encrypted = status == 'online' display_string = "" if status == 'api-error': raise VimboxClientError("api-error") elif status == 'online' and entries is False: # Folder/File non existing raise VimboxClientError("%s does not exist in remote" % remote_folder) elif status == 'online' and entries is None: # This was a file return True elif status == 'online': # Differentiate file and folders display_folders = [] for entry, is_file in zip(entries, is_files): # Add slash to files on root if remote_folder == '': entry = '/' + entry if is_file: # File display_folders.append(entry) else: # Folder display_folders.append("%s/" % entry) display_folders = sorted(display_folders) # Update to match folder if remote_folder: # Remove folder paths no more in remote for path in self.config['cache']: if path[:len(remote_folder)] == remote_folder: cache_folder = \ path[len(remote_folder):].split('/')[0] + '/' if (cache_folder not in display_folders and cache_folder != ''): self.config['cache'].remove(path) # Add missing folders if remote_folder not in self.config['cache']: self.config['cache'].append(remote_folder) for folder in display_folders: if folder[-1] == '/': new_path = "%s%s" % (remote_folder, folder) if new_path not in self.config['cache']: self.config['cache'].append(new_path) # Write cache self.config['cache'] = sorted(self.config['cache']) local.write_config(self.config_path, self.config) # Replace encrypted files entry_types = [] new_display_folders = [] for entry in display_folders: key = "%s%s" % (remote_folder, entry) if key in self.config['path_hashes'].keys(): entry_types.append('encrypted') new_display_folders.append( os.path.basename(self.config['path_hashes'][key])) elif entry[-1] == '/': entry_types.append('folder') new_display_folders.append(entry) else: entry_types.append(None) new_display_folders.append(entry) display_folders = new_display_folders # Display entries sorted and with colors new_display_folders = [] indices = sorted(range(len(display_folders)), key=display_folders.__getitem__) for file_folder, entry_type in zip(display_folders, entry_types): if entry_type == 'encrypted': file_folder = red(file_folder) elif entry_type == 'folder': file_folder = blue(file_folder) new_display_folders.append(file_folder) display_string = "".join( ["%s\n" % new_display_folders[index] for index in indices]) # Add file to cache if remote_folder not in self.config['cache']: self.config['cache'].append(remote_folder) local.write_config(self.config_path, self.config) elif os.path.isdir(local.get_local_file(remote_folder)): # If it fails resort to local cache display_folders = local.list_local(remote_folder, self.config) if self.verbose > 0: print("\n%s content for %s " % (red("offline"), remote_folder)) display_string = "".join( ["%s\n" % folder for folder in sorted(display_folders)]) # Print if self.verbose > 0: print("\n%s\n" % display_string.rstrip())
def get_local_file(self, remote_file): return local.get_local_file(remote_file, self.config)
def is_local_dir(file_path): local_file = local.get_local_file(file_path) return os.path.isdir(local_file)
def main(args=None, config_path=None, password=None, verbose=1): """ This is refered as vimbox in setup.py """ # Argument handling if config_path is None: config_path = local.CONFIG_FILE if args is None: # From command line args = sys.argv[1:] if len(args) == 0: vimbox_help() return False # Sanity check: back-end is installed if (args[0] not in ['setup', 'complete'] and not os.path.isfile(local.CONFIG_FILE)): print("\nMissing config in %s\nRun vimbox setup\n" % local.CONFIG_FILE) exit(1) # # LOCAL COMMANDS (will work offline) # if args[0] == 'help': # help if len(args) > 1 and args[1] in COMMAND_ORDER: vimbox_help(args[1]) else: vimbox_help() return True elif args[0] == 'complete': # strings to store when calling command -W in .basrc for autocomplete_option in local.get_complete_arguments(): print(autocomplete_option) return True elif args[0] == 'local': if len(args) == 2: print(local.get_local_file(args[1])) return True else: vimbox_help() return False elif args[0] == 'cache': # Folders cached in this computer (latter minus commans e.g. ls) for cached_file in sorted(local.get_cache()): print(cached_file) return True elif args[0] == 'local': if len(args) == 2: alert = assert_valid_path(args[1]) if alert: print("%s" % alert) return False print(local.get_local_file(args[1])) else: vimbox_help() return False elif args[0] == 'config': # Open config in editor local.edit_config() return True elif args[0] == 'setup': # Set-up back-end try: install() return True except VimboxOfflineError: print("\nCan not install vimbox offline! (keep the token)") return False # # REMOTE COMMANDS (some may have offline functionalities) # elif args[0] == 'ls': # List contents of folder # Argument handling if len(args) == 1: argument = '' elif len(args) == 2: argument = args[1] alert = assert_valid_path(argument) if alert: print("%s" % alert) return False else: vimbox_help() return False # Client client = VimboxClient(config_path=config_path, verbose=verbose) try: client.list_folders(argument) return True except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxClientError as exception: print("%s" % str(exception)) return False elif args[0] == 'mkdir': # Copy file to file or folder client = VimboxClient(config_path=config_path, verbose=verbose) if len(args) != 2: vimbox_help() return False try: alert = assert_valid_path(args[1], path_type='dir') if alert: print("%s" % alert) return False client.make_directory(args[1]) return True except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxOfflineError: print("\nCan not create folders offline") return False except VimboxClientError as exception: print("\n%s" % str(exception)) return False elif args[0] == 'cp': # Argument handling if len(args) != 3: vimbox_help() return False # Copy file to file or folder client = VimboxClient(config_path=config_path, verbose=verbose) try: alert = assert_valid_path(args[1]) if alert: print("%s" % alert) return False alert = assert_valid_path(args[2]) if alert: print("%s" % alert) return False client.copy(args[1], args[2]) return True except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxOfflineError: print("\nCan not copy files offline") return False except VimboxClientError as exception: print("\n%s" % str(exception)) return False elif args[0] == 'cat': # Copy file to file or folder client = VimboxClient(config_path=config_path, verbose=verbose) for arg in args[1:]: try: alert = assert_valid_path(arg, path_type='file') if alert: print("%s" % alert) return False client.cat(arg) return True except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxClientError as exception: print("\n%s" % str(exception)) return False elif args[0] == 'rm': # Remove file or folder # argument processing if len(args) == 2: arguments = args[1] recursive_flag = False elif len(args) == 3 and args[1] == '-R': arguments = args[2] recursive_flag = True else: vimbox_help() return False # Call client client = VimboxClient(config_path=config_path, verbose=verbose) try: alert = assert_valid_path(arguments) if alert: print("%s" % alert) return False client.remove(arguments, recursive=recursive_flag) return True except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxOfflineError: print("\nCan not remove files offline") return False except VimboxClientError as exception: print("%s" % str(exception)) return False elif args[0] == 'mv': # Move file to file or folder # Argument handling if len(args) != 3: vimbox_help() return False # Call client client = VimboxClient(config_path=config_path, verbose=verbose) try: alert = assert_valid_path(args[1]) if alert: print("%s" % alert) return False alert = assert_valid_path(args[2]) if alert: print("%s" % alert) return False client.move(args[1], args[2]) return True except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxOfflineError: print("\nCan not move files offline") return False except VimboxClientError as exception: print("%s" % str(exception)) return False else: # Get flags from arguments arguments = argument_handling(args) if not arguments: vimbox_help() return False remote_file, force_creation, encrypt, initial_text = arguments alert = assert_valid_path(remote_file) if alert: print("%s" % alert) return False # Edit if DOC_REGEX.match(remote_file): # Edit URL from vimbox.remote.primitives import edit_paper_url edit_paper_url(remote_file) elif remote_file[-1] == '/': # Alias for ls client = VimboxClient(config_path=config_path, verbose=verbose) client.list_folders(remote_file) return True else: # Edit file client = VimboxClient(config_path=config_path, verbose=verbose) # Create new encrypted file or register existing one # TODO: This should happend inside of the client if encrypt and password is None: try: password = password_prompt(remote_file, client.config) except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxClientError as exception: print("%s" % str(exception)) return False # Call function try: client.edit(remote_file, force_creation=force_creation, password=password, initial_text=initial_text) return True except KeyboardInterrupt: print("\nOperation canceled by user") return False except VimboxOfflineError: # Offline mode local_file = local.get_local_file(remote_file) if password: print("\nCan not create encrypted files offline") return False else: # Extra edit mode offline offline_edit(local_file, initial_text) return True except VimboxClientError as exception: print("%s" % str(exception)) return False