]> granicus.if.org Git - php/commitdiff
[unfinished] magically handle getcwd() and fopen() with include_path inside phar
authorGreg Beaver <cellog@php.net>
Tue, 18 Dec 2007 17:01:24 +0000 (17:01 +0000)
committerGreg Beaver <cellog@php.net>
Tue, 18 Dec 2007 17:01:24 +0000 (17:01 +0000)
this work is incomplete, but compiles and existing tests pass

ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/phar/tests/phar_magic.phpt [new file with mode: 0644]

index 9740a7f97813c44e2dcbf3f2bfce6175d4ab967d..5bb738b3449bd25cf67f271a9f5d9ca421f07929 100644 (file)
@@ -1254,7 +1254,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int
                        efree(entry.filename);
                        MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
 #else
-                       if (!PHAR_G(has_zlib)) {
+                       if (!phar_has_zlib) {
                                if (entry.metadata) {
                                        zval_ptr_dtor(&entry.metadata);
                                }
@@ -1271,7 +1271,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int
                        efree(entry.filename);
                        MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
 #else
-                       if (!PHAR_G(has_bz2)) {
+                       if (!phar_has_bz2) {
                                if (entry.metadata) {
                                        zval_ptr_dtor(&entry.metadata);
                                }
@@ -3753,7 +3753,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type
        zend_op_array *(*save)(zend_file_handle *file_handle, int type TSRMLS_DC);
 
        save = zend_compile_file; /* restore current handler or we cause trouble */
-       zend_compile_file = PHAR_G(orig_compile_file);
+       zend_compile_file = phar_orig_compile_file;
        if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
                char *arch, *entry;
                int arch_len, entry_len;
@@ -3790,16 +3790,91 @@ skip_phar:
 }
 /* }}} */
 
+static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS)
+{
+       char *filename, *mode;
+       int filename_len, mode_len;
+       zend_bool use_include_path = 0;
+       zval *zcontext = NULL;
+       php_stream *stream;
+
+       if (ht < 3 || !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
+               /* no need to check, include_path not even specified in fopen/ no active phars */
+               goto skip_phar;
+       }
+       if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ss|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE || !use_include_path) {
+               goto skip_phar;
+       }
+       {
+               char *arch, *entry, *fname;
+               int arch_len, entry_len, fname_len;
+               fname = zend_get_executed_filename(TSRMLS_C);
+               if (strncasecmp(fname, "phar://", 7)) {
+                       goto skip_phar;
+               }
+               fname_len = strlen(fname);
+               if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
+                       char *s, *name;
+
+                       efree(entry);
+                       entry = filename;
+                       /* include within phar, if :// is not in the url, then prepend phar://<archive>/ */
+                       entry_len = filename_len;
+                       for (s = entry; s < (entry + entry_len - 4); s++) {
+                               if (*s == ':' && *(s + 1) == '/' && *(s + 2) == '/') {
+                                       efree(arch);
+                                       goto skip_phar;
+                               }
+                       }
+                       /* auto-convert to phar:// */
+                       spprintf(&name, 4096, "phar://%s/%s", arch, entry);
+                       efree(arch);
+                       stream = php_stream_open_wrapper(name, mode, 0, NULL);
+                       efree(name);
+                       php_stream_to_zval(stream, return_value);
+                       return_value_used = 1;
+                       return;
+               }
+       }
+skip_phar:
+       return PHAR_G(orig_fopen)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+static void phar_getcwd(INTERNAL_FUNCTION_PARAMETERS)
+{
+       char *s, *fname;
+       int fname_len;
+       if (!zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
+               /* no need to check, no active phars */
+               goto skip_phar;
+       }
+       fname = zend_get_executed_filename(TSRMLS_C);
+       if (strncasecmp(fname, "phar://", 7)) {
+               goto skip_phar;
+       }
+       s = (char *) strrchr ((void *) fname, '/');
+       fname_len = s-fname + 1;
+       fname = estrndup(s, fname_len);
+       fname[fname_len] = '\0';
+       RETURN_STRINGL(fname, fname_len, 0);
+skip_phar:
+       return PHAR_G(orig_getcwd)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
 PHP_MINIT_FUNCTION(phar) /* {{{ */
 {
        ZEND_INIT_MODULE_GLOBALS(phar, php_phar_init_globals_module, NULL);
        REGISTER_INI_ENTRIES();
 
-       PHAR_G(has_gnupg) = zend_hash_exists(&module_registry, "gnupg", sizeof("gnupg"));
-       PHAR_G(has_bz2) = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
-       PHAR_G(has_zlib) = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
-       PHAR_G(orig_compile_file) = zend_compile_file;
+       PHAR_G(orig_fopen) = NULL;
+       PHAR_G(orig_getcwd) = NULL;
+       phar_has_gnupg = zend_hash_exists(&module_registry, "gnupg", sizeof("gnupg"));
+       phar_has_bz2 = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
+       phar_has_zlib = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
+
+       phar_orig_compile_file = zend_compile_file;
        zend_compile_file = phar_compile_file;
+
        phar_object_init(TSRMLS_C);
 
        return php_register_url_stream_wrapper("phar", &php_stream_phar_wrapper TSRMLS_CC);
@@ -3810,7 +3885,7 @@ PHP_MSHUTDOWN_FUNCTION(phar) /* {{{ */
 {
        return php_unregister_url_stream_wrapper("phar" TSRMLS_CC);
        if (zend_compile_file == phar_compile_file) {
-               zend_compile_file = PHAR_G(orig_compile_file);
+               zend_compile_file = phar_orig_compile_file;
        }
 }
 /* }}} */
@@ -3819,6 +3894,7 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */
 {
        if (!PHAR_GLOBALS->request_init)
        {
+               zend_function *orig;
                PHAR_GLOBALS->request_init = 1;
                PHAR_GLOBALS->request_ends = 0;
                PHAR_GLOBALS->request_done = 0;
@@ -3826,6 +3902,14 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */
                zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 0);
                zend_hash_init(&(PHAR_GLOBALS->phar_plain_map), sizeof(const char *),       zend_get_hash_value, NULL, 0);
                phar_split_extract_list(TSRMLS_C);
+               if (PHAR_G(orig_fopen) && SUCCESS == zend_hash_find(EG(function_table), "fopen", 5, (void **)&orig)) {
+                       PHAR_G(orig_fopen) = orig->internal_function.handler;
+                       orig->internal_function.handler = phar_fopen;
+               }
+               if (SUCCESS == zend_hash_find(EG(function_table), "getcwd", 5, (void **)&orig)) {
+                       PHAR_G(orig_getcwd) = orig->internal_function.handler;
+                       orig->internal_function.handler = phar_getcwd;
+               }
        }
 }
 /* }}} */
@@ -3835,6 +3919,13 @@ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */
        PHAR_GLOBALS->request_ends = 1;
        if (PHAR_GLOBALS->request_init)
        {
+               zend_function *orig;
+               if (PHAR_G(orig_fopen) && SUCCESS == zend_hash_find(CG(function_table), "fopen", 5, (void **)&orig)) {
+                       orig->internal_function.handler = PHAR_G(orig_fopen);
+               }
+               if (PHAR_G(orig_getcwd) && SUCCESS == zend_hash_find(CG(function_table), "getcwd", 5, (void **)&orig)) {
+                       orig->internal_function.handler = PHAR_G(orig_getcwd);
+               }
                zend_hash_destroy(&(PHAR_GLOBALS->phar_alias_map));
                zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map));
                zend_hash_destroy(&(PHAR_GLOBALS->phar_plain_map));
@@ -3853,7 +3944,7 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */
        php_info_print_table_row(2, "Phar API version", PHAR_API_VERSION_STR);
        php_info_print_table_row(2, "CVS revision", "$Revision$");
 #if HAVE_ZLIB
-       if (PHAR_G(has_zlib)) {
+       if (phar_has_zlib) {
                php_info_print_table_row(2, "gzip compression", 
                        "enabled");
        } else {
@@ -3865,7 +3956,7 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */
                "disabled");
 #endif
 #if HAVE_BZ2
-       if (PHAR_G(has_bz2)) {
+       if (phar_has_bz2 ) {
                php_info_print_table_row(2, "bzip2 compression", 
                        "disabled");
        } else {
@@ -3877,7 +3968,7 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */
                "disabled");
 #endif
 #if HAVE_GNUPGLIB
-        if (PHAR_G(has_gnupg)) {
+        if (phar_has_gnupg) {
                php_info_print_table_row(2, "GPG signature", 
                        "enabled");
        } else {
index ada891eb6bb07c41c1b62dcef18921f04cc2835f..636fc551f3de39957c6d75c959817c2804490a73 100755 (executable)
@@ -34,6 +34,7 @@
 #include "zend_operators.h"
 #include "zend_qsort.h"
 #include "main/php_streams.h"
+#include "main/streams/php_stream_plain_wrapper.h"
 #include "ext/standard/info.h"
 #include "ext/standard/basic_functions.h"
 #include "ext/standard/url.h"
@@ -114,14 +115,17 @@ ZEND_BEGIN_MODULE_GLOBALS(phar)
        int         require_hash;
        int         request_done;
        int         request_ends;
-       int         has_bz2:1;
-       int         has_gnupg:1;
-       int         has_zlib:1;
-       zend_op_array *(*orig_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
+       void        (*orig_fopen)(INTERNAL_FUNCTION_PARAMETERS);
+       void        (*orig_getcwd)(INTERNAL_FUNCTION_PARAMETERS);
 ZEND_END_MODULE_GLOBALS(phar)
 
 ZEND_EXTERN_MODULE_GLOBALS(phar)
 
+int phar_has_bz2;
+int phar_has_gnupg;
+int phar_has_zlib;
+zend_op_array *(*phar_orig_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
+
 #ifdef ZTS
 #      include "TSRM.h"
 #      define PHAR_G(v) TSRMG(phar_globals_id, zend_phar_globals *, v)
@@ -246,8 +250,12 @@ int phar_open_filename(char *fname, int fname_len, char *alias, int alias_len, i
 int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
 int phar_open_compiled_file(char *alias, int alias_len, char **error TSRMLS_DC);
 
-#ifdef PHAR_MAIN
+static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS);
+static void phar_cwd(INTERNAL_FUNCTION_PARAMETERS);
 
+#ifdef PHAR_MAIN
+static void phar_fopen(INTERNAL_FUNCTION_PARAMETERS);
+static void phar_getcwd(INTERNAL_FUNCTION_PARAMETERS);
 static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
 
 static php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char *mode, int options TSRMLS_DC);
index 7e97fdc2b34b127f3dbc27529c8502cee0827b18..e7dfcb0fbf2a38524685e30ac2643da7ec95445b 100755 (executable)
@@ -144,7 +144,7 @@ PHP_METHOD(Phar, canCompress)
        switch (method) {
        case PHAR_ENT_COMPRESSED_GZ:
 #if HAVE_ZLIB
-               if (PHAR_G(has_zlib)) {
+               if (phar_has_zlib) {
                        RETURN_TRUE;
                } else {
                        RETURN_FALSE;
@@ -155,7 +155,7 @@ PHP_METHOD(Phar, canCompress)
 
        case PHAR_ENT_COMPRESSED_BZ2:
 #if HAVE_BZ2
-               if (PHAR_G(has_bz2)) {
+               if (phar_has_bz2) {
                        RETURN_TRUE;
                } else {
                        RETURN_FALSE;
@@ -166,7 +166,7 @@ PHP_METHOD(Phar, canCompress)
 
        default:
 #if HAVE_ZLIB || HAVE_BZ2
-       if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) {
+       if (phar_has_zlib || phar_has_bz2) {
                RETURN_TRUE;
        } else {
                RETURN_FALSE;
@@ -296,6 +296,42 @@ PHP_METHOD(Phar, __construct)
 }
 /* }}} */
 
+/* {{{ proto array Phar::getSupportedSignatures()
+ * Return array of supported signature types
+ */
+PHP_METHOD(Phar, getSupportedSignatures)
+{
+       array_init(return_value);
+
+       add_next_index_stringl(return_value, "MD5", 3, 1);
+       add_next_index_stringl(return_value, "SHA-1", 5, 1);
+#if HAVE_HASH_EXT
+       add_next_index_stringl(return_value, "SHA-256", 7, 1);
+       add_next_index_stringl(return_value, "SHA-512", 7, 1);
+#endif
+}
+/* }}} */
+
+/* {{{ proto array Phar::getSupportedCompression()
+ * Return array of supported comparession algorithms
+ */
+PHP_METHOD(Phar, getSupportedCompression)
+{
+       array_init(return_value);
+
+#if HAVE_ZLIB
+       if (phar_has_zlib) {
+               add_next_index_stringl(return_value, "GZ", 2, 1);
+       }
+#endif
+#if HAVE_BZ2
+       if (phar_has_bz2) {
+               add_next_index_stringl(return_value, "BZIP2", 5, 1);
+       }
+#endif
+}
+/* }}} */
+
 #if HAVE_SPL
 
 #define PHAR_ARCHIVE_OBJECT() \
@@ -820,42 +856,6 @@ PHP_METHOD(Phar, setSignatureAlgorithm)
 }
 /* }}} */
 
-/* {{{ proto array Phar::getSupportedSignatures()
- * Return array of supported signature types
- */
-PHP_METHOD(Phar, getSupportedSignatures)
-{
-       array_init(return_value);
-
-       add_next_index_stringl(return_value, "MD5", 3, 1);
-       add_next_index_stringl(return_value, "SHA-1", 5, 1);
-#if HAVE_HASH_EXT
-       add_next_index_stringl(return_value, "SHA-256", 7, 1);
-       add_next_index_stringl(return_value, "SHA-512", 7, 1);
-#endif
-}
-/* }}} */
-
-/* {{{ proto array Phar::getSupportedCompression()
- * Return array of supported comparession algorithms
- */
-PHP_METHOD(Phar, getSupportedCompression)
-{
-       array_init(return_value);
-
-#if HAVE_ZLIB
-       if (PHAR_G(has_zlib)) {
-               add_next_index_stringl(return_value, "GZ", 2, 1);
-       }
-#endif
-#if HAVE_BZ2
-       if (PHAR_G(has_bz2)) {
-               add_next_index_stringl(return_value, "BZIP2", 5, 1);
-       }
-#endif
-}
-/* }}} */
-
 /* {{{ proto array|false Phar::getSignature()
  * Return signature or false
  */
@@ -925,7 +925,7 @@ static int phar_test_compression(void *pDest, void *argument TSRMLS_DC) /* {{{ *
                *(int *) argument = 0;
        }
 #else
-       if (!PHAR_G(has_bz2)) {
+       if (!phar_has_bz2) {
                if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
                        *(int *) argument = 0;
                }
@@ -936,7 +936,7 @@ static int phar_test_compression(void *pDest, void *argument TSRMLS_DC) /* {{{ *
                *(int *) argument = 0;
        }
 #else
-       if (!PHAR_G(has_zlib)) {
+       if (!phar_has_zlib) {
                if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
                        *(int *) argument = 0;
                }
@@ -976,7 +976,7 @@ PHP_METHOD(Phar, compressAllFilesGZ)
                        "Phar is readonly, cannot change compression");
        }
 #if HAVE_ZLIB
-       if (!PHAR_G(has_zlib)) {
+       if (!phar_has_zlib) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                        "Cannot compress with Gzip compression, zlib extension is not enabled");
        }
@@ -1014,7 +1014,7 @@ PHP_METHOD(Phar, compressAllFilesBZIP2)
                        "Phar is readonly, cannot change compression");
        }
 #if HAVE_BZ2
-       if (!PHAR_G(has_bz2)) {
+       if (!phar_has_bz2) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                        "Cannot compress with Bzip2 compression, bz2 extension is not enabled");
        }
@@ -1756,7 +1756,7 @@ PHP_METHOD(PharFileInfo, setCompressedGZ)
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                        "Cannot compress deleted file");
        }
-       if (!PHAR_G(has_zlib)) {
+       if (!phar_has_zlib) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                        "Cannot compress with Gzip compression, zlib extension is not enabled");
        }
@@ -1788,7 +1788,7 @@ PHP_METHOD(PharFileInfo, setCompressedBZIP2)
        char *error;
        PHAR_ENTRY_OBJECT();
 
-       if (!PHAR_G(has_bz2)) {
+       if (!phar_has_bz2) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                        "Cannot compress with Bzip2 compression, bz2 extension is not enabled");
        }
@@ -1858,7 +1858,7 @@ PHP_METHOD(PharFileInfo, setUncompressed)
                        "Cannot uncompress Gzip-compressed file, zlib extension is not enabled");
        }
 #else
-       if (!PHAR_G(has_zlib)) {
+       if (!phar_has_zlib) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                        "Cannot uncompress Gzip-compressed file, zlib extension is not enabled");
        }
@@ -1869,7 +1869,7 @@ PHP_METHOD(PharFileInfo, setUncompressed)
                        "Cannot uncompress Bzip2-compressed file, bzip2 extension is not enabled");
        }
 #else
-       if (!PHAR_G(has_bz2)) {
+       if (!phar_has_bz2) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                        "Cannot uncompress Bzip2-compressed file, bzip2 extension is not enabled");
        }
diff --git a/ext/phar/tests/phar_magic.phpt b/ext/phar/tests/phar_magic.phpt
new file mode 100644 (file)
index 0000000..adb3ad5
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Phar::setStub()
+--SKIPIF--
+<?php if (!extension_loaded("phar")) print "skip"; ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$p = new Phar($fname);
+$p['a'] = '<?php include "b.php";';
+?>
+===DONE===
+--CLEAN--
+<?php 
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php');
+__HALT_COMPILER();
+?>
+--EXPECT--
+===DONE===