def select_partition(self): selected_partition = findall( r"Name\:\ ([^\ \n]+)\ ", self.partitions_list_scroll_menu.get(), )[0] if self.partitions_dict[selected_partition]["IS_MOUNTED"]: # Warn the user to unmount his partition before searching in it self.master.show_warning_popup( "You probably should unmount first !", f"It is highly recommended to unmount {selected_partition}" " ASAP to avoid any data loss.", ) else: self.master.show_message_popup( "", f"Partition {selected_partition} selected.", ) self.partition_to_search = f"/dev/{selected_partition.strip()}" LOGGER.write( "info", f"Partition selected: {self.partition_to_search}", )
def confirm_search(self): if not helper.is_user_root(window=self.master): return self.string_to_search = self.string_text_box.get() if not hasattr(self, "partition_to_search") or self.partition_to_search == "": # No partition selected self.master.show_message_popup( "Whoops !", "You have to select a partition to search.", ) LOGGER.write("warning", "No partition selected for search") elif not self.string_to_search.strip(): # Blank string to search self.master.show_message_popup( "Oops !", "You have to enter a text to search.", ) LOGGER.write("warning", "No string given for search") else: # Prompt to confirm string self.master.show_yes_no_popup( "Do you want to search this text on partition " f"{self.partition_to_search} ?", self.start_search, )
def write_to_file(self, file_name: Path, content: str): with open(file_name, "w") as save_file: save_file.write(content) self.last_saved_file = file_name LOGGER.write("info", f"Output saved in file {file_name}")
def start_result_enqueue_thread(self, grep_process: Popen, search_screen: Screen): Thread( target=self.enqueue_grep_output, args=(grep_process.stdout, search_screen.queue_object), daemon=True, ).start() LOGGER.write("debug", "Started grep searching thread")
def is_user_root(window: PyCUI) -> bool: if geteuid() == 0: LOGGER.write("info", "User is root") return True window.show_error_popup("Not root :(", "You have to be root or use sudo.") LOGGER.write("warning", "User is not root") return False
def start_search(self, is_confirmed: bool): if is_confirmed: LOGGER.write("info", "Starting search") handler.SCREENS_HANDLER.open_screen( "search", partition=self.partition_to_search, string_to_search=self.string_to_search.strip(), )
def get_system_partitions(self): self.partitions_dict = helper.get_partitions() if not self.partitions_dict: LOGGER.write("Error", "No partition found !") self.master.show_error_popup("Hum...", "No partition found.") return self.add_partitions_to_list()
def add_block_to_file(self): if self.current_block in self.saved_blocks_dict: return self.master.show_message_popup("", "Result added to file") self.saved_blocks_dict[self.current_block] = self.current_result LOGGER.write( "debug", f"Stored block {self.current_block} for future save", )
def start_progress_monitoring_thread(self, grep_process: Popen, search_screen: Screen): if not is_dependency_installed(command="progress"): return Thread( target=self.monitor_search_progress, args=(search_screen, grep_process.pid), daemon=True, ).start() LOGGER.write("debug", "Started progress monitoring thread")
def update_horizontal_char_limit(self): text_box_dimensions: tuple = ( self.blockcontent_box.get_cursor_limits_horizontal() ) self.horizontal_char_limit: int = ( text_box_dimensions[1] - text_box_dimensions[0] ) LOGGER.write( "debug", f"Textbox char limit set to {self.horizontal_char_limit}", )
def __init__(self, master: PyCUI, partition: str, string_to_search: str): super().__init__(master) self.queue_object: Queue = Queue() self.blockindex: int = 0 self.block_numbers: list = [] self.partition: str = partition self.block_size: int = get_block_size(partition) self.searched_string: str = string_to_search self._first_line: str = string_to_search.strip().splitlines()[0] self.create_ui_content() SEARCH_ENGINE.start_search(self) LOGGER.write("info", f"Raw searched string:\n{self.searched_string}")
def monitor_search_progress(self, search_screen: Screen, grep_pid: int): while True: output: str = check_output( ["progress", "-p", str(grep_pid)], stderr=DEVNULL).decode("utf8") if not output: search_screen.set_title("100% - Search completed") return progress: list = findall(r"([0-9]+\.[0-9]+\%[^\)]+\))", output) if not progress: continue LOGGER.write("debug", f"Progress: {progress[0]}") search_screen.set_title(progress[0]) sleep(1)
def add_partitions_to_list(self): if self.partitions_dict is None: return for partition in self.partitions_dict: if self.partitions_dict[partition]["IS_MOUNTED"]: self.partitions_list_scroll_menu.add_item( f"Name: {partition} - " f"Type: {self.partitions_dict[partition]['FSTYPE']} - " f"Mounted at: {self.partitions_dict[partition]['MOUNT_POINT']}" ) else: self.partitions_list_scroll_menu.add_item( f"Name: {partition} - " f"Type: {self.partitions_dict[partition]['FSTYPE']}" ) LOGGER.write("debug", f"Partition added to list: {partition}")
def update_textbox(self): self.update_horizontal_char_limit() # Format raw result to fit in the text box blocklines: list = [ str(self.current_result)[i : i + self.horizontal_char_limit] for i in range( 0, len(str(self.current_result)) + self.horizontal_char_limit, self.horizontal_char_limit, ) ] formated_result: str = "\n".join(blocklines) # Fix for embedded null character formated_result = formated_result.replace(chr(0), "") self.blockcontent_box.set_text(formated_result) self.blockcontent_box.set_title(f"Block {self.current_block}") LOGGER.write("debug", f"Textbox updated with block {self.current_block}")
def load_config(): with open(_CONFIG_DIR / "config.yaml", "r") as config_file: config: dict = load(config_file, Loader=FullLoader) if "save_directory" not in config or config["save_directory"] == "": raise errors.NoSavePath if not is_path_valid(config["save_directory"]): raise errors.InvalidSavePath SAVER.save_path = Path(config["save_directory"]) if "log_directory" not in config or config["log_directory"] == "": LOGGER.log_enabled = False elif not is_path_valid(config["log_directory"]): raise errors.InvalidLogPath else: LOGGER.log_path = Path(config["log_directory"]) LOGGER.log_enabled = bool(config["enable_logging"]) if LOGGER.log_enabled: LOGGER.start_logging()
def get_dd_result(self, block_number: str = None): if block_number is None: block_number = self.current_block LOGGER.write( "debug", f"Getting 'dd' output for block {str(self.current_block)}", ) try: dd_result: bytes = SEARCH_ENGINE.get_dd_output( partition=self.partition, block_size=get_block_size(self.partition), block_number=block_number, ) self.current_result = decode_result(dd_result) self.current_block = block_number LOGGER.write("debug", "dd command successful") except CalledProcessError: self.master.show_error_popup( "Mmmmhhh...", f"Error while opening block {str(self.current_block)}", ) LOGGER.write( "error", f"Error while opening block {str(self.current_block)}", )
def test_error(): LOGGER.write("error", "error") assert "error" in get_log_file_content()
def display_next_block(self): try: self.display_block(str(int(self.current_block) + 1)) except ValueError: LOGGER.write("error", f"Cannot display block {self.current_block} + 1") return
def test_info(): LOGGER.write("info", "info") assert "info" in get_log_file_content()
def test_warning(): LOGGER.write("warning", "warning") assert "warning" in get_log_file_content()
def test_log_disabled(): LOGGER.log_enabled = False LOGGER.write("debug", "debug") assert "debug" not in get_log_file_content()
def test_critical(): LOGGER.write("critical", "critical") assert "critical" in get_log_file_content()
def start_result_dequeue_thread(self, search_screen: Screen): Thread( target=search_screen.dequeue_results, daemon=True, ).start() LOGGER.write("debug", "Started grep output fetching thread")
def test_debug(): LOGGER.log_enabled = True LOGGER.write("debug", "debug") assert "debug" in get_log_file_content()