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