Edenwaith Blog

Permanent Eraser + Yosemite

29th April 2015 | Permanent Eraser

Each new version of OS X brings changes, which often prompts software makers to update their own products to ensure that things work properly on the new system. Sometimes the changes are minor and other times they are quite severe. This article will focus on two areas, Gestalt and code signing, which required some additional work to get Permanent Eraser 2.6.3 to work properly with Apple's desktop OS of 2014 — Yosemite.

Gestalt + Yosemite

There have been numerous ways to determine the operating system version on OS X, but it hasn't been until recently that Apple provided a sanctioned way in Objective-C (and Swift) with the inclusion of NSProcessInfo's operatingSystemVersion method. This is a welcome, albeit highly belated, addition to the Cocoa framework.

Before the inclusion of the operatingSystemVersion method, programmers used a variety of methods to determine the operating system's version, including a mainstay which harkens back to the pre-Cocoa days — the Gestalt Manager. Up until Yosemite (aka OS X 10.10), the following code snippet worked pretty well.


SInt32	osVersion;
Gestalt(gestaltSystemVersion, (SInt32 *) &osVersion);	// Set OS Version

if (osVersion >= 0x00001060) { // Snow Leopard (10.6) or later
	...
}

Unfortunately, with a system version like 10.10.0, we have run out of space using this old format, which results in warnings such as the following to appear:

WARNING: The Gestalt selector gestaltSystemVersion is returning 10.9.0 instead of 10.10.0. Use NSProcessInfo's operatingSystemVersion property to get correct system version number.

The problem which is encountered is when either the minor or patch numbers exceed the number 9, so the version of Mac OS X 10.4.11 would be returned as 10.4.9 or 10.10.3 would be returned as 10.9.3. Years ago, some Adobe installers encountered an error when trying to install on Mac OS X 10.4.10 or 10.4.11, thinking that it was an earlier version of Tiger (Adobe InDesign 4.0.5 does no longer start up). The problem now results in the returned OS version has run out of space to properly represent the system version for Yosemite.

The work around for this problem was to make use of a back port which will use the latest methods, but will fallback to another method for earlier versions of OS X. The replacement for the Gestalt call I used was Jake Petroules' CocoaBackports, which checks if methods like operatingSystemVersion and isOperatingSystemAtLeastVersion are available. If not, swizzle the methods and use the custom methods. The updated code now looks like this:

if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 6, 0}] == YES)	{
	...
}

Code Signing + Yosemite

A year ago I detailed the process I took to code sign Permanent Eraser to work with Gatekeeper on Mountain Lion and Mavericks. However, when developing Permanent Eraser 2.6.3, I encountered the following error when trying to launch the app on Yosemite.

So what happened?! This was working before! Let's do a quick codesign verification to see what is happening. If your app has been signed with an older version of codesign, you will see the following message if you verify the package with current versions of OS X:

codesign --verify --verbose=4 MyGreatApp.app
MyGreatApp.app: resource envelope is obsolete (version 1 signature)

If everything is good, then it might look more like this:


codesign --verify --verbose=4 MyGreatApp.app 
--prepared:MyGreatApp.app/Contents/Library/Automator/Foo.action
--validated:MyGreatApp.app/Contents/Library/Automator/Foo.action
--prepared:MyGreatApp.app/Contents/PlugIns/Bar.workflow
--validated:MyGreatApp.app/Contents/PlugIns/Bar.workflow
--prepared:MyGreatApp.app/Contents/PlugIns/Baz.workflow
--validated:MyGreatApp.app/Contents/PlugIns/Baz.workflow
MyGreatApp.app: valid on disk
MyGreatApp.app: satisfies its Designated Requirement

Or for the more succinct version:


codesign --verify -v MyGreatApp.app 
MyGreatApp.app: valid on disk
MyGreatApp.app: satisfies its Designated Requirement

If the app hasn't been signed at all, then you will see a response like this:


