Last active
March 13, 2023 08:59
-
-
Save compwright/4ed5c0434044a897a5cd6a3339ae3b87 to your computer and use it in GitHub Desktop.
PHP build script for a Google Chrome browser extension
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 | |
class ChromePluginCompiler extends PluginCompiler | |
{ | |
// constants - set these in your subclass | |
public $major_version = '5.0'; | |
public $browser = 'chrome'; | |
protected $output_mime_type = 'application/x-chrome-extension'; | |
protected $output_filename = 'ChromeExtension.crx'; | |
protected $build_dir = 'chrome'; | |
protected $private_key = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; | |
protected $public_key = "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"; | |
protected $public_key_der_base64 = "..."; | |
protected $files = array( | |
'manifest.json', | |
'icon16.png', | |
'icon64.png', | |
'icon128.png', | |
'_locales/en/messages.json', | |
'content/jquery-1.5.1.js', | |
'content/mtoolbar.js', | |
'content/content.js', | |
'content/signrequest.js', | |
'content/background.html', | |
); | |
protected $tempdir; | |
public function compile() | |
{ | |
// create a temporary build directory | |
$this->tempdir = tempnam($this->_tmpdir(), 'msg'); | |
unlink($this->tempdir); | |
mkdir($this->tempdir); | |
$dir = $this->tempdir.'/'; | |
$key = $this->build_path; | |
$name = $this->build_dir; | |
$crx = "$name.crx"; | |
$zip = "$name.zip"; | |
$this->tempfile = $dir.$zip; | |
// data to insert into plugin files... | |
$version = $this->version(); | |
$tags = array( | |
'content/background.html' => array( | |
'{{msg_secret}}' => Config::get('msg_secret'), | |
'{{msg_api_endpoint}}' => Config::get('msg_api_endpoint'), | |
'{{version}}' => $version, | |
'{{distributor_id}}' => $this->distributor->pk(), | |
), | |
'manifest.json' => array( | |
'{{version}}' => $version, | |
'{{msg_api_endpoint}}' => Config::get('msg_api_endpoint'), | |
'{{updateURL}}' => Config::get('msg_include_update_url')? | |
'"update_url": "'.Config::get('msg_api_endpoint')."/download/crupdate.xml?distributor_id=".$this->distributor->pk().'",' : | |
'', | |
), | |
); | |
// Chrome plugins start with a zip archive... | |
$z = new ZipArchiveImproved(); | |
if ($z->open($this->tempfile, ZIPARCHIVE::CREATE) !== TRUE) | |
{ | |
throw new Exception("Cannot open $this->tempfile"); | |
} | |
// add each file to the archive | |
foreach ($this->files as $file) | |
{ | |
if ($tags[$file]) | |
{ | |
$filecontents = str_replace( | |
array_keys($tags[$file]), | |
array_values($tags[$file]), | |
file_get_contents($this->build_path.$file) | |
); | |
$z->addFromString($file, $filecontents); | |
} | |
else | |
{ | |
$z->addFile($this->build_path.$file, $file); | |
} | |
} | |
// build | |
$z->close(); | |
// make a SHA1 signature using our private key | |
$pk = openssl_pkey_get_private($this->private_key); | |
openssl_sign(file_get_contents($this->tempfile), $signature, $pk, 'sha1'); | |
openssl_free_key($pk); | |
// decode the public key | |
$key = base64_decode($this->public_key_der_base64); | |
// .crx package format: | |
// | |
// magic number char(4) | |
// crx format ver byte(4) | |
// pub key lenth byte(4) | |
// signature length byte(4) | |
// public key string | |
// signature string | |
// package contents, zipped string | |
// | |
// see http://code.google.com/chrome/extensions/crx.html | |
// | |
$fh = fopen($dir.$crx, 'wb'); | |
fwrite($fh, 'Cr24'); // extension file magic number | |
fwrite($fh, pack('V', 2)); // crx format version | |
fwrite($fh, pack('V', strlen($key))); // public key length | |
fwrite($fh, pack('V', strlen($signature))); // signature length | |
fwrite($fh, $key); // public key | |
fwrite($fh, $signature); // signature | |
fwrite($fh, file_get_contents($this->tempfile)); // package contents, zipped | |
fclose($fh); | |
// clean up build files | |
@unlink($this->tempfile); // zip file | |
$this->tempfile = array_shift(explode('.', $dir)).'.crx'; // move the .crx file up one level | |
if (@rename($dir.$crx, $this->tempfile)) | |
{ | |
// delete the temporary working dir | |
@rmdir($dir); | |
} | |
else | |
{ | |
// failsafe ('twas a nice thought!) | |
$this->tempfile = $dir.$crx; | |
} | |
// return the path to the compiled plugin | |
return $this->tempfile; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
www