Using Phar Archives: Introduction
Phar archives are similar in concept to Java JAR archives, but are tailored
to the needs and to the flexibility of PHP applications. A Phar archive is
used to distribute a complete PHP application or library in a single file. A
Phar archive application is used exactly like any other PHP application:
php coolapplication.phar
Using a Phar archive library is identical to using any other PHP library:
The phar stream wrapper provides the core of the phar extension, and
is explained in detail here.
The phar stream wrapper allows accessing the files within a phar archive using
PHP's standard file functions phar stream wrapper supports all
read/write operations on both files and directories.
The Phar class implements advanced functionality for accessing
files and for creating phar archives. The Phar class is explained in detail
here.
<?phptry {// open an existing phar$p= newPhar('coollibrary.phar',0);// Phar extends SPL's DirectoryIterator classforeach (newRecursiveIteratorIterator($p) as$file) {// $file is a PharFileInfo class, and inherits from SplFileInfoecho$file->getFileName() ."\n";
echofile_get_contents($file->getPathName()) ."\n";// display contents;}
if (isset($p['internal/file.php'])) {var_dump($p['internal/file.php']->getMetadata());
}// create a new phar - phar.readonly must be 0 in php.ini
// phar.readonly is enabled by default for security reasons.
// On production servers, Phars need never be created,
// only executed.if (Phar::canWrite()) {$p= newPhar('newphar.tar.phar',0,'newphar.tar.phar');// make this a tar-based phar archive, compressed with gzip compression (.tar.gz)$p=$p->convertToExecutable(Phar::TAR,Phar::GZ);// create transaction - nothing is written to newphar.phar
// until stopBuffering() is called, although temporary storage is needed$p->startBuffering();// add all files in /path/to/project, saving in the phar with the prefix "project"$p->buildFromIterator(newRecursiveIteratorIterator(newRecursiveDirectoryIterator('/path/to/project')),'/path/to/');// add a new file via the array access API$p['file1.txt'] ='Information';$fp=fopen('hugefile.dat','rb');// copy all data from the stream$p['data/hugefile.dat'] =$fp;
if (Phar::canCompress(Phar::GZ)) {$p['data/hugefile.dat']->compress(Phar::GZ);
}$p['images/wow.jpg'] =file_get_contents('images/wow.jpg');// any value can be saved as file-specific meta-data$p['images/wow.jpg']->setMetadata(array('mime-type'=>'image/jpeg'));$p['index.php'] =file_get_contents('index.php');$p->setMetadata(array('bootstrap'=>'index.php'));// save the phar archive to disk$p->stopBuffering();
}
} catch (Exception $e) {
echo'Could not open Phar: ',$e;
}?>
In addition, verification of phar file contents can be done using any of the
supported symmetric hash algorithms (MD5, SHA1, SHA256 and SHA512 if ext/hash is enabled)
and using asymmetric public/private key signing using OpenSSL (new in Phar 2.0.0). To
take advantage of OpenSSL signing, you need to generate a public/private key pair, and
use the private key to set the signature using
$public=openssl_get_publickey(file_get_contents('private.pem'));$pkey='';openssl_pkey_export($public,$pkey);?>
must be saved adjacent to the phar archive it verifies. If the phar archive
is saved as /path/to/my.phar, the public key must be saved
as /path/to/my.phar.pubkey, or phar will be unable to verify
the OpenSSL signature.
As of version 2.0.0, The Phar class also provides 3 static methods,
As an example, packaging up a release of the popular phpMyAdmin application for use as a phar archive requires
only this simple script and then phpMyAdmin.phar.tar.php can be accessed as a regular file
from your web server after modifying the user/password:
<?php @unlink('phpMyAdmin.phar.tar.php');copy('phpMyAdmin-2.11.3-english.tar.gz','phpMyAdmin.phar.tar.php');$a= newPhar('phpMyAdmin.phar.tar.php');$a->startBuffering();$a["phpMyAdmin-2.11.3-english/config.inc.php"] ='<?php
/* Servers configuration */
$i = 0;
/* Server localhost (config:root) [1] */
$i++;
$cfg[\'Servers\'][$i][\'host\'] = \'localhost\';
$cfg[\'Servers\'][$i][\'extension\'] = \'mysqli\';
$cfg[\'Servers\'][$i][\'connect_type\'] = \'tcp\';
$cfg[\'Servers\'][$i][\'compress\'] = false;
$cfg[\'Servers\'][$i][\'auth_type\'] = \'config\';
$cfg[\'Servers\'][$i][\'user\'] = \'root\';
$cfg[\'Servers\'][$i][\'password\'] = \'\';
/* End of servers configuration */
if (strpos(PHP_OS, \'WIN\') !== false) {
$cfg[\'UploadDir\'] = getcwd();
} else {
$cfg[\'UploadDir\'] = \'/tmp/pharphpmyadmin\';
@mkdir(\'/tmp/pharphpmyadmin\');
@chmod(\'/tmp/pharphpmyadmin\', 0777);
}';$a->setStub('<?php
Phar::interceptFileFuncs();
Phar::webPhar("phpMyAdmin.phar", "phpMyAdmin-2.11.3-english/index.php");
echo "phpMyAdmin is intended to be executed from a web browser\n";
exit -1;
__HALT_COMPILER();
');$a->stopBuffering();?>