codesign --verify --verbose=4 MyOldApp.app
MyOldApp.app: code object is not signed at all
In architecture: ppc

The short answer is that Gatekeeper has changed in the past year. For apps to be approved by Gatekeeper, they now need to be signed in OS X 10.9.5 or later, which contains the latest signature. Due to changes like these, there's little wonder why I have sprouted at least three grey hairs due to dealing with code signing and provisioning profiles.

Apple Says: Important: For your apps to run on updated versions of OS X they must be signed on OS X version 10.9 or later and thus have a version 2 signature. They also must not contain any custom resource rules. You must sign using OS X 10.9 or later. You cannot just take the codesign utility and move it to an older version of OS X. Mac applications signed with version 2 signatures will still work on older versions of OS X.

Gatekeeper changes in OS X 10.9.5 and later

What to sign

How to sign

Start by trying to sign the main application bundle. If any enclosed subcomponents need to be signed, you will be notified.


codesign --force --sign "Developer ID Application: John Doe" MyGreatApp.app/
MyGreatApp.app/: replacing existing signature
MyGreatApp.app/: code object is not signed at all
In subcomponent: /Users/jdoe/Desktop/MyGreatApp.app/Contents/Library/Automator/Foo.action

In this example, the Automator action named Foo still needs to be signed.


codesign --force --sign "Developer ID Application: John Doe" MyGreatApp.app/Contents/Library/Automator/Foo.action

In the UNIX world, no news is good news. If you sign this bundle and nothing else comes back after the process is complete, assume everything is good. This works fine for signing Automator actions. If you are trying to sign a workflow, the process requires a little extra work. If you try and sign the top level of the workflow package, you will receive the following error:


codesign --force --sign "Developer ID Application: John Doe" MyGreatApp.app/Contents/PlugIns/Bar.workflow/
MyGreatApp.app/Contents/PlugIns/Bar.workflow/: code object is not signed at all
In subcomponent: /Users/jdoe/Desktop/MyGreatApp.app/Contents/PlugIns/Bar.workflow/Contents/document.wflow

The correct way to sign a workflow is to first sign the XML file document.wflow, then sign the enclosing workflow file.


codesign --force --sign "Developer ID Application: John Doe" MyGreatApp.app/Contents/PlugIns/Bar.workflow/Contents/document.wflow
codesign --force --sign "Developer ID Application: John Doe" MyGreatApp.app/Contents/PlugIns/Bar.workflow/

Problem Signing an Old Automator Workflow

Here is an error which occurs when trying to codesign the old Automator workflow plug-in which is intended for Leopard systems.


codesign --force -v --sign "Developer ID Application: John Doe" MyGreatApp.app/Contents/PlugIns/Baz.workflow/
MyGreatApp.app/Contents/PlugIns/Baz.workflow/: bundle format unrecognized, invalid, or unsuitable

To work around this issue, an Info.plist file needs to be included into the workflow bundle's Contents folder. An example Info.plist file is below. Replace the CFBundleName's value with the name of the workflow.

Example Info.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleName</key>
	<string>Baz</string>
</dict>
</plist>

Verify

Once the application and all of its subcomponents have been properly code signed, verify using codesign and spctl to ensure that everything is good.


codesign --verify -v MyGreatApp.app 
MyGreatApp.app: valid on disk
MyGreatApp.app: satisfies its Designated Requirement


spctl -a -t exec -vv MyGreatApp.app
MyGreatApp.app: accepted
source=Developer ID
origin=Developer ID Application: John Doe

Packaging

When I was initially packaging Permanent Eraser 2.6.3 as a DMG, I used FileStorm 1.9.5. Unfortunately, this did not package the application correctly, so the app could not be verified properly by Gatekeeper. To work around this problem, I used FileStorm 2.0.2. Zipping the application from the Finder also works.

References

Permanent Eraser 2.6.3

7th April 2015 | Permanent Eraser

