]> granicus.if.org Git - php/commitdiff
add Phar::createDefaultStub(), which can take as an argument the filename
authorGreg Beaver <cellog@php.net>
Sat, 19 Jan 2008 04:26:22 +0000 (04:26 +0000)
committerGreg Beaver <cellog@php.net>
Sat, 19 Jan 2008 04:26:22 +0000 (04:26 +0000)
that should be loaded as a "bootstrap" for the phar archive

ext/phar/makestub.php
ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/phar/shortarc.php
ext/phar/stub.h
ext/phar/tests/nophar.phar
ext/phar/tests/phar_commitwrite.phpt
ext/phar/tests/phar_create_in_cwd.phpt
ext/phar/tests/phar_createdefaultstub.phpt [new file with mode: 0644]

index 4296cab2d526dfe3821b28fd2d2f5a1cac16eb09..3ce5a5072bf404d4f9a1102d63e60aefd0f8d357 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 $s = str_replace("\r", '', file_get_contents(dirname(__FILE__) . '/shortarc.php'));
+
 $s .= "\nExtract_Phar::go(XXXX);\n__HALT_COMPILER();";
 $news = '';
 $last = -1;
@@ -20,9 +21,14 @@ foreach (token_get_all($s) as $token) {
     }
 }
 $s = $news . ' ?>';
-$s = str_replace('XXXX', strlen($s)-1, $s);
+$slen = strlen($s) - strlen('index.php');
+//$s = str_replace('XXXX', strlen($s)-1, $s);
 $s = str_replace('"', '\\"', $s);
 $s = str_replace("\n", '\n', $s);
+$s1 = substr($s, 0, strpos($s, 'index.php'));
+$s2 = substr($s, strlen($s1) + strlen('index.php'));
+$s2 = substr($s2, 0, strpos($s2, 'XXXX'));
+$s3 = substr($s, strlen($s2) + 4 + strlen($s1) + strlen('index.php'));
 
 $stub = '/*
   +----------------------------------------------------------------------+
@@ -44,7 +50,10 @@ $stub = '/*
 
 /* $Id$ */
 
-static const char newstub[] = "' . $s . '";
+static const char newstub1[] = "' . $s1 . '";
+static const char newstub2[] = "' . $s2 . '";
+static const char newstub3[] = "' . $s3 . '";
+static const int newstub_len = ' . $slen . ';
 ';
 
 file_put_contents(dirname(__FILE__) . '/stub.h', $stub);
index 38f3f75bc115050bc6393297391af2cf8d47ffe4..09cedbfdc220b8fdbba4e2a31567b6c5420f18e2 100644 (file)
@@ -2335,6 +2335,39 @@ static int phar_flush_clean_deleted_apply(void *data TSRMLS_DC) /* {{{ */
 }
 /* }}} */
 
+char *phar_create_default_stub(const char *index_php, size_t *len, char **error TSRMLS_DC)
+{
+#include "stub.h"
+       char *stub = NULL;
+       static const char def[] = "index.php";
+       int name_len;
+       size_t dummy;
+
+       if (!len) {
+               len = &dummy;
+       }
+
+       if (index_php) {
+               name_len = strlen(index_php);
+       }
+       if (error) {
+               *error = NULL;
+       }
+       if (index_php && name_len > 400) {
+               /* ridiculous big not allowed for index.php startup filename */
+               if (error) {
+                       spprintf(error, 0, "Illegal filename passed in for stub creation, was %d characters long, and only 400 or less is allowed", name_len);
+                       return NULL;
+               }
+       }
+       if (!index_php) {
+               *len = spprintf(&stub, sizeof("index.php")-1 + newstub_len - 1, "%s%s%s%d%s", newstub1, def, newstub2, (int) sizeof("index.php")-1 + newstub_len - 1, newstub3);
+       } else {
+               *len = spprintf(&stub, name_len + newstub_len - 1, "%s%s%s%d%s", newstub1, index_php, newstub2, name_len + newstub_len - 1, newstub3);
+       }
+       return stub;
+}
+
 /**
  * Save phar contents to disk
  *
@@ -2343,8 +2376,8 @@ static int phar_flush_clean_deleted_apply(void *data TSRMLS_DC) /* {{{ */
  */
 int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error TSRMLS_DC) /* {{{ */
 {
-#include "stub.h"
 /*     static const char newstub[] = "<?php __HALT_COMPILER(); ?>\r\n"; */
+       char *newstub;
        phar_entry_info *entry, *newentry;
        int halt_offset, restore_alias_len, global_flags = 0, closeoldfile;
        char *buf, *pos;
@@ -2475,8 +2508,9 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error
                        }
                } else {
                        /* this is a brand new phar */
-                       phar->halt_offset = sizeof(newstub)-1;
-                       if (sizeof(newstub)-1 != php_stream_write(newfile, newstub, sizeof(newstub)-1)) {
+                       newstub = phar_create_default_stub(NULL, &(phar->halt_offset), NULL TSRMLS_CC);
+                       if (phar->halt_offset != php_stream_write(newfile, newstub, phar->halt_offset)) {
+                               efree(newstub);
                                if (closeoldfile) {
                                        php_stream_close(oldfile);
                                }
@@ -2486,6 +2520,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, char **error
                                }
                                return EOF;
                        }
+                       efree(newstub);
                }
        }
        manifest_ftell = php_stream_tell(newfile);
