def test_get_names_encrypted_mixed(self):
        # Create encrypted names.
        encryptor = Encryptor(secrets.password)
        encryptor.cipher_storage.create_cipher()

        names = ["Name1", "Name2"]
        current_node = dict()

        for name in names:
            encrypted_name = encryptor.encrypt(name, string=True)
            encrypted_gdrive_file = GoogleDriveFile(metadata={"title": encrypted_name})
            current_node[name] = encrypted_gdrive_file

        names.append("Name3")
        current_node["Name3"] = GoogleDriveFile(metadata={"title": "Name3"})

        # Assign the object filled with encrypted titles to the cuurrentNode field
        self.fileTreeState.currentNode = current_node
        # Decrypt the names.
        self.fileTreeState._decrypt_file_names_in_current_folder()
        # Test output.
        returned_names = self.fileTreeState.get_names()

        for name in names:
            self.assertTrue(name in returned_names)
Exemple #2
0
    def __init__(self, current_path=FILE_PATH_SEPARATOR):
        self.logger = control.tools.setup_logger("FileTreeLogger")
        self.file_tree = sf.tree()
        self.currentNode = self.file_tree
        self.currentNodeID = "root"
        self.currentPath = current_path
        self.valid = True

        self.file_cache = filesystem.decrypted_data_storage.DecryptedDataStorage()

        # Load metadata.
        self.metadata_wrapper = meta_data.MetaDataWrapper(self.file_tree)
        meta_data_list = self.metadata_wrapper.load()

        if meta_data_list is not True:
            sf.convert_list_to_tree(self.metadata_wrapper.file_tree,
                                    meta_data_list, 'root',
                                    self.metadata_wrapper.file_tree)

        self.file_tree = self.metadata_wrapper.file_tree
        self.rootNode = self.file_tree

        # Set up encryptor.
        self.encryptor = Encryptor(secrets.password)

        # Set up file tree updater.
        self.update_thread = FileTreeUpdater(self)