Permanent Eraser 2.6.3 is now available, albeit a couple months later than originally intended, mostly due to resolving issues related to the OS X Yosemite (further technical details on this will be posted later). However, the extra time was well spent resolving various issues (both large and small) and further UI refinements were made (such as Retina-level images).

The tentative plan at this point is to work on Permanent Eraser 2.7, which is intended to be one final hurrah for the long-standing 2.x line. Initial work for Permanent Eraser 3 has begun, which will most likely drop support for older versions of OS X, which will include PowerPC compatibility. This is the current roadmap for Permanent Eraser, but it is certainly possible that all, some or none of these plans will come to fruition.

Fashion Is The Design Of Our Products

13th November 2014 | Apple

When Apple Computer was founded, Steve Wozniak was the brains of the company, but Steve Jobs was the heart and soul of the organization. When Jobs left in 1985, an important piece of the company was lost until his return in early 1997. Watch the MacWorld 1997 video to see the distinct difference in presentation style between Jobs and former Apple CEO Gil Amelio. Just several days after Apple acquired Next Computers, Jobs already had a plan to get Apple back on track, while Amelio fumbled through his presentation.

MacWorld SF 1997

Watch the presentations Jobs made in the late 90s, and one will see a man who has clear cut goals. Quite often, Jobs' visions of the future were often over reaching (some ideas would never manage to land), but it's interesting to see how many of these ideas did manage to see the light of day.

Pundits have been crying for years that an Apple without Steve Jobs is doomed to fail. Time will ultimately rule the final verdict of these claims, but three years after the passing of the Apple co-founder, the company is still healthy and immensely profitable. However, Apple is currently riding an enormous wave of inertia from the products which were released while Jobs was at the helm. Eventually, this momentum will begin to falter, and the future of the company will depend upon new innovations.

In early September 2014, a fervor was buzzing throughout the tech circles, similar to that of December 2006, with all eyes turned toward Apple. Breaths were carefully held, only to be released in the zealous joy of another miracle product being born from the depths of Cupertino. A product that will carry Apple forward, that will prove that Apple can stand without Jobs.

Loud whispers predicted that Apple would be releasing a new brand of wearable, something which would formally herald the era of new computing devices. Many attempts have already been made at popularizing this concept, but no one single item has broken out from niche markets and entered the mainstream.

Enter the  Watch.

This new device isn't just of interest to the technorati, but it has also garnered the attention of those in higher fashion and design. It is the embodiment of both form and function. As the press has tried to glean every available detail from the announced (but unreleased) Apple Watch, it has introduced a broader audience to horology, the digital crown, and Milanese Loops.

Comments from Apple CEO Tim Cook and Senior Vice President of Design Jony Ive have indicated that the Apple Watch is the first new post-Jobs product from the company. This is perhaps true, that Jobs did not have direct input on the Apple Watch, but that does not necessarily mean that his vision and spirit did not have some influence over the design and construction of this product.

Let's play the Devil's Advocate and assume that the ethereal presence of Jobs rose from the grave and played a subtle part in the creation of this new device.

Step back sixteen years to WWDC '98 where Jobs presented to a crowd of the Apple faithful, and he espoused the ideas of simplicity, technology, design, and fashion. The original iMac had just been announced the prior week, the first indicator of a new Apple. Gone was the myriad of confusing beige boxes, to be replaced by a simple matrix of four focused products, with the candy-colored Bondi Blue iMac being the keystone of this new strategy.

"As we get more towards consumer products, fashion gets important," Steve Jobs mentioned at the 1998 Worldwide Developers Conference. "For us, fashion is the design of our products. And we think this is really important to consumers." While he was initially describing computers, he also gave an alternative example.

Of a watch.

The Casio G-Shock — the hottest selling watch of 1998. Because of design.

Ten years earlier in 1988, the average American owned only one watch. Jobs continued, "Ten years later today, because of design, the average American owns seven watches."

