How Mac OS X Timing app can track files - objective-c

I am curious about how Timing is able to know the amount of time you spend in a particular file. I understand that it needs Accessibility permission, but after that, how is it able to detect what's currently on the screen, plus accessing the path to a given file. I find intriguing, for example, that it knows that I am on Xcode, but how does it know I am working on a specific file, inside Xcode?

I don't work on Timing, so I can only make an educated guess on how their app was implemented.
Timing claims to keep track of three main data points: the apps you use, the websites you visit, and the documents you edit.
For applications, Timing probably listens to the NSWorkspaceDidLaunchApplicationNotification notification, which contains information on the application that was just launched. To check the currently open applications when Timing is launched, it probably checks the non-background processes from System Events, possibly like this:
osascript -e 'tell application "System Events" to get name of (processes where background only is false)'
(Source Get list of running Apps on Mac OS X in Bash?)
For history, Timing might use the HTML5 History API with Safari (I don't know what browsers Timing claims to support with this feature), or take an approach like Charles Proxy and monitor any incoming and outgoing packets and requests. The implementation may vary depending on if Timing requires admin privileges.
For documents, Timing might use the lsof command as Droppy suggested in their comment, or it might use one of the Apple interfaces. Pre-El Capitan, Apple listed recent documents in a plist file at the path ~/Library/Preferences/com.apple.recentitems.plist. In macOS versions newer than El Capitan, you can use the mdfind command and specify the kMDItemContentModificationDate value to find files modified between two dates:
mdfind -onlyin $HOME '((kMDItemContentModificationDate > $time.now(-60m)) && (kMDItemContentModificationDate < $time.now()))' | grep -v /Library/
(Source Alfred)

Related

Detect if a user logged in or logged out

I have a launch daemon that will need to spawn a tray icon in a users session on OSX. My current problem is: is there a way to get an event whenever a user logs in or logs out? Similar to using logind or consolekit on linux.
The tool you want is a LaunchAgent. LaunchAgents are automatically launched when a user logs in, and shut down when the log out. If you also have a LaunchDaemon, you can use a LaunchAgent to communicate to it from the user context. See Creating Launch Daemons and Agents for full details and how to set it up. Make sure to look at XPC services as well (in the same doc) to understand one way to communicate between processes. You can also use loopback networking, but XPC is more powerful and preferred when appropriate.
If you're building this kind of thing, you definitely want to read the entire Daemons and Services Programming Guide and also TN2083: Daemons and Agents. That tech note is probably the most important document you'll read for this kind of problem. OS X is not like Linux (or BSD) in this regard.

How To Do Privilege Elevation on OSX with Objective C

My custom Cocoa-based setup.app on Mac OSX that I made in Objective C needs to install a LaunchDaemon for doing elevated privilege tasks such as an antivirus program that needs to scan the entire hard drive and therefore needs root privileges. How can I make my setup application prompt the customer for their admin login and then install that LaunchDaemon into /Library/LaunchDaemons (and note I don't mean ~/Library/LaunchDaemons)?
The way I'm currently handling it is by using AppleScript with the admin privilege. It prompts for this login and then the AppleScript does the copying into this folder without the OS complaining. However, I assume that's not the proper technique -- that I should be doing this entirely in Objective C somehow?
Note that I can't use SMBlessJob in this case because it is for this reason that I'm creating the Launch Daemon in the first place.
BACKGROUND INFORMATION
I have a special need to create a custom setup.app -- just like the fact that Norton's AV application uses a custom setup.app. This is because the Apple PKG and DMG installers do not permit downloading of very large files (like virus definitions) from a server during install with some kind of friendly feedback. I mean, I can make a PKG file download a file from the server when running a Perl script or Bash script, but then the installer just hangs the progress bar for the amount of minutes it takes to download, not giving any other feedback to the user except that hung progress bar, and so the user thinks the installer is broke, when it's not. That's why I had to make my own custom setup.app, just like Norton did for their AV application.
Normally, SMJobBless would be the technique to do this. It's the one Apple recommends now as of 2016. Here's the readme.txt for Apple's sample project:
https://developer.apple.com/library/mac/samplecode/SMJobBless/Listings/ReadMe_txt.html
However, that's not the only way to do it. Another route would be to have your installer use AppleScript to prompt and run a Bash or Perl script with elevated privileges to install the LaunchDaemon, as well. (That's actually easier than SMJobBless.)
Basically, either technique installs a LaunchDaemon (e.g., "service") into a special folder, and that daemon can be set with elevated privileges, which can then run anything you want -- even command line commands. A super fantastic explanation of LaunchDaemons and LaunchAgents is here:
http://launchd.info/
Now, the problem is how to communicate with it from your application, once installed. They leave that up to you, and there are various techniques. However, they also leave it up to you to secure this so that it's not an attack vector.
A fantastic article on how to do IPC (Inter Process Communication between your application and this service) is here:
http://nshipster.com/inter-process-communication/
One IPC protocol on OSX is Distributed Objects, which is quite smooth from an architecture perspective -- you'll feel more like it's "coding" instead of "sending messages back and forth" like other IPC protocols. I've written a Stack Overflow post on this because the docs are shoddy and the existing examples on the Apple site and others are stale (won't compile on XCode7.1 with OSX 10.10+).
On communication protocol between your application and daemon/service, you can probably get away with key/value, XML, or JSON messages that are encrypted with AES256 with a long password and converted to Base64 encoding, and then use one of the various IPC mechanisms. However, that's another topic entirely.