index 82a60d9674bfb3e5e91c04161af1ce454e9bd173..f63a104f4283e6391032cf12dd13faab3232327c 100755 (executable)
@@ -333,6 +333,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
 int phar_open_compiled_file(char *alias, int alias_len, char **error TSRMLS_DC);
 int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len, char *alias, int alias_len, char **error TSRMLS_DC);
 int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
+char *phar_create_default_stub(const char *index_php, size_t *len, char **error TSRMLS_DC);
 
 char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC);
 phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, php_stream *fp,
index 8448ffb55d72b27a211a1aa76178d2228f9a5db0..26712263f5df42a2bc0feea996b65f24a275def6 100755 (executable)
@@ -735,6 +735,28 @@ PHP_METHOD(Phar, interceptFileFuncs)
 }
 /* }}} */
 
+/* {{ proto array Phar::createDefaultStub([string indexfile])
+ * Return a stub that can be used to run a phar-based archive without the phar extension
+ * indexfile is the startup filename, which defaults to "index.php"
+ */
+PHP_METHOD(Phar, createDefaultStub)
+{
+       char *index = NULL, *error;
+       int index_len;
+       size_t stub_len;
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &index, &index_len) == FAILURE) {
+               return;
+       }
+
+       index = phar_create_default_stub(index, &stub_len, &error TSRMLS_CC);
+       if (error) {
+               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, error);
+               efree(error);
+               return;
+       }
+       RETURN_STRINGL(index, stub_len, 0);
+}
+
 /* {{{ proto mixed Phar::mapPhar([string alias, [int dataoffset]])
  * Reads the currently executed file (a phar) and registers its manifest */
 PHP_METHOD(Phar, mapPhar)
@@ -3384,6 +3406,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mungServer, 0, 0, 1)
        ZEND_ARG_INFO(0, munglist)
 ZEND_END_ARG_INFO();
 
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_cDS, 0, 0, 0)
+       ZEND_ARG_INFO(0, index_php)
+ZEND_END_ARG_INFO();
+
 static
 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setStub, 0, 0, 1)
        ZEND_ARG_INFO(0, newstub)
