Last active
March 21, 2022 16:24
-
-
Save mohamedhafez/9a4794ebe589abd5861c76b792595c23 to your computer and use it in GitHub Desktop.
createPushPackage.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// This script creates a valid push package. | |
// This script assumes that the website.json file and iconset already exist. | |
// This script creates a manifest and signature, zips the folder, and returns the push package. | |
// Use this script as an example to generate a push package dynamically. | |
$package_version = 2; // Change this to the desired push package version. | |
$certificate_path = "/current/secret/pushy/safari/Certificates.p12"; // Change this to the path where your certificate is located | |
$intermediate_certificate_path = "/current/secret/pushy/safari/AppleWWDRCA.pem"; // Change this to the path where the intermediate certificate is located | |
$certificate_password = ""; // Change this to the certificate's import password | |
// Convenience function that returns an array of raw files needed to construct the package. | |
function raw_files() { | |
return array( | |
'icon.iconset/icon_16x16.png', | |
'icon.iconset/[email protected]', | |
'icon.iconset/icon_32x32.png', | |
'icon.iconset/[email protected]', | |
'icon.iconset/icon_128x128.png', | |
'icon.iconset/[email protected]', | |
'website.json' | |
); | |
} | |
// Copies the raw push package files to $package_dir. | |
function copy_raw_push_package_files($package_dir) { | |
mkdir($package_dir . '/icon.iconset'); | |
foreach (raw_files() as $raw_file) { | |
copy("pushPackage.raw/$raw_file", "$package_dir/$raw_file"); | |
} | |
} | |
// Creates the manifest by calculating the hashes for all of the raw files in the package. | |
function create_manifest($package_dir, $package_version) { | |
// Obtain hashes of all the files in the push package | |
$manifest_data = array(); | |
foreach (raw_files() as $raw_file) { | |
$file_contents = file_get_contents("$package_dir/$raw_file"); | |
if ($package_version === 1) { | |
$manifest_data[$raw_file] = sha1($file_contents); | |
} else if ($package_version === 2) { | |
$hashType = 'sha512'; | |
$manifest_data[$raw_file] = array( | |
'hashType' => $hashType, | |
'hashValue' => hash($hashType, $file_contents), | |
); | |
} else { | |
throw new Exception('Invalid push package version.'); | |
} | |
} | |
file_put_contents("$package_dir/manifest.json", json_encode((object)$manifest_data)); | |
} | |
// Creates a signature of the manifest using the push notification certificate. | |
function create_signature($package_dir, $cert_path, $cert_password) { | |
global $intermediate_certificate_path; | |
// Load the push notification certificate | |
$pkcs12 = file_get_contents($cert_path); | |
$certs = array(); | |
if(!openssl_pkcs12_read($pkcs12, $certs, $cert_password)) { | |
return; | |
} | |
$signature_path = "$package_dir/signature"; | |
// Sign the manifest.json file with the private key from the certificate | |
$cert_data = openssl_x509_read($certs['cert']); | |
$private_key = openssl_pkey_get_private($certs['pkey'], $cert_password); | |
openssl_pkcs7_sign("$package_dir/manifest.json", $signature_path, $cert_data, $private_key, array(), PKCS7_BINARY | PKCS7_DETACHED, $intermediate_certificate_path); | |
// Convert the signature from PEM to DER | |
$signature_pem = file_get_contents($signature_path); | |
$matches = array(); | |
if (!preg_match('~Content-Disposition:[^\n]+\s*?([A-Za-z0-9+=/\r\n]+)\s*?-----~', $signature_pem, $matches)) { | |
return; | |
} | |
$signature_der = base64_decode($matches[1]); | |
file_put_contents($signature_path, $signature_der); | |
} | |
// Zips the directory structure into a push package, and returns the path to the archive. | |
function package_raw_data($package_dir) { | |
$zip_path = "$package_dir.zip"; | |
// Package files as a zip file | |
$zip = new ZipArchive(); | |
if (!$zip->open("$package_dir.zip", ZIPARCHIVE::CREATE)) { | |
error_log('Could not create ' . $zip_path); | |
return; | |
} | |
$raw_files = raw_files(); | |
$raw_files[] = 'manifest.json'; | |
$raw_files[] = 'signature'; | |
foreach ($raw_files as $raw_file) { | |
$zip->addFile("$package_dir/$raw_file", $raw_file); | |
} | |
$zip->close(); | |
return $zip_path; | |
} | |
// Creates the push package, and returns the path to the archive. | |
function create_push_package() { | |
global $certificate_path, $certificate_password, $package_version; | |
// Create a temporary directory in which to assemble the push package | |
$package_dir = '/tmp/pushPackage' . time(); | |
if (!mkdir($package_dir)) { | |
unlink($package_dir); | |
die; | |
} | |
copy_raw_push_package_files($package_dir); | |
create_manifest($package_dir, $package_version); | |
create_signature($package_dir, $certificate_path, $certificate_password); | |
$package_path = package_raw_data($package_dir); | |
return $package_path; | |
} | |
// MAIN | |
$package_path = create_push_package(); | |
//if (empty($package_path)) { | |
// http_response_code(500); | |
// die; | |
//} | |
//header("Content-type: application/zip"); | |
//echo file_get_contents($package_path); | |
die; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What is your email? I send my file, you can test it with your code and see if it works.