The other day, I shipped my MacBook Pro off to be fixed, as the webcam and the backlight on the keyboard stopped working. (They broke some time ago, but it’s coming up on the end of the standard warranty, so I figured I’d get that done before it cost actual money to fix.) This post isn’t really about that computer, though; it’s much more about something that I managed to cobble together to take care of a thing I was doing on it. This post is much more about Platypus.
So, while I do still use my Macs a good bit, they don’t get used a whole lot for real work. (The ridiculous Ryzen machine takes care of that for the most part.) The Mac gets used for Web terminal stuff, email - Outlook on Mac is better than Outlook on Windows, because unified inbox and it actually checks gmail accounts on a regular basis why is this so freaking difficult - and messaging via Messages, so basically text messaging. With the new machine in for service, I set up my 2010 MacBook machine to handle the handful of Mac-type things I can’t reasonably do on the Windows PC. It works well enough for its age but it’s not the quickest thing to do Web browsing on, and I was getting somewhat annoyed anyway with having to switch machines to send Messages (or otherwise having to do all that on my phone).
To that end, I set up the MacBook as sort of a third screen next to the Ryzen machine’s monitors and put Synergy on it. Synergy still works really well, and I can control the MacBook from the Ryzen box. Then I got thinking on getting it set up to open links and stuff on the Ryzen system, rather than trying to do it on the MacBook itself. I did some poking around and found some manager apps that give you a lot more options on the Mac side - there’s Choosy and Finicky and a few other things - and I found a page talking about using the Chrome remote debugger, which has now been deprecated, and I had an epiphany: can’t I open a URL on the command line? And, well, yes - on either Mac or Windows, running a command will allow you to open arbitrary things through the GUI (on Mac you use “open”, on Windows you use “start”). So, “start http://www.google.com" opens a new tab in Chrome and loads that URL.
So now I just needed a way to get URLs across the wire from the Mac to Windows. The Windows side was actually pretty easy: I just wrote a (very) simple PHP script that looks for a “url” GET argument and then pipes that into an exec call. This is wildly insecure but it does at least check for a valid remote IP and it’d be pretty easy to put in a simple URL regex check in there or to add some simple request signing (and of course everything’s behind a firewall anyway), but, after firing it up with the built-in PHP server, I could hit a URL with another URL in it and it’d open on the Windows machine.
The Mac side was a bit more involved. I wrote a simple shell script to pump the first argument passed to it into curl, so curl’s hitting my fancy endpoint ont he Windows side of things, and so I could open URLs remotely via the command line that way. The next step was figuring out how to get macOS to treat it as a “Web browser” and therefore “open” links using it. That’s where Platypus comes in.
Platypus is a pretty neat utility that I had no idea existed until today. At its core, it allows you to wrap a script (including a shell script) in a standard Mac app bundle, so that to the system it looks and works mostly like a normal app. It’s also got a bunch of neat features to handle script output and do things like load bits into a WebView (not like an app-specific browser, though), or display progress bars, or etc. etc. etc. The only drawback to it nowadays is that modern macOS really, really wants your apps to be signed, and it doesn’t do that, so if you’re on a modern system you’ll have to jump through some hoops to get that to work. But, it’s a pretty versatile utility that’s available for free.
I packaged the shell script up using Platypus. That worked about as well as it could have - I didn’t make any attempt, really, to get it to do anything but launch and run the script, and it did that (and, somewhat hilariously, it kept blocking because on the Windows side it was spawning a command prompt, which I had to close before PHP would consider itself done and then also return data back to curl on the Mac). The next step was to figure out how to get the thing registered as a Web browser system-wide and hope that macOS passed the target URL into it in a sane way.
Registering an app as a Web browser requires a couple of things: the app’s Info.plist needs a couple of key/value pairs to tell the system that it can handle http and https links, and the app needs to be in the system Applications folder. Platypus doesn’t have any controls in it to edit the default app Info.plist, so a bit of poking about was needed to edit it. (The gist of it: on the command line, I just used the plutil -convert command to convert the plist to XML format, then made some chanages, and then same thing to convert it back to binary format.) The necessary values that had to go into the plist itself I found in this Stack Overflow post, and, once I had those in and move the app bundle to /Applications, it showed up in the Default Web Browser dropdown in System Preferences. Selecting it, then opening a URL.. actually worked. (Not the first time as.. well, that blocking issue? I’d managed to trigger that again, and had a couple of requests queued with no URL in there. So, once I cleared out the command prompt windows, I got a barrage of things I’d clicked on.) So, now I can click on URLs on the Mac and they’ll open in Chrome on my Ryzen machine.
Now, the next steps are to make this somewhat more secure. Platypus can run pretty much any script - it just, really, runs it, so it can be in any language; it just happened that shell script was the most straightforward for now. So, I’d like to switch it up a bit so that I can maybe accept an SSH key or something and do this that way, so it’s not just piping things in cleartext over the network and has at least some form of authentication. It’d also be great if the thing could figure out if nothing’s listening on that particular IP and port so that it can revert back to a local web browser - if I grab the machine and go elsewhere, I’ll have to remember to switch it back over to Chrome or I won’t be able to click links outside the browser, and that’ll be annoying. Then, maybe I can release it on Github or something.
Is this the easiest way to do this? Oh god no - the easiest way is probably just to keep using my phone for this stuff. And, as mentioned, I have Synergy set up between these systems - it syncs the clipboard, so I can right-click and copy links and paste them into Chrome (in either direction) that way too. But, this was a fun 30 minute distraction that honestly makes things a lot nicer. (And, as a note, I’ve spent easily two to three times as much time writing this post about all this - and it was supposed to be short, even! - than I did actually doing the thing. I don’t even want to calculate the difference in length here with code written as it’s quite literally less than 10 new lines of code so far.)
So, just a.. well, not quick post about this neat thing. Stay tuned for the next post, in which I will invariably do something stupid with an old computer!
(Updated shortly after posting: Platypus actually does have an interface in it to register URI handlers for your generated app. I missed that somehow, so you can probably use that instead of mucking about with the Info.plist directly. Whoops!)