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