-
Notifications
You must be signed in to change notification settings - Fork 103
/
Copy pathdockitems.py
160 lines (134 loc) · 6.72 KB
/
dockitems.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
'''
Copyright (c) 2018 Yogesh Khatri
This file is part of mac_apt (macOS Artifact Parsing Tool).
Usage or distribution of this software/code is subject to the
terms of the MIT License.
dockitems.py
---------------
Reads the dock plist file for each user.
'''
import logging
from plugins.helpers.common import CommonFunctions
from plugins.helpers.macinfo import *
from plugins.helpers.writer import *
__Plugin_Name = "DOCKITEMS"
__Plugin_Friendly_Name = "Dock Items"
__Plugin_Version = "1.0"
__Plugin_Description = "Reads the Dock plist for every user"
__Plugin_Author = "Adam Ferrante"
__Plugin_Author_Email = "adam@ferrante.io"
__Plugin_Modes = "MACOS,ARTIFACTONLY"
__Plugin_ArtifactOnly_Usage = 'Provide the plist file located at /Users/<USER>/Library/Preferences/com.apple.dock.plist'
log = logging.getLogger('MAIN.' + __Plugin_Name) # Do not rename or remove this ! This is the logger object
#---- Do not change the variable names in above section ----#
class DockItem:
def __init__(self, file_label, parent_mod_date, file_mod_date, recent_used, file_type, file_data, guid, user, source_path):
self.file_label = file_label
if parent_mod_date and (parent_mod_date > 0xFFFFFFFF): # On High Sierra and above..
parent_mod_date = parent_mod_date & 0xFFFFFFFF # Killing upper 32 bits!
# Upper 32 bits maybe the finer resolution (microseconds?).
if file_mod_date and (file_mod_date > 0xFFFFFFFF): # On High Sierra and above..
file_mod_date = file_mod_date & 0xFFFFFFFF # Killing upper 32 bits!
self.parent_mod_date = CommonFunctions.ReadMacHFSTime(parent_mod_date)
self.file_mod_date = CommonFunctions.ReadMacHFSTime(file_mod_date)
self.recent_used = recent_used
self.file_type = file_type
self.file_path = file_data
self.guid = guid
self.user = user
self.path = source_path
def PrintAll(docks, output_params, input_path=''):
dock_info = [ ('File Label',DataType.TEXT),
('Parent Modified',DataType.TEXT),('File Modified',DataType.DATE),
('Recently Used',DataType.TEXT),
('File Type',DataType.TEXT),('File Path',DataType.TEXT),
('GUID',DataType.TEXT),
('User',DataType.TEXT),('Source',DataType.TEXT)
]
log.info (str(len(docks)) + " user dock item(s) found")
dock_list_final = []
for item in docks:
single_dock_item = [item.file_label, item.parent_mod_date, item.file_mod_date,
item.recent_used, item.file_type, item.file_path,
item.guid,
item.user, item.path
]
dock_list_final.append(single_dock_item)
WriteList("Dock Information", "Dock Items", dock_list_final, dock_info, output_params, input_path)
def GetPath(file_data):
if file_data:
path = file_data.get("_CFURLString", "")
if path.startswith("file://"):
return path[7:]
else:
return path
return ""
def GetDockItemsPlistFromImage(mac_info, plist_path):
success, plist, error = mac_info.ReadPlist(plist_path)
if success:
return plist
else:
log.error(error)
return None
def ParseDockItemsPlist(plist, docks, user_name, plist_path):
'''Parse plist and add items to docks list'''
for key in ['persistent-others', 'persistent-apps', 'recent-apps']:
if plist.get(key, None) != None:
try:
for item in plist[key]:
tile_data = item.get('tile-data', None)
if tile_data:
instance = DockItem(tile_data.get('file-label', ''),
tile_data.get('parent-mod-date', None),
tile_data.get('file-mod-date', None),
'Yes' if key=='recent-apps' else '',
tile_data.get('file-type', ''),
GetPath(tile_data.get('file-data', None)),
item.get('GUID', ''),
user_name, plist_path)
docks.append(instance)
else:
log.warning('No tile-data found!! Perhaps a newer format?')
except ValueError:
log.exception("Exception while processing {}".format(key))
else:
log.debug('Key {} not found!'.format(key))
def Plugin_Start(mac_info):
'''Main Entry point function for plugin'''
dock_items_path = '{}/Library/Preferences/com.apple.dock.plist' # PList within each users directory.
docks = []
processed_paths = []
for user in mac_info.users:
user_name = user.user_name
if user.home_dir == '/private/var/empty': continue # Optimization, nothing should be here!
elif user.home_dir == '/private/var/root': user_name = 'root' # Some other users use the same root folder, we will list such all users as 'root', as there is no way to tell
if user.home_dir in processed_paths: continue # Avoid processing same folder twice (some users have same folder! (Eg: root & daemon))
processed_paths.append(user.home_dir)
source_path = dock_items_path.format(user.home_dir) # Set a variable to the path of all user dock plist files.
if mac_info.IsValidFilePath(source_path): # Determine if the above path is valid.
mac_info.ExportFile(source_path, __Plugin_Name, user_name + "_", False)
plist = GetDockItemsPlistFromImage(mac_info, source_path)
if plist:
ParseDockItemsPlist(plist, docks, user_name, source_path)
if len(docks) > 0:
PrintAll(docks, mac_info.output_params, '')
else:
log.info('No dock items found')
def ReadDockPlistFile(input_file, docks):
success, plist, error = CommonFunctions.ReadPlist(input_file)
if success:
ParseDockItemsPlist(plist, docks, '', input_file)
else:
log.error ("Could not open plist, error was : " + error)
def Plugin_Start_Standalone(input_files_list, output_params):
log.info("Module Started as standalone")
for input_path in input_files_list:
log.debug("Input file passed was: " + input_path)
docks = []
ReadDockPlistFile(input_path, docks)
if len(docks) > 0:
PrintAll(docks, output_params, input_path)
else:
log.info('No dock items found in {}'.format(input_path))
if __name__ == '__main__':
print ("This plugin is a part of a framework and does not run independently on its own!")