Annotation of embedaddon/php/pear/install-pear-nozlib.phar, revision 1.1
1.1 ! misho 1: <?php
! 2: error_reporting(1803);
! 3: if (function_exists('mb_internal_encoding')) {
! 4: mb_internal_encoding('ASCII');
! 5: }
! 6: if (!class_exists('PHP_Archive')) {/**
! 7: * PHP_Archive Class (implements .phar)
! 8: *
! 9: * @package PHP_Archive
! 10: * @category PHP
! 11: */
! 12: /**
! 13: * PHP_Archive Class (implements .phar)
! 14: *
! 15: * PHAR files a singular archive from which an entire application can run.
! 16: * To use it, simply package it using {@see PHP_Archive_Creator} and use phar://
! 17: * URIs to your includes. i.e. require_once 'phar://config.php' will include config.php
! 18: * from the root of the PHAR file.
! 19: *
! 20: * Gz code borrowed from the excellent File_Archive package by Vincent Lascaux.
! 21: *
! 22: * @copyright Copyright David Shafik and Synaptic Media 2004. All rights reserved.
! 23: * @author Davey Shafik <davey@synapticmedia.net>
! 24: * @author Greg Beaver <cellog@php.net>
! 25: * @link http://www.synapticmedia.net Synaptic Media
! 26: * @version Id: Archive.php,v 1.52 2007/09/01 20:28:14 cellog Exp $
! 27: * @package PHP_Archive
! 28: * @category PHP
! 29: */
! 30:
! 31: class PHP_Archive
! 32: {
! 33: const GZ = 0x00001000;
! 34: const BZ2 = 0x00002000;
! 35: const SIG = 0x00010000;
! 36: const SHA1 = 0x0002;
! 37: const MD5 = 0x0001;
! 38: /**
! 39: * Whether this archive is compressed with zlib
! 40: *
! 41: * @var bool
! 42: */
! 43: private $_compressed;
! 44: /**
! 45: * @var string Real path to the .phar archive
! 46: */
! 47: private $_archiveName = null;
! 48: /**
! 49: * Current file name in the phar
! 50: * @var string
! 51: */
! 52: protected $currentFilename = null;
! 53: /**
! 54: * Length of current file in the phar
! 55: * @var string
! 56: */
! 57: protected $internalFileLength = null;
! 58: /**
! 59: * Current file statistics (size, creation date, etc.)
! 60: * @var string
! 61: */
! 62: protected $currentStat = null;
! 63: /**
! 64: * @var resource|null Pointer to open .phar
! 65: */
! 66: protected $fp = null;
! 67: /**
! 68: * @var int Current Position of the pointer
! 69: */
! 70: protected $position = 0;
! 71:
! 72: /**
! 73: * Map actual realpath of phars to meta-data about the phar
! 74: *
! 75: * Data is indexed by the alias that is used by internal files. In other
! 76: * words, if a file is included via:
! 77: * <code>
! 78: * require_once 'phar://PEAR.phar/PEAR/Installer.php';
! 79: * </code>
! 80: * then the alias is "PEAR.phar"
! 81: *
! 82: * Information stored is a boolean indicating whether this .phar is compressed
! 83: * with zlib, another for bzip2, phar-specific meta-data, and
! 84: * the precise offset of internal files
! 85: * within the .phar, used with the {@link $_manifest} to load actual file contents
! 86: * @var array
! 87: */
! 88: private static $_pharMapping = array();
! 89: /**
! 90: * Map real file paths to alias used
! 91: *
! 92: * @var array
! 93: */
! 94: private static $_pharFiles = array();
! 95: /**
! 96: * File listing for the .phar
! 97: *
! 98: * The manifest is indexed per phar.
! 99: *
! 100: * Files within the .phar are indexed by their relative path within the
! 101: * .phar. Each file has this information in its internal array
! 102: *
! 103: * - 0 = uncompressed file size
! 104: * - 1 = timestamp of when file was added to phar
! 105: * - 2 = offset of file within phar relative to internal file's start
! 106: * - 3 = compressed file size (actual size in the phar)
! 107: * @var array
! 108: */
! 109: private static $_manifest = array();
! 110: /**
! 111: * Absolute offset of internal files within the .phar, indexed by absolute
! 112: * path to the .phar
! 113: *
! 114: * @var array
! 115: */
! 116: private static $_fileStart = array();
! 117: /**
! 118: * file name of the phar
! 119: *
! 120: * @var string
! 121: */
! 122: private $_basename;
! 123:
! 124:
! 125: /**
! 126: * Default MIME types used for the web front controller
! 127: *
! 128: * @var array
! 129: */
! 130: public static $defaultmimes = array(
! 131: 'aif' => 'audio/x-aiff',
! 132: 'aiff' => 'audio/x-aiff',
! 133: 'arc' => 'application/octet-stream',
! 134: 'arj' => 'application/octet-stream',
! 135: 'art' => 'image/x-jg',
! 136: 'asf' => 'video/x-ms-asf',
! 137: 'asx' => 'video/x-ms-asf',
! 138: 'avi' => 'video/avi',
! 139: 'bin' => 'application/octet-stream',
! 140: 'bm' => 'image/bmp',
! 141: 'bmp' => 'image/bmp',
! 142: 'bz2' => 'application/x-bzip2',
! 143: 'css' => 'text/css',
! 144: 'doc' => 'application/msword',
! 145: 'dot' => 'application/msword',
! 146: 'dv' => 'video/x-dv',
! 147: 'dvi' => 'application/x-dvi',
! 148: 'eps' => 'application/postscript',
! 149: 'exe' => 'application/octet-stream',
! 150: 'gif' => 'image/gif',
! 151: 'gz' => 'application/x-gzip',
! 152: 'gzip' => 'application/x-gzip',
! 153: 'htm' => 'text/html',
! 154: 'html' => 'text/html',
! 155: 'ico' => 'image/x-icon',
! 156: 'jpe' => 'image/jpeg',
! 157: 'jpg' => 'image/jpeg',
! 158: 'jpeg' => 'image/jpeg',
! 159: 'js' => 'application/x-javascript',
! 160: 'log' => 'text/plain',
! 161: 'mid' => 'audio/x-midi',
! 162: 'mov' => 'video/quicktime',
! 163: 'mp2' => 'audio/mpeg',
! 164: 'mp3' => 'audio/mpeg3',
! 165: 'mpg' => 'audio/mpeg',
! 166: 'pdf' => 'aplication/pdf',
! 167: 'png' => 'image/png',
! 168: 'rtf' => 'application/rtf',
! 169: 'tif' => 'image/tiff',
! 170: 'tiff' => 'image/tiff',
! 171: 'txt' => 'text/plain',
! 172: 'xml' => 'text/xml',
! 173: );
! 174:
! 175: public static $defaultphp = array(
! 176: 'php' => true
! 177: );
! 178:
! 179: public static $defaultphps = array(
! 180: 'phps' => true
! 181: );
! 182:
! 183: public static $deny = array('/.+\.inc$/');
! 184:
! 185: public static function viewSource($archive, $file)
! 186: {
! 187: // security, idea borrowed from PHK
! 188: if (!file_exists($archive . '.introspect')) {
! 189: header("HTTP/1.0 404 Not Found");
! 190: return false;
! 191: }
! 192: if (self::_fileExists($archive, $_GET['viewsource'])) {
! 193: $source = highlight_file('phar://install-pear-nozlib.phar/' .
! 194: $_GET['viewsource'], true);
! 195: header('Content-Type: text/html');
! 196: header('Content-Length: ' . strlen($source));
! 197: echo '<html><head><title>Source of ',
! 198: htmlspecialchars($_GET['viewsource']), '</title></head>';
! 199: echo '<body><h1>Source of ',
! 200: htmlspecialchars($_GET['viewsource']), '</h1>';
! 201: if (isset($_GET['introspect'])) {
! 202: echo '<a href="', htmlspecialchars($_SERVER['PHP_SELF']),
! 203: '?introspect=', urlencode(htmlspecialchars($_GET['introspect'])),
! 204: '">Return to ', htmlspecialchars($_GET['introspect']), '</a><br />';
! 205: }
! 206: echo $source;
! 207: return false;
! 208: } else {
! 209: header("HTTP/1.0 404 Not Found");
! 210: return false;
! 211: }
! 212:
! 213: }
! 214:
! 215: public static function introspect($archive, $dir)
! 216: {
! 217: // security, idea borrowed from PHK
! 218: if (!file_exists($archive . '.introspect')) {
! 219: header("HTTP/1.0 404 Not Found");
! 220: return false;
! 221: }
! 222: if (!$dir) {
! 223: $dir = '/';
! 224: }
! 225: $dir = self::processFile($dir);
! 226: if ($dir[0] != '/') {
! 227: $dir = '/' . $dir;
! 228: }
! 229: try {
! 230: $self = htmlspecialchars($_SERVER['PHP_SELF']);
! 231: $iterate = new DirectoryIterator('phar://install-pear-nozlib.phar' . $dir);
! 232: echo '<html><head><title>Introspect ', htmlspecialchars($dir),
! 233: '</title></head><body><h1>Introspect ', htmlspecialchars($dir),
! 234: '</h1><ul>';
! 235: if ($dir != '/') {
! 236: echo '<li><a href="', $self, '?introspect=',
! 237: htmlspecialchars(dirname($dir)), '">..</a></li>';
! 238: }
! 239: foreach ($iterate as $entry) {
! 240: if ($entry->isDot()) continue;
! 241: $name = self::processFile($entry->getPathname());
! 242: $name = str_replace('phar://install-pear-nozlib.phar/', '', $name);
! 243: if ($entry->isDir()) {
! 244: echo '<li><a href="', $self, '?introspect=',
! 245: urlencode(htmlspecialchars($name)),
! 246: '">',
! 247: htmlspecialchars($entry->getFilename()), '/</a> [directory]</li>';
! 248: } else {
! 249: echo '<li><a href="', $self, '?introspect=',
! 250: urlencode(htmlspecialchars($dir)), '&viewsource=',
! 251: urlencode(htmlspecialchars($name)),
! 252: '">',
! 253: htmlspecialchars($entry->getFilename()), '</a></li>';
! 254: }
! 255: }
! 256: return false;
! 257: } catch (Exception $e) {
! 258: echo '<html><head><title>Directory not found: ',
! 259: htmlspecialchars($dir), '</title></head>',
! 260: '<body><h1>Directory not found: ', htmlspecialchars($dir), '</h1>',
! 261: '<p>Try <a href="', htmlspecialchars($_SERVER['PHP_SELF']), '?introspect=/">',
! 262: 'This link</a></p></body></html>';
! 263: return false;
! 264: }
! 265: }
! 266:
! 267: public static function webFrontController($initfile)
! 268: {
! 269: if (isset($_SERVER) && isset($_SERVER['REQUEST_URI'])) {
! 270: $uri = parse_url($_SERVER['REQUEST_URI']);
! 271: $archive = realpath($_SERVER['SCRIPT_FILENAME']);
! 272: $subpath = str_replace('/' . basename($archive), '', $uri['path']);
! 273: if (!$subpath || $subpath == '/') {
! 274: if (isset($_GET['viewsource'])) {
! 275: return self::viewSource($archive, $_GET['viewsource']);
! 276: }
! 277: if (isset($_GET['introspect'])) {
! 278: return self::introspect($archive, $_GET['introspect']);
! 279: }
! 280: $subpath = '/' . $initfile;
! 281: }
! 282: if (!self::_fileExists($archive, substr($subpath, 1))) {
! 283: header("HTTP/1.0 404 Not Found");
! 284: return false;
! 285: }
! 286: foreach (self::$deny as $pattern) {
! 287: if (preg_match($pattern, $subpath)) {
! 288: header("HTTP/1.0 404 Not Found");
! 289: return false;
! 290: }
! 291: }
! 292: $inf = pathinfo(basename($subpath));
! 293: if (!isset($inf['extension'])) {
! 294: header('Content-Type: text/plain');
! 295: header('Content-Length: ' .
! 296: self::_filesize($archive, substr($subpath, 1)));
! 297: readfile('phar://install-pear-nozlib.phar' . $subpath);
! 298: return false;
! 299: }
! 300: if (isset(self::$defaultphp[$inf['extension']])) {
! 301: include 'phar://install-pear-nozlib.phar' . $subpath;
! 302: return false;
! 303: }
! 304: if (isset(self::$defaultmimes[$inf['extension']])) {
! 305: header('Content-Type: ' . self::$defaultmimes[$inf['extension']]);
! 306: header('Content-Length: ' .
! 307: self::_filesize($archive, substr($subpath, 1)));
! 308: readfile('phar://install-pear-nozlib.phar' . $subpath);
! 309: return false;
! 310: }
! 311: if (isset(self::$defaultphps[$inf['extension']])) {
! 312: header('Content-Type: text/html');
! 313: $c = highlight_file('phar://install-pear-nozlib.phar' . $subpath, true);
! 314: header('Content-Length: ' . strlen($c));
! 315: echo $c;
! 316: return false;
! 317: }
! 318: header('Content-Type: text/plain');
! 319: header('Content-Length: ' .
! 320: self::_filesize($archive, substr($subpath, 1)));
! 321: readfile('phar://install-pear-nozlib.phar' . $subpath);
! 322: }
! 323: }
! 324:
! 325: /**
! 326: * Detect end of stub
! 327: *
! 328: * @param string $buffer stub past '__HALT_'.'COMPILER();'
! 329: * @return end of stub, prior to length of manifest.
! 330: */
! 331: private static final function _endOfStubLength($buffer)
! 332: {
! 333: $pos = 0;
! 334: if (!strlen($buffer)) {
! 335: return $pos;
! 336: }
! 337: if (($buffer[0] == ' ' || $buffer[0] == "\n") && @substr($buffer, 1, 2) == '')
! 338: {
! 339: $pos += 3;
! 340: if ($buffer[$pos] == "\r" && $buffer[$pos+1] == "\n") {
! 341: $pos += 2;
! 342: }
! 343: else if ($buffer[$pos] == "\n") {
! 344: $pos += 1;
! 345: }
! 346: }
! 347: return $pos;
! 348: }
! 349:
! 350: /**
! 351: * Allows loading an external Phar archive without include()ing it
! 352: *
! 353: * @param string $file phar package to load
! 354: * @param string $alias alias to use
! 355: * @throws Exception
! 356: */
! 357: public static final function loadPhar($file, $alias = NULL)
! 358: {
! 359: $file = realpath($file);
! 360: if ($file) {
! 361: $fp = fopen($file, 'rb');
! 362: $buffer = '';
! 363: while (!feof($fp)) {
! 364: $buffer .= fread($fp, 8192);
! 365: // don't break phars
! 366: if ($pos = strpos($buffer, '__HALT_COMPI' . 'LER();')) {
! 367: $buffer .= fread($fp, 5);
! 368: fclose($fp);
! 369: $pos += 18;
! 370: $pos += self::_endOfStubLength(substr($buffer, $pos));
! 371: return self::_mapPhar($file, $pos, $alias);
! 372: }
! 373: }
! 374: fclose($fp);
! 375: }
! 376: }
! 377:
! 378: /**
! 379: * Map a full real file path to an alias used to refer to the .phar
! 380: *
! 381: * This function can only be called from the initialization of the .phar itself.
! 382: * Any attempt to call from outside the .phar or to re-alias the .phar will fail
! 383: * as a security measure.
! 384: * @param string $alias
! 385: * @param int $dataoffset the value of 42421
! 386: */
! 387: public static final function mapPhar($alias = NULL, $dataoffset = NULL)
! 388: {
! 389: try {
! 390: $trace = debug_backtrace();
! 391: $file = $trace[0]['file'];
! 392: // this ensures that this is safe
! 393: if (!in_array($file, get_included_files())) {
! 394: die('SECURITY ERROR: PHP_Archive::mapPhar can only be called from within ' .
! 395: 'the phar that initiates it');
! 396: }
! 397: $file = realpath($file);
! 398: if (!isset($dataoffset)) {
! 399: $dataoffset = constant('__COMPILER_HALT_OFFSET'.'__');
! 400: $fp = fopen($file, 'rb');
! 401: fseek($fp, $dataoffset, SEEK_SET);
! 402: $dataoffset = $dataoffset + self::_endOfStubLength(fread($fp, 5));
! 403: fclose($fp);
! 404: }
! 405:
! 406: self::_mapPhar($file, $dataoffset);
! 407: } catch (Exception $e) {
! 408: die($e->getMessage());
! 409: }
! 410: }
! 411:
! 412: /**
! 413: * Sub-function, allows recovery from errors
! 414: *
! 415: * @param unknown_type $file
! 416: * @param unknown_type $dataoffset
! 417: */
! 418: private static function _mapPhar($file, $dataoffset, $alias = NULL)
! 419: {
! 420: $file = realpath($file);
! 421: if (isset(self::$_manifest[$file])) {
! 422: return;
! 423: }
! 424: if (!is_array(self::$_pharMapping)) {
! 425: self::$_pharMapping = array();
! 426: }
! 427: $fp = fopen($file, 'rb');
! 428: // seek to __HALT_COMPILER_OFFSET__
! 429: fseek($fp, $dataoffset);
! 430: $manifest_length = unpack('Vlen', fread($fp, 4));
! 431: $manifest = '';
! 432: $last = '1';
! 433: while (strlen($last) && strlen($manifest) < $manifest_length['len']) {
! 434: $read = 8192;
! 435: if ($manifest_length['len'] - strlen($manifest) < 8192) {
! 436: $read = $manifest_length['len'] - strlen($manifest);
! 437: }
! 438: $last = fread($fp, $read);
! 439: $manifest .= $last;
! 440: }
! 441: if (strlen($manifest) < $manifest_length['len']) {
! 442: throw new Exception('ERROR: manifest length read was "' .
! 443: strlen($manifest) .'" should be "' .
! 444: $manifest_length['len'] . '"');
! 445: }
! 446: $info = self::_unserializeManifest($manifest);
! 447: if ($info['alias']) {
! 448: $alias = $info['alias'];
! 449: $explicit = true;
! 450: } else {
! 451: if (!isset($alias)) {
! 452: $alias = $file;
! 453: }
! 454: $explicit = false;
! 455: }
! 456: self::$_manifest[$file] = $info['manifest'];
! 457: $compressed = $info['compressed'];
! 458: self::$_fileStart[$file] = ftell($fp);
! 459: fclose($fp);
! 460: if ($compressed & 0x00001000) {
! 461: if (!function_exists('gzinflate')) {
! 462: throw new Exception('Error: zlib extension is not enabled - gzinflate() function needed' .
! 463: ' for compressed .phars');
! 464: }
! 465: }
! 466: if ($compressed & 0x00002000) {
! 467: if (!function_exists('bzdecompress')) {
! 468: throw new Exception('Error: bzip2 extension is not enabled - bzdecompress() function needed' .
! 469: ' for compressed .phars');
! 470: }
! 471: }
! 472: if (isset(self::$_pharMapping[$alias])) {
! 473: throw new Exception('ERROR: PHP_Archive::mapPhar has already been called for alias "' .
! 474: $alias . '" cannot re-alias to "' . $file . '"');
! 475: }
! 476: self::$_pharMapping[$alias] = array($file, $compressed, $dataoffset, $explicit,
! 477: $info['metadata']);
! 478: self::$_pharFiles[$file] = $alias;
! 479: }
! 480:
! 481: /**
! 482: * extract the manifest into an internal array
! 483: *
! 484: * @param string $manifest
! 485: * @return false|array
! 486: */
! 487: private static function _unserializeManifest($manifest)
! 488: {
! 489: // retrieve the number of files in the manifest
! 490: $info = unpack('V', substr($manifest, 0, 4));
! 491: $apiver = substr($manifest, 4, 2);
! 492: $apiver = bin2hex($apiver);
! 493: $apiver_dots = hexdec($apiver[0]) . '.' . hexdec($apiver[1]) . '.' . hexdec($apiver[2]);
! 494: $majorcompat = hexdec($apiver[0]);
! 495: $calcapi = explode('.', self::APIVersion());
! 496: if ($calcapi[0] != $majorcompat) {
! 497: throw new Exception('Phar is incompatible API version ' . $apiver_dots . ', but ' .
! 498: 'PHP_Archive is API version '.self::APIVersion());
! 499: }
! 500: if ($calcapi[0] === '0') {
! 501: if (self::APIVersion() != $apiver_dots) {
! 502: throw new Exception('Phar is API version ' . $apiver_dots .
! 503: ', but PHP_Archive is API version '.self::APIVersion(), E_USER_ERROR);
! 504: }
! 505: }
! 506: $flags = unpack('V', substr($manifest, 6, 4));
! 507: $ret = array('compressed' => $flags & 0x00003000);
! 508: // signature is not verified by default in PHP_Archive, phar is better
! 509: $ret['hassignature'] = $flags & 0x00010000;
! 510: $aliaslen = unpack('V', substr($manifest, 10, 4));
! 511: if ($aliaslen) {
! 512: $ret['alias'] = substr($manifest, 14, $aliaslen[1]);
! 513: } else {
! 514: $ret['alias'] = false;
! 515: }
! 516: $manifest = substr($manifest, 14 + $aliaslen[1]);
! 517: $metadatalen = unpack('V', substr($manifest, 0, 4));
! 518: if ($metadatalen[1]) {
! 519: $ret['metadata'] = unserialize(substr($manifest, 4, $metadatalen[1]));
! 520: $manifest = substr($manifest, 4 + $metadatalen[1]);
! 521: } else {
! 522: $ret['metadata'] = null;
! 523: $manifest = substr($manifest, 4);
! 524: }
! 525: $offset = 0;
! 526: $start = 0;
! 527: for ($i = 0; $i < $info[1]; $i++) {
! 528: // length of the file name
! 529: $len = unpack('V', substr($manifest, $start, 4));
! 530: $start += 4;
! 531: // file name
! 532: $savepath = substr($manifest, $start, $len[1]);
! 533: $start += $len[1];
! 534: // retrieve manifest data:
! 535: // 0 = uncompressed file size
! 536: // 1 = timestamp of when file was added to phar
! 537: // 2 = compressed filesize
! 538: // 3 = crc32
! 539: // 4 = flags
! 540: // 5 = metadata length
! 541: $ret['manifest'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($manifest, $start, 24)));
! 542: $ret['manifest'][$savepath][3] = sprintf('%u', $ret['manifest'][$savepath][3]
! 543: & 0xffffffff);
! 544: if ($ret['manifest'][$savepath][5]) {
! 545: $ret['manifest'][$savepath][6] = unserialize(substr($manifest, $start + 24,
! 546: $ret['manifest'][$savepath][5]));
! 547: } else {
! 548: $ret['manifest'][$savepath][6] = null;
! 549: }
! 550: $ret['manifest'][$savepath][7] = $offset;
! 551: $offset += $ret['manifest'][$savepath][2];
! 552: $start += 24 + $ret['manifest'][$savepath][5];
! 553: }
! 554: return $ret;
! 555: }
! 556:
! 557: /**
! 558: * @param string
! 559: */
! 560: private static function processFile($path)
! 561: {
! 562: if ($path == '.') {
! 563: return '';
! 564: }
! 565: $std = str_replace("\\", "/", $path);
! 566: while ($std != ($std = ereg_replace("[^\/:?]+/\.\./", "", $std))) ;
! 567: $std = str_replace("/./", "", $std);
! 568: if (strlen($std) > 1 && $std[0] == '/') {
! 569: $std = substr($std, 1);
! 570: }
! 571: if (strncmp($std, "./", 2) == 0) {
! 572: return substr($std, 2);
! 573: } else {
! 574: return $std;
! 575: }
! 576: }
! 577:
! 578: /**
! 579: * Seek in the master archive to a matching file or directory
! 580: * @param string
! 581: */
! 582: protected function selectFile($path, $allowdirs = true)
! 583: {
! 584: $std = self::processFile($path);
! 585: if (isset(self::$_manifest[$this->_archiveName][$path])) {
! 586: $this->_setCurrentFile($path);
! 587: return true;
! 588: }
! 589: if (!$allowdirs) {
! 590: return 'Error: "' . $path . '" is not a file in phar "' . $this->_basename . '"';
! 591: }
! 592: foreach (self::$_manifest[$this->_archiveName] as $file => $info) {
! 593: if (empty($std) ||
! 594: //$std is a directory
! 595: strncmp($std.'/', $path, strlen($std)+1) == 0) {
! 596: $this->currentFilename = $this->internalFileLength = $this->currentStat = null;
! 597: return true;
! 598: }
! 599: }
! 600: return 'Error: "' . $path . '" not found in phar "' . $this->_basename . '"';
! 601: }
! 602:
! 603: private function _setCurrentFile($path)
! 604: {
! 605: $this->currentStat = array(
! 606: 2 => 0100444, // file mode, readable by all, writeable by none
! 607: 4 => 0, // uid
! 608: 5 => 0, // gid
! 609: 7 => self::$_manifest[$this->_archiveName][$path][0], // size
! 610: 9 => self::$_manifest[$this->_archiveName][$path][1], // creation time
! 611: );
! 612: $this->currentFilename = $path;
! 613: $this->internalFileLength = self::$_manifest[$this->_archiveName][$path][2];
! 614: // seek to offset of file header within the .phar
! 615: if (is_resource(@$this->fp)) {
! 616: fseek($this->fp, self::$_fileStart[$this->_archiveName] + self::$_manifest[$this->_archiveName][$path][7]);
! 617: }
! 618: }
! 619:
! 620: private static function _fileExists($archive, $path)
! 621: {
! 622: return isset(self::$_manifest[$archive]) &&
! 623: isset(self::$_manifest[$archive][$path]);
! 624: }
! 625:
! 626: private static function _filesize($archive, $path)
! 627: {
! 628: return self::$_manifest[$archive][$path][0];
! 629: }
! 630:
! 631: /**
! 632: * Seek to a file within the master archive, and extract its contents
! 633: * @param string
! 634: * @return array|string an array containing an error message string is returned
! 635: * upon error, otherwise the file contents are returned
! 636: */
! 637: public function extractFile($path)
! 638: {
! 639: $this->fp = @fopen($this->_archiveName, "rb");
! 640: if (!$this->fp) {
! 641: return array('Error: cannot open phar "' . $this->_archiveName . '"');
! 642: }
! 643: if (($e = $this->selectFile($path, false)) === true) {
! 644: $data = '';
! 645: $count = $this->internalFileLength;
! 646: while ($count) {
! 647: if ($count < 8192) {
! 648: $data .= @fread($this->fp, $count);
! 649: $count = 0;
! 650: } else {
! 651: $count -= 8192;
! 652: $data .= @fread($this->fp, 8192);
! 653: }
! 654: }
! 655: @fclose($this->fp);
! 656: if (self::$_manifest[$this->_archiveName][$path][4] & self::GZ) {
! 657: $data = gzinflate($data);
! 658: } elseif (self::$_manifest[$this->_archiveName][$path][4] & self::BZ2) {
! 659: $data = bzdecompress($data);
! 660: }
! 661: if (!isset(self::$_manifest[$this->_archiveName][$path]['ok'])) {
! 662: if (strlen($data) != $this->currentStat[7]) {
! 663: return array("Not valid internal .phar file (size error {$size} != " .
! 664: $this->currentStat[7] . ")");
! 665: }
! 666: if (self::$_manifest[$this->_archiveName][$path][3] != sprintf("%u", crc32($data) & 0xffffffff)) {
! 667: return array("Not valid internal .phar file (checksum error)");
! 668: }
! 669: self::$_manifest[$this->_archiveName][$path]['ok'] = true;
! 670: }
! 671: return $data;
! 672: } else {
! 673: @fclose($this->fp);
! 674: return array($e);
! 675: }
! 676: }
! 677:
! 678: /**
! 679: * Parse urls like phar:///fullpath/to/my.phar/file.txt
! 680: *
! 681: * @param string $file
! 682: * @return false|array
! 683: */
! 684: static protected function parseUrl($file)
! 685: {
! 686: if (substr($file, 0, 7) != 'phar://') {
! 687: return false;
! 688: }
! 689: $file = substr($file, 7);
! 690:
! 691: $ret = array('scheme' => 'phar');
! 692: $pos_p = strpos($file, '.phar.php');
! 693: $pos_z = strpos($file, '.phar.gz');
! 694: $pos_b = strpos($file, '.phar.bz2');
! 695: if ($pos_p) {
! 696: if ($pos_z) {
! 697: return false;
! 698: }
! 699: $ret['host'] = substr($file, 0, $pos_p + strlen('.phar.php'));
! 700: $ret['path'] = substr($file, strlen($ret['host']));
! 701: } elseif ($pos_z) {
! 702: $ret['host'] = substr($file, 0, $pos_z + strlen('.phar.gz'));
! 703: $ret['path'] = substr($file, strlen($ret['host']));
! 704: } elseif ($pos_b) {
! 705: $ret['host'] = substr($file, 0, $pos_z + strlen('.phar.bz2'));
! 706: $ret['path'] = substr($file, strlen($ret['host']));
! 707: } elseif (($pos_p = strpos($file, ".phar")) !== false) {
! 708: $ret['host'] = substr($file, 0, $pos_p + strlen('.phar'));
! 709: $ret['path'] = substr($file, strlen($ret['host']));
! 710: } else {
! 711: return false;
! 712: }
! 713: if (!$ret['path']) {
! 714: $ret['path'] = '/';
! 715: }
! 716: return $ret;
! 717: }
! 718:
! 719: /**
! 720: * Locate the .phar archive in the include_path and detect the file to open within
! 721: * the archive.
! 722: *
! 723: * Possible parameters are phar://pharname.phar/filename_within_phar.ext
! 724: * @param string a file within the archive
! 725: * @return string the filename within the .phar to retrieve
! 726: */
! 727: public function initializeStream($file)
! 728: {
! 729: $file = self::processFile($file);
! 730: $info = @parse_url($file);
! 731: if (!$info) {
! 732: $info = self::parseUrl($file);
! 733: }
! 734: if (!$info) {
! 735: return false;
! 736: }
! 737: if (!isset($info['host'])) {
! 738: // malformed internal file
! 739: return false;
! 740: }
! 741: if (!isset(self::$_pharFiles[$info['host']]) &&
! 742: !isset(self::$_pharMapping[$info['host']])) {
! 743: try {
! 744: self::loadPhar($info['host']);
! 745: // use alias from here out
! 746: $info['host'] = self::$_pharFiles[$info['host']];
! 747: } catch (Exception $e) {
! 748: return false;
! 749: }
! 750: }
! 751: if (!isset($info['path'])) {
! 752: return false;
! 753: } elseif (strlen($info['path']) > 1) {
! 754: $info['path'] = substr($info['path'], 1);
! 755: }
! 756: if (isset(self::$_pharMapping[$info['host']])) {
! 757: $this->_basename = $info['host'];
! 758: $this->_archiveName = self::$_pharMapping[$info['host']][0];
! 759: $this->_compressed = self::$_pharMapping[$info['host']][1];
! 760: } elseif (isset(self::$_pharFiles[$info['host']])) {
! 761: $this->_archiveName = $info['host'];
! 762: $this->_basename = self::$_pharFiles[$info['host']];
! 763: $this->_compressed = self::$_pharMapping[$this->_basename][1];
! 764: }
! 765: $file = $info['path'];
! 766: return $file;
! 767: }
! 768:
! 769: /**
! 770: * Open the requested file - PHP streams API
! 771: *
! 772: * @param string $file String provided by the Stream wrapper
! 773: * @access private
! 774: */
! 775: public function stream_open($file)
! 776: {
! 777: return $this->_streamOpen($file);
! 778: }
! 779:
! 780: /**
! 781: * @param string filename to opne, or directory name
! 782: * @param bool if true, a directory will be matched, otherwise only files
! 783: * will be matched
! 784: * @uses trigger_error()
! 785: * @return bool success of opening
! 786: * @access private
! 787: */
! 788: private function _streamOpen($file, $searchForDir = false)
! 789: {
! 790: $path = $this->initializeStream($file);
! 791: if (!$path) {
! 792: trigger_error('Error: Unknown phar in "' . $file . '"', E_USER_ERROR);
! 793: }
! 794: if (is_array($this->file = $this->extractFile($path))) {
! 795: trigger_error($this->file[0], E_USER_ERROR);
! 796: return false;
! 797: }
! 798: if ($path != $this->currentFilename) {
! 799: if (!$searchForDir) {
! 800: trigger_error("Cannot open '$file', is a directory", E_USER_ERROR);
! 801: return false;
! 802: } else {
! 803: $this->file = '';
! 804: return true;
! 805: }
! 806: }
! 807:
! 808: if (!is_null($this->file) && $this->file !== false) {
! 809: return true;
! 810: } else {
! 811: return false;
! 812: }
! 813: }
! 814:
! 815: /**
! 816: * Read the data - PHP streams API
! 817: *
! 818: * @param int
! 819: * @access private
! 820: */
! 821: public function stream_read($count)
! 822: {
! 823: $ret = substr($this->file, $this->position, $count);
! 824: $this->position += strlen($ret);
! 825: return $ret;
! 826: }
! 827:
! 828: /**
! 829: * Whether we've hit the end of the file - PHP streams API
! 830: * @access private
! 831: */
! 832: function stream_eof()
! 833: {
! 834: return $this->position >= $this->currentStat[7];
! 835: }
! 836:
! 837: /**
! 838: * For seeking the stream - PHP streams API
! 839: * @param int
! 840: * @param SEEK_SET|SEEK_CUR|SEEK_END
! 841: * @access private
! 842: */
! 843: public function stream_seek($pos, $whence)
! 844: {
! 845: switch ($whence) {
! 846: case SEEK_SET:
! 847: if ($pos < 0) {
! 848: return false;
! 849: }
! 850: $this->position = $pos;
! 851: break;
! 852: case SEEK_CUR:
! 853: if ($pos + $this->currentStat[7] < 0) {
! 854: return false;
! 855: }
! 856: $this->position += $pos;
! 857: break;
! 858: case SEEK_END:
! 859: if ($pos + $this->currentStat[7] < 0) {
! 860: return false;
! 861: }
! 862: $this->position = $pos + $this->currentStat[7];
! 863: break;
! 864: default:
! 865: return false;
! 866: }
! 867: return true;
! 868: }
! 869:
! 870: /**
! 871: * The current position in the stream - PHP streams API
! 872: * @access private
! 873: */
! 874: public function stream_tell()
! 875: {
! 876: return $this->position;
! 877: }
! 878:
! 879: /**
! 880: * The result of an fstat call, returns mod time from creation, and file size -
! 881: * PHP streams API
! 882: * @uses _stream_stat()
! 883: * @access private
! 884: */
! 885: public function stream_stat()
! 886: {
! 887: return $this->_stream_stat();
! 888: }
! 889:
! 890: /**
! 891: * Retrieve statistics on a file or directory within the .phar
! 892: * @param string file/directory to stat
! 893: * @access private
! 894: */
! 895: public function _stream_stat($file = null)
! 896: {
! 897: $std = $file ? self::processFile($file) : $this->currentFilename;
! 898: if ($file) {
! 899: if (isset(self::$_manifest[$this->_archiveName][$file])) {
! 900: $this->_setCurrentFile($file);
! 901: $isdir = false;
! 902: } else {
! 903: do {
! 904: $isdir = false;
! 905: if ($file == '/') {
! 906: break;
! 907: }
! 908: foreach (self::$_manifest[$this->_archiveName] as $path => $info) {
! 909: if (strpos($path, $file) === 0) {
! 910: if (strlen($path) > strlen($file) &&
! 911: $path[strlen($file)] == '/') {
! 912: break 2;
! 913: }
! 914: }
! 915: }
! 916: // no files exist and no directories match this string
! 917: return false;
! 918: } while (false);
! 919: $isdir = true;
! 920: }
! 921: } else {
! 922: $isdir = false; // open streams must be files
! 923: }
! 924: $mode = $isdir ? 0040444 : 0100444;
! 925: // 040000 = dir, 010000 = file
! 926: // everything is readable, nothing is writeable
! 927: return array(
! 928: 0, 0, $mode, 0, 0, 0, 0, 0, 0, 0, 0, 0, // non-associative indices
! 929: 'dev' => 0, 'ino' => 0,
! 930: 'mode' => $mode,
! 931: 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'blksize' => 0, 'blocks' => 0,
! 932: 'size' => $this->currentStat[7],
! 933: 'atime' => $this->currentStat[9],
! 934: 'mtime' => $this->currentStat[9],
! 935: 'ctime' => $this->currentStat[9],
! 936: );
! 937: }
! 938:
! 939: /**
! 940: * Stat a closed file or directory - PHP streams API
! 941: * @param string
! 942: * @param int
! 943: * @access private
! 944: */
! 945: public function url_stat($url, $flags)
! 946: {
! 947: $path = $this->initializeStream($url);
! 948: return $this->_stream_stat($path);
! 949: }
! 950:
! 951: /**
! 952: * Open a directory in the .phar for reading - PHP streams API
! 953: * @param string directory name
! 954: * @access private
! 955: */
! 956: public function dir_opendir($path)
! 957: {
! 958: $info = @parse_url($path);
! 959: if (!$info) {
! 960: $info = self::parseUrl($path);
! 961: if (!$info) {
! 962: trigger_error('Error: "' . $path . '" is a file, and cannot be opened with opendir',
! 963: E_USER_ERROR);
! 964: return false;
! 965: }
! 966: }
! 967: $path = !empty($info['path']) ?
! 968: $info['host'] . $info['path'] : $info['host'] . '/';
! 969: $path = $this->initializeStream('phar://' . $path);
! 970: if (isset(self::$_manifest[$this->_archiveName][$path])) {
! 971: trigger_error('Error: "' . $path . '" is a file, and cannot be opened with opendir',
! 972: E_USER_ERROR);
! 973: return false;
! 974: }
! 975: if ($path == false) {
! 976: trigger_error('Error: Unknown phar in "' . $file . '"', E_USER_ERROR);
! 977: return false;
! 978: }
! 979: $this->fp = @fopen($this->_archiveName, "rb");
! 980: if (!$this->fp) {
! 981: trigger_error('Error: cannot open phar "' . $this->_archiveName . '"');
! 982: return false;
! 983: }
! 984: $this->_dirFiles = array();
! 985: foreach (self::$_manifest[$this->_archiveName] as $file => $info) {
! 986: if ($path == '/') {
! 987: if (strpos($file, '/')) {
! 988: $a = explode('/', $file);
! 989: $this->_dirFiles[array_shift($a)] = true;
! 990: } else {
! 991: $this->_dirFiles[$file] = true;
! 992: }
! 993: } elseif (strpos($file, $path) === 0) {
! 994: $fname = substr($file, strlen($path) + 1);
! 995: if (strpos($fname, '/')) {
! 996: // this is a directory
! 997: $a = explode('/', $fname);
! 998: $this->_dirFiles[array_shift($a)] = true;
! 999: } elseif ($file[strlen($path)] == '/') {
! 1000: // this is a file
! 1001: $this->_dirFiles[$fname] = true;
! 1002: }
! 1003: }
! 1004: }
! 1005: @fclose($this->fp);
! 1006: if (!count($this->_dirFiles)) {
! 1007: return false;
! 1008: }
! 1009: @uksort($this->_dirFiles, 'strnatcmp');
! 1010: return true;
! 1011: }
! 1012:
! 1013: /**
! 1014: * Read the next directory entry - PHP streams API
! 1015: * @access private
! 1016: */
! 1017: public function dir_readdir()
! 1018: {
! 1019: $ret = key($this->_dirFiles);
! 1020: @next($this->_dirFiles);
! 1021: if (!$ret) {
! 1022: return false;
! 1023: }
! 1024: return $ret;
! 1025: }
! 1026:
! 1027: /**
! 1028: * Close a directory handle opened with opendir() - PHP streams API
! 1029: * @access private
! 1030: */
! 1031: public function dir_closedir()
! 1032: {
! 1033: $this->_dirFiles = array();
! 1034: return true;
! 1035: }
! 1036:
! 1037: /**
! 1038: * Rewind to the first directory entry - PHP streams API
! 1039: * @access private
! 1040: */
! 1041: public function dir_rewinddir()
! 1042: {
! 1043: @reset($this->_dirFiles);
! 1044: return true;
! 1045: }
! 1046:
! 1047: /**
! 1048: * API version of this class
! 1049: * @return string
! 1050: */
! 1051: public static final function APIVersion()
! 1052: {
! 1053: return '1.0.0';
! 1054: }
! 1055:
! 1056: /**
! 1057: * Retrieve Phar-specific metadata for a Phar archive
! 1058: *
! 1059: * @param string $phar full path to Phar archive, or alias
! 1060: * @return null|mixed The value that was serialized for the Phar
! 1061: * archive's metadata
! 1062: * @throws Exception
! 1063: */
! 1064: public static function getPharMetadata($phar)
! 1065: {
! 1066: if (isset(self::$_pharFiles[$phar])) {
! 1067: $phar = self::$_pharFiles[$phar];
! 1068: }
! 1069: if (!isset(self::$_pharMapping[$phar])) {
! 1070: throw new Exception('Unknown Phar archive: "' . $phar . '"');
! 1071: }
! 1072: return self::$_pharMapping[$phar][4];
! 1073: }
! 1074:
! 1075: /**
! 1076: * Retrieve File-specific metadata for a Phar archive file
! 1077: *
! 1078: * @param string $phar full path to Phar archive, or alias
! 1079: * @param string $file relative path to file within Phar archive
! 1080: * @return null|mixed The value that was serialized for the Phar
! 1081: * archive's metadata
! 1082: * @throws Exception
! 1083: */
! 1084: public static function getFileMetadata($phar, $file)
! 1085: {
! 1086: if (!isset(self::$_pharFiles[$phar])) {
! 1087: if (!isset(self::$_pharMapping[$phar])) {
! 1088: throw new Exception('Unknown Phar archive: "' . $phar . '"');
! 1089: }
! 1090: $phar = self::$_pharMapping[$phar][0];
! 1091: }
! 1092: if (!isset(self::$_manifest[$phar])) {
! 1093: throw new Exception('Unknown Phar: "' . $phar . '"');
! 1094: }
! 1095: $file = self::processFile($file);
! 1096: if (!isset(self::$_manifest[$phar][$file])) {
! 1097: throw new Exception('Unknown file "' . $file . '" within Phar "'. $phar . '"');
! 1098: }
! 1099: return self::$_manifest[$phar][$file][6];
! 1100: }
! 1101:
! 1102: /**
! 1103: * @return list of supported signature algorithmns.
! 1104: */
! 1105: public static function getsupportedsignatures()
! 1106: {
! 1107: $ret = array('MD5', 'SHA-1');
! 1108: if (extension_loaded('hash')) {
! 1109: $ret[] = 'SHA-256';
! 1110: $ret[] = 'SHA-512';
! 1111: }
! 1112: return $ret;
! 1113: }
! 1114: }}
! 1115: if (!class_exists('Phar')) {
! 1116: PHP_Archive::mapPhar(null, 42421 );
! 1117: } else {
! 1118: try {
! 1119: Phar::mapPhar();
! 1120: } catch (Exception $e) {
! 1121: echo $e->getMessage();
! 1122: }
! 1123: }
! 1124: if (class_exists('PHP_Archive') && !in_array('phar', stream_get_wrappers())) {
! 1125: stream_wrapper_register('phar', 'PHP_Archive');
! 1126: }
! 1127:
! 1128: @ini_set('memory_limit', -1);
! 1129: if (extension_loaded('phar')) {if (isset($_SERVER) && isset($_SERVER['REQUEST_URI'])) {
! 1130: $uri = parse_url($_SERVER['REQUEST_URI']);
! 1131: $archive = realpath($_SERVER['SCRIPT_FILENAME']);
! 1132: $subpath = str_replace('/' . basename($archive), '', $uri['path']);
! 1133: $mimetypes = array (
! 1134: 'aif' => 'audio/x-aiff',
! 1135: 'aiff' => 'audio/x-aiff',
! 1136: 'arc' => 'application/octet-stream',
! 1137: 'arj' => 'application/octet-stream',
! 1138: 'art' => 'image/x-jg',
! 1139: 'asf' => 'video/x-ms-asf',
! 1140: 'asx' => 'video/x-ms-asf',
! 1141: 'avi' => 'video/avi',
! 1142: 'bin' => 'application/octet-stream',
! 1143: 'bm' => 'image/bmp',
! 1144: 'bmp' => 'image/bmp',
! 1145: 'bz2' => 'application/x-bzip2',
! 1146: 'css' => 'text/css',
! 1147: 'doc' => 'application/msword',
! 1148: 'dot' => 'application/msword',
! 1149: 'dv' => 'video/x-dv',
! 1150: 'dvi' => 'application/x-dvi',
! 1151: 'eps' => 'application/postscript',
! 1152: 'exe' => 'application/octet-stream',
! 1153: 'gif' => 'image/gif',
! 1154: 'gz' => 'application/x-gzip',
! 1155: 'gzip' => 'application/x-gzip',
! 1156: 'htm' => 'text/html',
! 1157: 'html' => 'text/html',
! 1158: 'ico' => 'image/x-icon',
! 1159: 'jpe' => 'image/jpeg',
! 1160: 'jpg' => 'image/jpeg',
! 1161: 'jpeg' => 'image/jpeg',
! 1162: 'js' => 'application/x-javascript',
! 1163: 'log' => 'text/plain',
! 1164: 'mid' => 'audio/x-midi',
! 1165: 'mov' => 'video/quicktime',
! 1166: 'mp2' => 'audio/mpeg',
! 1167: 'mp3' => 'audio/mpeg3',
! 1168: 'mpg' => 'audio/mpeg',
! 1169: 'pdf' => 'aplication/pdf',
! 1170: 'png' => 'image/png',
! 1171: 'rtf' => 'application/rtf',
! 1172: 'tif' => 'image/tiff',
! 1173: 'tiff' => 'image/tiff',
! 1174: 'txt' => 'text/plain',
! 1175: 'xml' => 'text/xml',
! 1176: );
! 1177: $phpfiles = array (
! 1178: 'php' => true,
! 1179: );
! 1180: $phpsfiles = array (
! 1181: 'phps' => true,
! 1182: );
! 1183: $deny = array (
! 1184: 0 => '/.+\\.inc$/',
! 1185: );
! 1186: $subpath = str_replace('/' . basename($archive), '', $uri['path']);
! 1187: if (!$subpath || $subpath == '/') {
! 1188: $subpath = '/PEAR.php';
! 1189: }
! 1190: if ($subpath[0] != '/') {
! 1191: $subpath = '/' . $subpath;
! 1192: }
! 1193: if (!@file_exists('phar://' . $archive . $subpath)) {
! 1194: header("HTTP/1.0 404 Not Found");
! 1195: exit;
! 1196: }
! 1197:
! 1198: foreach ($deny as $pattern) {
! 1199: if (preg_match($pattern, $subpath)) {
! 1200: header("HTTP/1.0 404 Not Found");
! 1201: exit;
! 1202: }
! 1203: }
! 1204: $inf = pathinfo(basename($subpath));
! 1205: if (!isset($inf['extension'])) {
! 1206: header('Content-Type: text/plain');
! 1207: header('Content-Length: ' . filesize('phar://' . $archive . $subpath));
! 1208: readfile('phar://' . $archive . $subpath);
! 1209: exit;
! 1210: }
! 1211: if (isset($phpfiles[$inf['extension']])) {
! 1212: include 'phar://' . $archive . '/' . $subpath;
! 1213: exit;
! 1214: }
! 1215: if (isset($mimetypes[$inf['extension']])) {
! 1216: header('Content-Type: ' . $mimetypes[$inf['extension']]);
! 1217: header('Content-Length: ' . filesize('phar://' . $archive . $subpath));
! 1218: readfile('phar://' . $archive . $subpath);
! 1219: exit;
! 1220: }
! 1221: if (isset($phpsfiles[$inf['extension']])) {
! 1222: header('Content-Type: text/html');
! 1223: $c = highlight_file('phar://' . $archive . $subpath, true);
! 1224: header('Content-Length: ' . strlen($c));
! 1225: echo $c;
! 1226: exit;
! 1227: }
! 1228: header('Content-Type: text/plain');
! 1229: header('Content-Length: ' . filesize('phar://' . $archive . '/' . $subpath));
! 1230: readfile('phar://' . $archive . '/' . $subpath);
! 1231: exit;
! 1232: }} else {if (!empty($_SERVER['REQUEST_URI'])) {PHP_Archive::webFrontController('PEAR.php');exit;}}
! 1233:
! 1234:
! 1235:
! 1236: require_once 'phar://install-pear-nozlib.phar/index.php';
! 1237: __HALT_COMPILER();- G &