forked from abrignoni/ALEAPP
-
Notifications
You must be signed in to change notification settings - Fork 0
/
aleappGUI.py
executable file
·344 lines (295 loc) · 26.1 KB
/
aleappGUI.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
import json
import typing
import aleapp
import PySimpleGUI as sg
import webbrowser
import plugin_loader
from scripts.ilapfuncs import *
from scripts.version_info import aleapp_version
from scripts.search_files import *
MODULE_START_INDEX = 1000
def add_case_data(casedata):
case_data_font = ("Helvetica", 12)
case_data_layout = [
[sg.Text('Add Case Data', font=("Helvetica", 18))],
[sg.Frame(layout=[
[sg.Input(size=(80,1), key='Case Number', default_text=casedata.get('Case Number', ''))]], title='Case Number')],
[sg.Frame(layout=[
[sg.Input(size=(80,1), key='Agency', default_text=casedata.get('Agency', ''))]], title='Agency')],
[sg.Frame(layout=[
[sg.Input(size=(80,1), key='Examiner', default_text=casedata.get('Examiner', ''))]], title='Examiner')],
[sg.Text('')],
[sg.Button('Load Case Data File', font=normal_font, key='LOADCASEDATA'),
sg.Button('Save Case Data File', font=normal_font, key='SAVECASEDATA'),
sg.Text(' | ', font=("Helvetica", 14)),
sg.Button('Clear', font=normal_font, key='CLEAR'),
sg.Button('Close', font=normal_font)]
]
case_data_window = sg.Window('Add Case Data', case_data_layout, font=case_data_font)
while True:
case_data_event, case_data_values = case_data_window.read()
if case_data_event in (None, 'Close'):
case_data_window.close()
return case_data_values
if case_data_event == 'CLEAR':
case_data_window['Case Number'].update('')
case_data_window['Agency'].update('')
case_data_window['Examiner'].update('')
continue
if case_data_event == 'SAVECASEDATA':
destination_path = sg.popup_get_file(
"Save case data file", save_as=True,
file_types=(('LEAPP Case Data (*.lcasedata)', '*.lcasedata'),),
default_extension='.icasedata', no_window=True, keep_on_top=True)
if destination_path:
with open(destination_path, "wt", encoding="utf-8") as case_data_out:
json.dump({"leapp": "case_data", "case_data_values": case_data_values}, case_data_out)
sg.Popup(f"Case Data saved: {destination_path}", title="Save Case Data")
case_data_window.close()
else:
continue
return case_data_values
if case_data_event == 'LOADCASEDATA':
destination_path = sg.popup_get_file(
"Load case data", save_as=False,
file_types=(('LEAPP Case Data (*.lcasedata)', '*.lcasedata'), ('All Files', '*')),
default_extension='.lcasedata', no_window=True)
if destination_path and os.path.exists(destination_path):
case_data_load_error = None
with open(destination_path, "rt", encoding="utf-8") as case_data_in:
try:
case_data = json.load(case_data_in)
except:
case_data_load_error = "File was not a valid case data file: invalid format"
if not case_data_load_error:
if isinstance(case_data, dict):
if case_data.get("leapp") != "case_data":
case_data_load_error = "File was not a valid case data file"
else:
casedata = case_data.get('case_data_values', {})
for key, value in casedata.items():
case_data_window[key].update(value)
else:
case_data_load_error = "File was not a valid case data file: invalid format"
if case_data_load_error:
sg.popup(case_data_load_error)
continue
else:
sg.popup(f"Loaded Case Data: {destination_path}", title="Load Case Data")
continue
else:
continue
def ValidateInput(values, window):
'''Returns tuple (success, extraction_type)'''
global module_end_index
i_path = values['INPUTPATH'] # input file/folder
o_path = values['OUTPUTPATH'] # output folder
ext_type = ''
if len(i_path) == 0:
sg.PopupError('No INPUT file or folder selected!', title="Error")
return False, ext_type
elif not os.path.exists(i_path):
sg.PopupError('INPUT file/folder does not exist!', title="Error")
return False, ext_type
elif os.path.isdir(i_path):
ext_type = 'fs'
else: # must be an existing file then
if not i_path.lower().endswith('.tar') and not i_path.lower().endswith('.zip') and not i_path.lower().endswith('.gz'):
sg.PopupError('Input file is not a supported archive! ', i_path, title="Error")
return False, ext_type
else:
ext_type = Path(i_path).suffix[1:].lower()
# check output now
if len(o_path) == 0 : # output folder
sg.PopupError('No OUTPUT folder selected!', title="Error")
return False, ext_type
one_element_is_selected = False
for x in range(1000, module_end_index):
if window[x].Get():
one_element_is_selected = True
break
if not one_element_is_selected:
sg.PopupError('No module selected for processing!', title="Error")
return False, ext_type
return True, ext_type
# initialize CheckBox control with module name
def CheckList(mtxt, lkey, mdstring, disable=False):
if mdstring == 'walStrings': #items in the if are modules that take a long time to run. Deselects them by default.
dstate = False
else:
dstate = True
return [sg.CBox(mtxt, default=dstate, key=lkey, metadata=mdstring, disabled=disable)]
def pickModules():
global module_end_index
global mlist
global loader
loader = plugin_loader.PluginLoader()
module_end_index = MODULE_START_INDEX # arbitrary number to not interfere with other controls
for plugin in sorted(loader.plugins, key=lambda p: p.category.upper()):
disabled = plugin.module_name == 'usagestatsVersion'
mlist.append(CheckList(f'{plugin.category} [{plugin.name} - {plugin.module_name}.py]', module_end_index, plugin.name, disabled))
module_end_index = module_end_index + 1
sg.theme('LightGreen5') # Add a touch of color
# All the stuff inside your window.
normal_font = ("Helvetica", 12)
if is_platform_macos():
log_window_height = 29
elif is_platform_linux():
log_window_height = 23
else:
log_window_height = 20
loader: typing.Optional[plugin_loader.PluginLoader] = None
mlist = []
# go through list of available modules and confirm they exist on the disk
pickModules()
GuiWindow.progress_bar_total = len(loader)
tzvalues = ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', 'Africa/Asmara', 'Africa/Asmera', 'Africa/Bamako', 'Africa/Bangui', 'Africa/Banjul', 'Africa/Bissau', 'Africa/Blantyre', 'Africa/Brazzaville', 'Africa/Bujumbura', 'Africa/Cairo', 'Africa/Casablanca', 'Africa/Ceuta', 'Africa/Conakry', 'Africa/Dakar', 'Africa/Dar_es_Salaam', 'Africa/Djibouti', 'Africa/Douala', 'Africa/El_Aaiun', 'Africa/Freetown', 'Africa/Gaborone', 'Africa/Harare', 'Africa/Johannesburg', 'Africa/Juba', 'Africa/Kampala', 'Africa/Khartoum', 'Africa/Kigali', 'Africa/Kinshasa', 'Africa/Lagos', 'Africa/Libreville', 'Africa/Lome', 'Africa/Luanda', 'Africa/Lubumbashi', 'Africa/Lusaka', 'Africa/Malabo', 'Africa/Maputo', 'Africa/Maseru', 'Africa/Mbabane', 'Africa/Mogadishu', 'Africa/Monrovia', 'Africa/Nairobi', 'Africa/Ndjamena', 'Africa/Niamey', 'Africa/Nouakchott', 'Africa/Ouagadougou', 'Africa/Porto-Novo', 'Africa/Sao_Tome', 'Africa/Timbuktu', 'Africa/Tripoli', 'Africa/Tunis', 'Africa/Windhoek', 'America/Adak', 'America/Anchorage', 'America/Anguilla', 'America/Antigua', 'America/Araguaina', 'America/Argentina/Buenos_Aires', 'America/Argentina/Catamarca', 'America/Argentina/ComodRivadavia', 'America/Argentina/Cordoba', 'America/Argentina/Jujuy', 'America/Argentina/La_Rioja', 'America/Argentina/Mendoza', 'America/Argentina/Rio_Gallegos', 'America/Argentina/Salta', 'America/Argentina/San_Juan', 'America/Argentina/San_Luis', 'America/Argentina/Tucuman', 'America/Argentina/Ushuaia', 'America/Aruba', 'America/Asuncion', 'America/Atikokan', 'America/Atka', 'America/Bahia', 'America/Bahia_Banderas', 'America/Barbados', 'America/Belem', 'America/Belize', 'America/Blanc-Sablon', 'America/Boa_Vista', 'America/Bogota', 'America/Boise', 'America/Buenos_Aires', 'America/Cambridge_Bay', 'America/Campo_Grande', 'America/Cancun', 'America/Caracas', 'America/Catamarca', 'America/Cayenne', 'America/Cayman', 'America/Chicago', 'America/Chihuahua', 'America/Ciudad_Juarez', 'America/Coral_Harbour', 'America/Cordoba', 'America/Costa_Rica', 'America/Creston', 'America/Cuiaba', 'America/Curacao', 'America/Danmarkshavn', 'America/Dawson', 'America/Dawson_Creek', 'America/Denver', 'America/Detroit', 'America/Dominica', 'America/Edmonton', 'America/Eirunepe', 'America/El_Salvador', 'America/Ensenada', 'America/Fort_Nelson', 'America/Fort_Wayne', 'America/Fortaleza', 'America/Glace_Bay', 'America/Godthab', 'America/Goose_Bay', 'America/Grand_Turk', 'America/Grenada', 'America/Guadeloupe', 'America/Guatemala', 'America/Guayaquil', 'America/Guyana', 'America/Halifax', 'America/Havana', 'America/Hermosillo', 'America/Indiana/Indianapolis', 'America/Indiana/Knox', 'America/Indiana/Marengo', 'America/Indiana/Petersburg', 'America/Indiana/Tell_City', 'America/Indiana/Vevay', 'America/Indiana/Vincennes', 'America/Indiana/Winamac', 'America/Indianapolis', 'America/Inuvik', 'America/Iqaluit', 'America/Jamaica', 'America/Jujuy', 'America/Juneau', 'America/Kentucky/Louisville', 'America/Kentucky/Monticello', 'America/Knox_IN', 'America/Kralendijk', 'America/La_Paz', 'America/Lima', 'America/Los_Angeles', 'America/Louisville', 'America/Lower_Princes', 'America/Maceio', 'America/Managua', 'America/Manaus', 'America/Marigot', 'America/Martinique', 'America/Matamoros', 'America/Mazatlan', 'America/Mendoza', 'America/Menominee', 'America/Merida', 'America/Metlakatla', 'America/Mexico_City', 'America/Miquelon', 'America/Moncton', 'America/Monterrey', 'America/Montevideo', 'America/Montreal', 'America/Montserrat', 'America/Nassau', 'America/New_York', 'America/Nipigon', 'America/Nome', 'America/Noronha', 'America/North_Dakota/Beulah', 'America/North_Dakota/Center', 'America/North_Dakota/New_Salem', 'America/Nuuk', 'America/Ojinaga', 'America/Panama', 'America/Pangnirtung', 'America/Paramaribo', 'America/Phoenix', 'America/Port-au-Prince', 'America/Port_of_Spain', 'America/Porto_Acre', 'America/Porto_Velho', 'America/Puerto_Rico', 'America/Punta_Arenas', 'America/Rainy_River', 'America/Rankin_Inlet', 'America/Recife', 'America/Regina', 'America/Resolute', 'America/Rio_Branco', 'America/Rosario', 'America/Santa_Isabel', 'America/Santarem', 'America/Santiago', 'America/Santo_Domingo', 'America/Sao_Paulo', 'America/Scoresbysund', 'America/Shiprock', 'America/Sitka', 'America/St_Barthelemy', 'America/St_Johns', 'America/St_Kitts', 'America/St_Lucia', 'America/St_Thomas', 'America/St_Vincent', 'America/Swift_Current', 'America/Tegucigalpa', 'America/Thule', 'America/Thunder_Bay', 'America/Tijuana', 'America/Toronto', 'America/Tortola', 'America/Vancouver', 'America/Virgin', 'America/Whitehorse', 'America/Winnipeg', 'America/Yakutat', 'America/Yellowknife', 'Antarctica/Casey', 'Antarctica/Davis', 'Antarctica/DumontDUrville', 'Antarctica/Macquarie', 'Antarctica/Mawson', 'Antarctica/McMurdo', 'Antarctica/Palmer', 'Antarctica/Rothera', 'Antarctica/South_Pole', 'Antarctica/Syowa', 'Antarctica/Troll', 'Antarctica/Vostok', 'Arctic/Longyearbyen', 'Asia/Aden', 'Asia/Almaty', 'Asia/Amman', 'Asia/Anadyr', 'Asia/Aqtau', 'Asia/Aqtobe', 'Asia/Ashgabat', 'Asia/Ashkhabad', 'Asia/Atyrau', 'Asia/Baghdad', 'Asia/Bahrain', 'Asia/Baku', 'Asia/Bangkok', 'Asia/Barnaul', 'Asia/Beirut', 'Asia/Bishkek', 'Asia/Brunei', 'Asia/Calcutta', 'Asia/Chita', 'Asia/Choibalsan', 'Asia/Chongqing', 'Asia/Chungking', 'Asia/Colombo', 'Asia/Dacca', 'Asia/Damascus', 'Asia/Dhaka', 'Asia/Dili', 'Asia/Dubai', 'Asia/Dushanbe', 'Asia/Famagusta', 'Asia/Gaza', 'Asia/Harbin', 'Asia/Hebron', 'Asia/Ho_Chi_Minh', 'Asia/Hong_Kong', 'Asia/Hovd', 'Asia/Irkutsk', 'Asia/Istanbul', 'Asia/Jakarta', 'Asia/Jayapura', 'Asia/Jerusalem', 'Asia/Kabul', 'Asia/Kamchatka', 'Asia/Karachi', 'Asia/Kashgar', 'Asia/Kathmandu', 'Asia/Katmandu', 'Asia/Khandyga', 'Asia/Kolkata', 'Asia/Krasnoyarsk', 'Asia/Kuala_Lumpur', 'Asia/Kuching', 'Asia/Kuwait', 'Asia/Macao', 'Asia/Macau', 'Asia/Magadan', 'Asia/Makassar', 'Asia/Manila', 'Asia/Muscat', 'Asia/Nicosia', 'Asia/Novokuznetsk', 'Asia/Novosibirsk', 'Asia/Omsk', 'Asia/Oral', 'Asia/Phnom_Penh', 'Asia/Pontianak', 'Asia/Pyongyang', 'Asia/Qatar', 'Asia/Qostanay', 'Asia/Qyzylorda', 'Asia/Rangoon', 'Asia/Riyadh', 'Asia/Saigon', 'Asia/Sakhalin', 'Asia/Samarkand', 'Asia/Seoul', 'Asia/Shanghai', 'Asia/Singapore', 'Asia/Srednekolymsk', 'Asia/Taipei', 'Asia/Tashkent', 'Asia/Tbilisi', 'Asia/Tehran', 'Asia/Tel_Aviv', 'Asia/Thimbu', 'Asia/Thimphu', 'Asia/Tokyo', 'Asia/Tomsk', 'Asia/Ujung_Pandang', 'Asia/Ulaanbaatar', 'Asia/Ulan_Bator', 'Asia/Urumqi', 'Asia/Ust-Nera', 'Asia/Vientiane', 'Asia/Vladivostok', 'Asia/Yakutsk', 'Asia/Yangon', 'Asia/Yekaterinburg', 'Asia/Yerevan', 'Atlantic/Azores', 'Atlantic/Bermuda', 'Atlantic/Canary', 'Atlantic/Cape_Verde', 'Atlantic/Faeroe', 'Atlantic/Faroe', 'Atlantic/Jan_Mayen', 'Atlantic/Madeira', 'Atlantic/Reykjavik', 'Atlantic/South_Georgia', 'Atlantic/St_Helena', 'Atlantic/Stanley', 'Australia/ACT', 'Australia/Adelaide', 'Australia/Brisbane', 'Australia/Broken_Hill', 'Australia/Canberra', 'Australia/Currie', 'Australia/Darwin', 'Australia/Eucla', 'Australia/Hobart', 'Australia/LHI', 'Australia/Lindeman', 'Australia/Lord_Howe', 'Australia/Melbourne', 'Australia/NSW', 'Australia/North', 'Australia/Perth', 'Australia/Queensland', 'Australia/South', 'Australia/Sydney', 'Australia/Tasmania', 'Australia/Victoria', 'Australia/West', 'Australia/Yancowinna', 'Brazil/Acre', 'Brazil/DeNoronha', 'Brazil/East', 'Brazil/West', 'CET', 'CST6CDT', 'Canada/Atlantic', 'Canada/Central', 'Canada/Eastern', 'Canada/Mountain', 'Canada/Newfoundland', 'Canada/Pacific', 'Canada/Saskatchewan', 'Canada/Yukon', 'Chile/Continental', 'Chile/EasterIsland', 'Cuba', 'EET', 'EST', 'EST5EDT', 'Egypt', 'Eire', 'Etc/GMT', 'Etc/GMT+0', 'Etc/GMT+1', 'Etc/GMT+10', 'Etc/GMT+11', 'Etc/GMT+12', 'Etc/GMT+2', 'Etc/GMT+3', 'Etc/GMT+4', 'Etc/GMT+5', 'Etc/GMT+6', 'Etc/GMT+7', 'Etc/GMT+8', 'Etc/GMT+9', 'Etc/GMT-0', 'Etc/GMT-1', 'Etc/GMT-10', 'Etc/GMT-11', 'Etc/GMT-12', 'Etc/GMT-13', 'Etc/GMT-14', 'Etc/GMT-2', 'Etc/GMT-3', 'Etc/GMT-4', 'Etc/GMT-5', 'Etc/GMT-6', 'Etc/GMT-7', 'Etc/GMT-8', 'Etc/GMT-9', 'Etc/GMT0', 'Etc/Greenwich', 'Etc/UCT', 'Etc/UTC', 'Etc/Universal', 'Etc/Zulu', 'Europe/Amsterdam', 'Europe/Andorra', 'Europe/Astrakhan', 'Europe/Athens', 'Europe/Belfast', 'Europe/Belgrade', 'Europe/Berlin', 'Europe/Bratislava', 'Europe/Brussels', 'Europe/Bucharest', 'Europe/Budapest', 'Europe/Busingen', 'Europe/Chisinau', 'Europe/Copenhagen', 'Europe/Dublin', 'Europe/Gibraltar', 'Europe/Guernsey', 'Europe/Helsinki', 'Europe/Isle_of_Man', 'Europe/Istanbul', 'Europe/Jersey', 'Europe/Kaliningrad', 'Europe/Kiev', 'Europe/Kirov', 'Europe/Kyiv', 'Europe/Lisbon', 'Europe/Ljubljana', 'Europe/London', 'Europe/Luxembourg', 'Europe/Madrid', 'Europe/Malta', 'Europe/Mariehamn', 'Europe/Minsk', 'Europe/Monaco', 'Europe/Moscow', 'Europe/Nicosia', 'Europe/Oslo', 'Europe/Paris', 'Europe/Podgorica', 'Europe/Prague', 'Europe/Riga', 'Europe/Rome', 'Europe/Samara', 'Europe/San_Marino', 'Europe/Sarajevo', 'Europe/Saratov', 'Europe/Simferopol', 'Europe/Skopje', 'Europe/Sofia', 'Europe/Stockholm', 'Europe/Tallinn', 'Europe/Tirane', 'Europe/Tiraspol', 'Europe/Ulyanovsk', 'Europe/Uzhgorod', 'Europe/Vaduz', 'Europe/Vatican', 'Europe/Vienna', 'Europe/Vilnius', 'Europe/Volgograd', 'Europe/Warsaw', 'Europe/Zagreb', 'Europe/Zaporozhye', 'Europe/Zurich', 'GB', 'GB-Eire', 'GMT', 'GMT+0', 'GMT-0', 'GMT0', 'Greenwich', 'HST', 'Hongkong', 'Iceland', 'Indian/Antananarivo', 'Indian/Chagos', 'Indian/Christmas', 'Indian/Cocos', 'Indian/Comoro', 'Indian/Kerguelen', 'Indian/Mahe', 'Indian/Maldives', 'Indian/Mauritius', 'Indian/Mayotte', 'Indian/Reunion', 'Iran', 'Israel', 'Jamaica', 'Japan', 'Kwajalein', 'Libya', 'MET', 'MST', 'MST7MDT', 'Mexico/BajaNorte', 'Mexico/BajaSur', 'Mexico/General', 'NZ', 'NZ-CHAT', 'Navajo', 'PRC', 'PST8PDT', 'Pacific/Apia', 'Pacific/Auckland', 'Pacific/Bougainville', 'Pacific/Chatham', 'Pacific/Chuuk', 'Pacific/Easter', 'Pacific/Efate', 'Pacific/Enderbury', 'Pacific/Fakaofo', 'Pacific/Fiji', 'Pacific/Funafuti', 'Pacific/Galapagos', 'Pacific/Gambier', 'Pacific/Guadalcanal', 'Pacific/Guam', 'Pacific/Honolulu', 'Pacific/Johnston', 'Pacific/Kanton', 'Pacific/Kiritimati', 'Pacific/Kosrae', 'Pacific/Kwajalein', 'Pacific/Majuro', 'Pacific/Marquesas', 'Pacific/Midway', 'Pacific/Nauru', 'Pacific/Niue', 'Pacific/Norfolk', 'Pacific/Noumea', 'Pacific/Pago_Pago', 'Pacific/Palau', 'Pacific/Pitcairn', 'Pacific/Pohnpei', 'Pacific/Ponape', 'Pacific/Port_Moresby', 'Pacific/Rarotonga', 'Pacific/Saipan', 'Pacific/Samoa', 'Pacific/Tahiti', 'Pacific/Tarawa', 'Pacific/Tongatapu', 'Pacific/Truk', 'Pacific/Wake', 'Pacific/Wallis', 'Pacific/Yap', 'Poland', 'Portugal', 'ROC', 'ROK', 'Singapore', 'Turkey', 'UCT', 'US/Alaska', 'US/Aleutian', 'US/Arizona', 'US/Central', 'US/East-Indiana', 'US/Eastern', 'US/Hawaii', 'US/Indiana-Starke', 'US/Michigan', 'US/Mountain', 'US/Pacific', 'US/Samoa', 'UTC', 'Universal', 'W-SU', 'WET', 'Zulu']
layout = [ [sg.Text('Android Logs, Events, And Protobuf Parser', font=("Helvetica", 22))],
[sg.Text('https://github.com/abrignoni/ALEAPP', font=("Helvetica", 14))],
[sg.Frame(layout=[
[sg.Input(size=(97,1), key='INPUTPATH'),
sg.FileBrowse(font=normal_font, button_text='Browse File', key='INPUTFILEBROWSE'),
sg.FolderBrowse(font=normal_font, button_text='Browse Folder', target=(sg.ThisRow, -2), key='INPUTFOLDERBROWSE')
]
],
title='Select the file (tar/zip/gz) or directory of the target Android full file system extraction for parsing:')],
[sg.Frame(layout=[
[sg.Input(size=(112,1), key='OUTPUTPATH'),
sg.FolderBrowse(font=normal_font, button_text='Browse Folder')
]
],
title='Select Output Folder:')],
[sg.Text('Available Modules')],
[sg.Button('Select All', key='SELECT ALL'), sg.Button('Deselect All', key='DESELECT ALL'),
sg.Button('Load Profile', key='LOAD PROFILE'), sg.Button('Save Profile', key='SAVE PROFILE'),
# sg.FileBrowse(
# button_text='Load Profile', key='LOADPROFILE', enable_events=True, target='LOADPROFILE',
# file_types=(('ALEAPP Profile (*.alprofile)', '*.alprofile'), ('All Files', '*'))),
# sg.FileSaveAs(
# button_text='Save Profile', key='SAVEPROFILE', enable_events=True, target='SAVEPROFILE',
# file_types=(('ALEAPP Profile (*.alprofile)', '*.alprofile'), ('All Files', '*')),
# default_extension='.alprofile')
sg.Text(' |', font=("Helvetica", 14)),
sg.Button('Add Case Data', key='ADD CASE DATA'),
sg.Text(' |', font=("Helvetica", 14)),
sg.Text('Timezone Offset (Not Implemented Yet):', font=("Helvetica", 14)),
sg.Combo(list(tzvalues), size=(20,15), key='timezone',readonly=True)
],
[sg.Column(mlist, size=(300,310), scrollable=True), sg.Output(size=(85,log_window_height))],
[sg.ProgressBar(max_value=GuiWindow.progress_bar_total, orientation='h', size=(86, 7), key='PROGRESSBAR', bar_color=('DarkGreen', 'White'))],
[sg.Submit('Process', font=normal_font), sg.Button('Close', font=normal_font)] ]
# Create the Window
window = sg.Window(f'ALEAPP version {aleapp_version}', layout)
GuiWindow.progress_bar_handle = window['PROGRESSBAR']
profile_filename = None
casedata = {}
# Event Loop to process "events" and get the "values" of the inputs
while True:
event, values = window.read()
if event in (None, 'Close'): # if user closes window or clicks cancel
break
if event == "SELECT ALL":
# mark all modules
for x in range(MODULE_START_INDEX, module_end_index):
window[x].Update(True)
if event == "DESELECT ALL":
# none modules
for x in range(MODULE_START_INDEX, module_end_index):
window[x].Update(False if window[x].metadata != 'usagestatsVersion' else True) # usagestatsVersion.py is REQUIRED
if event == "SAVE PROFILE":
destination_path = sg.popup_get_file(
"Save a profile", save_as=True,
file_types=(('ALEAPP Profile (*.alprofile)', '*.alprofile'),),
default_extension='.alprofile', no_window=True)
if destination_path:
ticked = []
for x in range(MODULE_START_INDEX, module_end_index):
if window[x].Get():
key = window[x].metadata
ticked.append(key)
with open(destination_path, "wt", encoding="utf-8") as profile_out:
json.dump({"leapp": "aleapp", "format_version": 1, "plugins": ticked}, profile_out)
sg.Popup(f"Profile saved: {destination_path}", title="Save a profile")
if event == "LOAD PROFILE":
destination_path = sg.popup_get_file(
"Load a profile", save_as=False,
file_types=(('ALEAPP Profile (*.alprofile)', '*.alprofile'), ('All Files', '*')),
default_extension='.alprofile', no_window=True)
if destination_path and os.path.exists(destination_path):
profile_load_error = None
with open(destination_path, "rt", encoding="utf-8") as profile_in:
try:
profile = json.load(profile_in)
except:
profile_load_error = "File was not a valid profile file: invalid format"
if not profile_load_error:
if isinstance(profile, dict):
if profile.get("leapp") != "aleapp" or profile.get("format_version") != 1:
profile_load_error = "File was not a valid profile file: incorrect LEAPP or version"
else:
ticked = set(profile.get("plugins", []))
ticked.add("usagestatsVersion") # always
for x in range(MODULE_START_INDEX, module_end_index):
if window[x].metadata in ticked:
window[x].update(True)
else:
window[x].update(False)
else:
profile_load_error = "File was not a valid profile file: invalid format"
if profile_load_error:
sg.popup(profile_load_error)
else:
sg.popup(f"Loaded profile: {destination_path}", title="Load a profile")
profile_filename = destination_path
if event == "ADD CASE DATA":
casedata = add_case_data(casedata)
if event == 'Process':
#check is selections made properly; if not we will return to input form without exiting app altogether
is_valid, extracttype = ValidateInput(values, window)
if is_valid:
GuiWindow.window_handle = window
input_path = values['INPUTPATH']
output_folder = values['OUTPUTPATH']
# 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():
if input_path[1] == ':' and extracttype =='fs': input_path = '\\\\?\\' + input_path.replace('/', '\\')
if output_folder[1] == ':': output_folder = '\\\\?\\' + output_folder.replace('/', '\\')
# re-create modules list based on user selection
# search_list = { 'usagestatsVersion' : tosearch['usagestatsVersion'] } # hardcode usagestatsVersion as first item
search_list = [loader['usagestatsVersion']] # hardcode usagestatsVersion as first item
s_items = 0
for x in range(MODULE_START_INDEX, module_end_index):
if window[x].Get():
key = window[x].metadata
if key in loader and key != 'usagestatsVersion':
search_list.append(loader[key])
s_items = s_items + 1 # for progress bar
# no more selections allowed
window[x].Update(disabled=True)
window['SELECT ALL'].update(disabled=True)
window['DESELECT ALL'].update(disabled=True)
GuiWindow.window_handle = window
out_params = OutputParameters(output_folder)
wrap_text = True
time_offset = values['timezone']
if time_offset == '':
time_offset = 'UTC'
crunch_successful = aleapp.crunch_artifacts(
search_list, extracttype, input_path, out_params, len(loader)/s_items, wrap_text, loader, casedata, time_offset, profile_filename)
if crunch_successful:
report_path = os.path.join(out_params.report_folder_base, 'index.html')
if report_path.startswith('\\\\?\\'): # windows
report_path = report_path[4:]
if report_path.startswith('\\\\'): # UNC path
report_path = report_path[2:]
locationmessage = 'Report name: ' + report_path
sg.Popup('Processing completed', locationmessage)
webbrowser.open_new_tab('file://' + report_path)
else:
log_path = out_params.screen_output_file_path
if log_path.startswith('\\\\?\\'): # windows
log_path = log_path[4:]
sg.Popup('Processing failed :( ', f'See log for error details..\nLog file located at {log_path}', title="Error")
break
window.close()