Exemple #3
0
class FileTreeState:
    def __init__(self, current_path=FILE_PATH_SEPARATOR):
        self.logger = control.tools.setup_logger("FileTreeLogger")
        self.file_tree = sf.tree()
        self.currentNode = self.file_tree
        self.currentNodeID = "root"
        self.currentPath = current_path
        self.valid = True

        self.file_cache = filesystem.decrypted_data_storage.DecryptedDataStorage()

        # Load metadata.
        self.metadata_wrapper = meta_data.MetaDataWrapper(self.file_tree)
        meta_data_list = self.metadata_wrapper.load()

        if meta_data_list is not True:
            sf.convert_list_to_tree(self.metadata_wrapper.file_tree,
                                    meta_data_list, 'root',
                                    self.metadata_wrapper.file_tree)

        self.file_tree = self.metadata_wrapper.file_tree
        self.rootNode = self.file_tree

        # Set up encryptor.
        self.encryptor = Encryptor(secrets.password)

        # Set up file tree updater.
        self.update_thread = FileTreeUpdater(self)
        # self.update_thread.start()

    def get_current_contents(self, content_type=0, name=None):
        """
        Returns the file objects contained in the current folder.
        Args:
            content_type: integer, 0 for all files, 1 for files, 2 for folders.
            name: The name of the file object.
        Returns:
            file_object.FileObject | list
        """
        if self.valid:
            output = []
            for key in [x for x in self.currentNode.keys() if x not in ['parent', 'self']]:
                current_el = self.currentNode[key]
                # Ignore object if incorrect instance content_type.
                if not isinstance(current_el, pydrive.files.GoogleDriveFile):
                    continue

                # Check if is correct file (i.e. mimetype, ignoring Google Drive specific file types).
                is_file = sf.is_file(current_el)
                is_folder = sf.is_folder(current_el)

                if is_file or is_folder:
                    if content_type == 0 or \
                                            content_type == 1 and is_file or \
                                            content_type == 2 and is_folder:
                        output.append(current_el)
                else:
                    continue

            if name:
                for element in output:
                    if element['title'] == name:
                        return file_object.FileObject(element)
                return None
            return output

        else:
            return False

    def get_current_element(self):
        if self.valid:
            if isinstance(self.currentNode, pydrive.files.GoogleDriveFile):
                return file_object.FileObject(self.currentNode)
            elif isinstance(self.currentNode, dict):
                return file_object.FileObject(self.currentNode['self'])
        else:
            return False

    def get_names(self, file_type=0):
        contents = self.get_current_contents(file_type)
        return [y[DECRYPTED_TITLE] if DECRYPTED_TITLE in y else y['title'] for y in contents]

    def change_path(self, new_folder):
        if new_folder == ".":
            return True  # Do nothing.
        elif new_folder == "..":
            # Update path.
            new_path_parts = self.currentPath.split(FILE_PATH_SEPARATOR)[:-1]
            new_path = FILE_PATH_SEPARATOR.join(new_path_parts)

            if not new_path:
                new_path = FILE_PATH_SEPARATOR

            self.currentPath = new_path

            # Update current node.
            self.currentNode = self.currentNode["parent"]
            return True

        else:
            # Check if current element is folder.

            # Check if element exists.
            new_object = self.get_current_contents(0, new_folder)

            if new_object:
                self.currentNodeID = new_object.get_id()
                self.currentNode = self.currentNode[self.currentNodeID]

                path_parts = self.currentPath.split(FILE_PATH_SEPARATOR)
                path_parts.append(new_folder)
                if path_parts[1] == '':
                    del path_parts[1]
                self.currentPath = FILE_PATH_SEPARATOR.join(path_parts)

                # Decrypt all file names.
                # self._decrypt_file_names_in_current_folder()

                return True

            else:
                return False

    def get_current_path(self):
        return self.currentPath

        # TODO implement additional accessors to deal with encrypted names.
        #   If encrypted name encountered add attribute indicating that it it is encoded, and add the decoded name.

    def add_file_entry(self, file_obj, is_folder=False):
        file_id = file_obj.get_id()
        if is_folder:
            self.currentNode[file_id]['parent'] = self.currentNode
            self.currentNode[file_id]['self'] = file_obj.file
            self.currentNode[file_id + "_folder"] = file_obj.file
        else:
            self.currentNode[file_id] = file_obj.file
        return self

    def add_file_entry_id(self, file_obj):
        print "Adding file based on id."
        return self

    def update_file_entry_id(self, file_obj):
        print "Updating file entry based on id."
        return self

    def remove_current_element(self):
        curr_el = self.get_current_element()
        curr_id = curr_el.get_id()

        # Remove the part of the element from the file tree.
        if curr_el.is_file() and curr_id in self.file_tree['parent']:
            # Remove from tree structure
            del self.file_tree['parent'][curr_id]
        elif curr_el.is_folder():  # If folder
            del self.currentNode['parent'][curr_id]
            del self.currentNode['parent'][curr_id + "_folder"]
        else:
            print Exception("remove_current_element failed as element not present")

        # Remove the backed file.
        curr_el.remove()

    def set_utime(self, times):
        curr_el = self.get_current_element()

    def navigate(self, path):
        # Reset current node.
        self.currentNode = self.rootNode
        self.currentNodeID = "root"
        self.currentPath = FILE_PATH_SEPARATOR
        self.valid = True

        split_path = path.split(FILE_PATH_SEPARATOR)[1:]
        if split_path[-1] == '':
            split_path = split_path[:-1]
        for new_folder in split_path:
            self.valid = self.change_path(new_folder) != False
            if not self.valid:
                break

        return self

    # File access points.
    def open_file(self, path, flags):
        """
        Opens a file and returns an OpenFileWrapper object
        Args:
            path: The path to the file
            flags: The flags to open the file with
        Returns:
            OpenFileWrapper
        """
        self.logger.info("open_file path:%s with flags:%s" % (path, flags))
        # Resolve the path.
        current_element = self.navigate(path).get_current_element()

        # Request open file handle from cache.
        os_fptr, cache_state = self.file_cache.open_file(current_element, flags)

        # Wrap up all components.
        open_file_wrap = open_file_wrapper.OpenFileWrapper(current_element, os_fptr, cache_state)

        return open_file_wrap

    def create_file(self, path, flags, mode):
        self.logger.info("create_file path:%s with flags:%d, mode:%d" % (path, flags, mode))
        dir_name = os.path.dirname(path)
        file_name = os.path.basename(path)
        folder_el = self.navigate(dir_name).get_current_element()

        # Create new backing store object.
        folder_id = folder_el.get_id()
        new_file = file_object.FileObject(file_name=file_name, parent_id=folder_id)
        fptr, cache_state = self.file_cache.create_file(new_file, mode, flags)

        open_file_wrap = open_file_wrapper.OpenFileWrapper(new_file, fptr, cache_state)

        # Add object to file tree. USING GoogleDriveFile.
        self.add_file_entry(new_file)

        return open_file_wrap

    def create_folder(self, path, mode):
        self.logger.info("create_folder path:%s with flags:%d" % (path, mode))
        dir_name = os.path.dirname(path)
        folder_name = os.path.basename(path)
        par_folder_el = self.navigate(dir_name).get_current_element()

        par_fol_id = par_folder_el.get_id()
        new_folder = file_object.FileObject(file_name=folder_name, parent_id=par_fol_id, is_folder=True)
        self.add_file_entry(new_folder, is_folder=True)
        return new_folder

    def read(self):
        pass

    def _decrypt_file_names_in_current_folder(self):
        for file_id, file_obj in self.currentNode.iteritems():
            title = file_obj["title"]

            if ENCRYPTED_FLAG not in file_obj:
                try:
                    decrypted_title = self.encryptor.decrypt(title, string=True)
                    file_obj[ENCRYPTED_FLAG] = True
                    file_obj[DECRYPTED_TITLE] = decrypted_title

                except Exception as e:
                    file_obj["encrypted"] = False

    def tear_down(self):
        self.logger.info("tear_down ---------------------------------------------------")
        # End worker threads.
        try:
            self.update_thread.set_stop_flag()
            self.update_thread.join()
        except Exception as e:
            pass

        # Save metadata.
        self.logger.info("Saving metadata...")
        self.metadata_wrapper.save()
        self.logger.info("Tear-down finished.")
        return 0