WWDC 1998

To summarize: Design is very powerful.

Jobs has long recognized this, and it has been a common theme that Apple is at the crossroads of technology and the liberal arts. The marriage of tasteful design and fashion sense with technology. The wedding of Form and Function in the style of Apple.

Perhaps this is merely a coincidence that Jobs had mentioned a watch back in 1998, and Jobs had no hand in the creation of the Apple Watch, but it does provide for plenty of fodder for conspiracy theories. Regardless of where the line is drawn that divides fact and fiction, what we do know is that while Steve Jobs the man is gone, the ideals he presented persist.

JSON Utilities

19th October 2014 | Programming

When working with RESTful services and JSON, there are several utilities which will make it easier to work with this format.

JSON Quick Look Plug-in

Since a blob of JSON data is just text, it can be saved into a simple, flat file. Amazingly enough, though, OS X does not have a native Quick Look plug-in to quickly preview files which end with the json extension. Fortunately, third-party extensions are available, such as the quick look JSON plug-in from sagtau.com2. Installing the Quick Look plug-in can be performed in three quick steps.

  1. Download QuickLookJSON.qlgenerator
  2. Copy the file to the directory /Library/QuickLook/
  3. Restart the Quick Look Server with the Terminal command: qlmanage -r

Text Filter Plug-Ins

BareBones Software makes two great text editors for the Mac, BBEdit and its little sister, TextWrangler. Both can also be extended with text filters which can be written in a variety of scripting languages like Perl, Python, or even a shell script. Text Filters are located in the following directories:

TextWrangler: ~/Library/Application Support/TextWrangler/Text Filters/
BBEdit: ~/Library/Application Support/BBEdit/Text Filters/

Formatting JSON

After receiving an unorganized blob of JSON data from a web service, it would be nice to neatly format the information to make it easier to read for human consumption. An entry at Interactive Logic's1 site details how to create a Python scripts to take an unmanageable blob of JSON data and format it into a neater blob of JSON data.

Compacting JSON

Perhaps you don't like your JSON to be all nice and orderly and prefer a compressed mass of bits. No problem, there is a script for that, as well.

After a little research 3 through Python's documentation, I found that I could easily modify the Format JSON.py file to strip out the unwanted white space from the formatted JSON.

Compact JSON.py

References

  1. How to Format JSON in TextWrangler
  2. quick look JSON
  3. JSON encoder and decoder Python documentation
  4. Compact JSON Gist
  5. Format JSON Gist

Swift Factorial

6th July 2014 | Programming

With the introduction of Swift at WWDC 2014, I was eager to begin experimenting with this new language. My initial impression of Swift was that it was like learning a new language which is vaguely foreign, yet inherits enough niceities/commonalities from other languages, (such as C, Scala, Ada, and of course, Objective-C) that it doesn't feel overly strange.

Following up on a recommendation, I decided to design a small Mac application with Swift that would calculate factorials, including non-integer numbers. The result is Swift Factorial. The source code is available on GitHub. The Mac app can be downloaded here.

As simple and straightforward of an exercise this was, it proved useful in resolving an issue in calculating factorials for floating-point numbers on Intel Macs. EdenMath and EdenGraph currently use the following logic to calculate the factorial for floating-point numbers:


	lg = lgamma(currentValue+1.0);
	currentValue = signgam*exp(lg); /* signgam is a predefined variable */ 

This worked fine originally when EdenMath 1.1.1 and EdenGraph 1.2.0 were introduced in 2004 and Macs were powered by PowerPC processors. However, something doesn't seem to work quite right initially on Intel chips (perhaps the signgam isn't set yet), and the first run of a factorial returns 0. The new solution simplifies the calculation of non-integer factorials down to one line:


	newValue = exp(lgamma(originalValue + 1)) 

This code fix will be incorporated into future versions of EdenMath and EdenGraph.

