Annotation of embedaddon/php/pear/install-pear-nozlib.phar, revision 1.1.1.2
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';
1.1.1.2 ! misho 1237: __HALT_COMPILER();\ k &