diff --git a/aleapp.py b/aleapp.py index 1d0c873d..4c860bb4 100755 --- a/aleapp.py +++ b/aleapp.py @@ -42,74 +42,70 @@ def validate_args(args): raise argparse.ArgumentError(None, 'Unknown timezone! Run the program again.') -def create_profile(available_plugins, path): - available_parsers = [] - for parser_data in available_plugins: - if parser_data.name != 'usagestatsVersion': - available_parsers.append((parser_data.category, parser_data.name)) - - available_parsers.sort() - parsers_in_profile = {} - +def create_profile(plugins, path): + available_modules = [(module_data.category, module_data.name) for module_data in plugins] + available_modules.sort() + modules_in_profile = {} + user_choice = '' print('--- ALEAPP Profile file creation ---\n') instructions = 'You can type:\n' - instructions += ' - \'a\' to add or remove parsers in the profile file\n' - instructions += ' - \'l\' to display the list of all available parsers with their number\n' - instructions += ' - \'p\' to display the parsers added into the profile file\n' + instructions += ' - \'a\' to add or remove modules in the profile file\n' + instructions += ' - \'l\' to display the list of all available modules with their number\n' + instructions += ' - \'p\' to display the modules added into the profile file\n' instructions += ' - \'q\' to quit and save\n' while not user_choice: print(instructions) user_choice = input('Please enter your choice: ').lower() print() if user_choice == "l": - print('Available parsers:') - for number, available_plugin in enumerate(available_parsers): - print(number + 1, available_plugin) + print('Available modules:') + for number, available_module in enumerate(available_modules): + print(number + 1, available_module) print() user_choice = '' elif user_choice == "p": - if parsers_in_profile: - for number, parser in parsers_in_profile.items(): - print(number, parser) + if modules_in_profile: + for number, module in modules_in_profile.items(): + print(number, module) print() else: - print('No parser added to the profile file\n') + print('No module added to the profile file\n') user_choice = '' elif user_choice == 'a': - parser_numbers = input('Enter the numbers of parsers, seperated by a comma, to add or remove in the profile file: ') - parser_numbers = parser_numbers.split(',') - parser_numbers = [parser_number.strip() for parser_number in parser_numbers] - for parser_number in parser_numbers: - if parser_number.isdigit(): - parser_number = int(parser_number) - if parser_number > 0 and parser_number <= len(available_parsers): - if parser_number not in parsers_in_profile: - parser_to_add = available_parsers[parser_number - 1] - parsers_in_profile[parser_number] = parser_to_add - print(f'parser number {parser_number} {parser_to_add} was added') + modules_numbers = input('Enter the numbers of modules, seperated by a comma, to add or remove in the profile file: ') + modules_numbers = modules_numbers.split(',') + modules_numbers = [module_number.strip() for module_number in modules_numbers] + for module_number in modules_numbers: + if module_number.isdigit(): + module_number = int(module_number) + if module_number > 0 and module_number <= len(available_modules): + if module_number not in modules_in_profile: + module_to_add = available_modules[module_number - 1] + modules_in_profile[module_number] = module_to_add + print(f'module number {module_number} {module_to_add} was added') else: - parser_to_remove = parsers_in_profile[parser_number] - print(f'parser number {parser_number} {parser_to_remove} was removed') - del parsers_in_profile[parser_number] + module_to_remove = modules_in_profile[module_number] + print(f'module number {module_number} {module_to_remove} was removed') + del modules_in_profile[module_number] else: - print('Please enter the number of a parser!!!\n') + print('Please enter the number of a module!!!\n') print() user_choice = '' elif user_choice == "q": - if parsers_in_profile: - parsers = [parser_info[1] for parser_info in parsers_in_profile.values()] + if modules_in_profile: + modules = [module_info[1] for module_info in modules_in_profile.values()] profile_filename = '' while not profile_filename: profile_filename = input('Enter the name of the profile: ') profile_filename += '.alprofile' filename = os.path.join(path, profile_filename) with open(filename, "wt", encoding="utf-8") as profile_file: - json.dump({"leapp": "aleapp", "format_version": 1, "plugins": parsers}, profile_file) + json.dump({"leapp": "aleapp", "format_version": 1, "plugins": modules}, profile_file) print('\nProfile saved:', filename) print() else: - print('No parser added. The profile file was not created.\n') + print('No module added. The profile file was not created.\n') print() return else: @@ -162,13 +158,16 @@ def main(): profile_filename = None casedata = {} - # Move usagestatsVersion plugin to first position - usagestatsVersion_index = next((i for i, selected_plugin in enumerate(available_plugins) - if selected_plugin.name == 'usagestatsVersion'), -1) - if usagestatsVersion_index != -1: - available_plugins.insert(0, available_plugins.pop(usagestatsVersion_index)) + plugins = [] + plugins_parsed_first = [] + + for plugin in available_plugins: + if plugin.name == 'usagestatsVersion': + plugins_parsed_first.append(plugin) + else: + plugins.append(plugin) - selected_plugins = available_plugins.copy() + selected_plugins = plugins.copy() args = parser.parse_args() @@ -207,7 +206,7 @@ def main(): create_choice = input('Please enter your choice: ').lower() print() if create_choice == '1': - create_profile(selected_plugins, args.create_profile_casedata) + create_profile(plugins, args.create_profile_casedata) create_choice = '' elif create_choice == '2': create_casedata(args.create_profile_casedata) @@ -264,10 +263,9 @@ def main(): print(profile_load_error) return else: - print(f'Profile loaded: {profile_filename}') profile_plugins = set(profile.get("plugins", [])) - selected_plugins = [selected_plugin for selected_plugin in available_plugins - if selected_plugin.name in profile_plugins or selected_plugin.name == 'usagestatsVersion'] + selected_plugins = [selected_plugin for selected_plugin in plugins + if selected_plugin.name in profile_plugins] else: profile_load_error = "File was not a valid profile file: invalid format" print(profile_load_error) @@ -278,7 +276,7 @@ def main(): wrap_text = args.wrap_text output_path = os.path.abspath(args.output_path) time_offset = args.timezone - + # Android file system extractions contain paths > 260 char, which causes problems # This fixes the problem by prefixing \\?\ on each windows path. if is_platform_windows(): @@ -286,8 +284,9 @@ def main(): if output_path[1] == ':': output_path = '\\\\?\\' + output_path.replace('/', '\\') out_params = OutputParameters(output_path) - print(f"Info: {len(available_plugins)} plugins loaded.") + selected_plugins = plugins_parsed_first + selected_plugins + crunch_artifacts(selected_plugins, extracttype, input_path, out_params, wrap_text, loader, casedata, time_offset, profile_filename) @@ -329,9 +328,10 @@ def crunch_artifacts( return False # Now ready to run + logfunc(f'Info: {len(loader) - 1} modules loaded.') # excluding usagestatsVersion if profile_filename: logfunc(f'Loaded profile: {profile_filename}') - logfunc(f'Artifact categories to parse: {len(plugins)}') + logfunc(f'Artifact categories to parse: {len(plugins) - 1}') # excluding usagestatsVersion always executed first logfunc(f'File/Directory selected: {input_path}') logfunc('\n--------------------------------------------------------------------------------------') @@ -340,7 +340,7 @@ def crunch_artifacts( log.write(f'Timezone selected: {time_offset}