@@ -3483,6 +3510,7 @@ zend_function_entry php_archive_methods[] = {
        PHP_ME(Phar, getSupportedSignatures,NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
        PHP_ME(Phar, getSupportedCompression,NULL,                     ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
        PHP_ME(Phar, isValidPharFilename,   NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
+       PHP_ME(Phar, createDefaultStub,     arginfo_phar_cDS,          ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
        {NULL, NULL, NULL}
 };
 
index 5ab57577a36b8577dda8488ce542ed64a3ce6452..28b5f28cb3d1fb206a1dc68d5becf428f192e50d 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
     Phar::interceptFileFuncs();
-    include 'phar://' . __FILE__ . '/index.php';
+    include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
     return;
 }
 class Extract_Phar
@@ -11,6 +11,7 @@ class Extract_Phar
     const GZ = 0x1000;
     const BZ2 = 0x2000;
     const MASK = 0x3000;
+    const START = 'index.php';
     static function go($D)
     {
         register_shutdown_function(array('Extract_Phar', '_removeTmpFiles'));
@@ -75,7 +76,7 @@ class Extract_Phar
             self::$tmp[] = realpath($temp . '/' . $path);
         }
         chdir($temp);
-        include 'index.php';
+        include self::START;
     }
 
     static function tmpdir()
index 7f42a99f9c1f7ee7e9eaf3eec3b8eea8e547dbae..74db1fb448520449d9be7ef5d2257a9afb724dff 100644 (file)
@@ -18,4 +18,7 @@
 
 /* $Id$ */
 
-static const char newstub[] = "<?php\nif (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {\nPhar::interceptFileFuncs();\ninclude 'phar://' . __FILE__ . '/index.php';\nreturn;\n}\nclass Extract_Phar\n{\nstatic $tmp = array();\nstatic $origdir;\nconst GZ = 0x1000;\nconst BZ2 = 0x2000;\nconst MASK = 0x3000;\nstatic function go($D)\n{\nregister_shutdown_function(array('Extract_Phar', '_removeTmpFiles'));\n$fp = fopen(__FILE__, 'rb');\nfseek($fp, $D);\n$L = unpack('V', fread($fp, 4));\n$m = '';\ndo {\n$read = 8192;\nif ($L[1] - strlen($m) < 8192) {\n$read = $L[1] - strlen($m);\n}\n$last = fread($fp, $read);\n$m .= $last;\n} while (strlen($last) && strlen($m) < $L[1]);\nif (strlen($m) < $L[1]) {\ndie('ERROR: manifest length read was \"' .\nstrlen($m) .'\" should be \"' .\n$L[1] . '\"');\n}\n$info = self::_unpack($m);\n$f = $info['c'];\nif ($f & self::GZ) {\nif (!function_exists('gzinflate')) {\ndie('Error: zlib extension is not enabled - gzinflate() function needed' .\n' for compressed .phars');\n}\n}\nif ($f & self::BZ2) {\nif (!function_exists('bzdecompress')) {\ndie('Error: bzip2 extension is not enabled - bzdecompress() function needed' .\n' for compressed .phars');\n}\n}\n$temp = self::tmpdir();\nif (!$temp) {\n$sessionpath = session_save_path();\nif (strpos ($sessionpath, \";\") !== FALSE)\n$sessionpath = substr ($sessionpath, strpos ($sessionpath, \";\")+1);\nif (!file_exists($sessionpath) && !is_dir($sessionpath)) {\ndie('Could not locate temporary directory to extract phar');\n}\n$temp = $sessionpath;\n}\n$temp .= '/pharextract';\nif (!file_exists($temp)) {\n@mkdir($temp);\n$temp = realpath($temp);\nself::$tmp[] = $temp;\n}\nself::$origdir = getcwd();\nforeach ($info['m'] as $path => $file) {\n$a = !file_exists(dirname($temp . '/' . $path));\n@mkdir(dirname($temp . '/' . $path), 0777, true);\nclearstatcache();\nif ($a) self::$tmp[] = realpath(dirname($temp . '/' . $path));\nif ($path[strlen($path) - 1] == '/') {\nmkdir($temp . '/' . $path);\n} else {\nfile_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));\n}\nself::$tmp[] = realpath($temp . '/' . $path);\n}\nchdir($temp);\ninclude 'index.php';\n}\n\nstatic function tmpdir()\n{\nif (strpos(PHP_OS, 'WIN') !== false) {\nif ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {\nreturn $var;\n}\nif ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {\nreturn $var;\n}\nif ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : @getenv('USERPROFILE')) {\nreturn $var;\n}\nif ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {\nreturn $var;\n}\nreturn @getenv('SystemRoot') . '\temp';\n}\nif ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {\nreturn $var;\n}\nreturn realpath('/tmp');\n}\n\nstatic function _unpack($m)\n{\n$info = unpack('V', substr($m, 0, 4));\n// skip API version, phar flags, alias, metadata\n$l = unpack('V', substr($m, 10, 4));\n$m = substr($m, 14 + $l[1]);\n$s = unpack('V', substr($m, 0, 4));\n$o = 0;\n$start = 4 + $s[1];\n$ret['c'] = 0;\nfor ($i = 0; $i < $info[1]; $i++) {\n// length of the file name\n$len = unpack('V', substr($m, $start, 4));\n$start += 4;\n// file name\n$savepath = substr($m, $start, $len[1]);\n$start += $len[1];\n// retrieve manifest data:\n// 0 = size, 1 = timestamp, 2 = compressed size, 3 = crc32, 4 = flags\n// 5 = metadata length\n$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));\n$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]\n& 0xffffffff);\n$ret['m'][$savepath][7] = $o;\n$o += $ret['m'][$savepath][2];\n$start += 24 + $ret['m'][$savepath][5];\n$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;\n}\nreturn $ret;\n}\n\nstatic function extractFile($path, $entry, $fp)\n{\n$data = '';\n$c = $entry[2];\nwhile ($c) {\nif ($c < 8192) {\n$data .= @fread($fp, $c);\n$c = 0;\n} else {\n$c -= 8192;\n$data .= @fread($fp, 8192);\n}\n}\nif ($entry[4] & self::GZ) {\n$data = gzinflate($data);\n} elseif ($entry[4] & self::BZ2) {\n$data = bzdecompress($data);\n}\nif (strlen($data) != $entry[0]) {\ndie(\"Not valid internal .phar file (size error \" . strlen($data) . \" != \" .\n$stat[7] . \")\");\n}\nif ($entry[3] != sprintf(\"%u\", crc32($data) & 0xffffffff)) {\ndie(\"Not valid internal .phar file (checksum error)\");\n}\nreturn $data;\n}\n\nstatic function _removeTmpFiles()\n{\n// for removal of temp files\nusort(self::$tmp, 'strnatcasecmp');\narray_reverse(self::$tmp, 1);\nif (count(self::$tmp)) {\nforeach (self::$tmp as $f) {\nif (file_exists($f)) is_dir($f) ? @rmdir($f) : @unlink($f);\n}\n\n}\nchdir(self::$origdir);\n}\n}\nExtract_Phar::go(4461);\n__HALT_COMPILER(); ?>";
+static const char newstub1[] = "<?php\nif (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {\nPhar::interceptFileFuncs();\ninclude 'phar://' . __FILE__ . '/' . Extract_Phar::START;\nreturn;\n}\nclass Extract_Phar\n{\nstatic $tmp = array();\nstatic $origdir;\nconst GZ = 0x1000;\nconst BZ2 = 0x2000;\nconst MASK = 0x3000;\nconst START = '";
+static const char newstub2[] = "';\nstatic function go($D)\n{\nregister_shutdown_function(array('Extract_Phar', '_removeTmpFiles'));\n$fp = fopen(__FILE__, 'rb');\nfseek($fp, $D);\n$L = unpack('V', fread($fp, 4));\n$m = '';\ndo {\n$read = 8192;\nif ($L[1] - strlen($m) < 8192) {\n$read = $L[1] - strlen($m);\n}\n$last = fread($fp, $read);\n$m .= $last;\n} while (strlen($last) && strlen($m) < $L[1]);\nif (strlen($m) < $L[1]) {\ndie('ERROR: manifest length read was \"' .\nstrlen($m) .'\" should be \"' .\n$L[1] . '\"');\n}\n$info = self::_unpack($m);\n$f = $info['c'];\nif ($f & self::GZ) {\nif (!function_exists('gzinflate')) {\ndie('Error: zlib extension is not enabled - gzinflate() function needed' .\n' for compressed .phars');\n}\n}\nif ($f & self::BZ2) {\nif (!function_exists('bzdecompress')) {\ndie('Error: bzip2 extension is not enabled - bzdecompress() function needed' .\n' for compressed .phars');\n}\n}\n$temp = self::tmpdir();\nif (!$temp) {\n$sessionpath = session_save_path();\nif (strpos ($sessionpath, \";\") !== FALSE)\n$sessionpath = substr ($sessionpath, strpos ($sessionpath, \";\")+1);\nif (!file_exists($sessionpath) && !is_dir($sessionpath)) {\ndie('Could not locate temporary directory to extract phar');\n}\n$temp = $sessionpath;\n}\n$temp .= '/pharextract';\nif (!file_exists($temp)) {\n@mkdir($temp);\n$temp = realpath($temp);\nself::$tmp[] = $temp;\n}\nself::$origdir = getcwd();\nforeach ($info['m'] as $path => $file) {\n$a = !file_exists(dirname($temp . '/' . $path));\n@mkdir(dirname($temp . '/' . $path), 0777, true);\nclearstatcache();\nif ($a) self::$tmp[] = realpath(dirname($temp . '/' . $path));\nif ($path[strlen($path) - 1] == '/') {\nmkdir($temp . '/' . $path);\n} else {\nfile_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));\n}\nself::$tmp[] = realpath($temp . '/' . $path);\n}\nchdir($temp);\ninclude self::START;\n}\n\nstatic function tmpdir()\n{\nif (strpos(PHP_OS, 'WIN') !== false) {\nif ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {\nreturn $var;\n}\nif ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {\nreturn $var;\n}\nif ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : @getenv('USERPROFILE')) {\nreturn $var;\n}\nif ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {\nreturn $var;\n}\nreturn @getenv('SystemRoot') . '\temp';\n}\nif ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {\nreturn $var;\n}\nreturn realpath('/tmp');\n}\n\nstatic function _unpack($m)\n{\n$info = unpack('V', substr($m, 0, 4));\n// skip API version, phar flags, alias, metadata\n$l = unpack('V', substr($m, 10, 4));\n$m = substr($m, 14 + $l[1]);\n$s = unpack('V', substr($m, 0, 4));\n$o = 0;\n$start = 4 + $s[1];\n$ret['c'] = 0;\nfor ($i = 0; $i < $info[1]; $i++) {\n// length of the file name\n$len = unpack('V', substr($m, $start, 4));\n$start += 4;\n// file name\n$savepath = substr($m, $start, $len[1]);\n$start += $len[1];\n// retrieve manifest data:\n// 0 = size, 1 = timestamp, 2 = compressed size, 3 = crc32, 4 = flags\n// 5 = metadata length\n$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));\n$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]\n& 0xffffffff);\n$ret['m'][$savepath][7] = $o;\n$o += $ret['m'][$savepath][2];\n$start += 24 + $ret['m'][$savepath][5];\n$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;\n}\nreturn $ret;\n}\n\nstatic function extractFile($path, $entry, $fp)\n{\n$data = '';\n$c = $entry[2];\nwhile ($c) {\nif ($c < 8192) {\n$data .= @fread($fp, $c);\n$c = 0;\n} else {\n$c -= 8192;\n$data .= @fread($fp, 8192);\n}\n}\nif ($entry[4] & self::GZ) {\n$data = gzinflate($data);\n} elseif ($entry[4] & self::BZ2) {\n$data = bzdecompress($data);\n}\nif (strlen($data) != $entry[0]) {\ndie(\"Not valid internal .phar file (size error \" . strlen($data) . \" != \" .\n$stat[7] . \")\");\n}\nif ($entry[3] != sprintf(\"%u\", crc32($data) & 0xffffffff)) {\ndie(\"Not valid internal .phar file (checksum error)\");\n}\nreturn $data;\n}\n\nstatic function _removeTmpFiles()\n{\n// for removal of temp files\nusort(self::$tmp, 'strnatcasecmp');\narray_reverse(self::$tmp, 1);\nif (count(self::$tmp)) {\nforeach (self::$tmp as $f) {\nif (file_exists($f)) is_dir($f) ? @rmdir($f) : @unlink($f);\n}\n\n}\nchdir(self::$origdir);\n}\n}\nExtract_Phar::go(";
+static const char newstub3[] = ");\n__HALT_COMPILER(); ?>";
+static const int newstub_len = 4493;
index e3235b28f6ca51d24a9277961435f1c432a02221..04f4384ee1dbf41c56413ef0f5e3099ec3a662fc 100644 (file)
Binary files a/ext/phar/tests/nophar.phar and b/ext/phar/tests/nophar.phar differ
index b1ad5cffdafbed336169c891be2adee1fdc18abc..ed786b31af2cb93890b1cab0fd30cc3e0aa1b89e 100644 (file)
@@ -29,10 +29,10 @@ unlink(dirname(__FILE__) . '/brandnewphar.phar');
 __HALT_COMPILER();
 ?>
 --EXPECT--
-string(4461) "<?php
+string(4501) "<?php
 if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
 Phar::interceptFileFuncs();
-include 'phar://' . __FILE__ . '/index.php';
+include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
 return;
 }
 class Extract_Phar
@@ -42,6 +42,7 @@ static $origdir;
 const GZ = 0x1000;
 const BZ2 = 0x2000;
 const MASK = 0x3000;
+const START = 'index.php';
 static function go($D)
 {
 register_shutdown_function(array('Extract_Phar', '_removeTmpFiles'));
@@ -106,7 +107,7 @@ file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
 self::$tmp[] = realpath($temp . '/' . $path);
 }
 chdir($temp);
-include 'index.php';
+include self::START;
 }
 
 static function tmpdir()