Mac OS X how can binary application (packaged in .app) change System Configuration without asking for password?

I am writing an application that when is running should modify SystemConfiguration to set system wide proxy.
I know it is possible to do that using "Authorization Services" framework provided by Apple, however I see that it keeps asking for a user password to allow changes.
On the other hand I have 3rd party application (not the one I am writing) that does the same, but does not require user password. The application is not even written in Objective-C, but written in FreePascal (FPC) instead. Unfortunately I have no source code for this application to see how it does this trick.
I know I should be able to achieve the same (system config changes without sudo password) by either having Privileged Helper Tool supplied with the application (and perhaps install it on first run) or by going even nastier and loading a kext.
However I see that this application does neither of above. It only performs system calls and no password asked! I am completely puzzled how did they achieve that and would like to find a way to do the same.
So the question is - how to achieve complete "no password asked" for changing System Configuration on Mac OS X with an application?
PS: Application I have at hand runs as user, not root. And there is no modifications to sudoers neither.
This is silly, but after 2 days straight of searching for a solution I found that there is no special code nor any tricks required.
This is easily done via setting setuid bit to binary that requires escalated privilege and calling setuid(0) in the code before doing operations that require privilege (not sure if second part is necessary).
Relevant links:
Apple documentation
Related question on SO
PS: This works basically on any Unix-like system (BSD, Linux Solaris etc) with one details - this does not work on scripts (the ones that require hash-bang #! in order to execute interpreter) with exception of Solaris, where it seems to work just fine.

Any way to make file resource forks uncopyable by Finder?

Is there any way to make resource forks uncopyable? In particular I'm setting a custom badge icon to the files contained in a specific directory through NSWorkspace via – setIcon:forFile:options: and I'd like those badges to be lost as soon as the files gets copied outside the folder.
AFAIK there is no easy/standard way to make that happen...
IF the filesystems we are talking about are based locally on the the Mac itself then you can achieve what you want by implementing a daemon (running with high priviliges). This daemon basically integrates itself into the OS (via both FSEvent and kqueue) - this way it can monitor any file activity and act accordingly (remove the badge or similar).
For some source on how to build such a mechanism you can check this and this and this too.
IF you want to achieve this server-side there are several mechanisms - but they solely depend on the server technology (an notification and/or hooking mechanism).

What folder should my application write its launchd file?

I am trying to write a small Cocoa application that helps me manage my time, I want it check on startup if already has a launchd entry and if not, add itself an entry.
What is the correct folder to write the launchd file, and/or is there a special cocoa method to retrieve what the correct folder is (ie in the same way you retrieve the users document folder) or do you just assume one of the following hard coded locations?
The man pages list the following possible URL's I probably want to use ~/Library/LaunchAgents?
~/Library/LaunchAgents Per-user agents provided by the user.
/Library/LaunchAgents Per-user agents provided by the administrator.
/Library/LaunchDaemons System-wide daemons provided by the administrator.
/System/Library/LaunchAgents Per-user agents provided by Mac OS X.
/System/Library/LaunchDaemons System-wide daemons provided by Mac OS X.
You probably want ~/Library/LaunchAgents if your app will interact with the user. I'm not aware of a Cocoa method that will return this path for you.
There is a detailed tech note on agents and daemons that you should probably check out:
http://developer.apple.com/mac/library/technotes/tn2005/tn2083.html