Permanent Eraser 2.6.2 and Gatekeeper

4th January 2014 | Permanent Eraser

Permanent Eraser 2.6.2 came out at the end of December 2013, fixing some issues related to Gatekeeper and the latest version of OS X — Mavericks. 2013 almost became the first year since the inception of Permanent Eraser that the app was not updated at least once. Since 2003, Permanent Eraser has received at least one or two yearly updates, sometimes even more, depending upon the development schedule. Looking forward to 2014, work on Permanent Eraser 2.7 will begin.

What's new in Permanent Eraser 2.6.2

One of the biggest fixes in Permanent Eraser 2.6.2 was to properly code sign the app so it would be identified by Gatekeeper as an app by a trusted source. The article Code Signing and Mavericks by Craig Hockenberry helped reveal some trouble areas to resolve. Even though Permanent Eraser 2.6.1 had been code signed, it was not validating properly with Gatekeeper. If I verified the code signature of the app, I saw the following results:

codesign --verify --verbose=4 Permanent\ Eraser\ 2.6.1.app
Permanent Eraser 2.6.1.app: valid on disk
Permanent Eraser 2.6.1.app: satisfies its Designated Requirement

Looks good so far. For the interest of it, I then tried verifying an earlier version of Permanent Eraser which had not been code signed.

codesign --verify --verbose=4 Permanent\ Eraser\ 2.6.0.app
Permanent Eraser 2.6.0.app: code object is not signed at all

Once again, this is returning the expected results. However, if I used the new spctl utility to verify Permanent Eraser in OS X 10.8+, I encountered a problem.

spctl --verbose=4 --assess --type execute Permanent\ Eraser\ 2.6.1.app
Permanent Eraser 2.6.1.app: rejected

spctl, which manages the system policy security, is a command line utility which first appeared in Mac OS X 10.7.3, but the security system known as Gatekeeper came to prominence with OS X 10.8 "Mountain Lion".

The solution was not to use the Mac Developer signing idenity to sign the app (which is used for signing an app for the Mac App Store), but to use the Developer ID Application one, instead. Now when I perform the appropriate checks in OS X Mavericks, everything is looking good.

codesign --verify --verbose=4 Permanent\ Eraser.app/
Permanent Eraser.app/: valid on disk
Permanent Eraser.app/: satisfies its Designated Requirement

spctl --verbose=4 --assess --type execute Permanent\ Eraser.app
../Permanent Eraser.app: accepted
source=Developer ID

Oddly enough, after signing this way in Snow Leopard, trying to verify the app returned this result:

codesign --verify --verbose=4 Permanent\ Eraser.app
Permanent Eraser.app: valid on disk
Permanent Eraser.app: does not satisfy its designated Requirement

However, since the other checks appear to be in proper working order on post-Snow Leopard systems, this looks to be the proper route to properly code sign the app and let it verify properly with Gatekeeper.

References:

git-branch-delete : Deleting local and remote git branches in one fell swoop

25th December 2013 | Tutorial

At my work, I build up a large collection of branches in my git repository over time. Eventually the large number of branches gets overwhelming and requires some maintenance to make the project more manageable (AKA less cluttered). Cleaning up the local and remote branches tends to follow this two step process:

  1. Delete local branch: git branch -d name_of_branch
  2. Delete remote branch: git push origin :name_of_branch

After doing some research, I did not find any quick and dirty way to delete both the local and remote branches with one simple command in git on a Mac. However, I did eventually discover a Ruby script named git-branch-delete that someone1 had written which does nicely perform this task.

Installation for OS X

  1. Download the file git-branch-delete
  2. Extract the file git-branch-delete from the compressed tarball
  3. Copy the file git-branch-delete to /usr/local/bin
  4. Set the proper permissions: chmod 755 /usr/local/bin/git-branch-delete

Usage

Once this has been set up, open up a new Terminal session and delete old git branches from the command line using the following command: git branch-delete <branch-name>

