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