PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/phar - util.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 740 974 76.0 %
Date: 2015-05-21 Functions: 28 29 96.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | phar php single-file executable PHP extension                        |
       4             :   | utility functions                                                    |
       5             :   +----------------------------------------------------------------------+
       6             :   | Copyright (c) 2005-2015 The PHP Group                                |
       7             :   +----------------------------------------------------------------------+
       8             :   | This source file is subject to version 3.01 of the PHP license,      |
       9             :   | that is bundled with this package in the file LICENSE, and is        |
      10             :   | available through the world-wide-web at the following url:           |
      11             :   | http://www.php.net/license/3_01.txt.                                 |
      12             :   | If you did not receive a copy of the PHP license and are unable to   |
      13             :   | obtain it through the world-wide-web, please send a note to          |
      14             :   | license@php.net so we can mail you a copy immediately.               |
      15             :   +----------------------------------------------------------------------+
      16             :   | Authors: Gregory Beaver <cellog@php.net>                             |
      17             :   |          Marcus Boerger <helly@php.net>                              |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #include "phar_internal.h"
      24             : #ifdef PHAR_HASH_OK
      25             : #include "ext/hash/php_hash_sha.h"
      26             : #endif
      27             : 
      28             : #ifdef PHAR_HAVE_OPENSSL
      29             : /* OpenSSL includes */
      30             : #include <openssl/evp.h>
      31             : #include <openssl/x509.h>
      32             : #include <openssl/x509v3.h>
      33             : #include <openssl/crypto.h>
      34             : #include <openssl/pem.h>
      35             : #include <openssl/err.h>
      36             : #include <openssl/conf.h>
      37             : #include <openssl/rand.h>
      38             : #include <openssl/ssl.h>
      39             : #include <openssl/pkcs12.h>
      40             : #else
      41             : static int phar_call_openssl_signverify(int is_sign, php_stream *fp, zend_off_t end, char *key, int key_len, char **signature, int *signature_len);
      42             : #endif
      43             : 
      44             : /* for links to relative location, prepend cwd of the entry */
      45          31 : static char *phar_get_link_location(phar_entry_info *entry) /* {{{ */
      46             : {
      47          31 :         char *p, *ret = NULL;
      48          31 :         if (!entry->link) {
      49           0 :                 return NULL;
      50             :         }
      51          31 :         if (entry->link[0] == '/') {
      52           1 :                 return estrdup(entry->link + 1);
      53             :         }
      54          30 :         p = strrchr(entry->filename, '/');
      55          30 :         if (p) {
      56           3 :                 *p = '\0';
      57           3 :                 spprintf(&ret, 0, "%s/%s", entry->filename, entry->link);
      58           3 :                 return ret;
      59             :         }
      60          27 :         return entry->link;
      61             : }
      62             : /* }}} */
      63             : 
      64        7973 : phar_entry_info *phar_get_link_source(phar_entry_info *entry) /* {{{ */
      65             : {
      66             :         phar_entry_info *link_entry;
      67             :         char *link;
      68             : 
      69        7973 :         if (!entry->link) {
      70        7942 :                 return entry;
      71             :         }
      72             : 
      73          31 :         link = phar_get_link_location(entry);
      74          65 :         if (NULL != (link_entry = zend_hash_str_find_ptr(&(entry->phar->manifest), entry->link, strlen(entry->link))) ||
      75           3 :                 NULL != (link_entry = zend_hash_str_find_ptr(&(entry->phar->manifest), link, strlen(link)))) {
      76          31 :                 if (link != entry->link) {
      77           4 :                         efree(link);
      78             :                 }
      79          31 :                 return phar_get_link_source(link_entry);
      80             :         } else {
      81           0 :                 if (link != entry->link) {
      82           0 :                         efree(link);
      83             :                 }
      84           0 :                 return NULL;
      85             :         }
      86             : }
      87             : /* }}} */
      88             : 
      89             : /* retrieve a phar_entry_info's current file pointer for reading contents */
      90       59781 : php_stream *phar_get_efp(phar_entry_info *entry, int follow_links) /* {{{ */
      91             : {
      92       59781 :         if (follow_links && entry->link) {
      93           3 :                 phar_entry_info *link_entry = phar_get_link_source(entry);
      94             : 
      95           3 :                 if (link_entry && link_entry != entry) {
      96           3 :                         return phar_get_efp(link_entry, 1);
      97             :                 }
      98             :         }
      99             : 
     100       59778 :         if (phar_get_fp_type(entry) == PHAR_FP) {
     101       16020 :                 if (!phar_get_entrypfp(entry)) {
     102             :                         /* re-open just in time for cases where our refcount reached 0 on the phar archive */
     103          22 :                         phar_open_archive_fp(entry->phar);
     104             :                 }
     105       16020 :                 return phar_get_entrypfp(entry);
     106       43758 :         } else if (phar_get_fp_type(entry) == PHAR_UFP) {
     107       15638 :                 return phar_get_entrypufp(entry);
     108       28120 :         } else if (entry->fp_type == PHAR_MOD) {
     109       28109 :                 return entry->fp;
     110             :         } else {
     111             :                 /* temporary manifest entry */
     112          11 :                 if (!entry->fp) {
     113           0 :                         entry->fp = php_stream_open_wrapper(entry->tmp, "rb", STREAM_MUST_SEEK|0, NULL);
     114             :                 }
     115          11 :                 return entry->fp;
     116             :         }
     117             : }
     118             : /* }}} */
     119             : 
     120       23822 : int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links) /* {{{ */
     121             : {
     122       23822 :         php_stream *fp = phar_get_efp(entry, follow_links);
     123             :         zend_off_t temp, eoffset;
     124             : 
     125       23822 :         if (!fp) {
     126           1 :                 return -1;
     127             :         }
     128             : 
     129       23821 :         if (follow_links) {
     130             :                 phar_entry_info *t;
     131        7718 :                 t = phar_get_link_source(entry);
     132        7718 :                 if (t) {
     133        7718 :                         entry = t;
     134             :                 }
     135             :         }
     136             : 
     137       23821 :         if (entry->is_dir) {
     138          18 :                 return 0;
     139             :         }
     140             : 
     141       23803 :         eoffset = phar_get_fp_offset(entry);
     142             : 
     143       23803 :         switch (whence) {
     144             :                 case SEEK_END:
     145           0 :                         temp = eoffset + entry->uncompressed_filesize + offset;
     146           0 :                         break;
     147             :                 case SEEK_CUR:
     148           0 :                         temp = eoffset + position + offset;
     149           0 :                         break;
     150             :                 case SEEK_SET:
     151       23803 :                         temp = eoffset + offset;
     152       23803 :                         break;
     153             :                 default:
     154           0 :                         temp = 0;
     155             :         }
     156             : 
     157       23803 :         if (temp > eoffset + (zend_off_t) entry->uncompressed_filesize) {
     158           0 :                 return -1;
     159             :         }
     160             : 
     161       23803 :         if (temp < eoffset) {
     162           0 :                 return -1;
     163             :         }
     164             : 
     165       23803 :         return php_stream_seek(fp, temp, SEEK_SET);
     166             : }
     167             : /* }}} */
     168             : 
     169             : /* mount an absolute path or uri to a path internal to the phar archive */
     170          23 : int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len) /* {{{ */
     171             : {
     172          23 :         phar_entry_info entry = {0};
     173             :         php_stream_statbuf ssb;
     174             :         int is_phar;
     175             :         const char *err;
     176             : 
     177          23 :         if (phar_path_check(&path, &path_len, &err) > pcr_is_ok) {
     178           0 :                 return FAILURE;
     179             :         }
     180             : 
     181          23 :         if (path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", sizeof(".phar")-1)) {
     182             :                 /* no creating magic phar files by mounting them */
     183           1 :                 return FAILURE;
     184             :         }
     185             : 
     186          22 :         is_phar = (filename_len > 7 && !memcmp(filename, "phar://", 7));
     187             : 
     188          22 :         entry.phar = phar;
     189          22 :         entry.filename = estrndup(path, path_len);
     190             : #ifdef PHP_WIN32
     191             :         phar_unixify_path_separators(entry.filename, path_len);
     192             : #endif
     193          22 :         entry.filename_len = path_len;
     194          22 :         if (is_phar) {
     195           4 :                 entry.tmp = estrndup(filename, filename_len);
     196             :         } else {
     197          18 :                 entry.tmp = expand_filepath(filename, NULL);
     198          18 :                 if (!entry.tmp) {
     199           0 :                         entry.tmp = estrndup(filename, filename_len);
     200             :                 }
     201             :         }
     202             : #if PHP_API_VERSION < 20100412
     203             :         if (PG(safe_mode) && !is_phar && (!php_checkuid(entry.tmp, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
     204             :                 efree(entry.tmp);
     205             :                 efree(entry.filename);
     206             :                 return FAILURE;
     207             :         }
     208             : #endif
     209          22 :         filename = entry.tmp;
     210             : 
     211             :         /* only check openbasedir for files, not for phar streams */
     212          22 :         if (!is_phar && php_check_open_basedir(filename)) {
     213           0 :                 efree(entry.tmp);
     214           0 :                 efree(entry.filename);
     215           0 :                 return FAILURE;
     216             :         }
     217             : 
     218          22 :         entry.is_mounted = 1;
     219          22 :         entry.is_crc_checked = 1;
     220          22 :         entry.fp_type = PHAR_TMP;
     221             : 
     222          22 :         if (SUCCESS != php_stream_stat_path(filename, &ssb)) {
     223           3 :                 efree(entry.tmp);
     224           3 :                 efree(entry.filename);
     225           3 :                 return FAILURE;
     226             :         }
     227             : 
     228          19 :         if (ssb.sb.st_mode & S_IFDIR) {
     229           5 :                 entry.is_dir = 1;
     230          10 :                 if (NULL == zend_hash_str_add_ptr(&phar->mounted_dirs, entry.filename, path_len, entry.filename)) {
     231             :                         /* directory already mounted */
     232           1 :                         efree(entry.tmp);
     233           1 :                         efree(entry.filename);
     234           1 :                         return FAILURE;
     235             :                 }
     236             :         } else {
     237          14 :                 entry.is_dir = 0;
     238          14 :                 entry.uncompressed_filesize = entry.compressed_filesize = ssb.sb.st_size;
     239             :         }
     240             : 
     241          18 :         entry.flags = ssb.sb.st_mode;
     242             : 
     243          36 :         if (NULL != zend_hash_str_add_mem(&phar->manifest, entry.filename, path_len, (void*)&entry, sizeof(phar_entry_info))) {
     244          15 :                 return SUCCESS;
     245             :         }
     246             : 
     247           3 :         efree(entry.tmp);
     248           3 :         efree(entry.filename);
     249           3 :         return FAILURE;
     250             : }
     251             : /* }}} */
     252             : 
     253       14925 : zend_string *phar_find_in_include_path(char *filename, int filename_len, phar_archive_data **pphar) /* {{{ */
     254             : {
     255             :         zend_string *ret;
     256             :         char *path, *fname, *arch, *entry, *test;
     257             :         int arch_len, entry_len, fname_len;
     258             :         phar_archive_data *phar;
     259             : 
     260       14925 :         if (pphar) {
     261           0 :                 *pphar = NULL;
     262             :         } else {
     263       14925 :                 pphar = &phar;
     264             :         }
     265             : 
     266       14925 :         if (!zend_is_executing() || !PHAR_G(cwd)) {
     267       14903 :                 return phar_save_resolve_path(filename, filename_len);
     268             :         }
     269             : 
     270          22 :         fname = (char*)zend_get_executed_filename();
     271          22 :         fname_len = strlen(fname);
     272             : 
     273          22 :         if (PHAR_G(last_phar) && !memcmp(fname, "phar://", 7) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
     274           1 :                 arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
     275           1 :                 arch_len = PHAR_G(last_phar_name_len);
     276           1 :                 phar = PHAR_G(last_phar);
     277           1 :                 goto splitted;
     278             :         }
     279             : 
     280          21 :         if (fname_len < 7 || memcmp(fname, "phar://", 7) || SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 1, 0)) {
     281          14 :                 return phar_save_resolve_path(filename, filename_len);
     282             :         }
     283             : 
     284           7 :         efree(entry);
     285             : 
     286           7 :         if (*filename == '.') {
     287             :                 int try_len;
     288             : 
     289           4 :                 if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
     290           0 :                         efree(arch);
     291           0 :                         return phar_save_resolve_path(filename, filename_len);
     292             :                 }
     293             : splitted:
     294           5 :                 if (pphar) {
     295           5 :                         *pphar = phar;
     296             :                 }
     297             : 
     298           5 :                 try_len = filename_len;
     299           5 :                 test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1);
     300             : 
     301           5 :                 if (*test == '/') {
     302           2 :                         if (zend_hash_str_exists(&(phar->manifest), test + 1, try_len - 1)) {
     303           2 :                                 ret = strpprintf(0, "phar://%s%s", arch, test);
     304           2 :                                 efree(arch);
     305           2 :                                 efree(test);
     306           2 :                                 return ret;
     307             :                         }
     308             :                 } else {
     309           3 :                         if (zend_hash_str_exists(&(phar->manifest), test, try_len)) {
     310           2 :                                 ret = strpprintf(0, "phar://%s/%s", arch, test);
     311           2 :                                 efree(arch);
     312           2 :                                 efree(test);
     313           2 :                                 return ret;
     314             :                         }
     315             :                 }
     316           1 :                 efree(test);
     317             :         }
     318             : 
     319           4 :         spprintf(&path, MAXPATHLEN, "phar://%s/%s%c%s", arch, PHAR_G(cwd), DEFAULT_DIR_SEPARATOR, PG(include_path));
     320           4 :         efree(arch);
     321           4 :         ret = php_resolve_path(filename, filename_len, path);
     322           4 :         efree(path);
     323             : 
     324           4 :         if (ret && ret->len > 8 && !strncmp(ret->val, "phar://", 7)) {
     325             :                 /* found phar:// */
     326           2 :                 if (SUCCESS != phar_split_fname(ret->val, ret->len, &arch, &arch_len, &entry, &entry_len, 1, 0)) {
     327           0 :                         return ret;
     328             :                 }
     329             : 
     330           4 :                 *pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), arch, arch_len);
     331             : 
     332           2 :                 if (!*pphar && PHAR_G(manifest_cached)) {
     333           0 :                         *pphar = zend_hash_str_find_ptr(&cached_phars, arch, arch_len);
     334             :                 }
     335             : 
     336           2 :                 efree(arch);
     337           2 :                 efree(entry);
     338             :         }
     339             : 
     340           4 :         return ret;
     341             : }
     342             : /* }}} */
     343             : 
     344             : /**
     345             :  * Retrieve a copy of the file information on a single file within a phar, or null.
     346             :  * This also transfers the open file pointer, if any, to the entry.
     347             :  *
     348             :  * If the file does not already exist, this will fail.  Pre-existing files can be
     349             :  * appended, truncated, or read.  For read, if the entry is marked unmodified, it is
     350             :  * assumed that the file pointer, if present, is opened for reading
     351             :  */
     352        8212 : int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */
     353             : {
     354             :         phar_archive_data *phar;
     355             :         phar_entry_info *entry;
     356        8212 :         int for_write  = mode[0] != 'r' || mode[1] == '+';
     357        8212 :         int for_append = mode[0] == 'a';
     358        8212 :         int for_create = mode[0] != 'r';
     359        8212 :         int for_trunc  = mode[0] == 'w';
     360             : 
     361        8212 :         if (!ret) {
     362           0 :                 return FAILURE;
     363             :         }
     364             : 
     365        8212 :         *ret = NULL;
     366             : 
     367        8212 :         if (error) {
     368        8212 :                 *error = NULL;
     369             :         }
     370             : 
     371        8212 :         if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) {
     372           0 :                 return FAILURE;
     373             :         }
     374             : 
     375        8212 :         if (for_write && PHAR_G(readonly) && !phar->is_data) {
     376           0 :                 if (error) {
     377           0 :                         spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, fname);
     378             :                 }
     379           0 :                 return FAILURE;
     380             :         }
     381             : 
     382        8212 :         if (!path_len) {
     383           4 :                 if (error) {
     384           4 :                         spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" cannot be empty", fname);
     385             :                 }
     386           4 :                 return FAILURE;
     387             :         }
     388             : really_get_entry:
     389        8209 :         if (allow_dir) {
     390          18 :                 if ((entry = phar_get_entry_info_dir(phar, path, path_len, allow_dir, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, security)) == NULL) {
     391          16 :                         if (for_create && (!PHAR_G(readonly) || phar->is_data)) {
     392          16 :                                 return SUCCESS;
     393             :                         }
     394           0 :                         return FAILURE;
     395             :                 }
     396             :         } else {
     397        8191 :                 if ((entry = phar_get_entry_info(phar, path, path_len, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, security)) == NULL) {
     398        3541 :                         if (for_create && (!PHAR_G(readonly) || phar->is_data)) {
     399        3517 :                                 return SUCCESS;
     400             :                         }
     401          24 :                         return FAILURE;
     402             :                 }
     403             :         }
     404             : 
     405        4652 :         if (for_write && phar->is_persistent) {
     406           1 :                 if (FAILURE == phar_copy_on_write(&phar)) {
     407           0 :                         if (error) {
     408           0 :                                 spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, could not make cached phar writeable", path, fname);
     409             :                         }
     410           0 :                         return FAILURE;
     411             :                 } else {
     412           1 :                         goto really_get_entry;
     413             :                 }
     414             :         }
     415             : 
     416        4651 :         if (entry->is_modified && !for_write) {
     417           0 :                 if (error) {
     418           0 :                         spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, fname);
     419             :                 }
     420           0 :                 return FAILURE;
     421             :         }
     422             : 
     423        4651 :         if (entry->fp_refcount && for_write) {
     424           1 :                 if (error) {
     425           1 :                         spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, fname);
     426             :                 }
     427           1 :                 return FAILURE;
     428             :         }
     429             : 
     430        4650 :         if (entry->is_deleted) {
     431           0 :                 if (!for_create) {
     432           0 :                         return FAILURE;
     433             :                 }
     434           0 :                 entry->is_deleted = 0;
     435             :         }
     436             : 
     437        4650 :         if (entry->is_dir) {
     438           2 :                 *ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
     439           2 :                 (*ret)->position = 0;
     440           2 :                 (*ret)->fp = NULL;
     441           2 :                 (*ret)->phar = phar;
     442           2 :                 (*ret)->for_write = for_write;
     443           2 :                 (*ret)->internal_file = entry;
     444           2 :                 (*ret)->is_zip = entry->is_zip;
     445           2 :                 (*ret)->is_tar = entry->is_tar;
     446             : 
     447           2 :                 if (!phar->is_persistent) {
     448           2 :                         ++(entry->phar->refcount);
     449           2 :                         ++(entry->fp_refcount);
     450             :                 }
     451             : 
     452           2 :                 return SUCCESS;
     453             :         }
     454             : 
     455        4648 :         if (entry->fp_type == PHAR_MOD) {
     456           0 :                 if (for_trunc) {
     457           0 :                         if (FAILURE == phar_create_writeable_entry(phar, entry, error)) {
     458           0 :                                 return FAILURE;
     459             :                         }
     460           0 :                 } else if (for_append) {
     461           0 :                         phar_seek_efp(entry, 0, SEEK_END, 0, 0);
     462             :                 }
     463             :         } else {
     464        4648 :                 if (for_write) {
     465        4124 :                         if (entry->link) {
     466           1 :                                 efree(entry->link);
     467           1 :                                 entry->link = NULL;
     468           1 :                                 entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
     469             :                         }
     470             : 
     471        4124 :                         if (for_trunc) {
     472        4123 :                                 if (FAILURE == phar_create_writeable_entry(phar, entry, error)) {
     473           0 :                                         return FAILURE;
     474             :                                 }
     475             :                         } else {
     476           1 :                                 if (FAILURE == phar_separate_entry_fp(entry, error)) {
     477           0 :                                         return FAILURE;
     478             :                                 }
     479             :                         }
     480             :                 } else {
     481         524 :                         if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
     482           4 :                                 return FAILURE;
     483             :                         }
     484             :                 }
     485             :         }
     486             : 
     487        4644 :         *ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
     488        4644 :         (*ret)->position = 0;
     489        4644 :         (*ret)->phar = phar;
     490        4644 :         (*ret)->for_write = for_write;
     491        4644 :         (*ret)->internal_file = entry;
     492        4644 :         (*ret)->is_zip = entry->is_zip;
     493        4644 :         (*ret)->is_tar = entry->is_tar;
     494        4644 :         (*ret)->fp = phar_get_efp(entry, 1);
     495        4644 :         if (entry->link) {
     496           3 :                 (*ret)->zero = phar_get_fp_offset(phar_get_link_source(entry));
     497             :         } else {
     498        4641 :                 (*ret)->zero = phar_get_fp_offset(entry);
     499             :         }
     500             : 
     501        4644 :         if (!phar->is_persistent) {
     502        4644 :                 ++(entry->fp_refcount);
     503        4644 :                 ++(entry->phar->refcount);
     504             :         }
     505             : 
     506        4644 :         return SUCCESS;
     507             : }
     508             : /* }}} */
     509             : 
     510             : /**
     511             :  * Create a new dummy file slot within a writeable phar for a newly created file
     512             :  */
     513        7664 : phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, const char *mode, char allow_dir, char **error, int security) /* {{{ */
     514             : {
     515             :         phar_archive_data *phar;
     516             :         phar_entry_info *entry, etemp;
     517             :         phar_entry_data *ret;
     518             :         const char *pcr_error;
     519             :         char is_dir;
     520             : 
     521             : #ifdef PHP_WIN32
     522             :         phar_unixify_path_separators(path, path_len);
     523             : #endif
     524             : 
     525        7664 :         is_dir = (path_len && path[path_len - 1] == '/') ? 1 : 0;
     526             : 
     527        7664 :         if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error)) {
     528           0 :                 return NULL;
     529             :         }
     530             : 
     531        7664 :         if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, allow_dir, error, security)) {
     532           5 :                 return NULL;
     533        7659 :         } else if (ret) {
     534        4126 :                 return ret;
     535             :         }
     536             : 
     537        3533 :         if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
     538           8 :                 if (error) {
     539           8 :                         spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
     540             :                 }
     541           8 :                 return NULL;
     542             :         }
     543             : 
     544        3525 :         if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar)) {
     545           0 :                 if (error) {
     546           0 :                         spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be created, could not make cached phar writeable", path, fname);
     547             :                 }
     548           0 :                 return NULL;
     549             :         }
     550             : 
     551             :         /* create a new phar data holder */
     552        3525 :         ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
     553             : 
     554             :         /* create an entry, this is a new file */
     555        3525 :         memset(&etemp, 0, sizeof(phar_entry_info));
     556        3525 :         etemp.filename_len = path_len;
     557        3525 :         etemp.fp_type = PHAR_MOD;
     558        3525 :         etemp.fp = php_stream_fopen_tmpfile();
     559             : 
     560        3525 :         if (!etemp.fp) {
     561           0 :                 if (error) {
     562           0 :                         spprintf(error, 0, "phar error: unable to create temporary file");
     563             :                 }
     564           0 :                 efree(ret);
     565           0 :                 return NULL;
     566             :         }
     567             : 
     568        3525 :         etemp.fp_refcount = 1;
     569             : 
     570        3525 :         if (allow_dir == 2) {
     571          16 :                 etemp.is_dir = 1;
     572          16 :                 etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_DIR;
     573             :         } else {
     574        3509 :                 etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_FILE;
     575             :         }
     576        3525 :         if (is_dir) {
     577           2 :                 etemp.filename_len--; /* strip trailing / */
     578           2 :                 path_len--;
     579             :         }
     580             : 
     581        3525 :         phar_add_virtual_dirs(phar, path, path_len);
     582        3525 :         etemp.is_modified = 1;
     583        3525 :         etemp.timestamp = time(0);
     584        3525 :         etemp.is_crc_checked = 1;
     585        3525 :         etemp.phar = phar;
     586        3525 :         etemp.filename = estrndup(path, path_len);
     587        3525 :         etemp.is_zip = phar->is_zip;
     588             : 
     589        3525 :         if (phar->is_tar) {
     590         100 :                 etemp.is_tar = phar->is_tar;
     591         100 :                 etemp.tar_type = etemp.is_dir ? TAR_DIR : TAR_FILE;
     592             :         }
     593             : 
     594        7050 :         if (NULL == (entry = zend_hash_str_add_mem(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info)))) {
     595           0 :                 php_stream_close(etemp.fp);
     596           0 :                 if (error) {
     597           0 :                         spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", etemp.filename, phar->fname);
     598             :                 }
     599           0 :                 efree(ret);
     600           0 :                 efree(etemp.filename);
     601           0 :                 return NULL;
     602             :         }
     603             : 
     604        3525 :         if (!entry) {
     605           0 :                 php_stream_close(etemp.fp);
     606           0 :                 efree(etemp.filename);
     607           0 :                 efree(ret);
     608           0 :                 return NULL;
     609             :         }
     610             : 
     611        3525 :         ++(phar->refcount);
     612        3525 :         ret->phar = phar;
     613        3525 :         ret->fp = entry->fp;
     614        3525 :         ret->position = ret->zero = 0;
     615        3525 :         ret->for_write = 1;
     616        3525 :         ret->is_zip = entry->is_zip;
     617        3525 :         ret->is_tar = entry->is_tar;
     618        3525 :         ret->internal_file = entry;
     619             : 
     620        3525 :         return ret;
     621             : }
     622             : /* }}} */
     623             : 
     624             : /* initialize a phar_archive_data's read-only fp for existing phar data */
     625         346 : int phar_open_archive_fp(phar_archive_data *phar) /* {{{ */
     626             : {
     627         346 :         if (phar_get_pharfp(phar)) {
     628         177 :                 return SUCCESS;
     629             :         }
     630             : 
     631         169 :         if (php_check_open_basedir(phar->fname)) {
     632           0 :                 return FAILURE;
     633             :         }
     634             : 
     635         169 :         phar_set_pharfp(phar, php_stream_open_wrapper(phar->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL));
     636             : 
     637         169 :         if (!phar_get_pharfp(phar)) {
     638           4 :                 return FAILURE;
     639             :         }
     640             : 
     641         165 :         return SUCCESS;
     642             : }
     643             : /* }}} */
     644             : 
     645             : /* copy file data from an existing to a new phar_entry_info that is not in the manifest */
     646           6 : int phar_copy_entry_fp(phar_entry_info *source, phar_entry_info *dest, char **error) /* {{{ */
     647             : {
     648             :         phar_entry_info *link;
     649             : 
     650           6 :         if (FAILURE == phar_open_entry_fp(source, error, 1)) {
     651           0 :                 return FAILURE;
     652             :         }
     653             : 
     654           6 :         if (dest->link) {
     655           0 :                 efree(dest->link);
     656           0 :                 dest->link = NULL;
     657           0 :                 dest->tar_type = (dest->is_tar ? TAR_FILE : '\0');
     658             :         }
     659             : 
     660           6 :         dest->fp_type = PHAR_MOD;
     661           6 :         dest->offset = 0;
     662           6 :         dest->is_modified = 1;
     663           6 :         dest->fp = php_stream_fopen_tmpfile();
     664           6 :         if (dest->fp == NULL) {
     665           0 :                 spprintf(error, 0, "phar error: unable to create temporary file");
     666           0 :                 return EOF;
     667             :         }
     668           6 :         phar_seek_efp(source, 0, SEEK_SET, 0, 1);
     669           6 :         link = phar_get_link_source(source);
     670             : 
     671           6 :         if (!link) {
     672           0 :                 link = source;
     673             :         }
     674             : 
     675           6 :         if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), dest->fp, link->uncompressed_filesize, NULL)) {
     676           0 :                 php_stream_close(dest->fp);
     677           0 :                 dest->fp_type = PHAR_FP;
     678           0 :                 if (error) {
     679           0 :                         spprintf(error, 4096, "phar error: unable to copy contents of file \"%s\" to \"%s\" in phar archive \"%s\"", source->filename, dest->filename, source->phar->fname);
     680             :                 }
     681           0 :                 return FAILURE;
     682             :         }
     683             : 
     684           6 :         return SUCCESS;
     685             : }
     686             : /* }}} */
     687             : 
     688             : /* open and decompress a compressed phar entry
     689             :  */
     690        2431 : int phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links) /* {{{ */
     691             : {
     692             :         php_stream_filter *filter;
     693        2431 :         phar_archive_data *phar = entry->phar;
     694             :         char *filtername;
     695             :         zend_off_t loc;
     696             :         php_stream *ufp;
     697             :         phar_entry_data dummy;
     698             : 
     699        2431 :         if (follow_links && entry->link) {
     700           3 :                 phar_entry_info *link_entry = phar_get_link_source(entry);
     701           3 :                 if (link_entry && link_entry != entry) {
     702           3 :                         return phar_open_entry_fp(link_entry, error, 1);
     703             :                 }
     704             :         }
     705             : 
     706        2428 :         if (entry->is_modified) {
     707        1362 :                 return SUCCESS;
     708             :         }
     709             : 
     710        1066 :         if (entry->fp_type == PHAR_TMP) {
     711           9 :                 if (!entry->fp) {
     712           8 :                         entry->fp = php_stream_open_wrapper(entry->tmp, "rb", STREAM_MUST_SEEK|0, NULL);
     713             :                 }
     714           9 :                 return SUCCESS;
     715             :         }
     716             : 
     717        1057 :         if (entry->fp_type != PHAR_FP) {
     718             :                 /* either newly created or already modified */
     719           2 :                 return SUCCESS;
     720             :         }
     721             : 
     722        1055 :         if (!phar_get_pharfp(phar)) {
     723         147 :                 if (FAILURE == phar_open_archive_fp(phar)) {
     724           1 :                         spprintf(error, 4096, "phar error: Cannot open phar archive \"%s\" for reading", phar->fname);
     725           1 :                         return FAILURE;
     726             :                 }
     727             :         }
     728             : 
     729        1054 :         if ((entry->old_flags && !(entry->old_flags & PHAR_ENT_COMPRESSION_MASK)) || !(entry->flags & PHAR_ENT_COMPRESSION_MASK)) {
     730        1013 :                 dummy.internal_file = entry;
     731        1013 :                 dummy.phar = phar;
     732        1013 :                 dummy.zero = entry->offset;
     733        1013 :                 dummy.fp = phar_get_pharfp(phar);
     734        1013 :                 if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 1)) {
     735           0 :                         return FAILURE;
     736             :                 }
     737        1013 :                 return SUCCESS;
     738             :         }
     739             : 
     740          41 :         if (!phar_get_entrypufp(entry)) {
     741          24 :                 phar_set_entrypufp(entry, php_stream_fopen_tmpfile());
     742          24 :                 if (!phar_get_entrypufp(entry)) {
     743           0 :                         spprintf(error, 4096, "phar error: Cannot open temporary file for decompressing phar archive \"%s\" file \"%s\"", phar->fname, entry->filename);
     744           0 :                         return FAILURE;
     745             :                 }
     746             :         }
     747             : 
     748          41 :         dummy.internal_file = entry;
     749          41 :         dummy.phar = phar;
     750          41 :         dummy.zero = entry->offset;
     751          41 :         dummy.fp = phar_get_pharfp(phar);
     752          41 :         if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 1)) {
     753           0 :                 return FAILURE;
     754             :         }
     755             : 
     756          41 :         ufp = phar_get_entrypufp(entry);
     757             : 
     758          41 :         if ((filtername = phar_decompress_filter(entry, 0)) != NULL) {
     759          41 :                 filter = php_stream_filter_create(filtername, NULL, 0);
     760             :         } else {
     761           0 :                 filter = NULL;
     762             :         }
     763             : 
     764          41 :         if (!filter) {
     765           0 :                 spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry->filename);
     766           0 :                 return FAILURE;
     767             :         }
     768             : 
     769             :         /* now we can safely use proper decompression */
     770             :         /* save the new offset location within ufp */
     771          41 :         php_stream_seek(ufp, 0, SEEK_END);
     772          41 :         loc = php_stream_tell(ufp);
     773          41 :         php_stream_filter_append(&ufp->writefilters, filter);
     774          41 :         php_stream_seek(phar_get_entrypfp(entry), phar_get_fp_offset(entry), SEEK_SET);
     775             : 
     776          41 :         if (entry->uncompressed_filesize) {
     777          40 :                 if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_entrypfp(entry), ufp, entry->compressed_filesize, NULL)) {
     778           0 :                         spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
     779           0 :                         php_stream_filter_remove(filter, 1);
     780           0 :                         return FAILURE;
     781             :                 }
     782             :         }
     783             : 
     784          41 :         php_stream_filter_flush(filter, 1);
     785          41 :         php_stream_flush(ufp);
     786          41 :         php_stream_filter_remove(filter, 1);
     787             : 
     788          41 :         if (php_stream_tell(ufp) - loc != (zend_off_t) entry->uncompressed_filesize) {
     789           4 :                 spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
     790           4 :                 return FAILURE;
     791             :         }
     792             : 
     793          37 :         entry->old_flags = entry->flags;
     794             : 
     795             :         /* this is now the new location of the file contents within this fp */
     796          37 :         phar_set_fp_type(entry, PHAR_UFP, loc);
     797          37 :         dummy.zero = entry->offset;
     798          37 :         dummy.fp = ufp;
     799          37 :         if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 0)) {
     800           0 :                 return FAILURE;
     801             :         }
     802          37 :         return SUCCESS;
     803             : }
     804             : /* }}} */
     805             : 
     806        4123 : int phar_create_writeable_entry(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */
     807             : {
     808        4123 :         if (entry->fp_type == PHAR_MOD) {
     809             :                 /* already newly created, truncate */
     810           0 :                 php_stream_truncate_set_size(entry->fp, 0);
     811             : 
     812           0 :                 entry->old_flags = entry->flags;
     813           0 :                 entry->is_modified = 1;
     814           0 :                 phar->is_modified = 1;
     815             :                 /* reset file size */
     816           0 :                 entry->uncompressed_filesize = 0;
     817           0 :                 entry->compressed_filesize = 0;
     818           0 :                 entry->crc32 = 0;
     819           0 :                 entry->flags = PHAR_ENT_PERM_DEF_FILE;
     820           0 :                 entry->fp_type = PHAR_MOD;
     821           0 :                 entry->offset = 0;
     822           0 :                 return SUCCESS;
     823             :         }
     824             : 
     825        4123 :         if (error) {
     826        4123 :                 *error = NULL;
     827             :         }
     828             : 
     829             :         /* open a new temp file for writing */
     830        4123 :         if (entry->link) {
     831           0 :                 efree(entry->link);
     832           0 :                 entry->link = NULL;
     833           0 :                 entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
     834             :         }
     835             : 
     836        4123 :         entry->fp = php_stream_fopen_tmpfile();
     837             : 
     838        4123 :         if (!entry->fp) {
     839           0 :                 if (error) {
     840           0 :                         spprintf(error, 0, "phar error: unable to create temporary file");
     841             :                 }
     842           0 :                 return FAILURE;
     843             :         }
     844             : 
     845        4123 :         entry->old_flags = entry->flags;
     846        4123 :         entry->is_modified = 1;
     847        4123 :         phar->is_modified = 1;
     848             :         /* reset file size */
     849        4123 :         entry->uncompressed_filesize = 0;
     850        4123 :         entry->compressed_filesize = 0;
     851        4123 :         entry->crc32 = 0;
     852        4123 :         entry->flags = PHAR_ENT_PERM_DEF_FILE;
     853        4123 :         entry->fp_type = PHAR_MOD;
     854        4123 :         entry->offset = 0;
     855        4123 :         return SUCCESS;
     856             : }
     857             : /* }}} */
     858             : 
     859           1 : int phar_separate_entry_fp(phar_entry_info *entry, char **error) /* {{{ */
     860             : {
     861             :         php_stream *fp;
     862             :         phar_entry_info *link;
     863             : 
     864           1 :         if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
     865           0 :                 return FAILURE;
     866             :         }
     867             : 
     868           1 :         if (entry->fp_type == PHAR_MOD) {
     869           0 :                 return SUCCESS;
     870             :         }
     871             : 
     872           1 :         fp = php_stream_fopen_tmpfile();
     873           1 :         if (fp == NULL) {
     874           0 :                 spprintf(error, 0, "phar error: unable to create temporary file");
     875           0 :                 return FAILURE;
     876             :         }
     877           1 :         phar_seek_efp(entry, 0, SEEK_SET, 0, 1);
     878           1 :         link = phar_get_link_source(entry);
     879             : 
     880           1 :         if (!link) {
     881           0 :                 link = entry;
     882             :         }
     883             : 
     884           1 :         if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) {
     885           0 :                 if (error) {
     886           0 :                         spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname);
     887             :                 }
     888           0 :                 return FAILURE;
     889             :         }
     890             : 
     891           1 :         if (entry->link) {
     892           0 :                 efree(entry->link);
     893           0 :                 entry->link = NULL;
     894           0 :                 entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
     895             :         }
     896             : 
     897           1 :         entry->offset = 0;
     898           1 :         entry->fp = fp;
     899           1 :         entry->fp_type = PHAR_MOD;
     900           1 :         entry->is_modified = 1;
     901           1 :         return SUCCESS;
     902             : }
     903             : /* }}} */
     904             : 
     905             : /**
     906             :  * helper function to open an internal file's fp just-in-time
     907             :  */
     908           1 : phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, char **error) /* {{{ */
     909             : {
     910           1 :         if (error) {
     911           1 :                 *error = NULL;
     912             :         }
     913             :         /* seek to start of internal file and read it */
     914           1 :         if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
     915           1 :                 return NULL;
     916             :         }
     917           0 :         if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1)) {
     918           0 :                 spprintf(error, 4096, "phar error: cannot seek to start of file \"%s\" in phar \"%s\"", entry->filename, phar->fname);
     919           0 :                 return NULL;
     920             :         }
     921           0 :         return entry;
     922             : }
     923             : /* }}} */
     924             : 
     925           0 : PHP_PHAR_API int phar_resolve_alias(char *alias, int alias_len, char **filename, int *filename_len) /* {{{ */ {
     926             :         phar_archive_data *fd_ptr;
     927           0 :         if (PHAR_G(phar_alias_map.u.flags)
     928           0 :                         && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
     929           0 :                 *filename = fd_ptr->fname;
     930           0 :                 *filename_len = fd_ptr->fname_len;
     931           0 :                 return SUCCESS;
     932             :         }
     933           0 :         return FAILURE;
     934             : }
     935             : /* }}} */
     936             : 
     937          16 : int phar_free_alias(phar_archive_data *phar, char *alias, int alias_len) /* {{{ */
     938             : {
     939          16 :         if (phar->refcount || phar->is_persistent) {
     940          13 :                 return FAILURE;
     941             :         }
     942             : 
     943             :         /* this archive has no open references, so emit an E_STRICT and remove it */
     944           3 :         if (zend_hash_str_del(&(PHAR_G(phar_fname_map)), phar->fname, phar->fname_len) != SUCCESS) {
     945           0 :                 return FAILURE;
     946             :         }
     947             : 
     948             :         /* invalidate phar cache */
     949           3 :         PHAR_G(last_phar) = NULL;
     950           3 :         PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
     951             : 
     952           3 :         return SUCCESS;
     953             : }
     954             : /* }}} */
     955             : 
     956             : /**
     957             :  * Looks up a phar archive in the filename map, connecting it to the alias
     958             :  * (if any) or returns null
     959             :  */
     960       19974 : int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len, char *alias, int alias_len, char **error) /* {{{ */
     961             : {
     962             :         phar_archive_data *fd, *fd_ptr;
     963             :         char *my_realpath, *save;
     964             :         int save_len;
     965             : 
     966       19974 :         phar_request_initialize();
     967             : 
     968       19974 :         if (error) {
     969       19389 :                 *error = NULL;
     970             :         }
     971             : 
     972       19974 :         *archive = NULL;
     973             : 
     974       19974 :         if (PHAR_G(last_phar) && fname_len == PHAR_G(last_phar_name_len) && !memcmp(fname, PHAR_G(last_phar_name), fname_len)) {
     975       18267 :                 *archive = PHAR_G(last_phar);
     976       18267 :                 if (alias && alias_len) {
     977             : 
     978         175 :                         if (!PHAR_G(last_phar)->is_temporary_alias && (alias_len != PHAR_G(last_phar)->alias_len || memcmp(PHAR_G(last_phar)->alias, alias, alias_len))) {
     979           3 :                                 if (error) {
     980           3 :                                         spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, PHAR_G(last_phar)->fname, fname);
     981             :                                 }
     982           3 :                                 *archive = NULL;
     983           3 :                                 return FAILURE;
     984             :                         }
     985             : 
     986         344 :                         if (PHAR_G(last_phar)->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len))) {
     987         135 :                                 zend_hash_str_del(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len);
     988             :                         }
     989             : 
     990         172 :                         zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, *archive);
     991         172 :                         PHAR_G(last_alias) = alias;
     992         172 :                         PHAR_G(last_alias_len) = alias_len;
     993             :                 }
     994             : 
     995       18264 :                 return SUCCESS;
     996             :         }
     997             : 
     998        1707 :         if (alias && alias_len && PHAR_G(last_phar) && alias_len == PHAR_G(last_alias_len) && !memcmp(alias, PHAR_G(last_alias), alias_len)) {
     999           3 :                 fd = PHAR_G(last_phar);
    1000           3 :                 fd_ptr = fd;
    1001           3 :                 goto alias_success;
    1002             :         }
    1003             : 
    1004        1704 :         if (alias && alias_len) {
    1005         256 :                 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
    1006             : alias_success:
    1007          21 :                         if (fname && (fname_len != fd_ptr->fname_len || strncmp(fname, fd_ptr->fname, fname_len))) {
    1008           5 :                                 if (error) {
    1009           5 :                                         spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname);
    1010             :                                 }
    1011           5 :                                 if (SUCCESS == phar_free_alias(fd_ptr, alias, alias_len)) {
    1012           0 :                                         if (error) {
    1013           0 :                                                 efree(*error);
    1014           0 :                                                 *error = NULL;
    1015             :                                         }
    1016             :                                 }
    1017           5 :                                 return FAILURE;
    1018             :                         }
    1019             : 
    1020          16 :                         *archive = fd_ptr;
    1021          16 :                         fd = fd_ptr;
    1022          16 :                         PHAR_G(last_phar) = fd;
    1023          16 :                         PHAR_G(last_phar_name) = fd->fname;
    1024          16 :                         PHAR_G(last_phar_name_len) = fd->fname_len;
    1025          16 :                         PHAR_G(last_alias) = alias;
    1026          16 :                         PHAR_G(last_alias_len) = alias_len;
    1027             : 
    1028          16 :                         return SUCCESS;
    1029             :                 }
    1030             : 
    1031         110 :                 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_alias, alias, alias_len))) {
    1032           0 :                         goto alias_success;
    1033             :                 }
    1034             :         }
    1035             : 
    1036        1686 :         my_realpath = NULL;
    1037        1686 :         save = fname;
    1038        1686 :         save_len = fname_len;
    1039             : 
    1040        1686 :         if (fname && fname_len) {
    1041        3372 :                 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len))) {
    1042         775 :                         *archive = fd_ptr;
    1043         775 :                         fd = fd_ptr;
    1044             : 
    1045         775 :                         if (alias && alias_len) {
    1046          44 :                                 if (!fd->is_temporary_alias && (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len))) {
    1047           0 :                                         if (error) {
    1048           0 :                                                 spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname);
    1049             :                                         }
    1050           0 :                                         return FAILURE;
    1051             :                                 }
    1052             : 
    1053          88 :                                 if (fd->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), fd->alias, fd->alias_len))) {
    1054           1 :                                         zend_hash_str_del(&(PHAR_G(phar_alias_map)), fd->alias, fd->alias_len);
    1055             :                                 }
    1056             : 
    1057          44 :                                 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd);
    1058             :                         }
    1059             : 
    1060         775 :                         PHAR_G(last_phar) = fd;
    1061         775 :                         PHAR_G(last_phar_name) = fd->fname;
    1062         775 :                         PHAR_G(last_phar_name_len) = fd->fname_len;
    1063         775 :                         PHAR_G(last_alias) = fd->alias;
    1064         775 :                         PHAR_G(last_alias_len) = fd->alias_len;
    1065             : 
    1066         775 :                         return SUCCESS;
    1067             :                 }
    1068             : 
    1069        1036 :                 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) {
    1070           3 :                         *archive = fd_ptr;
    1071           3 :                         fd = fd_ptr;
    1072             : 
    1073             :                         /* this could be problematic - alias should never be different from manifest alias
    1074             :                            for cached phars */
    1075           3 :                         if (!fd->is_temporary_alias && alias && alias_len) {
    1076           0 :                                 if (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len)) {
    1077           0 :                                         if (error) {
    1078           0 :                                                 spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, fd_ptr->fname, fname);
    1079             :                                         }
    1080           0 :                                         return FAILURE;
    1081             :                                 }
    1082             :                         }
    1083             : 
    1084           3 :                         PHAR_G(last_phar) = fd;
    1085           3 :                         PHAR_G(last_phar_name) = fd->fname;
    1086           3 :                         PHAR_G(last_phar_name_len) = fd->fname_len;
    1087           3 :                         PHAR_G(last_alias) = fd->alias;
    1088           3 :                         PHAR_G(last_alias_len) = fd->alias_len;
    1089             : 
    1090           3 :                         return SUCCESS;
    1091             :                 }
    1092             : 
    1093        1816 :                 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), save, save_len))) {
    1094         130 :                         fd = *archive = fd_ptr;
    1095             : 
    1096         130 :                         PHAR_G(last_phar) = fd;
    1097         130 :                         PHAR_G(last_phar_name) = fd->fname;
    1098         130 :                         PHAR_G(last_phar_name_len) = fd->fname_len;
    1099         130 :                         PHAR_G(last_alias) = fd->alias;
    1100         130 :                         PHAR_G(last_alias_len) = fd->alias_len;
    1101             : 
    1102         130 :                         return SUCCESS;
    1103             :                 }
    1104             : 
    1105         900 :                 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_alias, save, save_len))) {
    1106           0 :                         fd = *archive = fd_ptr;
    1107             : 
    1108           0 :                         PHAR_G(last_phar) = fd;
    1109           0 :                         PHAR_G(last_phar_name) = fd->fname;
    1110           0 :                         PHAR_G(last_phar_name_len) = fd->fname_len;
    1111           0 :                         PHAR_G(last_alias) = fd->alias;
    1112           0 :                         PHAR_G(last_alias_len) = fd->alias_len;
    1113             : 
    1114           0 :                         return SUCCESS;
    1115             :                 }
    1116             : 
    1117             :                 /* not found, try converting \ to / */
    1118         778 :                 my_realpath = expand_filepath(fname, my_realpath);
    1119             : 
    1120         778 :                 if (my_realpath) {
    1121         778 :                         fname_len = strlen(my_realpath);
    1122         778 :                         fname = my_realpath;
    1123             :                 } else {
    1124           0 :                         return FAILURE;
    1125             :                 }
    1126             : #ifdef PHP_WIN32
    1127             :                 phar_unixify_path_separators(fname, fname_len);
    1128             : #endif
    1129             : 
    1130        1556 :                 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len))) {
    1131             : realpath_success:
    1132          15 :                         *archive = fd_ptr;
    1133          15 :                         fd = fd_ptr;
    1134             : 
    1135          15 :                         if (alias && alias_len) {
    1136           0 :                                 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd);
    1137             :                         }
    1138             : 
    1139          15 :                         efree(my_realpath);
    1140             : 
    1141          15 :                         PHAR_G(last_phar) = fd;
    1142          15 :                         PHAR_G(last_phar_name) = fd->fname;
    1143          15 :                         PHAR_G(last_phar_name_len) = fd->fname_len;
    1144          15 :                         PHAR_G(last_alias) = fd->alias;
    1145          15 :                         PHAR_G(last_alias_len) = fd->alias_len;
    1146             : 
    1147          15 :                         return SUCCESS;
    1148             :                 }
    1149             : 
    1150         885 :                 if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) {
    1151           0 :                         goto realpath_success;
    1152             :                 }
    1153             : 
    1154         763 :                 efree(my_realpath);
    1155             :         }
    1156             : 
    1157         763 :         return FAILURE;
    1158             : }
    1159             : /* }}} */
    1160             : 
    1161             : /**
    1162             :  * Determine which stream compression filter (if any) we need to read this file
    1163             :  */
    1164          49 : char * phar_compress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */
    1165             : {
    1166          49 :         switch (entry->flags & PHAR_ENT_COMPRESSION_MASK) {
    1167             :         case PHAR_ENT_COMPRESSED_GZ:
    1168          33 :                 return "zlib.deflate";
    1169             :         case PHAR_ENT_COMPRESSED_BZ2:
    1170          16 :                 return "bzip2.compress";
    1171             :         default:
    1172           0 :                 return return_unknown ? "unknown" : NULL;
    1173             :         }
    1174             : }
    1175             : /* }}} */
    1176             : 
    1177             : /**
    1178             :  * Determine which stream decompression filter (if any) we need to read this file
    1179             :  */
    1180          41 : char * phar_decompress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */
    1181             : {
    1182             :         php_uint32 flags;
    1183             : 
    1184          41 :         if (entry->is_modified) {
    1185           0 :                 flags = entry->old_flags;
    1186             :         } else {
    1187          41 :                 flags = entry->flags;
    1188             :         }
    1189             : 
    1190          41 :         switch (flags & PHAR_ENT_COMPRESSION_MASK) {
    1191             :                 case PHAR_ENT_COMPRESSED_GZ:
    1192          28 :                         return "zlib.inflate";
    1193             :                 case PHAR_ENT_COMPRESSED_BZ2:
    1194          13 :                         return "bzip2.decompress";
    1195             :                 default:
    1196           0 :                         return return_unknown ? "unknown" : NULL;
    1197             :         }
    1198             : }
    1199             : /* }}} */
    1200             : 
    1201             : /**
    1202             :  * retrieve information on a file contained within a phar, or null if it ain't there
    1203             :  */
    1204        8278 : phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error, int security) /* {{{ */
    1205             : {
    1206        8278 :         return phar_get_entry_info_dir(phar, path, path_len, 0, error, security);
    1207             : }
    1208             : /* }}} */
    1209             : /**
    1210             :  * retrieve information on a file or directory contained within a phar, or null if none found
    1211             :  * allow_dir is 0 for none, 1 for both empty directories in the phar and temp directories, and 2 for only
    1212             :  * valid pre-existing empty directory entries
    1213             :  */
    1214        9058 : phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error, int security) /* {{{ */
    1215             : {
    1216             :         const char *pcr_error;
    1217             :         phar_entry_info *entry;
    1218             :         int is_dir;
    1219             : 
    1220             : #ifdef PHP_WIN32
    1221             :         phar_unixify_path_separators(path, path_len);
    1222             : #endif
    1223             : 
    1224        9058 :         is_dir = (path_len && (path[path_len - 1] == '/')) ? 1 : 0;
    1225             : 
    1226        9058 :         if (error) {
    1227        1325 :                 *error = NULL;
    1228             :         }
    1229             : 
    1230        9058 :         if (security && path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", sizeof(".phar")-1)) {
    1231           1 :                 if (error) {
    1232           0 :                         spprintf(error, 4096, "phar error: cannot directly access magic \".phar\" directory or files within it");
    1233             :                 }
    1234           1 :                 return NULL;
    1235             :         }
    1236             : 
    1237        9057 :         if (!path_len && !dir) {
    1238           2 :                 if (error) {
    1239           2 :                         spprintf(error, 4096, "phar error: invalid path \"%s\" must not be empty", path);
    1240             :                 }
    1241           2 :                 return NULL;
    1242             :         }
    1243             : 
    1244        9055 :         if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
    1245           8 :                 if (error) {
    1246           0 :                         spprintf(error, 4096, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
    1247             :                 }
    1248           8 :                 return NULL;
    1249             :         }
    1250             : 
    1251        9047 :         if (!phar->manifest.u.flags) {
    1252           0 :                 return NULL;
    1253             :         }
    1254             : 
    1255        9047 :         if (is_dir) {
    1256           5 :                 if (!path_len || path_len == 1) {
    1257           0 :                         return NULL;
    1258             :                 }
    1259           5 :                 path_len--;
    1260             :         }
    1261             : 
    1262       18094 :         if (NULL != (entry = zend_hash_str_find_ptr(&phar->manifest, path, path_len))) {
    1263        5446 :                 if (entry->is_deleted) {
    1264             :                         /* entry is deleted, but has not been flushed to disk yet */
    1265           0 :                         return NULL;
    1266             :                 }
    1267        5446 :                 if (entry->is_dir && !dir) {
    1268           1 :                         if (error) {
    1269           1 :                                 spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
    1270             :                         }
    1271           1 :                         return NULL;
    1272             :                 }
    1273        5445 :                 if (!entry->is_dir && dir == 2) {
    1274             :                         /* user requested a directory, we must return one */
    1275           3 :                         if (error) {
    1276           3 :                                 spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
    1277             :                         }
    1278           3 :                         return NULL;
    1279             :                 }
    1280        5442 :                 return entry;
    1281             :         }
    1282             : 
    1283        3601 :         if (dir) {
    1284          53 :                 if (zend_hash_str_exists(&phar->virtual_dirs, path, path_len)) {
    1285             :                         /* a file or directory exists in a sub-directory of this path */
    1286          20 :                         entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info));
    1287             :                         /* this next line tells PharFileInfo->__destruct() to efree the filename */
    1288          20 :                         entry->is_temp_dir = entry->is_dir = 1;
    1289          20 :                         entry->filename = (char *) estrndup(path, path_len + 1);
    1290          20 :                         entry->filename_len = path_len;
    1291          20 :                         entry->phar = phar;
    1292          20 :                         return entry;
    1293             :                 }
    1294             :         }
    1295             : 
    1296        3581 :         if (phar->mounted_dirs.u.flags && zend_hash_num_elements(&phar->mounted_dirs)) {
    1297             :                 zend_string *str_key;
    1298             : 
    1299           6 :                 ZEND_HASH_FOREACH_STR_KEY(&phar->mounted_dirs, str_key) {
    1300           3 :                         if ((int)str_key->len >= path_len || strncmp(str_key->val, path, str_key->len)) {
    1301           0 :                                 continue;
    1302             :                         } else {
    1303             :                                 char *test;
    1304             :                                 int test_len;
    1305             :                                 php_stream_statbuf ssb;
    1306             : 
    1307           6 :                                 if (NULL == (entry = zend_hash_find_ptr(&phar->manifest, str_key))) {
    1308           0 :                                         if (error) {
    1309           0 :                                                 spprintf(error, 4096, "phar internal error: mounted path \"%s\" could not be retrieved from manifest", str_key->val);
    1310             :                                         }
    1311           0 :                                         return NULL;
    1312             :                                 }
    1313             : 
    1314           3 :                                 if (!entry->tmp || !entry->is_mounted) {
    1315           0 :                                         if (error) {
    1316           0 :                                                 spprintf(error, 4096, "phar internal error: mounted path \"%s\" is not properly initialized as a mounted path", str_key->val);
    1317             :                                         }
    1318           0 :                                         return NULL;
    1319             :                                 }
    1320             : 
    1321           3 :                                 test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, path + str_key->len);
    1322             : 
    1323           3 :                                 if (SUCCESS != php_stream_stat_path(test, &ssb)) {
    1324           0 :                                         efree(test);
    1325           0 :                                         return NULL;
    1326             :                                 }
    1327             : 
    1328           3 :                                 if (ssb.sb.st_mode & S_IFDIR && !dir) {
    1329           1 :                                         efree(test);
    1330           1 :                                         if (error) {
    1331           1 :                                                 spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
    1332             :                                         }
    1333           1 :                                         return NULL;
    1334             :                                 }
    1335             : 
    1336           2 :                                 if ((ssb.sb.st_mode & S_IFDIR) == 0 && dir) {
    1337           0 :                                         efree(test);
    1338             :                                         /* user requested a directory, we must return one */
    1339           0 :                                         if (error) {
    1340           0 :                                                 spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
    1341             :                                         }
    1342           0 :                                         return NULL;
    1343             :                                 }
    1344             : 
    1345             :                                 /* mount the file just in time */
    1346           2 :                                 if (SUCCESS != phar_mount_entry(phar, test, test_len, path, path_len)) {
    1347           0 :                                         efree(test);
    1348           0 :                                         if (error) {
    1349           0 :                                                 spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be mounted", path, test);
    1350             :                                         }
    1351           0 :                                         return NULL;
    1352             :                                 }
    1353             : 
    1354           2 :                                 efree(test);
    1355             : 
    1356           4 :                                 if (NULL == (entry = zend_hash_str_find_ptr(&phar->manifest, path, path_len))) {
    1357           0 :                                         if (error) {
    1358           0 :                                                 spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be retrieved after being mounted", path, test);
    1359             :                                         }
    1360           0 :                                         return NULL;
    1361             :                                 }
    1362           2 :                                 return entry;
    1363             :                         }
    1364             :                 } ZEND_HASH_FOREACH_END();
    1365             :         }
    1366             : 
    1367        3578 :         return NULL;
    1368             : }
    1369             : /* }}} */
    1370             : 
    1371             : static const char hexChars[] = "0123456789ABCDEF";
    1372             : 
    1373        5112 : static int phar_hex_str(const char *digest, size_t digest_len, char **signature) /* {{{ */
    1374             : {
    1375        5112 :         int pos = -1;
    1376        5112 :         size_t len = 0;
    1377             : 
    1378        5112 :         *signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
    1379             : 
    1380      108380 :         for (; len < digest_len; ++len) {
    1381      103268 :                 (*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] >> 4];
    1382      103268 :                 (*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] & 0x0F];
    1383             :         }
    1384        5112 :         (*signature)[++pos] = '\0';
    1385        5112 :         return pos;
    1386             : }
    1387             : /* }}} */
    1388             : 
    1389             : #ifndef PHAR_HAVE_OPENSSL
    1390             : static int phar_call_openssl_signverify(int is_sign, php_stream *fp, zend_off_t end, char *key, int key_len, char **signature, int *signature_len) /* {{{ */
    1391             : {
    1392             :         zend_fcall_info fci;
    1393             :         zend_fcall_info_cache fcc;
    1394             :         zval retval, zp[3], openssl;
    1395             :         zend_string *str;
    1396             : 
    1397             :         ZVAL_STRINGL(&openssl, is_sign ? "openssl_sign" : "openssl_verify", is_sign ? sizeof("openssl_sign")-1 : sizeof("openssl_verify")-1);
    1398             :         ZVAL_STRINGL(&zp[1], *signature, *signature_len);
    1399             :         ZVAL_STRINGL(&zp[2], key, key_len);
    1400             :         php_stream_rewind(fp);
    1401             :         str = php_stream_copy_to_mem(fp, (size_t) end, 0);
    1402             :         if (str) {
    1403             :                 ZVAL_STR(&zp[0], str);
    1404             :         } else {
    1405             :                 ZVAL_EMPTY_STRING(&zp[0]);
    1406             :         }
    1407             : 
    1408             :         if (end != Z_STRLEN(zp[0])) {
    1409             :                 zval_dtor(&zp[0]);
    1410             :                 zval_dtor(&zp[1]);
    1411             :                 zval_dtor(&zp[2]);
    1412             :                 zval_dtor(&openssl);
    1413             :                 return FAILURE;
    1414             :         }
    1415             : 
    1416             :         if (FAILURE == zend_fcall_info_init(&openssl, 0, &fci, &fcc, NULL, NULL)) {
    1417             :                 zval_dtor(&zp[0]);
    1418             :                 zval_dtor(&zp[1]);
    1419             :                 zval_dtor(&zp[2]);
    1420             :                 zval_dtor(&openssl);
    1421             :                 return FAILURE;
    1422             :         }
    1423             : 
    1424             :         fci.param_count = 3;
    1425             :         fci.params = zp;
    1426             :         Z_ADDREF(zp[0]);
    1427             :         if (is_sign) {
    1428             :                 ZVAL_NEW_REF(&zp[1], &zp[1]);
    1429             :         } else {
    1430             :                 Z_ADDREF(zp[1]);
    1431             :         }
    1432             :         Z_ADDREF(zp[2]);
    1433             : 
    1434             :         fci.retval = &retval;
    1435             : 
    1436             :         if (FAILURE == zend_call_function(&fci, &fcc)) {
    1437             :                 zval_dtor(&zp[0]);
    1438             :                 zval_dtor(&zp[1]);
    1439             :                 zval_dtor(&zp[2]);
    1440             :                 zval_dtor(&openssl);
    1441             :                 return FAILURE;
    1442             :         }
    1443             : 
    1444             :         zval_dtor(&openssl);
    1445             :         Z_DELREF(zp[0]);
    1446             : 
    1447             :         if (is_sign) {
    1448             :                 ZVAL_UNREF(&zp[1]);
    1449             :         } else {
    1450             :                 Z_DELREF(zp[1]);
    1451             :         }
    1452             :         Z_DELREF(zp[2]);
    1453             : 
    1454             :         zval_dtor(&zp[0]);
    1455             :         zval_dtor(&zp[2]);
    1456             : 
    1457             :         switch (Z_TYPE(retval)) {
    1458             :                 default:
    1459             :                 case IS_LONG:
    1460             :                         zval_dtor(&zp[1]);
    1461             :                         if (1 == Z_LVAL(retval)) {
    1462             :                                 return SUCCESS;
    1463             :                         }
    1464             :                         return FAILURE;
    1465             :                 case IS_TRUE:
    1466             :                         *signature = estrndup(Z_STRVAL(zp[1]), Z_STRLEN(zp[1]));
    1467             :                         *signature_len = Z_STRLEN(zp[1]);
    1468             :                         zval_dtor(&zp[1]);
    1469             :                         return SUCCESS;
    1470             :                 case IS_FALSE:
    1471             :                         zval_dtor(&zp[1]);
    1472             :                         return FAILURE;
    1473             :         }
    1474             : }
    1475             : /* }}} */
    1476             : #endif /* #ifndef PHAR_HAVE_OPENSSL */
    1477             : 
    1478         235 : int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error) /* {{{ */
    1479             : {
    1480             :         int read_size, len;
    1481             :         zend_off_t read_len;
    1482             :         unsigned char buf[1024];
    1483             : 
    1484         235 :         php_stream_rewind(fp);
    1485             : 
    1486         235 :         switch (sig_type) {
    1487             :                 case PHAR_SIG_OPENSSL: {
    1488             : #ifdef PHAR_HAVE_OPENSSL
    1489             :                         BIO *in;
    1490             :                         EVP_PKEY *key;
    1491           3 :                         EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
    1492             :                         EVP_MD_CTX md_ctx;
    1493             : #else
    1494             :                         int tempsig;
    1495             : #endif
    1496           3 :                         zend_string *pubkey = NULL;
    1497             :                         char *pfile;
    1498             :                         php_stream *pfp;
    1499             : #ifndef PHAR_HAVE_OPENSSL
    1500             :                         if (!zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) {
    1501             :                                 if (error) {
    1502             :                                         spprintf(error, 0, "openssl not loaded");
    1503             :                                 }
    1504             :                                 return FAILURE;
    1505             :                         }
    1506             : #endif
    1507             :                         /* use __FILE__ . '.pubkey' for public key file */
    1508           3 :                         spprintf(&pfile, 0, "%s.pubkey", fname);
    1509           3 :                         pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
    1510           3 :                         efree(pfile);
    1511             : 
    1512           3 :                         if (!pfp || !(pubkey = php_stream_copy_to_mem(pfp, PHP_STREAM_COPY_ALL, 0)) || !pubkey->len) {
    1513           0 :                                 if (pfp) {
    1514           0 :                                         php_stream_close(pfp);
    1515             :                                 }
    1516           0 :                                 if (error) {
    1517           0 :                                         spprintf(error, 0, "openssl public key could not be read");
    1518             :                                 }
    1519           0 :                                 return FAILURE;
    1520             :                         }
    1521             : 
    1522           3 :                         php_stream_close(pfp);
    1523             : #ifndef PHAR_HAVE_OPENSSL
    1524             :                         tempsig = sig_len;
    1525             : 
    1526             :                         if (FAILURE == phar_call_openssl_signverify(0, fp, end_of_phar, pubkey ? pubkey->val : NULL, pubkey ? pubkey->len : 0, &sig, &tempsig)) {
    1527             :                                 if (pubkey) {
    1528             :                                         zend_string_release(pubkey);
    1529             :                                 }
    1530             : 
    1531             :                                 if (error) {
    1532             :                                         spprintf(error, 0, "openssl signature could not be verified");
    1533             :                                 }
    1534             : 
    1535             :                                 return FAILURE;
    1536             :                         }
    1537             : 
    1538             :                         if (pubkey) {
    1539             :                                 zend_string_release(pubkey);
    1540             :                         }
    1541             : 
    1542             :                         sig_len = tempsig;
    1543             : #else
    1544           3 :                         in = BIO_new_mem_buf(pubkey ? pubkey->val : NULL, pubkey ? pubkey->len : 0);
    1545             : 
    1546           3 :                         if (NULL == in) {
    1547             :                                 zend_string_release(pubkey);
    1548           0 :                                 if (error) {
    1549           0 :                                         spprintf(error, 0, "openssl signature could not be processed");
    1550             :                                 }
    1551           0 :                                 return FAILURE;
    1552             :                         }
    1553             : 
    1554           3 :                         key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
    1555           3 :                         BIO_free(in);
    1556             :                         zend_string_release(pubkey);
    1557             : 
    1558           3 :                         if (NULL == key) {
    1559           0 :                                 if (error) {
    1560           0 :                                         spprintf(error, 0, "openssl signature could not be processed");
    1561             :                                 }
    1562           0 :                                 return FAILURE;
    1563             :                         }
    1564             : 
    1565           3 :                         EVP_VerifyInit(&md_ctx, mdtype);
    1566           3 :                         read_len = end_of_phar;
    1567             : 
    1568           3 :                         if (read_len > sizeof(buf)) {
    1569           2 :                                 read_size = sizeof(buf);
    1570             :                         } else {
    1571           1 :                                 read_size = (int)read_len;
    1572             :                         }
    1573             : 
    1574           3 :                         php_stream_seek(fp, 0, SEEK_SET);
    1575             : 
    1576          22 :                         while (read_size && (len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
    1577          16 :                                 EVP_VerifyUpdate (&md_ctx, buf, len);
    1578          16 :                                 read_len -= (zend_off_t)len;
    1579             : 
    1580          16 :                                 if (read_len < read_size) {
    1581           5 :                                         read_size = (int)read_len;
    1582             :                                 }
    1583             :                         }
    1584             : 
    1585           3 :                         if (EVP_VerifyFinal(&md_ctx, (unsigned char *)sig, sig_len, key) != 1) {
    1586             :                                 /* 1: signature verified, 0: signature does not match, -1: failed signature operation */
    1587           0 :                                 EVP_MD_CTX_cleanup(&md_ctx);
    1588             : 
    1589           0 :                                 if (error) {
    1590           0 :                                         spprintf(error, 0, "broken openssl signature");
    1591             :                                 }
    1592             : 
    1593           0 :                                 return FAILURE;
    1594             :                         }
    1595             : 
    1596           3 :                         EVP_MD_CTX_cleanup(&md_ctx);
    1597             : #endif
    1598             : 
    1599           3 :                         *signature_len = phar_hex_str((const char*)sig, sig_len, signature);
    1600             :                 }
    1601           3 :                 break;
    1602             : #ifdef PHAR_HASH_OK
    1603             :                 case PHAR_SIG_SHA512: {
    1604             :                         unsigned char digest[64];
    1605             :                         PHP_SHA512_CTX context;
    1606             : 
    1607           2 :                         PHP_SHA512Init(&context);
    1608           2 :                         read_len = end_of_phar;
    1609             : 
    1610           2 :                         if (read_len > sizeof(buf)) {
    1611           0 :                                 read_size = sizeof(buf);
    1612             :                         } else {
    1613           2 :                                 read_size = (int)read_len;
    1614             :                         }
    1615             : 
    1616           6 :                         while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
    1617           2 :                                 PHP_SHA512Update(&context, buf, len);
    1618           2 :                                 read_len -= (zend_off_t)len;
    1619           2 :                                 if (read_len < read_size) {
    1620           2 :                                         read_size = (int)read_len;
    1621             :                                 }
    1622             :                         }
    1623             : 
    1624           2 :                         PHP_SHA512Final(digest, &context);
    1625             : 
    1626           2 :                         if (memcmp(digest, sig, sizeof(digest))) {
    1627           0 :                                 if (error) {
    1628           0 :                                         spprintf(error, 0, "broken signature");
    1629             :                                 }
    1630           0 :                                 return FAILURE;
    1631             :                         }
    1632             : 
    1633           2 :                         *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
    1634           2 :                         break;
    1635             :                 }
    1636             :                 case PHAR_SIG_SHA256: {
    1637             :                         unsigned char digest[32];
    1638             :                         PHP_SHA256_CTX context;
    1639             : 
    1640           2 :                         PHP_SHA256Init(&context);
    1641           2 :                         read_len = end_of_phar;
    1642             : 
    1643           2 :                         if (read_len > sizeof(buf)) {
    1644           0 :                                 read_size = sizeof(buf);
    1645             :                         } else {
    1646           2 :                                 read_size = (int)read_len;
    1647             :                         }
    1648             : 
    1649           6 :                         while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
    1650           2 :                                 PHP_SHA256Update(&context, buf, len);
    1651           2 :                                 read_len -= (zend_off_t)len;
    1652           2 :                                 if (read_len < read_size) {
    1653           2 :                                         read_size = (int)read_len;
    1654             :                                 }
    1655             :                         }
    1656             : 
    1657           2 :                         PHP_SHA256Final(digest, &context);
    1658             : 
    1659           2 :                         if (memcmp(digest, sig, sizeof(digest))) {
    1660           0 :                                 if (error) {
    1661           0 :                                         spprintf(error, 0, "broken signature");
    1662             :                                 }
    1663           0 :                                 return FAILURE;
    1664             :                         }
    1665             : 
    1666           2 :                         *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
    1667           2 :                         break;
    1668             :                 }
    1669             : #else
    1670             :                 case PHAR_SIG_SHA512:
    1671             :                 case PHAR_SIG_SHA256:
    1672             :                         if (error) {
    1673             :                                 spprintf(error, 0, "unsupported signature");
    1674             :                         }
    1675             :                         return FAILURE;
    1676             : #endif
    1677             :                 case PHAR_SIG_SHA1: {
    1678             :                         unsigned char digest[20];
    1679             :                         PHP_SHA1_CTX  context;
    1680             : 
    1681         226 :                         PHP_SHA1Init(&context);
    1682         226 :                         read_len = end_of_phar;
    1683             : 
    1684         226 :                         if (read_len > sizeof(buf)) {
    1685          98 :                                 read_size = sizeof(buf);
    1686             :                         } else {
    1687         128 :                                 read_size = (int)read_len;
    1688             :                         }
    1689             : 
    1690        1673 :                         while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
    1691        1221 :                                 PHP_SHA1Update(&context, buf, len);
    1692        1221 :                                 read_len -= (zend_off_t)len;
    1693        1221 :                                 if (read_len < read_size) {
    1694         291 :                                         read_size = (int)read_len;
    1695             :                                 }
    1696             :                         }
    1697             : 
    1698         226 :                         PHP_SHA1Final(digest, &context);
    1699             : 
    1700         226 :                         if (memcmp(digest, sig, sizeof(digest))) {
    1701           0 :                                 if (error) {
    1702           0 :                                         spprintf(error, 0, "broken signature");
    1703             :                                 }
    1704           0 :                                 return FAILURE;
    1705             :                         }
    1706             : 
    1707         226 :                         *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
    1708         226 :                         break;
    1709             :                 }
    1710             :                 case PHAR_SIG_MD5: {
    1711             :                         unsigned char digest[16];
    1712             :                         PHP_MD5_CTX   context;
    1713             : 
    1714           2 :                         PHP_MD5Init(&context);
    1715           2 :                         read_len = end_of_phar;
    1716             : 
    1717           2 :                         if (read_len > sizeof(buf)) {
    1718           0 :                                 read_size = sizeof(buf);
    1719             :                         } else {
    1720           2 :                                 read_size = (int)read_len;
    1721             :                         }
    1722             : 
    1723           6 :                         while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) {
    1724           2 :                                 PHP_MD5Update(&context, buf, len);
    1725           2 :                                 read_len -= (zend_off_t)len;
    1726           2 :                                 if (read_len < read_size) {
    1727           2 :                                         read_size = (int)read_len;
    1728             :                                 }
    1729             :                         }
    1730             : 
    1731           2 :                         PHP_MD5Final(digest, &context);
    1732             : 
    1733           2 :                         if (memcmp(digest, sig, sizeof(digest))) {
    1734           0 :                                 if (error) {
    1735           0 :                                         spprintf(error, 0, "broken signature");
    1736             :                                 }
    1737           0 :                                 return FAILURE;
    1738             :                         }
    1739             : 
    1740           2 :                         *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
    1741           2 :                         break;
    1742             :                 }
    1743             :                 default:
    1744           0 :                         if (error) {
    1745           0 :                                 spprintf(error, 0, "broken or unsupported signature");
    1746             :                         }
    1747           0 :                         return FAILURE;
    1748             :         }
    1749         235 :         return SUCCESS;
    1750             : }
    1751             : /* }}} */
    1752             : 
    1753        4877 : int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, int *signature_length, char **error) /* {{{ */
    1754             : {
    1755             :         unsigned char buf[1024];
    1756             :         int sig_len;
    1757             : 
    1758        4877 :         php_stream_rewind(fp);
    1759             : 
    1760        4877 :         if (phar->signature) {
    1761         272 :                 efree(phar->signature);
    1762         272 :                 phar->signature = NULL;
    1763             :         }
    1764             : 
    1765        4877 :         switch(phar->sig_flags) {
    1766             : #ifdef PHAR_HASH_OK
    1767             :                 case PHAR_SIG_SHA512: {
    1768             :                         unsigned char digest[64];
    1769             :                         PHP_SHA512_CTX context;
    1770             : 
    1771           3 :                         PHP_SHA512Init(&context);
    1772             : 
    1773          16 :                         while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
    1774          10 :                                 PHP_SHA512Update(&context, buf, sig_len);
    1775             :                         }
    1776             : 
    1777           3 :                         PHP_SHA512Final(digest, &context);
    1778           3 :                         *signature = estrndup((char *) digest, 64);
    1779           3 :                         *signature_length = 64;
    1780           3 :                         break;
    1781             :                 }
    1782             :                 case PHAR_SIG_SHA256: {
    1783             :                         unsigned char digest[32];
    1784             :                         PHP_SHA256_CTX  context;
    1785             : 
    1786           3 :                         PHP_SHA256Init(&context);
    1787             : 
    1788          16 :                         while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
    1789          10 :                                 PHP_SHA256Update(&context, buf, sig_len);
    1790             :                         }
    1791             : 
    1792           3 :                         PHP_SHA256Final(digest, &context);
    1793           3 :                         *signature = estrndup((char *) digest, 32);
    1794           3 :                         *signature_length = 32;
    1795           3 :                         break;
    1796             :                 }
    1797             : #else
    1798             :                 case PHAR_SIG_SHA512:
    1799             :                 case PHAR_SIG_SHA256:
    1800             :                         if (error) {
    1801             :                                 spprintf(error, 0, "unable to write to phar \"%s\" with requested hash type", phar->fname);
    1802             :                         }
    1803             : 
    1804             :                         return FAILURE;
    1805             : #endif
    1806             :                 case PHAR_SIG_OPENSSL: {
    1807             :                         int siglen;
    1808             :                         unsigned char *sigbuf;
    1809             : #ifdef PHAR_HAVE_OPENSSL
    1810             :                         BIO *in;
    1811             :                         EVP_PKEY *key;
    1812             :                         EVP_MD_CTX *md_ctx;
    1813             : 
    1814           3 :                         in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len));
    1815             : 
    1816           3 :                         if (in == NULL) {
    1817           0 :                                 if (error) {
    1818           0 :                                         spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname);
    1819             :                                 }
    1820           0 :                                 return FAILURE;
    1821             :                         }
    1822             : 
    1823           3 :                         key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
    1824           3 :                         BIO_free(in);
    1825             : 
    1826           3 :                         if (!key) {
    1827           0 :                                 if (error) {
    1828           0 :                                         spprintf(error, 0, "unable to process private key");
    1829             :                                 }
    1830           0 :                                 return FAILURE;
    1831             :                         }
    1832             : 
    1833           3 :                         md_ctx = EVP_MD_CTX_create();
    1834             : 
    1835           3 :                         siglen = EVP_PKEY_size(key);
    1836           3 :                         sigbuf = emalloc(siglen + 1);
    1837             : 
    1838           3 :                         if (!EVP_SignInit(md_ctx, EVP_sha1())) {
    1839           0 :                                 efree(sigbuf);
    1840           0 :                                 if (error) {
    1841           0 :                                         spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname);
    1842             :                                 }
    1843           0 :                                 return FAILURE;
    1844             :                         }
    1845             : 
    1846          16 :                         while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
    1847          10 :                                 if (!EVP_SignUpdate(md_ctx, buf, sig_len)) {
    1848           0 :                                         efree(sigbuf);
    1849           0 :                                         if (error) {
    1850           0 :                                                 spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", phar->fname);
    1851             :                                         }
    1852           0 :                                         return FAILURE;
    1853             :                                 }
    1854             :                         }
    1855             : 
    1856           3 :                         if (!EVP_SignFinal (md_ctx, sigbuf,(unsigned int *)&siglen, key)) {
    1857           0 :                                 efree(sigbuf);
    1858           0 :                                 if (error) {
    1859           0 :                                         spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
    1860             :                                 }
    1861           0 :                                 return FAILURE;
    1862             :                         }
    1863             : 
    1864           3 :                         sigbuf[siglen] = '\0';
    1865           3 :                         EVP_MD_CTX_destroy(md_ctx);
    1866             : #else
    1867             :                         sigbuf = NULL;
    1868             :                         siglen = 0;
    1869             :                         php_stream_seek(fp, 0, SEEK_END);
    1870             : 
    1871             :                         if (FAILURE == phar_call_openssl_signverify(1, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen)) {
    1872             :                                 if (error) {
    1873             :                                         spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
    1874             :                                 }
    1875             :                                 return FAILURE;
    1876             :                         }
    1877             : #endif
    1878           3 :                         *signature = (char *) sigbuf;
    1879           3 :                         *signature_length = siglen;
    1880             :                 }
    1881           3 :                 break;
    1882             :                 default:
    1883         170 :                         phar->sig_flags = PHAR_SIG_SHA1;
    1884             :                 case PHAR_SIG_SHA1: {
    1885             :                         unsigned char digest[20];
    1886             :                         PHP_SHA1_CTX  context;
    1887             : 
    1888        4863 :                         PHP_SHA1Init(&context);
    1889             : 
    1890       42602 :                         while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
    1891       32876 :                                 PHP_SHA1Update(&context, buf, sig_len);
    1892             :                         }
    1893             : 
    1894        4863 :                         PHP_SHA1Final(digest, &context);
    1895        4863 :                         *signature = estrndup((char *) digest, 20);
    1896        4863 :                         *signature_length = 20;
    1897        4863 :                         break;
    1898             :                 }
    1899             :                 case PHAR_SIG_MD5: {
    1900             :                         unsigned char digest[16];
    1901             :                         PHP_MD5_CTX   context;
    1902             : 
    1903           5 :                         PHP_MD5Init(&context);
    1904             : 
    1905          22 :                         while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
    1906          12 :                                 PHP_MD5Update(&context, buf, sig_len);
    1907             :                         }
    1908             : 
    1909           5 :                         PHP_MD5Final(digest, &context);
    1910           5 :                         *signature = estrndup((char *) digest, 16);
    1911           5 :                         *signature_length = 16;
    1912             :                         break;
    1913             :                 }
    1914             :         }
    1915             : 
    1916        4877 :         phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature);
    1917        4877 :         return SUCCESS;
    1918             : }
    1919             : /* }}} */
    1920             : 
    1921       21174 : void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len) /* {{{ */
    1922             : {
    1923             :         const char *s;
    1924             : 
    1925      119980 :         while ((s = zend_memrchr(filename, '/', filename_len))) {
    1926       35272 :                 filename_len = s - filename;
    1927       35272 :                 if (NULL == zend_hash_str_add_empty_element(&phar->virtual_dirs, filename, filename_len)) {
    1928        7043 :                         break;
    1929             :                 }
    1930             :         }
    1931       21174 : }
    1932             : /* }}} */
    1933             : 
    1934           4 : static int phar_update_cached_entry(zval *data, void *argument) /* {{{ */
    1935             : {
    1936           4 :         phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(data);
    1937             : 
    1938           4 :         entry->phar = (phar_archive_data *)argument;
    1939             : 
    1940           4 :         if (entry->link) {
    1941           0 :                 entry->link = estrdup(entry->link);
    1942             :         }
    1943             : 
    1944           4 :         if (entry->tmp) {
    1945           0 :                 entry->tmp = estrdup(entry->tmp);
    1946             :         }
    1947             : 
    1948           4 :         entry->metadata_str.s = NULL;
    1949           4 :         entry->filename = estrndup(entry->filename, entry->filename_len);
    1950           4 :         entry->is_persistent = 0;
    1951             : 
    1952           8 :         if (Z_TYPE(entry->metadata) != IS_UNDEF) {
    1953           3 :                 if (entry->metadata_len) {
    1954           3 :                         char *buf = estrndup((char *) Z_PTR(entry->metadata), entry->metadata_len);
    1955             :                         /* assume success, we would have failed before */
    1956           3 :                         phar_parse_metadata((char **) &buf, &entry->metadata, entry->metadata_len);
    1957           3 :                         efree(buf);
    1958             :                 } else {
    1959           0 :                         zval_copy_ctor(&entry->metadata);
    1960           0 :                         entry->metadata_str.s = NULL;
    1961             :                 }
    1962             :         }
    1963           4 :         return ZEND_HASH_APPLY_KEEP;
    1964             : }
    1965             : /* }}} */
    1966             : 
    1967           4 : static void phar_manifest_copy_ctor(zval *zv) /* {{{ */
    1968             : {
    1969           4 :         phar_entry_info *info = emalloc(sizeof(phar_entry_info));
    1970           4 :         memcpy(info, Z_PTR_P(zv), sizeof(phar_entry_info));
    1971           4 :         Z_PTR_P(zv) = info;
    1972           4 : }
    1973             : /* }}} */
    1974             : 
    1975           3 : static void phar_copy_cached_phar(phar_archive_data **pphar) /* {{{ */
    1976             : {
    1977             :         phar_archive_data *phar;
    1978             :         HashTable newmanifest;
    1979             :         char *fname;
    1980             :         phar_archive_object *objphar;
    1981             : 
    1982           3 :         phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
    1983           3 :         *phar = **pphar;
    1984           3 :         phar->is_persistent = 0;
    1985           3 :         fname = phar->fname;
    1986           3 :         phar->fname = estrndup(phar->fname, phar->fname_len);
    1987           3 :         phar->ext = phar->fname + (phar->ext - fname);
    1988             : 
    1989           3 :         if (phar->alias) {
    1990           3 :                 phar->alias = estrndup(phar->alias, phar->alias_len);
    1991             :         }
    1992             : 
    1993           3 :         if (phar->signature) {
    1994           3 :                 phar->signature = estrdup(phar->signature);
    1995             :         }
    1996             : 
    1997           6 :         if (Z_TYPE(phar->metadata) != IS_UNDEF) {
    1998             :                 /* assume success, we would have failed before */
    1999           3 :                 if (phar->metadata_len) {
    2000           3 :                         char *buf = estrndup((char *) Z_PTR(phar->metadata), phar->metadata_len);
    2001           3 :                         phar_parse_metadata(&buf, &phar->metadata, phar->metadata_len);
    2002           3 :                         efree(buf);
    2003             :                 } else {
    2004           0 :                         zval_copy_ctor(&phar->metadata);
    2005             :                 }
    2006             :         }
    2007             : 
    2008           3 :         zend_hash_init(&newmanifest, sizeof(phar_entry_info),
    2009             :                 zend_get_hash_value, destroy_phar_manifest_entry, 0);
    2010           3 :         zend_hash_copy(&newmanifest, &(*pphar)->manifest, phar_manifest_copy_ctor);
    2011           3 :         zend_hash_apply_with_argument(&newmanifest, phar_update_cached_entry, (void *)phar);
    2012           3 :         phar->manifest = newmanifest;
    2013           3 :         zend_hash_init(&phar->mounted_dirs, sizeof(char *),
    2014             :                 zend_get_hash_value, NULL, 0);
    2015           3 :         zend_hash_init(&phar->virtual_dirs, sizeof(char *),
    2016             :                 zend_get_hash_value, NULL, 0);
    2017           3 :         zend_hash_copy(&phar->virtual_dirs, &(*pphar)->virtual_dirs, NULL);
    2018           3 :         *pphar = phar;
    2019             : 
    2020             :         /* now, scan the list of persistent Phar objects referencing this phar and update the pointers */
    2021           7 :         ZEND_HASH_FOREACH_PTR(&PHAR_G(phar_persist_map), objphar) {
    2022           2 :                 if (objphar->archive->fname_len == phar->fname_len && !memcmp(objphar->archive->fname, phar->fname, phar->fname_len)) {
    2023           2 :                         objphar->archive = phar;
    2024             :                 }
    2025             :         } ZEND_HASH_FOREACH_END();
    2026           3 : }
    2027             : /* }}} */
    2028             : 
    2029           3 : int phar_copy_on_write(phar_archive_data **pphar) /* {{{ */
    2030             : {
    2031             :         zval zv, *pzv;
    2032             :         phar_archive_data *newpphar;
    2033             : 
    2034           3 :         ZVAL_PTR(&zv, *pphar);
    2035           3 :         if (NULL == (pzv = zend_hash_str_add(&(PHAR_G(phar_fname_map)), (*pphar)->fname, (*pphar)->fname_len, &zv))) {
    2036           0 :                 return FAILURE;
    2037             :         }
    2038             : 
    2039           3 :         phar_copy_cached_phar((phar_archive_data **)&Z_PTR_P(pzv));
    2040           3 :         newpphar = Z_PTR_P(pzv);
    2041             :         /* invalidate phar cache */
    2042           3 :         PHAR_G(last_phar) = NULL;
    2043           3 :         PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
    2044             : 
    2045           6 :         if (newpphar->alias_len && NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), newpphar->alias, newpphar->alias_len, newpphar)) {
    2046           0 :                 zend_hash_str_del(&(PHAR_G(phar_fname_map)), (*pphar)->fname, (*pphar)->fname_len);
    2047           0 :                 return FAILURE;
    2048             :         }
    2049             : 
    2050           3 :         *pphar = newpphar;
    2051           3 :         return SUCCESS;
    2052             : }
    2053             : /* }}} */
    2054             : 
    2055             : /*
    2056             :  * Local variables:
    2057             :  * tab-width: 4
    2058             :  * c-basic-offset: 4
    2059             :  * End:
    2060             :  * vim600: noet sw=4 ts=4 fdm=marker
    2061             :  * vim<600: noet sw=4 ts=4
    2062             :  */

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:59:01 +0000 (18 hours ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.