]> granicus.if.org Git - php/commitdiff
optimize phar filename extension detection to first search through known phars. ...
authorGreg Beaver <cellog@php.net>
Wed, 7 May 2008 17:24:22 +0000 (17:24 +0000)
committerGreg Beaver <cellog@php.net>
Wed, 7 May 2008 17:24:22 +0000 (17:24 +0000)
ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/phar/tar.c
ext/phar/tests/phar_convert_again.phpt
ext/phar/zip.c

index d31bb71e6ed361fb5de552c9db33e77d4c24f98c..b668e043e4065d80338670596fb2ea685d5281dd 100644 (file)
@@ -380,7 +380,9 @@ int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_len, int
                        /* prevent any ".phar" without a stub getting through */
                        if (!phar->halt_offset && !phar->is_brandnew) {
                                if (PHAR_G(readonly) && FAILURE == zend_hash_find(&(phar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
-                                       spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
+                                       if (error) {
+                                               spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
+                                       }
                                        return FAILURE;
                                }
                        }
@@ -908,6 +910,16 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int
        phar_unixify_path_separators(mydata->fname, fname_len);
 #endif
        mydata->fname_len = fname_len;
+       endbuffer = strrchr(mydata->fname, '/');
+       if (endbuffer) {
+               mydata->ext = memchr(endbuffer, '.', (mydata->fname + fname_len) - endbuffer);
+               if (mydata->ext == endbuffer) {
+                       mydata->ext = memchr(endbuffer + 1, '.', (mydata->fname + fname_len) - endbuffer - 1);
+               }
+               if (mydata->ext) {
+                       mydata->ext_len = (mydata->fname + mydata->fname_len) - mydata->ext;
+               }
+       }
        mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
        mydata->alias_len = alias ? alias_len : fname_len;
        mydata->sig_flags = sig_flags;
@@ -1008,7 +1020,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
        phar_archive_data *mydata;
        int register_alias;
        php_stream *fp;
-       char *actual = NULL;
+       char *actual = NULL, *p;
 
        if (!pphar) {
                pphar = &mydata;
@@ -1068,7 +1080,17 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
 #ifdef PHP_WIN32
        phar_unixify_path_separators(mydata->fname, fname_len);
 #endif
-       
+       p = strrchr(mydata->fname, '/');
+       if (p) {
+               mydata->ext = memchr(p, '.', (mydata->fname + fname_len) - p);
+               if (mydata->ext == p) {
+                       mydata->ext = memchr(p + 1, '.', (mydata->fname + fname_len) - p - 1);
+               }
+               if (mydata->ext) {
+                       mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
+               }
+       }
+
        if (pphar) {
                *pphar = mydata;
        }
@@ -1508,6 +1530,53 @@ int phar_detect_phar_fname_ext(const char *filename, int check_length, const cha
                }
        }
 
+       if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
+               phar_archive_data **pphar;
+
+               if (is_complete) {
+                       if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), filename, filename_len, (void **)&pphar)) {
+                               *ext_str = filename + (filename_len - (*pphar)->ext_len);
+woohoo:
+                               *ext_len = (*pphar)->ext_len;
+                               if (executable == 2) {
+                                       return SUCCESS;
+                               }
+                               if (executable == 1 && !(*pphar)->is_data) {
+                                       return SUCCESS;
+                               }
+                               if (!executable && (*pphar)->is_data) {
+                                       return SUCCESS;
+                               }
+                               return FAILURE;
+                       }
+               } else {
+                       char *key;
+                       uint keylen;
+                       ulong unused;
+
+                       zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_fname_map));
+                       while (FAILURE != zend_hash_has_more_elements(&(PHAR_GLOBALS->phar_fname_map))) {
+                               if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_fname_map), &key, &keylen, &unused, 0, NULL)) {
+                                       break;
+                               }
+
+                               if (keylen > filename_len) {
+                                       zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
+                                       continue;
+                               }
+                               if (!memcmp(filename, key, keylen) && (filename_len == keylen
+                                       || filename[keylen] == '/' || filename[keylen] == '\0')) {
+                                       if (FAILURE == zend_hash_get_current_data(&(PHAR_GLOBALS->phar_fname_map), (void **) &pphar)) {
+                                               break;
+                                       }
+                                       *ext_str = filename + (keylen - (*pphar)->ext_len);
+                                       goto woohoo;
+                               }
+                               zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
+                       }
+               }
+       }
+
        pos = strchr(filename + 1, '.');
 next_extension:
        if (!pos) {
index d6a7eaa7eaa084ff07a88f70fdf3fd69c602908d..1aa54251250e5d7dab76d83d9450ca4cab3e9eba 100755 (executable)
@@ -260,6 +260,9 @@ typedef struct _phar_entry_info {
 struct _phar_archive_data {
        char                     *fname;
        int                      fname_len;
+       /* for phar_detect_fname_ext, this stores the location of the file extension within fname */
+       char                     *ext;
+       int                      ext_len;
        char                     *alias;
        int                      alias_len;
        char                     version[12];
index 485b84ec9d473a20b3ca7768cbd1c394eb82afa2..ef59ba5e5ee18166a620727cad57da0dcd0325cf 100755 (executable)
@@ -1837,7 +1837,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
        }
 
        if (!phar->is_data) {
-               if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &ext, &ext_len, 1, 1, 1 TSRMLS_CC)) {
+               if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 1, 1, 1 TSRMLS_CC)) {
                        efree(oldpath);
                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar \"%s\" has invalid extension %s", phar->fname, ext);
                        return NULL;
