root/ext/phar/util.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. phar_get_link_location
  2. phar_get_link_source
  3. phar_get_efp
  4. phar_seek_efp
  5. phar_mount_entry
  6. phar_find_in_include_path
  7. phar_get_entry_data
  8. phar_get_or_create_entry_data
  9. phar_open_archive_fp
  10. phar_copy_entry_fp
  11. phar_open_entry_fp
  12. phar_create_writeable_entry
  13. phar_separate_entry_fp
  14. phar_open_jit
  15. phar_resolve_alias
  16. phar_free_alias
  17. phar_get_archive
  18. phar_compress_filter
  19. phar_decompress_filter
  20. phar_get_entry_info
  21. phar_get_entry_info_dir
  22. phar_hex_str
  23. phar_call_openssl_signverify
  24. phar_verify_signature
  25. phar_create_signature
  26. phar_add_virtual_dirs
  27. phar_update_cached_entry
  28. phar_manifest_copy_ctor
  29. phar_copy_cached_phar
  30. phar_copy_on_write

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

/* [<][>][^][v][top][bottom][index][help] */