Reference

Edenwaith git-branch-delete Gist : https://gist.github.com/edenwaith/8118506

Footnote

1) Original source : https://github.com/scottwb/dotfiles/blob/master/bin/git-branch-delete

Compiling Git for PowerPC Macs

3rd August 2013 | Tutorial

This year I've begun using the version control system Git for managing source control. I've been putting up some of my older projects on GitHub, which were built as Universal Binaries on Xcode 3 (or earlier). Since I've been working on a long-due update for EdenGraph, I began looking around for a Git client for older PowerPC Macs. The results were disappointing, but this may not be too surprising since Git is a relatively new tool and PowerPC Macs were fazed out in 2006.

However, I did come across a blog post on how to compile Git from source for a PPC Leopard machine, but the instructions, while close, didn't work entirely in my tests. When trying to build the source code, it resulted in the following error:

	$:git-master admin$ make prefix=/usr/local
	GIT_VERSION = 1.8.4-rc0
		* new build flags
		CC credential-store.o
	In file included from cache.h:8,
					 from credential-store.c:1:
	gettext.h:17:22: error: libintl.h: No such file or directory
	In file included from cache.h:8,
					 from credential-store.c:1:
	gettext.h: In function ‘_’:
	gettext.h:54: warning: implicit declaration of function ‘gettext’
	gettext.h:54: warning: incompatible implicit declaration of built-in function ‘gettext’
	gettext.h: In function ‘Q_’:
	gettext.h:62: warning: implicit declaration of function ‘ngettext’
	gettext.h:62: warning: return makes pointer from integer without a cast
	make: *** [credential-store.o] Error 1
	

I found that I needed to create a configuration file first, configure the project, and then build it. These instructions installed git 1.8.2 on a PowerBook G4 running Mac OS X 10.5.8.

  1. Download the latest Git source from http://git-scm.com/downloads
  2. Create configuration file: make configure
  3. ./configure --disable-nls
  4. make prefix=/usr/local
  5. sudo make prefix=/usr/local install

Once Git has been installed, go to the project folder (via the Terminal) and create an empty Git repository with the git init command and then download a project with the command git clone git://path/to/MyProject.git. If you are looking for a GUI-based Git client for PPC Macs, check out GitX.

EdenMath 1.2

31st May 2013 | EdenMath

After a nine year long hiatus, EdenMath has been polished and updated, ready to run on the latest versions of OS X.

New Features

Evolution

EdenMath was the first Cocoa-based application I wrote for the Mac. Cracking open the time capsule shows how EdenMath has evolved over the years, from an embarrassingly bad and inconsistent user interface in the first version of the application, to the more refined later versions.

The interface for EdenMath 1.1 was a dramatic improvement over its predecessors', but it still had its flaws. Developing for EdenMath 1.2 allowed for the opportunity to rethink the entire interface. The following screenshots are a couple of experimental interfaces which were designed during the process of constructing EdenMath 1.2.


Source Code

The source code has always been available, but the source is now even more accessible at its own Github repository.

The Future

The original plan was to update EdenMath with several key features and then lovingly retire the program. However, time was running short and not every feature made it into this version. I am tentatively planning a 1.3 version of EdenMath for the future, which might include the following features:

2013 : Turning The Corner

1st January 2013 | Edenwaith

2012 was intended as a year for cleaning out the old to make way for the new. Some good progress was made, but not everything has been completed yet, which will continue throughout this year, in addition to updating the active projects.

Here is 2012 at a glance:

The progress is half-way complete in retiring the older programs. In 2013, GUI Tar, EdenGraph, and EdenMath will each receive at least one more update before being retired. This will leave 33 RPM, Permanent Eraser, and EdenList as the remaining Edenwaith projects.

Aside from the plans for application retirement, preparations are being made for the development of Permanent Eraser 2.7 and EdenList 1.2 for iOS.

« Newer posts Older posts »