@@ -1854,7 +1854,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
                        }
                }
        } else {
-               if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &ext, &ext_len, 0, 1, 1 TSRMLS_CC)) {
+               if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 0, 1, 1 TSRMLS_CC)) {
                        efree(oldpath);
                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
                        return NULL;
index eb0c9a058fd64aca6c845aa16a1855ec521c5068..7288b3bbffb7f0d16f28e975c061e980e5b04397 100644 (file)
@@ -154,7 +154,7 @@ int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_l
 
 int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
 {
-       char buf[512], *actual_alias = NULL;
+       char buf[512], *actual_alias = NULL, *p;
        phar_entry_info entry = {0};
        size_t pos = 0, read, totalsize;
        tar_header *hdr;
@@ -371,6 +371,16 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
        phar_unixify_path_separators(myphar->fname, fname_len);
 #endif
        myphar->fname_len = fname_len;
+       p = strrchr(myphar->fname, '/');
+       if (p) {
+               myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p);
+               if (myphar->ext == p) {
+                       myphar->ext = memchr(p + 1, '.', (myphar->fname + fname_len) - p - 1);
+               }
+               if (myphar->ext) {
+                       myphar->ext_len = (myphar->fname + fname_len) - p;
+               }
+       }
        myphar->fp = fp;
        phar_request_initialize(TSRMLS_C);
        if (SUCCESS != zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len, (void*)&myphar, sizeof(phar_archive_data*), (void **)&actual)) {
index c58a8df14d5b31525294df700accc86593380500..4543a238d584c0a4205ae3089af515da66d15105 100644 (file)
@@ -212,7 +212,7 @@ A Phar stub cannot be set in a plain tar archive
 A Phar alias cannot be set in a plain tar archive
 A Phar stub cannot be set in a plain tar archive
 Cannot set signature algorithm, not possible with tar-based phar archives
-data phar "%sphar_convert_again2.phar.tgz.oops" has invalid extension .phar.tgz.oops
-phar "%sphar_convert_again2.tgz.oops" has invalid extension .tgz.oops
-data phar "%sphar_convert_again2.phar/.tgz.oops" has invalid extension .phar/.tgz.oops
+data phar "%sphar_convert_again2.phar.tgz.oops" has invalid extension phar.tgz.oops
+phar "%sphar_convert_again2.tgz.oops" has invalid extension tgz.oops
+data phar "%sphar_convert_again2.phar/.tgz.oops" has invalid extension phar/.tgz.oops
 ===DONE===
index 888d135f51b39186e179a09738d004eaa813d600..816180f550b0bb6c24f4081c4af8ddbabdd3ec18 100644 (file)
@@ -152,7 +152,7 @@ int phar_open_zipfile(php_stream *fp, char *fname, int fname_len, char *alias, i
        php_uint16 i;
        phar_archive_data *mydata = NULL;
        phar_entry_info entry = {0};
-       char *p = buf;
+       char *p = buf, *ext;
 
        size = php_stream_tell(fp);
        if (size > sizeof(locator) + 65536) {
@@ -231,6 +231,16 @@ foundit:
 #endif
        mydata->is_zip = 1;
        mydata->fname_len = fname_len;
+       ext = strrchr(mydata->fname, '/');
+       if (ext) {
+               mydata->ext = memchr(ext, '.', (mydata->fname + fname_len) - ext);
+               if (mydata->ext == ext) {
+                       mydata->ext = memchr(ext + 1, '.', (mydata->fname + fname_len) - ext - 1);
+               }
+               if (mydata->ext) {
+                       mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
+               }
+       }
        /* clean up on big-endian systems */
        /* seek to central directory */
        php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);