def closeChrome(self): for tabId, tabInfo in self.tabList.iteritems(): event = 'Close' text = '{"time": ' + str(t) + ', "browser": "Google Chrome", "url": "' + tabInfo['url'] + '", "title": "' + tabInfo['title'] + '", "event": ' + '"Close"' +' }' utils_cocoa.write_to_file(text, cfg.URLLOG) self.tabList = {}
def move_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference('eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: if event.type() == NSMouseMoved: loc = NSEvent.mouseLocation() # get all the image size information scr = NSScreen.screens() xmin = 0 ymin = 0 for s in scr: if s.frame().origin.x < xmin: xmin = s.frame().origin.x if s.frame().origin.y < ymin: ymin = s.frame().origin.y x = int(loc.x) - xmin y = int(loc.y) - ymin # write JSON object to movelog file text = '{"time": '+ str(cfg.NOW()) + ' , "location": [' + str(x) + ',' + str(y) + ']}' utils_cocoa.write_to_file(text, cfg.MOVELOG)
def safariCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: notification_title = str(kwargs['notification'])[2:] if notification_title != "MenuItemSelected" and notification_title != "TitleChanged": self.AppRecorder.windowCallback(**kwargs) if self.lastSafariTime == None: self.lastSafariTime = int(utils_cocoa.unix_to_safari(cfg.NOW())) return conn = sqlite3.connect(os.path.expanduser('~/Library/Safari/History.db')) c = conn.cursor() c.execute("SELECT visit_time, title, url FROM history_visits LEFT JOIN history_items ON history_visits.history_item == history_items.id where visit_time > " + str(self.lastSafariTime)) # looks like safari writes every ~10 seconds so offset by 10. Add an extra 0.1 sec for roundoff issues safariTimeOffset = int(utils_cocoa.unix_to_safari(cfg.NOW())) - 9.9 if self.lastSafariTime < safariTimeOffset: self.lastSafariTime = safariTimeOffset for entry in c.fetchall(): url = entry[2] title = entry[1] time = entry[0] if self.lastSafariTime < time: self.lastSafariTime = time text = '{"time": ' + str(utils_cocoa.safari_to_unix(time)) + ', "browser": "Safari", "url": "' + str(url) + '", "title": "' + str(title) + '", "event": ' + '"Open"' +' }' utils_cocoa.write_to_file(text, cfg.URLLOG) if not recording: self.lastSafariTime = None
def appTerminateCallback_(self, notification): recording = preferences.getValueForPreference('recording') # get event info t = cfg.NOW() app = notification.userInfo()["NSWorkspaceApplicationKey"] #TODO find out why we are getting no name from the app terminate name = unicode(app.localizedName()) pid = int(app.processIdentifier()) # let app listener be garbage collected by removing our saved reference to it if pid in self.watched.keys(): del self.watched[pid] # watcher = self.watched[p] if recording: # log the the application has closed text = '{"time": '+ str(t) + ' , "type": "Close", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) #TODO throw app deactivate event when active application terminates? # would have to tell what app this is, and if it was the most # previously active app if unicode(app.localizedName()) == "\"Google Chrome\"": self.wr.closeChrome() # check if the screen geometry changed and update active window self.updateWindowList()
def windowCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: # get event info t = cfg.NOW() notification_title = str(kwargs['notification'])[2:-1] # remove 'AX' from front of event names before we save that info # TODO this app title may not match what we get from app.localizedName() # find way to reconcile app_title = unicode(kwargs['element']['AXTitle']) # take screenshot eventScreenshots = preferences.getValueForPreference('eventScreenshots') if eventScreenshots: self.sniffer.activity_tracker.take_screenshot() # when miniaturized, we may not be able to get window title and position data if notification_title == "WindowMiniaturized": # write to window log file about event text = '{"time": '+ str(t) + ' , "type": "' + notification_title + '", "app": "' + app_title + '"}' utils_cocoa.write_to_file(text, cfg.WINDOWLOG) # all other events should let us get title and postiion data else: # get the relevant window data title = unicode(kwargs['element']['AXFocusedWindow']['AXTitle']) position = str(kwargs['element']['AXFocusedWindow']['AXPosition']) size = str(kwargs['element']['AXFocusedWindow']['AXSize']) # write to window log file about event text = '{"time": ' + str(t) + ' , "type": "' + notification_title + '", "app": "' + app_title + '", "window": "' + title + '", "position": ' + position + ' , "size": ' + size +' }' utils_cocoa.write_to_file(text, cfg.WINDOWLOG) # get most recent screen geometry and update active window self.updateWindowList()
def click_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference('eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: # check if the clipboard has updated self.sniffer.clr.get_clipboard_contents() # get data ready to write loc = NSEvent.mouseLocation() scr = NSScreen.screens() xmin = 0 ymin = 0 for s in scr: if s.frame().origin.x < xmin: xmin = s.frame().origin.x if s.frame().origin.y < ymin: ymin = s.frame().origin.y x = int(loc.x) - xmin y = int(loc.y) - ymin #get click type click_type = "Unknown" if event.type() == NSLeftMouseDown: click_type = "Left" elif event.type() == NSRightMouseDown: click_type = "Right" # write JSON object to clicklog file text = '{"time": '+ str(cfg.NOW()) + ' , "button": "' + click_type + '", "location": [' + str(x) + ',' + str(y) + ']}' utils_cocoa.write_to_file(text, cfg.CLICKLOG)
def appLaunchCallback_(self, notification): recording = preferences.getValueForPreference('recording') # get event info t = cfg.NOW() app = notification.userInfo()["NSWorkspaceApplicationKey"] name = unicode(app.localizedName()) pid = int(app.processIdentifier()) # create app listener for this app's window events if app.activationPolicy() == 0: mess = acc.create_application_ref(pid = pid) mess.set_callback(self.windowCallback) mess.watch("AXMoved", "AXWindowResized", "AXFocusedWindowChanged", "AXWindowCreated","AXWindowMiniaturized", "AXWindowDeminiaturized") self.watched[pid] = mess if recording: # log that the application launched text = '{"time": '+ str(t) + ' , "type": "Open", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) # log that application is active if app.isActive(): text = '{"time": '+ str(t) + ' , "type": "Active", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) # take a screenshot eventScreenshots = preferences.getValueForPreference('eventScreenshots') if eventScreenshots: self.sniffer.activity_tracker.take_screenshot() # check if the screen geometry changed and update active window self.updateWindowList()
def unpause_app_observers(self): t = cfg.NOW() # get workspace and list of all applications workspace = NSWorkspace.sharedWorkspace() activeApps = workspace.runningApplications() # prune list of applications to apps that appear in the dock regularApps = [] for app in activeApps: if app.activationPolicy() == 0: regularApps.append(app) # listen for window events of these applications for app in regularApps: name = unicode(app.localizedName()) # log that the app recording will stop text = '{"time": '+ str(t) + ' , "type": "Open", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) if app.isActive(): text = '{"time": '+ str(t) + ' , "type": "Active", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) # check if the screen geometry changed and update active window self.updateWindowList()
def closeChrome(self): for tabId, tabInfo in self.tabList.iteritems(): event = 'Close' text = '{"time": ' + str( t) + ', "browser": "Google Chrome", "url": "' + tabInfo[ 'url'] + '", "title": "' + tabInfo[ 'title'] + '", "event": ' + '"Close"' + ' }' utils_cocoa.write_to_file(text, cfg.URLLOG) self.tabList = {}
def scroll_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference('eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: if event.type() == NSScrollWheel: # write JSON object to scrolllog file text = '{"time": '+ str(cfg.NOW()) + ' , "distance": [' + str(event.deltaX()) + ',' + str(event.deltaY()) + '], "window_number": ' + str(event.windowNumber()) + '}' utils_cocoa.write_to_file(text, cfg.SCROLLLOG)
def firefoxCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: notification_title = str(kwargs['notification'])[2:] if notification_title != "MenuItemSelected" and notification_title != "TitleChanged": self.AppRecorder.windowCallback(**kwargs) if self.lastFirefoxTime == None: self.lastFirefoxTime = int( utils_cocoa.unix_to_firefox(cfg.NOW())) return profiles = [] profFile = open( os.path.expanduser( '~/Library/Application Support/Firefox/profiles.ini')) for line in profFile: if line[:5] == 'Path=': profiles.append(line[5:-1]) for profile in profiles: conn = sqlite3.connect( os.path.expanduser( '~/Library/Application Support/Firefox/' + profile + '/places.sqlite')) c = conn.cursor() c.execute( "SELECT visit_date, title, url FROM moz_historyvisits LEFT JOIN moz_places ON moz_historyvisits.place_id == moz_places.id where visit_date > " + str(self.lastFirefoxTime)) # offset by 10. Add an extra 0.1 sec for roundoff issues ffTimeOffset = int(utils_cocoa.unix_to_firefox( cfg.NOW())) - 9.9 if self.lastFirefoxTime < ffTimeOffset: self.lastFirefoxTime = ffTimeOffset for entry in c.fetchall(): url = entry[2] title = entry[1] time = entry[0] if self.lastFirefoxTime < time: self.lastFirefoxTime = time text = '{"time": ' + str(utils_cocoa.firefox_to_unix( time)) + ', "browser": "Firefox", "url": "' + str( url) + '", "title": "' + str( title) + '", "event": ' + '"Open"' + ' }' utils_cocoa.write_to_file(text, cfg.URLLOG) if not recording: self.lastFirefoxTime = None
def get_clipboard_contents(self): # only store data if we have new items recording = preferences.getValueForPreference('recording') if recording: clip = NSPasteboard.generalPasteboard() count = clip.changeCount() if self.last_count == None: self.last_count = count elif count != self.last_count: self.last_count = count text = "" url = "" image = None path = "" items = clip.pasteboardItems() for i in items: t = i.types() # get the textual data if 'public.utf8-plain-text' in t: text = i.stringForType_('public.utf8-plain-text') if 'public.url' in t: url = i.stringForType_('public.url') if 'public.url-name' in t: url = i.stringForType_('public.url-name') if 'public.file-url' in t: url = i.stringForType_('public.file-url') # get image data if 'public.tiff' in t: image = i.dataForType_('public.tiff') if 'public.png' in t: image = i.dataForType_('public.png') if 'public.jpeg' in t: image = i.dataForType_('public.jpeg') # save image file if we have one if image != None: folder = os.path.join(cfg.CURRENT_DIR, "clipboard") filename = datetime.datetime.now().strftime( "%y%m%d-%H%M%S%f") path = os.path.join(folder, "" + filename + ".jpg") image.writeToFile_atomically_(path, False) # clean up text and url text = json.dumps(text) url = json.dumps(url) # save to a clipboard file tex = '{"time": ' + str( cfg.NOW() ) + ' , "text": ' + text + ' , "url": ' + url + ' , "image": "' + path + '"}' utils_cocoa.write_to_file(tex, cfg.CLIPLOG)
def wakeCallback_(self, notification): recording = preferences.getValueForPreference('recording') if recording: t = cfg.NOW() text = '{"time": '+ str(t) + ' , "type": "Wake"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) # take a screenshot eventScreenshots = preferences.getValueForPreference('eventScreenshots') if eventScreenshots: self.sniffer.activity_tracker.take_screenshot() # get updated list of applications and windows self.updateWindowList()
def scroll_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference( 'eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: if event.type() == NSScrollWheel: # write JSON object to scrolllog file text = '{"time": ' + str(cfg.NOW()) + ' , "distance": [' + str( event.deltaX()) + ',' + str( event.deltaY()) + '], "window_number": ' + str( event.windowNumber()) + '}' utils_cocoa.write_to_file(text, cfg.SCROLLLOG)
def get_clipboard_contents(self): # only store data if we have new items recording = preferences.getValueForPreference('recording') if recording: clip = NSPasteboard.generalPasteboard() count = clip.changeCount() if self.last_count == None: self.last_count = count elif count != self.last_count: self.last_count = count text = "" url = "" image = None path = "" items = clip.pasteboardItems() for i in items: t = i.types() # get the textual data if 'public.utf8-plain-text' in t: text = i.stringForType_('public.utf8-plain-text') if 'public.url' in t: url = i.stringForType_('public.url') if 'public.url-name' in t: url = i.stringForType_('public.url-name') if 'public.file-url' in t: url = i.stringForType_('public.file-url') # get image data if 'public.tiff' in t: image = i.dataForType_('public.tiff') if 'public.png' in t: image = i.dataForType_('public.png') if 'public.jpeg' in t: image = i.dataForType_('public.jpeg') # save image file if we have one if image != None: folder = os.path.join(cfg.CURRENT_DIR,"clipboard") filename = datetime.datetime.now().strftime("%y%m%d-%H%M%S%f") path = os.path.join(folder,""+filename+".jpg") image.writeToFile_atomically_(path ,False) # clean up text and url text = json.dumps(text) url = json.dumps(url) # save to a clipboard file tex = '{"time": '+ str(cfg.NOW()) + ' , "text": ' + text + ' , "url": ' + url + ' , "image": "' + path + '"}' utils_cocoa.write_to_file(tex, cfg.CLIPLOG)
def applicationWillTerminate_(self, application): t = cfg.NOW() # close all open app and window listeners sc.ar.stop_app_observers() # save recorder turned off event text = '{"time": '+ str(t) + ' , "type": "Exit"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) #TODO tell application to parse logs one last time before quiting sc.activity_tracker.storage.parseToSqlite() sc.activity_tracker.storage.sqlcommit() print "Exiting Traces..." sc.cancel()
def applicationDidFinishLaunching_(self, notification): print "Traces finished launching..." # save recorder turned on event t = cfg.NOW() text = '{"time": '+ str(t) + ' , "type": "Start"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) # set inital values for the preferences preferences.setInitialPreferenceValues() # create status-bar menu self.createStatusMenu() # start loops to take screenshots and parse log files self.activity_tracker.checkLoops()
def appDeactivateCallback_(self, notification): recording = preferences.getValueForPreference('recording') # get event info t = cfg.NOW() app = notification.userInfo()["NSWorkspaceApplicationKey"] # only save the info if we have app information # we don't get app information when this is thrown after an app closes if app.processIdentifier() == -1: return name = unicode(app.localizedName()) pid = int(app.processIdentifier()) # log that the application has become inactive if pid in self.watched.keys() and recording: text = '{"time": '+ str(t) + ' , "type": "Inactive", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) # check if the screen geometry changed and update active window self.updateWindowList()
def appActivateCallback_(self, notification): recording = preferences.getValueForPreference('recording') # get event info t = cfg.NOW() app = notification.userInfo()["NSWorkspaceApplicationKey"] name = unicode(app.localizedName()) pid = int(app.processIdentifier()) # log that the application has become active if pid in self.watched.keys() and recording: text = '{"time": '+ str(t) + ' , "type": "Active", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) # take screenshot eventScreenshots = preferences.getValueForPreference('eventScreenshots') if eventScreenshots: self.sniffer.activity_tracker.take_screenshot() # check if the screen geometry changed and update active window self.updateWindowList()
def pause_app_observers(self): t = cfg.NOW() # get workspace and list of all applications workspace = NSWorkspace.sharedWorkspace() activeApps = workspace.runningApplications() # prune list of applications to apps that appear in the dock regularApps = [] for app in activeApps: if app.activationPolicy() == 0: regularApps.append(app) # listen for window events of these applications for app in regularApps: name = unicode(app.localizedName()) # log that the app recording will stop text = '{"time": '+ str(t) + ' , "type": "Close", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) if app.isActive(): text = '{"time": '+ str(t) + ' , "type": "Inactive", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) # write a blank line to the geometry table to close out all windows text = '{"time": ' + str(t) + ', "geometry": {} }' utils_cocoa.write_to_file(text, cfg.GEOLOG)
def safariCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: notification_title = str(kwargs['notification'])[2:] if notification_title != "MenuItemSelected" and notification_title != "TitleChanged": self.AppRecorder.windowCallback(**kwargs) if self.lastSafariTime == None: self.lastSafariTime = int(utils_cocoa.unix_to_safari( cfg.NOW())) return conn = sqlite3.connect( os.path.expanduser('~/Library/Safari/History.db')) c = conn.cursor() c.execute( "SELECT visit_time, title, url FROM history_visits LEFT JOIN history_items ON history_visits.history_item == history_items.id where visit_time > " + str(self.lastSafariTime)) # looks like safari writes every ~10 seconds so offset by 10. Add an extra 0.1 sec for roundoff issues safariTimeOffset = int(utils_cocoa.unix_to_safari(cfg.NOW())) - 9.9 if self.lastSafariTime < safariTimeOffset: self.lastSafariTime = safariTimeOffset for entry in c.fetchall(): url = entry[2] title = entry[1] time = entry[0] if self.lastSafariTime < time: self.lastSafariTime = time text = '{"time": ' + str(utils_cocoa.safari_to_unix( time)) + ', "browser": "Safari", "url": "' + str( url) + '", "title": "' + str( title) + '", "event": ' + '"Open"' + ' }' utils_cocoa.write_to_file(text, cfg.URLLOG) if not recording: self.lastSafariTime = None
def toggleLogging_(self, notification): print "Toggle Recording" t = cfg.NOW() recording = preferences.getValueForPreference('recording') recording = not recording NSUserDefaultsController.sharedUserDefaultsController().defaults().setBool_forKey_(recording,'recording') self.activity_tracker.checkLoops() #change text and enabled status of screenshot menu item if recording: self.loggingMenuItem.setTitle_("Pause Recording") sc.ar.unpause_app_observers() text = '{"time": '+ str(t) + ' , "type": "Unpause"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) else: self.loggingMenuItem.setTitle_("Start Recording") sc.ar.pause_app_observers() text = '{"time": '+ str(t) + ' , "type": "Pause"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG) self.changeIcon()
def firefoxCallback(self, **kwargs): recording = preferences.getValueForPreference('recording') if recording: notification_title = str(kwargs['notification'])[2:] if notification_title != "MenuItemSelected" and notification_title != "TitleChanged": self.AppRecorder.windowCallback(**kwargs) if self.lastFirefoxTime == None: self.lastFirefoxTime = int(utils_cocoa.unix_to_firefox(cfg.NOW())) return profiles = [] profFile = open(os.path.expanduser('~/Library/Application Support/Firefox/profiles.ini')) for line in profFile: if line[:5] == 'Path=': profiles.append(line[5:-1]) for profile in profiles: conn = sqlite3.connect(os.path.expanduser('~/Library/Application Support/Firefox/' + profile + '/places.sqlite')) c = conn.cursor() c.execute("SELECT visit_date, title, url FROM moz_historyvisits LEFT JOIN moz_places ON moz_historyvisits.place_id == moz_places.id where visit_date > " + str(self.lastFirefoxTime)) # offset by 10. Add an extra 0.1 sec for roundoff issues ffTimeOffset = int(utils_cocoa.unix_to_firefox(cfg.NOW())) - 9.9 if self.lastFirefoxTime < ffTimeOffset: self.lastFirefoxTime = ffTimeOffset for entry in c.fetchall(): url = entry[2] title = entry[1] time = entry[0] if self.lastFirefoxTime < time: self.lastFirefoxTime = time text = '{"time": ' + str(utils_cocoa.firefox_to_unix(time)) + ', "browser": "Firefox", "url": "' + str(url) + '", "title": "' + str(title) + '", "event": ' + '"Open"' +' }' utils_cocoa.write_to_file(text, cfg.URLLOG) if not recording: self.lastFirefoxTime = None
def click_handler(self, event): recording = preferences.getValueForPreference('recording') event_screenshots = preferences.getValueForPreference( 'eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if recording: # check if the clipboard has updated self.sniffer.clr.get_clipboard_contents() # get data ready to write loc = NSEvent.mouseLocation() scr = NSScreen.screens() xmin = 0 ymin = 0 for s in scr: if s.frame().origin.x < xmin: xmin = s.frame().origin.x if s.frame().origin.y < ymin: ymin = s.frame().origin.y x = int(loc.x) - xmin y = int(loc.y) - ymin #get click type click_type = "Unknown" if event.type() == NSLeftMouseDown: click_type = "Left" elif event.type() == NSRightMouseDown: click_type = "Right" # write JSON object to clicklog file text = '{"time": ' + str(cfg.NOW( )) + ' , "button": "' + click_type + '", "location": [' + str( x) + ',' + str(y) + ']}' utils_cocoa.write_to_file(text, cfg.CLICKLOG)
def key_handler(self, event): # neither of these is returning a valid value, just None and 0 # print event.window() # print event.windowNumber() recording = preferences.getValueForPreference('recording') record_keystrokes = preferences.getValueForPreference('keystrokes') if recording and record_keystrokes: event_screenshots = preferences.getValueForPreference( 'eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if event.type() == NSKeyDown: # get list of applications that show up in the dock # workspace = NSWorkspace.sharedWorkspace() # activeApps = workspace.runningApplications() # app_name = "" # window_name = "" # for app in activeApps: # if app.isActive(): # app_name = app.localizedName() # # print type(app) # # window_name = app.windows() # # print app_name # # print window_name # # options = kCGWindowListOptionAll + kCGWindowListExcludeDesktopElements # windows = CGWindowListCopyWindowInfo(options, kCGNullWindowID) # print windows[0].keys() # for window in windows: # activeApp = utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']) # not working because I'm not calling it on the app itself # print NSApp.keyWindow() # print utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication().keys()) # keyWindow = utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication().keyWindow()) # get the modifier keys that were depressed when this key was pressed flags = event.modifierFlags() modifiers = [] # OS X api doesn't care it if is left or right if flags & NSControlKeyMask: modifiers.append('Ctrl') if flags & NSAlternateKeyMask: modifiers.append('Alt') if flags & NSCommandKeyMask: modifiers.append('Cmd') if flags & (NSShiftKeyMask | NSAlphaShiftKeyMask): modifiers.append('Shift') # TODO determine why we have to use keycodes here for enter and # backspace but can rely on the charachter list for the others # get the charachter of the pressed key character = event.charactersIgnoringModifiers() if event.keyCode() is 51: character = "Backspace" elif event.keyCode() is 8 and modifiers == ["Cmd"]: # trigger clipboard check self.sniffer.clr.get_clipboard_contents() elif event.keyCode() is 36: character = "Enter" elif event.keyCode() is 39 and modifiers == ["Shift"]: character = "\\\"" elif event.keyCode() is 42 and modifiers != ["Shift"]: character = "\\\\" elif event.keyCode() is 46 and modifiers == ["Cmd", "Shift"]: self.sniffer.delegate.showExperience_("Fake Notification") string = KEYCODES.get(character, character) if string in SKIP_MODIFIERS: return # write JSON object to keylog file text = '{"time": ' + str(cfg.NOW( )) + ' , "key": "' + string + '" , "modifiers": ' + str( modifiers) + '}' utils_cocoa.write_to_file(text, cfg.KEYLOG)
def updateWindowList(self): # get an early timestamp recording = preferences.getValueForPreference('recording') t = cfg.NOW() if recording: # clear our past geometry and active window self.apps_and_windows = {} active_window = None # get list of applications that show up in the dock workspace = NSWorkspace.sharedWorkspace() activeApps = workspace.runningApplications() regularApps = [] for app in activeApps: if app.activationPolicy() == 0: regularApps.append(app) # save app info to dictionary for app in regularApps: name = unicode(app.localizedName()) active = app.isActive() pid = app.processIdentifier() d = {'name': name, 'active': active, 'windows':{}} # get window and tab info for browsers if name == 'Google Chrome': d['windows'] = self.wr.getChromeURLs(active) if pid not in self.browser_pids: self.browser_pids.append(pid) elif name == 'Safari': d['windows'] = self.wr.getSafariURLs(active) if pid not in self.browser_pids: self.browser_pids.append(pid) self.apps_and_windows[int(pid)] = d # store app data by pid # get title of the active window if possible if active: try: mess = self.watched[pid] active_window = unicode(mess['AXFocusedWindow']['AXTitle']) except: pass # add list of current windows options = kCGWindowListOptionAll + kCGWindowListExcludeDesktopElements windows = CGWindowListCopyWindowInfo(options, kCGNullWindowID) for window in windows: try: # get window data owning_app_pid = window['kCGWindowOwnerPID'] # don't record window data if for a browser if owning_app_pid in self.browser_pids: continue window_layer = window['kCGWindowLayer'] name = unicode(window['kCGWindowName']) # window_id = window['kCGWindowNumber'] window_id = str(window['kCGWindowNumber']) if window_id[-1] == "L": window_id = window_id[0:-1] window_id = int(window_id) bounds = window['kCGWindowBounds'] win_bounds = {'width':bounds['Width'], 'height':bounds['Height'], 'x':bounds['X'], 'y':bounds['Y']} active = False if unicode(window['kCGWindowName']) == active_window: active = True on_screen = False if 'kCGWindowIsOnscreen' in window.keys(): on_screen = window['kCGWindowIsOnscreen'] # unless it has a name and is on the top layer, we don't count it if owning_app_pid in self.apps_and_windows and window_layer == 0 and name: # add window data to the app_window dictionary window_dict = {'name': name, 'bounds': win_bounds, 'active': active, 'onscreen': on_screen} self.apps_and_windows[owning_app_pid]['windows'][window_id] = window_dict except: pass # write self.apps_and_windows to a geometry file text = '{"time": ' + str(t) + ', "geometry": ' + str(self.apps_and_windows) + "}" utils_cocoa.write_to_file(text, cfg.GEOLOG)
def sleepCallback_(self, notification): recording = preferences.getValueForPreference('recording') if recording: t = cfg.NOW() text = '{"time": '+ str(t) + ' , "type": "Sleep"}' utils_cocoa.write_to_file(text, cfg.RECORDERLOG)
def start_app_observers(self): recording = preferences.getValueForPreference('recording') # prompt user to grant accessibility access to Traces, if not already granted acc.is_enabled() # get an early timestamp t = cfg.NOW() # create listeners for application events workspace = NSWorkspace.sharedWorkspace() nc = workspace.notificationCenter() s = objc.selector(self.appLaunchCallback_,signature='v@:@') nc.addObserver_selector_name_object_(self, s, 'NSWorkspaceDidLaunchApplicationNotification', None) s = objc.selector(self.appTerminateCallback_,signature='v@:@') nc.addObserver_selector_name_object_(self, s, 'NSWorkspaceDidTerminateApplicationNotification', None) s = objc.selector(self.appActivateCallback_,signature='v@:@') nc.addObserver_selector_name_object_(self, s, 'NSWorkspaceDidActivateApplicationNotification', None) s = objc.selector(self.appDeactivateCallback_,signature='v@:@') nc.addObserver_selector_name_object_(self, s, 'NSWorkspaceDidDeactivateApplicationNotification', None) # create listeners for system events s = objc.selector(self.wakeCallback_,signature='v@:@') nc.addObserver_selector_name_object_(self, s, 'NSWorkspaceDidWakeNotification', None) s = objc.selector(self.sleepCallback_,signature='v@:@') nc.addObserver_selector_name_object_(self, s, 'NSWorkspaceWillSleepNotification', None) # other events that may be useful to track in the future # https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/ # NSWorkspaceDidHideApplicationNotification # NSWorkspaceDidUnhideApplicationNotification # NSWorkspaceActiveSpaceDidChangeNotification # NSWorkspaceWillPowerOffNotification # NSWorkspaceDidPerformFileOperationNotification # get list of active applications activeApps = workspace.runningApplications() regularApps = [] for app in activeApps: if app.activationPolicy() == 0: # those that show up in the Dock regularApps.append(app) # listen for window events of these applications for app in regularApps: try: p = int(app.processIdentifier()) name = unicode(app.localizedName()) mess = acc.create_application_ref(pid=p) mess.set_callback(self.windowCallback) mess.watch("AXMoved", "AXWindowResized", "AXFocusedWindowChanged", "AXWindowCreated","AXWindowMiniaturized", "AXWindowDeminiaturized") # AXMainWindowChanged self.watched[p] = mess # we need to maintain the listener or it will be deleted on cleanup if recording: # log that the app is open text = '{"time": '+ str(t) + ' , "type": "Open", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) if app.isActive(): text = '{"time": '+ str(t) + ' , "type": "Active", "app": "' + name + '"}' utils_cocoa.write_to_file(text, cfg.APPLOG) except: raise print "Could not create event listener for application: " + str(name) # get inital list of windows and add window listeners self.updateWindowList() # start event loop to track events from other applications CFRunLoopRun()
def key_handler(self, event): # neither of these is returning a valid value, just None and 0 # print event.window() # print event.windowNumber() recording = preferences.getValueForPreference('recording') record_keystrokes = preferences.getValueForPreference('keystrokes') if recording and record_keystrokes: event_screenshots = preferences.getValueForPreference('eventScreenshots') if event_screenshots: self.sniffer.activity_tracker.take_screenshot() if event.type() == NSKeyDown: # get list of applications that show up in the dock # workspace = NSWorkspace.sharedWorkspace() # activeApps = workspace.runningApplications() # app_name = "" # window_name = "" # for app in activeApps: # if app.isActive(): # app_name = app.localizedName() # # print type(app) # # window_name = app.windows() # # print app_name # # print window_name # # options = kCGWindowListOptionAll + kCGWindowListExcludeDesktopElements # windows = CGWindowListCopyWindowInfo(options, kCGNullWindowID) # print windows[0].keys() # for window in windows: # activeApp = utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']) # not working because I'm not calling it on the app itself # print NSApp.keyWindow() # print utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication().keys()) # keyWindow = utils_cocoa.ascii_encode(NSWorkspace.sharedWorkspace().activeApplication().keyWindow()) # get the modifier keys that were depressed when this key was pressed flags = event.modifierFlags() modifiers = [] # OS X api doesn't care it if is left or right if flags & NSControlKeyMask: modifiers.append('Ctrl') if flags & NSAlternateKeyMask: modifiers.append('Alt') if flags & NSCommandKeyMask: modifiers.append('Cmd') if flags & (NSShiftKeyMask | NSAlphaShiftKeyMask): modifiers.append('Shift') # TODO determine why we have to use keycodes here for enter and # backspace but can rely on the charachter list for the others # get the charachter of the pressed key character = event.charactersIgnoringModifiers() if event.keyCode() is 51: character = "Backspace" elif event.keyCode() is 8 and modifiers == ["Cmd"]: # trigger clipboard check self.sniffer.clr.get_clipboard_contents() elif event.keyCode() is 36: character = "Enter" elif event.keyCode() is 39 and modifiers == ["Shift"]: character = "\\\"" elif event.keyCode() is 42 and modifiers != ["Shift"]: character = "\\\\" elif event.keyCode() is 46 and modifiers == ["Cmd", "Shift"]: self.sniffer.delegate.showExperience_("Fake Notification") string = KEYCODES.get(character, character) if string in SKIP_MODIFIERS: return # write JSON object to keylog file text = '{"time": '+ str(cfg.NOW()) + ' , "key": "' + string + '" , "modifiers": ' + str(modifiers) + '}' utils_cocoa.write_to_file(text, cfg.KEYLOG)