Source for file Manager.php
Documentation is available at Manager.php
* PHP_Archive Manager Class creator (allows debugging/manipulation of phar files)
* Needed for file manipulation
require_once 'System.php';
require_once 'PHP/Archive/Exception.php';
* @copyright Copyright ? Gregory Beaver
* @author Greg Beaver <cellog@php.net>
* @version $Id: Manager.php,v 1.14 2007/08/18 03:57:34 cellog Exp $
private $_knownAPIVersions = array ('1.0.0');
private $_signature = false;
* Locate the .phar archive in the include_path and detect the file to open within
* Possible parameters are phar://filename_within_phar.ext or
* phar://pharname.phar/filename_within_phar.ext
* phar://filename_within_phar.ext will simply use the last .phar opened.
* @param string a file within the archive
* @return string the filename within the .phar to retrieve
$this->_archiveName = $phar;
* validate a phar prior to manipulating it
* @throws PHP_Archive_Exception
public function validate($strict = false )
$fp = fopen($this->_archiveName, 'rb');
array ('archive' => $this->_archiveName));
$header = fread($fp, strlen('<?php #PHP_ARCHIVE_HEADER-'));
if ($header == '<?php #PHP_ARCHIVE_HEADER-') {
while (!feof($fp) && (false !== $c = fgetc($fp))) {
if ((ord($c) < ord('0') || ord($c) > ord('9')) && $c != '.') {
$this->_version = $version;
// seek to __HALT_COMPILER_OFFSET__
while (!feof($fp) && false != ($next = fread($fp, 8192 ))) {
if (false != ($t = strpos($next, '__HALT_COMPILER();'))) {
array ('archive' => $this->_archiveName));
$manifest_length = fread($fp, 4 );
$manifest_length = unpack('Vlen', $manifest_length);
$this->_manifestSize = $manifest_length = $manifest_length['len'];
if ($manifest_length > 1048576 ) {
'archive' => $this->_archiveName));
'archive' => $this->_archiveName));
$manifest = fread($fp, $manifest_length);
// retrieve the number of files in the manifest
if ($info[1 ] * 24 > $manifest_length) {
'archive' => $this->_archiveName));
$manifest = substr($manifest, 4 );
'archive' => $this->_archiveName));
// get API version and compressed flag
$apiver = substr($manifest, 0 , 2 );
$this->_apiVersion = hexdec($apiver[0 ]) . '.' . hexdec($apiver[1 ]) .
if (!in_array($this->_apiVersion, $this->_knownAPIVersions)) {
'archive' => $this->_archiveName, 'ver' => $this->_apiVersion));
$manifest = substr($manifest, 2 );
'archive' => $this->_archiveName));
$this->_flags = $flags[1 ];
$manifest = substr($manifest, 4 );
'archive' => $this->_archiveName));
$aliaslen = $aliaslen[1 ];
$manifest = substr($manifest, 4 );
if (strlen($manifest) < $aliaslen) {
'archive' => $this->_archiveName));
$this->_alias = substr($manifest, 0 , $aliaslen);
$manifest = substr($manifest, $aliaslen);
'archive' => $this->_archiveName));
$metadatalen = $metadatalen[1 ];
$manifest = substr($manifest, 4 );
if (strlen($manifest) < $metadatalen) {
'archive' => $this->_archiveName));
$manifest = substr($manifest, $metadatalen);
for ($i = 0; $i < $info[1 ]; $i++ ) {
'archive' => $this->_archiveName, 'last' => $savepath,
'current' => '*unknown*', 'size' => $info[1 ], 'cur' => $i));
'archive' => $this->_archiveName, 'last' => '*none*',
'current' => '*unknown*', 'size' => $info[1 ], 'cur' => $i));
// length of the file name
if (strlen($manifest) < $len[1 ] + 4 ) {
'archive' => $this->_archiveName, 'last' => $savepath,
'current' => '*unknown*', 'size' => $info[1 ], 'cur' => $i));
'archive' => $this->_archiveName, 'last' => '*none*',
'current' => '*unknown*', 'size' => $info[1 ], 'cur' => $i));
$savepath = substr($manifest, 4 , $len[1 ]);
$manifest = substr($manifest, $len[1 ] + 4 );
'archive' => $this->_archiveName, 'last' => $last,
'current' => $savepath, 'size' => $info[1 ], 'cur' => $i));
'archive' => $this->_archiveName, 'last' => $last,
'current' => $savepath, 'size' => $info[1 ], 'cur' => $i));
// retrieve manifest data:
// 0 = uncompressed file size
// 2 = compressed file size
$ret[$savepath][3 ] = sprintf('%u', $ret[$savepath][3 ]
$manifest = substr($manifest, 24 );
if ($ret[$savepath][5 ]) {
if (strlen($manifest) < $ret[$savepath][5 ]) {
array ('archive' => $this->_archiveName, 'last' => $last,
'current' => $savepath, 'size' => $info[1 ], 'cur' => $i));
$ret[$savepath][7 ] = $offset;
$offset += $ret[$savepath][2 ];
$this->_fileStart = ftell($fp);
foreach ($this->_manifest as $path => $info) {
$currentFilename = $path;
$internalFileLength = $info[2 ];
// seek to offset of file header within the .phar
if (fseek($fp, $this->_fileStart + $info[7 ])) {
array ('archive' => $this->_archiveName, 'file' => $path, 'loc' => $this->_fileStart + $info[7 ],
'size' => filesize($this->_archiveName)));
$temp = array ('crc32' => $info[3 ], 'isize' => $info[0 ]);
$count = $internalFileLength;
$data .= @fread($fp, $count);
$data .= @fread($fp, 8192 );
if ($info[4 ] & self ::GZ ) {
array ('archive' => $this->_archiveName, 'file' => $path, 'loc' => $this->_fileStart + $info[2 ]));
if ($info[4 ] & self ::BZ2 ) {
$data = @bzdecompress ($data, true );
array ('archive' => $this->_archiveName, 'file' => $path, 'loc' => $this->_fileStart + $info[2 ]));
if ($temp['isize'] != strlen($data)) {
array ('archive' => $this->_archiveName, 'file' => $path, 'expected' => $temp['isize'],
if ($temp['crc32'] != sprintf("%u", crc32($data) & 0xffffffff )) {
array ('archive' => $this->_archiveName, 'file' => $path, 'expected' => $temp['crc32'],
'actual' => crc32($data)));
if ($this->_flags & self ::SIG ) {
array ('archive' => $this->_archiveName));
if (md5(substr($all, 0 , $end), true ) != $hash) {
array ('archive' => $this->_archiveName));
$this->_signature = md5($all);
array ('archive' => $this->_archiveName));
$this->_sigtype = 'SHA1';
$this->_signature = sha1($all);
array ('archive' => $this->_archiveName,
* Display information on a phar
public function dump($return_array = false )
$filesize = filesize($this->_archiveName);
'Phar name' => $this->_archiveName,
'API version' => $this->_apiVersion,
'Manifest size (bytes)' => $this->_manifestSize,
'Manifest entries' => count($this->_manifest),
'Alias' => $this->_alias,
'Phar Metadata' => var_export($this->_metadata, true ),
'Global compressed flag' => bin2hex($this->_flags),
$ret['Signature Type'] = $this->_sigtype;
$ret['Signature'] = $this->_signature;
// 0 = uncompressed file size
// 2 = compressed file size
foreach ($this->_manifest as $file => $info) {
$ret['File phar://' . $this->_alias . '/' . $file . ' size'] = $info[0 ];
$ret['File phar://' . $this->_alias . '/' . $file . ' save date'] =
date('Y-m-d H:i', $info[1 ]);
$ret['File phar://' . $this->_alias . '/' . $file . ' crc'] = $info[3 ];
$ret['File phar://' . $this->_alias . '/' . $file . ' size in archive'] = $info[2 ];
$ret['File phar://' . $this->_alias . '/' . $file . ' offset in archive'] = $offset;
$ret['File phar://' . $this->_alias . '/' . $file . ' meta-data length'] = $info[5 ];
$ret['File phar://' . $this->_alias . '/' . $file . ' meta-data'] =
$ret['File phar://' . $this->_alias . '/' . $file . ' GZ compressed'] =
$info[4 ] & self ::GZ ? 'yes' : 'no';
$ret['File phar://' . $this->_alias . '/' . $file . ' BZ2 compressed'] =
$info[4 ] & self ::BZ2 ? 'yes' : 'no';
$ret = $this->dump(true );
* Extract the .phar to a particular location
public function unPhar($toHere)
* Re-make the phar from a previously after having done work on an unPharred phar
* @param string $fromHere
public function rePhar($fromHere)
* For display of data in a browser
* @return PHP_Archive_Manager
Documentation generated on Mon, 19 May 2008 11:30:16 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.
|