') parsed_modules = 0 - + # Search for the files per the arguments for plugin in plugins: if isinstance(plugin.search, list) or isinstance(plugin.search, tuple): @@ -350,7 +350,7 @@ def crunch_artifacts( parsed_modules += 1 GuiWindow.SetProgressBar(parsed_modules, len(plugins)) files_found = [] - log.write(f'For {plugin.name} parser') + log.write(f'For {plugin.name} module') for artifact_search_regex in search_regexes: found = seeker.search(artifact_search_regex) if not found: @@ -383,7 +383,6 @@ def crunch_artifacts( continue # nope logfunc('{} [{}] artifact completed'.format(plugin.name, plugin.module_name)) - logfunc('') log.close() diff --git a/aleapp.spec b/aleapp.spec index 14e02ef4..01d72c30 100755 --- a/aleapp.spec +++ b/aleapp.spec @@ -5,26 +5,7 @@ block_cipher = None a = Analysis(['aleapp.py'], pathex=['.\\scripts\\artifacts'], binaries=[], - datas=[('.\\scripts\\logo.jpg', '.\\scripts'), - ('.\\scripts\\dashboard.css', '.\\scripts'), - ('.\\scripts\\dark-mode.css', '.\\scripts'), - ('.\\scripts\\dark-mode-switch.js', '.\\scripts'), - ('.\\scripts\\feather.min.js', '.\\scripts'), - ('.\\scripts\\chart.umd.min.js', '.\\scripts'), - ('.\\scripts\\cal-heatmap.min.js', '.\\scripts'), - ('.\\scripts\\cal-heatmap.css', '.\\scripts'), - ('.\\scripts\\d3.v7.min.js', '.\\scripts'), - ('.\\scripts\\chat.js', '.\\scripts'), - ('.\\scripts\\chat.css', '.\\scripts'), - ('.\\scripts\\garmin-functions.js', '.\\scripts'), - ('.\\scripts\\highlight.min.js', '.\\scripts'), - ('.\\scripts\\highlight.min.css', '.\\scripts'), - ('.\\scripts\\moment.min.js', '.\\scripts'), - ('.\\scripts\\popper.min.js', '.\\scripts'), - ('.\\scripts\\Tooltip.min.js', '.\\scripts'), - ('.\\scripts\\MDB-Free_4.13.0', '.\\scripts\\MDB-Free_4.13.0'), - ('.\\scripts\\timeline', '.\\scripts\\timeline'), - ('.\\scripts\\artifacts', '.\\scripts\\artifacts')], + datas=[('.\\scripts', '.\\scripts')], hiddenimports=['simplekml'], hookspath=['.\\'], runtime_hooks=[], @@ -49,4 +30,3 @@ exe = EXE(pyz, upx_exclude=[], runtime_tmpdir=None, console=True ) - diff --git a/aleappGUI.py b/aleappGUI.py index 38fc2cec..9a10b92e 100755 --- a/aleappGUI.py +++ b/aleappGUI.py @@ -480,7 +480,6 @@ def load_case(): v.grid(row=0, column=1, sticky='ns') mlist_text = tk.Text(mlist_frame, name='tbox', bg=theme_bgcolor, highlightthickness=0, yscrollcommand=v.set, height=mlist_window_height) -# mlist_text.pack(anchor='w') mlist_text.grid(row=0, column=0, sticky='we') v.config(command=mlist_text.yview) for plugin, enabled in mlist.items(): diff --git a/aleappGUI.spec b/aleappGUI.spec index f3fbbd46..91ea6b16 100755 --- a/aleappGUI.spec +++ b/aleappGUI.spec @@ -3,26 +3,7 @@ block_cipher = None a = Analysis(['aleappGUI.py'], pathex=['.\\scripts\\artifacts'], binaries=[], - datas=[('.\\scripts\\logo.jpg', '.\\scripts'), - ('.\\scripts\\dashboard.css', '.\\scripts'), - ('.\\scripts\\dark-mode.css', '.\\scripts'), - ('.\\scripts\\dark-mode-switch.js', '.\\scripts'), - ('.\\scripts\\feather.min.js', '.\\scripts'), - ('.\\scripts\\chart.umd.min.js', '.\\scripts'), - ('.\\scripts\\cal-heatmap.min.js', '.\\scripts'), - ('.\\scripts\\cal-heatmap.css', '.\\scripts'), - ('.\\scripts\\d3.v7.min.js', '.\\scripts'), - ('.\\scripts\\chat.js', '.\\scripts'), - ('.\\scripts\\chat.css', '.\\scripts'), - ('.\\scripts\\garmin-functions.js', '.\\scripts'), - ('.\\scripts\\highlight.min.js', '.\\scripts'), - ('.\\scripts\\highlight.min.css', '.\\scripts'), - ('.\\scripts\\moment.min.js', '.\\scripts'), - ('.\\scripts\\popper.min.js', '.\\scripts'), - ('.\\scripts\\Tooltip.min.js', '.\\scripts'), - ('.\\scripts\\MDB-Free_4.13.0', '.\\scripts\\MDB-Free_4.13.0'), - ('.\\scripts\\timeline', '.\\scripts\\timeline'), - ('.\\scripts\\artifacts', '.\\scripts\\artifacts')], + datas=[('.\\scripts', '.\\scripts')], hiddenimports=[], hookspath=['.\\'], runtime_hooks=[], @@ -44,6 +25,8 @@ exe = EXE(pyz, bootloader_ignore_signals=False, strip=False, upx=True, - console=False, + console=True, + hide_console='hide-early', + disable_windowed_traceback=False, upx_exclude=[], runtime_tmpdir=None ) \ No newline at end of file diff --git a/aleappGUI_macOS.spec b/aleappGUI_macOS.spec new file mode 100755 index 00000000..689f73a8 --- /dev/null +++ b/aleappGUI_macOS.spec @@ -0,0 +1,62 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['aleappGUI.py'], + pathex=['scripts/artifacts'], + binaries=[], + datas=[('scripts/', 'scripts')], + hiddenimports=[ + 'bcrypt', + 'bencoding', + 'blackboxprotobuf', + 'Crypto.Cipher.AES', + 'Crypto.Util.Padding', + 'fitdecode', + 'folium', + 'PIL.Image', + 'polyline', + 'xmltodict', + 'xlsxwriter', + ], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='aleappGUI', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity='42F9AD88C52A9888352AB869F1E6EC207A29D308', + entitlements_file=None, +) +coll = COLLECT( + exe, + a.binaries, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='aleappGUI', +) +app = BUNDLE( + coll, + name='aleappGUI.app', + icon='../icon.icns', + bundle_identifier='4n6.brigs.ALEAPP', + version='3.2.1', +) diff --git a/aleapp_macOS.spec b/aleapp_macOS.spec new file mode 100644 index 00000000..96c96322 --- /dev/null +++ b/aleapp_macOS.spec @@ -0,0 +1,49 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['aleapp.py'], + pathex=['scripts/artifacts'], + binaries=[], + datas=[('scripts/', 'scripts')], + hiddenimports=[ + 'bcrypt', + 'bencoding', + 'blackboxprotobuf', + 'Crypto.Cipher.AES', + 'Crypto.Util.Padding', + 'fitdecode', + 'folium', + 'PIL.Image', + 'polyline', + 'xmltodict', + 'xlsxwriter', + ], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='aleapp', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity='42F9AD88C52A9888352AB869F1E6EC207A29D308', + entitlements_file=None, +) diff --git a/scripts/version_info.py b/scripts/version_info.py index 24bfa56a..f49ac87a 100755 --- a/scripts/version_info.py +++ b/scripts/version_info.py @@ -1,4 +1,4 @@ -aleapp_version = '3.1.11' +aleapp_version = '3.2.1' # Contributors List # Format = [ Name, Blog-url, Twitter-handle, Github-url]