@@ -205,7 +206,7 @@ if (file_exists($f)) is_dir($f) ? @rmdir($f) : @unlink($f);
 chdir(self::$origdir);
 }
 }
-Extract_Phar::go(4433);
+Extract_Phar::go(4501);
 __HALT_COMPILER(); ?>"
 string(200) "<?php
 function __autoload($class)
index 86a211df1dc9cdc29af16bab8159f8ca75434a2a..a54274466b44ac7889890becf3784688a7b4c8a9 100644 (file)
@@ -32,7 +32,7 @@ __HALT_COMPILER();
 unlink(dirname(__FILE__) . '/brandnewphar.phar');
 ?>
 --EXPECT--
-int(4461)
+int(4501)
 string(200) "<?php
 function __autoload($class)
 {
diff --git a/ext/phar/tests/phar_createdefaultstub.phpt b/ext/phar/tests/phar_createdefaultstub.phpt
new file mode 100644 (file)
index 0000000..4629f55
--- /dev/null
@@ -0,0 +1,378 @@
+--TEST--
+Phar: Phar::createDefaultStub() with and without arg
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--FILE--
+<?php
+try {
+var_dump(Phar::createDefaultStub());
+var_dump(Phar::createDefaultStub('my/custom/thingy.php'));
+var_dump(strlen(Phar::createDefaultStub(str_repeat('a', 400))));
+var_dump(Phar::createDefaultStub(str_repeat('a', 401)));
+} catch(Exception $e) {
+echo $e->getMessage() . "\n";
+}
+?>
+===DONE===
+--EXPECT--
+string(4501) "<?php
+if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
+Phar::interceptFileFuncs();
+include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
+return;
+}
+class Extract_Phar
+{
+static $tmp = array();
+static $origdir;
+const GZ = 0x1000;
+const BZ2 = 0x2000;
+const MASK = 0x3000;
+const START = 'index.php';
+static function go($D)
+{
+register_shutdown_function(array('Extract_Phar', '_removeTmpFiles'));
+$fp = fopen(__FILE__, 'rb');
+fseek($fp, $D);
+$L = unpack('V', fread($fp, 4));
+$m = '';
+do {
+$read = 8192;
+if ($L[1] - strlen($m) < 8192) {
+$read = $L[1] - strlen($m);
+}
+$last = fread($fp, $read);
+$m .= $last;
+} while (strlen($last) && strlen($m) < $L[1]);
+if (strlen($m) < $L[1]) {
+die('ERROR: manifest length read was "' .
+strlen($m) .'" should be "' .
+$L[1] . '"');
+}
+$info = self::_unpack($m);
+$f = $info['c'];
+if ($f & self::GZ) {
+if (!function_exists('gzinflate')) {
+die('Error: zlib extension is not enabled - gzinflate() function needed' .
+' for compressed .phars');
+}
+}
+if ($f & self::BZ2) {
+if (!function_exists('bzdecompress')) {
+die('Error: bzip2 extension is not enabled - bzdecompress() function needed' .
+' for compressed .phars');
+}
+}
+$temp = self::tmpdir();
+if (!$temp) {
+$sessionpath = session_save_path();
+if (strpos ($sessionpath, ";") !== FALSE)
+$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
+if (!file_exists($sessionpath) && !is_dir($sessionpath)) {
+die('Could not locate temporary directory to extract phar');
+}
+$temp = $sessionpath;
+}
+$temp .= '/pharextract';
+if (!file_exists($temp)) {
+@mkdir($temp);
+$temp = realpath($temp);
+self::$tmp[] = $temp;
+}
+self::$origdir = getcwd();
+foreach ($info['m'] as $path => $file) {
+$a = !file_exists(dirname($temp . '/' . $path));
+@mkdir(dirname($temp . '/' . $path), 0777, true);
+clearstatcache();
+if ($a) self::$tmp[] = realpath(dirname($temp . '/' . $path));
+if ($path[strlen($path) - 1] == '/') {
+mkdir($temp . '/' . $path);
+} else {
+file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
+}
+self::$tmp[] = realpath($temp . '/' . $path);
+}
+chdir($temp);
+include self::START;
+}
+
+static function tmpdir()
+{
+if (strpos(PHP_OS, 'WIN') !== false) {
+if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
+return $var;
+}
+if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
+return $var;
+}
+if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : @getenv('USERPROFILE')) {
+return $var;
+}
+if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
+return $var;
+}
+return @getenv('SystemRoot') . '       emp';
+}
+if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
+return $var;
+}
+return realpath('/tmp');
+}
+
+static function _unpack($m)
+{
+$info = unpack('V', substr($m, 0, 4));
+// skip API version, phar flags, alias, metadata
+$l = unpack('V', substr($m, 10, 4));
+$m = substr($m, 14 + $l[1]);
+$s = unpack('V', substr($m, 0, 4));
+$o = 0;
+$start = 4 + $s[1];
+$ret['c'] = 0;
+for ($i = 0; $i < $info[1]; $i++) {
+// length of the file name
+$len = unpack('V', substr($m, $start, 4));
+$start += 4;
+// file name
+$savepath = substr($m, $start, $len[1]);
+$start += $len[1];
+// retrieve manifest data:
+// 0 = size, 1 = timestamp, 2 = compressed size, 3 = crc32, 4 = flags
+// 5 = metadata length
+$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));
+$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]
+& 0xffffffff);
+$ret['m'][$savepath][7] = $o;
+$o += $ret['m'][$savepath][2];
+$start += 24 + $ret['m'][$savepath][5];
+$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;
+}
+return $ret;
+}
+
+static function extractFile($path, $entry, $fp)
+{
+$data = '';
+$c = $entry[2];
+while ($c) {
+if ($c < 8192) {
+$data .= @fread($fp, $c);
+$c = 0;
+} else {
+$c -= 8192;
+$data .= @fread($fp, 8192);
+}
+}
+if ($entry[4] & self::GZ) {
+$data = gzinflate($data);
+} elseif ($entry[4] & self::BZ2) {
+$data = bzdecompress($data);
+}
+if (strlen($data) != $entry[0]) {
+die("Not valid internal .phar file (size error " . strlen($data) . " != " .
+$stat[7] . ")");
+}
+if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) {
+die("Not valid internal .phar file (checksum error)");
+}
+return $data;
+}
+
+static function _removeTmpFiles()
+{
+// for removal of temp files
+usort(self::$tmp, 'strnatcasecmp');
+array_reverse(self::$tmp, 1);
+if (count(self::$tmp)) {
+foreach (self::$tmp as $f) {
+if (file_exists($f)) is_dir($f) ? @rmdir($f) : @unlink($f);
+}
+
+}
+chdir(self::$origdir);
+}
+}
+Extract_Phar::go(4501);
+__HALT_COMPILER(); ?>"
+string(4512) "<?php
+if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
+Phar::interceptFileFuncs();
+include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
+return;
+}
+class Extract_Phar
+{
+static $tmp = array();
+static $origdir;
+const GZ = 0x1000;
+const BZ2 = 0x2000;
+const MASK = 0x3000;
+const START = 'my/custom/thingy.php';
+static function go($D)
+{
+register_shutdown_function(array('Extract_Phar', '_removeTmpFiles'));
+$fp = fopen(__FILE__, 'rb');
+fseek($fp, $D);
+$L = unpack('V', fread($fp, 4));
+$m = '';
+do {
+$read = 8192;
+if ($L[1] - strlen($m) < 8192) {
+$read = $L[1] - strlen($m);
+}
+$last = fread($fp, $read);
+$m .= $last;
+} while (strlen($last) && strlen($m) < $L[1]);
+if (strlen($m) < $L[1]) {
+die('ERROR: manifest length read was "' .
+strlen($m) .'" should be "' .
+$L[1] . '"');
+}
+$info = self::_unpack($m);
+$f = $info['c'];
+if ($f & self::GZ) {
+if (!function_exists('gzinflate')) {
+die('Error: zlib extension is not enabled - gzinflate() function needed' .
+' for compressed .phars');
+}
+}
+if ($f & self::BZ2) {
+if (!function_exists('bzdecompress')) {
+die('Error: bzip2 extension is not enabled - bzdecompress() function needed' .
+' for compressed .phars');
+}
+}
+$temp = self::tmpdir();
+if (!$temp) {
+$sessionpath = session_save_path();
+if (strpos ($sessionpath, ";") !== FALSE)
+$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
+if (!file_exists($sessionpath) && !is_dir($sessionpath)) {
+die('Could not locate temporary directory to extract phar');
+}
+$temp = $sessionpath;
+}
+$temp .= '/pharextract';
+if (!file_exists($temp)) {
+@mkdir($temp);
+$temp = realpath($temp);
+self::$tmp[] = $temp;
+}
+self::$origdir = getcwd();
+foreach ($info['m'] as $path => $file) {
+$a = !file_exists(dirname($temp . '/' . $path));
+@mkdir(dirname($temp . '/' . $path), 0777, true);
+clearstatcache();
+if ($a) self::$tmp[] = realpath(dirname($temp . '/' . $path));
+if ($path[strlen($path) - 1] == '/') {
+mkdir($temp . '/' . $path);
+} else {
+file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
+}
+self::$tmp[] = realpath($temp . '/' . $path);
+}
+chdir($temp);
+include self::START;
+}
+
+static function tmpdir()
+{
+if (strpos(PHP_OS, 'WIN') !== false) {
+if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
+return $var;
+}
+if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
+return $var;
+}
+if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : @getenv('USERPROFILE')) {
+return $var;
+}
+if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
+return $var;
+}
+return @getenv('SystemRoot') . '       emp';
+}
+if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
+return $var;
+}
+return realpath('/tmp');
+}
+
+static function _unpack($m)
+{
+$info = unpack('V', substr($m, 0, 4));
+// skip API version, phar flags, alias, metadata
+$l = unpack('V', substr($m, 10, 4));
+$m = substr($m, 14 + $l[1]);
+$s = unpack('V', substr($m, 0, 4));
+$o = 0;
+$start = 4 + $s[1];
+$ret['c'] = 0;
+for ($i = 0; $i < $info[1]; $i++) {
+// length of the file name
+$len = unpack('V', substr($m, $start, 4));
+$start += 4;
+// file name
+$savepath = substr($m, $start, $len[1]);
+$start += $len[1];
+// retrieve manifest data:
+// 0 = size, 1 = timestamp, 2 = compressed size, 3 = crc32, 4 = flags
+// 5 = metadata length
+$ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));
+$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]
+& 0xffffffff);
+$ret['m'][$savepath][7] = $o;
+$o += $ret['m'][$savepath][2];
+$start += 24 + $ret['m'][$savepath][5];
+$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;
+}
+return $ret;
+}
+
+static function extractFile($path, $entry, $fp)
+{
+$data = '';
+$c = $entry[2];
+while ($c) {
+if ($c < 8192) {
+$data .= @fread($fp, $c);
+$c = 0;
+} else {
+$c -= 8192;
+$data .= @fread($fp, 8192);
+}
+}
+if ($entry[4] & self::GZ) {
+$data = gzinflate($data);
+} elseif ($entry[4] & self::BZ2) {
+$data = bzdecompress($data);
+}
+if (strlen($data) != $entry[0]) {
+die("Not valid internal .phar file (size error " . strlen($data) . " != " .
+$stat[7] . ")");
+}
+if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) {
+die("Not valid internal .phar file (checksum error)");
+}
+return $data;
+}
+
+static function _removeTmpFiles()
+{
+// for removal of temp files
+usort(self::$tmp, 'strnatcasecmp');
+array_reverse(self::$tmp, 1);
+if (count(self::$tmp)) {
+foreach (self::$tmp as $f) {
+if (file_exists($f)) is_dir($f) ? @rmdir($f) : @unlink($f);
+}
+
+}
+chdir(self::$origdir);
+}
+}
+Extract_Phar::go(4512);
+__HALT_COMPILER(); ?>"
+int(4892)
+Illegal filename passed in for stub creation, was 401 characters long, and only 400 or less is allowed
+===DONE===