Skip to content

Instantly share code, notes, and snippets.

@nicked
Created June 13, 2012 08:30
Show Gist options
  • Save nicked/2922795 to your computer and use it in GitHub Desktop.
Save nicked/2922795 to your computer and use it in GitHub Desktop.
A PHP script for packaging up an iOS 6 Passbook file
<?
DEFINE('BASE_PATH', '.');
//relative to where you are running this script from. All paths below are relative to this
DEFINE('P12_FILE', 'My Certificate.p12');
//your Pass Certificate, exported from Keychain Access as a P12 file
DEFINE('P12_PASSWORD', '');
//if you exported your P12 with a password, enter it here
DEFINE('OUTPUT_FILE', 'test.pkpass');
//where you want the resulting PKPass file saved to
//-- NO NEED TO MODIFY ANY DEFINES BELOW --
DEFINE('PEM_CERT_FILE', 'certificate.pem');
DEFINE('PEM_KEY_FILE', 'key.pem');
DEFINE('PEM_PASSWORD', 'Password1'); //must be at least 4 chars
DEFINE('MANIFEST_FILE', 'manifest.json');
DEFINE('PASSBOOK_FILE', 'pass.json');
DEFINE('SIGNATURE_FILE', 'signature');
$P12_FILE = escapeshellarg(P12_FILE);
$P12_PASSWORD = escapeshellarg(P12_PASSWORD);
$PEM_CERT_FILE = escapeshellarg(PEM_CERT_FILE);
$PEM_KEY_FILE = escapeshellarg(PEM_KEY_FILE);
$PEM_PASSWORD = escapeshellarg(PEM_PASSWORD);
$MANIFEST_FILE = escapeshellarg(MANIFEST_FILE);
$PASSBOOK_FILE = escapeshellarg(PASSBOOK_FILE);
$SIGNATURE_FILE = escapeshellarg(SIGNATURE_FILE);
ensureExists(BASE_PATH, 'pass folder');
chdir(BASE_PATH);
ensureExists(P12_FILE, 'P12 file');
ensureExists(PASSBOOK_FILE, 'passbook json file');
ensureExists('icon.png', 'icon file'); //only required image
//don't check manifest or signature - generated
validateJson(PASSBOOK_FILE);
$files = imagePaths();
$files[] = PASSBOOK_FILE;
createManifest($files);
generateFile(PEM_CERT_FILE, 'certificate file', "openssl pkcs12 -in $P12_FILE -clcerts -nokeys -out $PEM_CERT_FILE -passin pass:$P12_PASSWORD");
generateFile(PEM_KEY_FILE, 'key file', "openssl pkcs12 -in $P12_FILE -nocerts -out $PEM_KEY_FILE -passin pass:$P12_PASSWORD -passout pass:$PEM_PASSWORD");
generateFile(SIGNATURE_FILE, 'signature file', "openssl smime -binary -sign -signer $PEM_CERT_FILE -inkey $PEM_KEY_FILE -in $MANIFEST_FILE -out $SIGNATURE_FILE -outform DER -passin pass:$PEM_PASSWORD");
$files[] = MANIFEST_FILE;
$files[] = SIGNATURE_FILE;
zipFiles($files, OUTPUT_FILE);
function ensureExists($path, $desc) {
if (!file_exists($path)) die("Could not create $desc at: $path\n");
}
function ensureNotExists($path, $desc) {
if (file_exists($path)) unlink($path);
if (file_exists($path)) die("Could not delete existing $desc at: $path\n");
}
function generateFile($file, $desc, $cmd) {
echo "Generating $desc... ";
ensureNotExists($file, $desc);
shell_exec($cmd.' 1> /dev/null 2> /dev/null');
ensureExists($file, $desc);
echo "OK\n";
}
function imagePaths() {
$paths = array();
foreach (array('background', 'icon', 'logo', 'thumbnail') as $path) {
if (file_exists("$path.png")) $paths[] = "$path.png";
if (file_exists("$path@2x.png")) $paths[] = "$path@2x.png";
}
return $paths;
}
function createManifest($files) {
$manifest = array();
foreach ($files as $file) {
$manifest[$file] = sha1_file($file);
}
echo "Generating manifest... ";
ensureNotExists(MANIFEST_FILE, 'manifest');
file_put_contents(MANIFEST_FILE, json_encode($manifest));
ensureExists(MANIFEST_FILE, 'manifest');
echo "OK\n";
}
function zipFiles($files, $zipfile) {
echo "Zipping pkpass file... ";
$zip = new ZipArchive();
if (!$zip->open($zipfile, ZIPARCHIVE::OVERWRITE)) die("Could not create zip file at: $zipfile\n");
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();
echo "created $zipfile OK\n";
}
function validateJson($file) {
$json = file_get_contents($file);
if (is_null(json_decode($json))) die("Could not validate JSON file: $file\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment