NeutronEncyclopedia
NeutronEncyclopedia by Alain Filhol
The initial version of the encyclopedia was published in 2004 in the form of the CD-ROM "Exploring matter with neutrons". Its many files (.swf, .mov, .html, etc.) were displayed by an embedded FlashPlayer.app (also known as Flash Projector).
Flash being now persona non grata on the web, the goal here was to publish the encyclopedia in the form of a standalone application compatible with Apple's App Store: <https://itunes.apple.com/us/app/pages/id933660286?mt=12>
Things would have been a lot simpler if the many encyclopedia data files could be placed into the "Resources" folder of the Flash Player, Unfortunately, without the original files (e.g. Flash .fla files), there is no way to change the file hierarchy inherited from the CD-ROM. Indeed, the file movie.swf has a hard coded link inside that we failed to change even after a decompilation to movie.fla was performed.
As shown below this leads to NeutronEncyclopedia.app being a bundle with an embedded bundle, and these have to be both signed and sandboxed.
NeutronEncyclopedia.app <-- main bundle Contents MacOS NeutronEncyclopedia <-- a small binary that launches Flash Player.app Ressources many encyclopedia files (.swf, .mov, etc.) FlashPlayer.app <-- secondary bundle initially signed by Adobe Contents MacOS flashplayer <-- the binary Resources movie.swf <-- the starting point for the encyclopedia many Adobe's files |
1. Adobe's permission
Flash Player Projector <https://www.adobe.com/support/flashplayer/debug_downloads.html> is a standalone version of Flash Player for macOS, Window and Linux. Adobe makes it clear that it is is for development only and must not be distributed. In practice, Adobe never complained about Flash based CD-ROMS which have an embedded Flash Projector.
For NeutronEncyclopedia, the problem was more serious since the Flash Player interface must be modifyed to comply Apple's requirements (see section 5).
Therefore I asked Adobe for the permission to do so. They kindly accepted for free and we had a contact signed. The main difficulty was to reach a Legal Officer since my querry was totally out of scope for the Support (Chat, AI based support or 1st telephonic support).
2. Signing with Xcode
My solution:
- Cleanup files for resources and other detritus
First of all, FlashPlayer.app contains many old files that must be cleaned.
xattr -cr Flash\ Player.app - As indicated by Apple, the Adobe signature of the embedded FlashPlayer.app must be replaced by the ILL signature. It was 1st renammed "Launcher" not to confuse with any other Flash Player that might be already present on the disk.
codesign -d --keychain /Users/filhol/Library/Keychains/login.keychain --force --verbose -s "Developer ID Application: INSTITUT MAX VON LAUE - PAUL LANGEVIN (P65398CN49)" /Users/filhol/Development/Dev-NeutronEncyclopedia/Resources/Launcher.app
Note that --entitlements Launcher.entitlements must be added if you target the AppStore - The main bundle is signed by Xcode with the ILL certificate
Xcode gives a warning which says that the embedded bundle is already signed.
The resulting application has a Finder icon and name (NeutronEncyclopedia) which are replaced by the Flash Player icon and name when started.
When launching the signed application on an other computer, GateKeeper does not complain but you get two alerts, one for each bundle.
--> screen captures to be added
Unfortunately enough, I failed publishing this to the App Store as explained in section 4, thus I switched to Application Loader.
3. Publishing to the App Store with Application Loader
Here my solution followed by a detailed description of the steps I had to go through.
- the embedded bundle, Flash Player.app, is renamed Encyclopedia-player.app
This is for not to confuse users at first launch since they will have to successively grant permission for the main bundle (NeutronEncyclopedia.app) and then the embedded bundle (Encyclopedia-player.app) - Embedded bundle: the original bundle ID from Adobe was not accepted
<key>CFBundleIdentifier</key>
<string>com.macromedia.Flash Player.app</string>
I replaced it with a bundle ID registrated in page <https://developer.apple.com/account/mac/identifier/bundle/>
Since the Xcode procedure failed (see section 4) I used the manual procedure below:
Two entitlement files were used:
Encyclopedia-player.entitlements <-- embedded bundle
NeutronEncyclopedia.entitlements <-- main bundle
- Signing the embedded bundle first
$ codesign -d --keychain /Users/filhol/Library/Keychains/login.keychain --entitlements Encyclopedia-player.entitlements --force --verbose -s "E5560E6BCB17DDCEA3E640CC36E3B71E52C5D09B" NeutronEncyclopedia.app/Contents/Resources/Encyclopedia-player.app - Signing the main bundle
$ codesign -d --keychain /Users/filhol/Library/Keychains/login.keychain --entitlements NeutronEncyclopedia.entitlements --force --verbose -s "E5560E6BCB17DDCEA3E640CC36E3B71E52C5D09B" NeutronEncyclopedia.app - Creating an unsigned .pkg archive
$ productbuild --component NeutronEncyclopedia.app /Applications NeutronEncyclopedia.pkg - Signing this .pkg file
$ productsign --sign "3rd Party Mac Developer Installer: INSTITUT MAX VON LAUE - PAUL LANGEVIN (P65398CN49)" --keychain ~/Library/Keychains/login.keychain NeutronEncyclopedia.pkg /Users/afilhol/Desktop/NeutronEncyclopediaSigned.pkg
Note that the target folder (signed .pkg) is different from the source folder (unsigned .pkg) because otherwise the file will never show. (Is this a bug?)
Associated error messages:
ERROR ITMS-90277: "Invalid Bundle Identifier. The application bundle contains a tool or framework Flash Player [eu.ill.comm.NeutronEncyclopedia.pkg/Payload/NeutronEncyclopedia.app/Contents/Resources/Launcher.app] using the bundle identifier 'com.macromedia.Flash Player.app', which is not a valid bundle identifier.”
—> Note that the problem may have come from the space character in "Flash Player" in the original Bundle ID
—> I used a new bundle Identifier for the embedded bundle
ERROR ITMS-90237: "The product archive package's signature is invalid. Ensure that it is signed with your "3rd Party Mac Developer Installer" certificate.”
—> The .pkg must be signed
4. My own mistakes and Apple's bugs
- Xcode/Organizer nightmare
The "Upload to App Store" process says it is preparing a .pkg but iTunes complains Xcode is submitting an .ipa.
“the info.plist indicates a mac app, but submitting an ipa”
The newsgroups suggestion is "try Application Loader 3 instead !"
- What is the problem with Xcode ?
As an alternative I downloaded the signed .pkg created by Xcode (Export "App Store") then submitted it to the App Store using Application Loader v3.0 (see section 3). I got the strange error message below:
ERROR ITMS-90268: "The 'Bundle OS Type Code' [CFBundlePackageType] in your application bundle's Info.plist file must be 'APPL’."
I extracted the bundle from that .pkg and found that the Info.plist file contains:
<key>CFBundlePackageType</key>
<string>BNDL</string>
instead of:
<key>CFBundlePackageType</key>
<string>APPL</string>
This is clearly a BUG in Xcode since Export "Developer ID" gives a CFBundlePackageType string correctly set to "APPL".
- Application Loader
It can be found here: Xcode/Open Developer Tool/Application Loader (v3.9)
As suggested by some newsgroup, I used an older version (v3.0)
1st dialogue: the Apple ID
2nd dialogue: a password defined here <appleid.apple.com> Security/APP-SPECIFIC PASSWORDS
Accepted files are:
signed .pkg (macOS)
signed .ipa (iOS)
- Creating an unsigned .pkg suitable for the App Store
$ productbuild --component NeutronEncyclopedia.app /Applications NeutronEncyclopedia.pkg
productbuild: Adding component at /Users/afilhol/Desktop/NE/NeutronEncyclopedia.app
productbuild: Wrote product to NeutronEncyclopedia.pkg
productbuild: Supported OS versions: [10.8, )
$
Simple but ... if you try to use that .pkg, it installs nothing in /Applications
This is explained here: <stackoverflow.com/questions/19283889/osx-pkg-installer-sometimes-does-not-install-app-file>
I lost hours before understanding that.
- Creating a signed .pkg
The archive must be signed with my "3rd Party Mac Developer Installer" certificate.
$ productsign --sign "3rd Party Mac Developer Installer: INSTITUT MAX VON LAUE - PAUL LANGEVIN (P65398CN49)" --keychain ~/Library/Keychains/login.keychain NeutronEncyclopedia.pkg NeutronEncyclopediaSigned.pkg
productsign: signing product with identity "3rd Party Mac Developer Installer: INSTITUT MAX VON LAUE - PAUL LANGEVIN (P65398CN49)" from keychain /Users/afilhol/Library/Keychains/login.keychain-db
productsign: adding certificate "Apple Worldwide Developer Relations Certification Authority"
productsign: adding certificate "Apple Root CA"
productsign: Wrote signed product archive to NeutronEncyclopediaSigned.pkg
$
This might seems simple but it is not. As such the command is Okay but no file NeutronEncyclopediaSigned.pkg is produced if the target (last file name) is defined as /Users/afilhol/Desktop/NeutronEncyclopediaSigned.pkg. No file path is accepted for the latter.
5. Complying with Apple's requirements
Apple refused the unmodified Flash Player embedded in the application for two reasons:
1- neither the name nor the icon of "Flash Player" must show
2- no URL display on top of the window <-- this was not feasible, Apple finally accepted it
This required changes in the resources of Flash Player, changes which are strictly forbidden by Adobe's copyright.
Adobe's permission was asked in January 2018 and finally obtained in October 2019.
B.H. Director Business Development, 9 Oct 2018, "Yes – you can consider this as a permission".
Several month later a contract was signed with Adobe.
Thus I performed the following modifications:
1- Apple no longer accept neither 32bit code nor fat code
lipo -remove i386 NeutronEncyclopedia.app/Contents/Resources/Encyclopedia-Player.app/Contents/MacOS/Flash\ Player -output /Users/afilhol/Desktop/Flash\ Player
Then replace the "fat" Flash Player of the bundle by the one the above command created on the Desktop
2- The bundle name must be "NeutronEncyclopedia"
<key>CFBundleLongVersionString</key>
<string>NeutronEncyclopedia - Adobe Flash Player 32.0 r0</string>
<key>CFBundleName</key>
<string>NeutronEncyclopedia</string>
3- The Icon must not be the Flash Player icon
<key>CFBundleTypeIconFile</key>
<string>NeutronEncyclopedia.icns</string>
<key>CFBundleIconFile</key>
<string>NeutronEncyclopedia.icns</string>
4- "About"
Added a file Credits.rtf to each .lproj. It will take the precedence over "StandalonePlayerLocalizable.strings"
The latter is kept to satisfy Adobe.
5- Application's ID change
One ID for the main application: <eu.ill.comm.neutronencyclopedia>
One ID for the player:
<key>CFBundleIdentifier</key>
<string>eu.ill.comm.NeutronEncyclopediaP</string>
This ID is registrated in <https://developer.apple.com/account/mac/identifier/bundle/>
6- Version numbers for both NE and Flash Player
Info.plist
<key>CFBundleShortVersionString</key>
<string>3.0.1 (Flash 14.0.0.125)</string>
<key>CFBundleVersion</key>
<string>3.0.1 (Flash Player 14.0.0.125)</string>
The two are shown in the About dialogue via Credits.rtf
=> 3.0.1 (Flash 14.0.0.125) 3.0.1 (Flash 14.0.0.125)
however only the 1st one shows in the Finder, thus the second was deleted.
7- Modified Menus
In the interface, any occurance of "Flash Player" must be replaced by "NeutronEncyclopedia-player" and any out of scope menu item must be removed.
The original resource file "MainMenu.nib" of Flash Player is in a very old format which cannot be edited by modern tools. It must be unlocked and converted.
To make it editable place it inside a bundle as follows:
Non-editable ressource file:
MainMenu.nib <— the Finder command "Show package contents" is disabled
Ressource package that Xcode can edit:
MainMenu.nib <— "Show package contents" enabled
designable.nib
keyedobjects.nib <— renamed MainMenu.nib
One solution to edit the editable .nib is the following:
1- NibUnlocker.app : this app converts the non-editable .nib into an editable .xib
2- Modify the .xib with Xcode
3- convert the .xib into a .nib
Xcode 10 shouts that this is an old format and crashes when saving. Use an older Xcode.
4- replace old .nib in both folders en.lproj and fr.lpro, located in the folder Resources of the Flash Player bundle (now renamed NeutronEncyclopedia)
8- Binary hardening
The binary hardening is a new Apple's requirement which implies that binaries be compiled with the extra option:
-mmacosx-version-min=10.10 (10.6 is the minimum supported version)
A library can be checked :
otool -l <library path> | grep -B 1 -A 3 LC_VERSION_MIN
With an output such as:
Load command 8
cmd LC_VERSION_MIN_MACOSX
cmdsize 16
version 10.6 <-- Minimum macOS version
sdk 10.11
The following codesign option is also associated with binary hardening:
codesign --options runtime ...
6. Problems with Apple procedure
iTunesConnect support proved to be very efficient once I managed to pass its 1st level. I was even called by Cork. In short I had both distribution profile problem and a build number selection.
Each attempt to publish with iTunes Connect gave the error message:
We identified one or more issues with a recent submission for your app, “NeutronEncyclopedia”. Please correct the following issues, then upload again.
I would have found by myself if the error message was more informative:
We identified one or more issues with a recent submission for your app, “NeutronEncyclopedia” build nber xxx uploaded xx/xx/xxxx. Please correct the following issues, then upload again.
In other words the error message did not explain that, while I uploaded many builds but was always intending to publish the same 1st build updated long ago.
Furthermore, to my point of view, the procedure is ambiguous:
- each time a build is submitted, the button "Submit" of iTunes Connect turns grey or vanishes
- for each new upload, either Application Loader or the server says a new build number is compulsory
thus the user may reasonably think that both iTunes Connect will never submit gain a build that was already submitted, and that the last upload is the one which is submitted by default.
In practice, a new upload makes the "Submit" button reappear but the last uploaded build is not the one selected in iTunes Connect, :-( I lost days !