This source file includes following definitions.
- ZEND_DECLARE_MODULE_GLOBALS
- ZEND_INI_MH
- phar_split_cache_list
- ZEND_INI_MH
- PHP_INI_BEGIN
- phar_archive_delref
- destroy_phar_data_only
- phar_unalias_apply
- phar_tmpclose_apply
- destroy_phar_data
- destroy_phar_manifest_entry_int
- destroy_phar_manifest_entry
- phar_entry_delref
- phar_entry_remove
- phar_open_parsed_phar
- phar_parse_metadata
- phar_parse_pharfile
- phar_open_or_create_filename
- phar_create_or_parse_filename
- phar_open_from_filename
- phar_strnstr
- phar_open_from_fp
- phar_analyze_path
- phar_check_str
- phar_detect_phar_fname_ext
- php_check_dots
- phar_fix_filepath
- phar_split_fname
- phar_open_executed_filename
- phar_postprocess_file
- phar_set_32
- phar_flush_clean_deleted_apply
- phar_create_default_stub
- phar_flush
- phar_zend_stream_reader
- phar_zend_stream_fsizer
- phar_resolve_path
- phar_compile_file
- mime_type_dtor
- PHP_GINIT_FUNCTION
- PHP_GSHUTDOWN_FUNCTION
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- phar_request_initialize
- PHP_RSHUTDOWN_FUNCTION
- PHP_MINFO_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #define PHAR_MAIN 1
23 #include "phar_internal.h"
24 #include "SAPI.h"
25 #include "func_interceptors.h"
26
27 static void destroy_phar_data(zval *zv);
28
29 ZEND_DECLARE_MODULE_GLOBALS(phar)
30 zend_string *(*phar_save_resolve_path)(const char *filename, int filename_len);
31
32
33
34
35 static int phar_set_writeable_bit(zval *zv, void *argument)
36 {
37 zend_bool keep = *(zend_bool *)argument;
38 phar_archive_data *phar = (phar_archive_data *)Z_PTR_P(zv);
39
40 if (!phar->is_data) {
41 phar->is_writeable = !keep;
42 }
43
44 return ZEND_HASH_APPLY_KEEP;
45 }
46
47
48
49 ZEND_INI_MH(phar_ini_modify_handler)
50 {
51 zend_bool old, ini;
52
53 if (ZSTR_LEN(entry->name) == sizeof("phar.readonly")-1) {
54 old = PHAR_G(readonly_orig);
55 } else {
56 old = PHAR_G(require_hash_orig);
57 }
58
59 if (ZSTR_LEN(new_value) == 2 && !strcasecmp("on", ZSTR_VAL(new_value))) {
60 ini = (zend_bool) 1;
61 }
62 else if (ZSTR_LEN(new_value) == 3 && !strcasecmp("yes", ZSTR_VAL(new_value))) {
63 ini = (zend_bool) 1;
64 }
65 else if (ZSTR_LEN(new_value) == 4 && !strcasecmp("true", ZSTR_VAL(new_value))) {
66 ini = (zend_bool) 1;
67 }
68 else {
69 ini = (zend_bool) atoi(ZSTR_VAL(new_value));
70 }
71
72
73 if (stage == ZEND_INI_STAGE_STARTUP) {
74 if (ZSTR_LEN(entry->name) == sizeof("phar.readonly")-1) {
75 PHAR_G(readonly_orig) = ini;
76 } else {
77 PHAR_G(require_hash_orig) = ini;
78 }
79 } else if (old && !ini) {
80 return FAILURE;
81 }
82
83 if (ZSTR_LEN(entry->name) == sizeof("phar.readonly")-1) {
84 PHAR_G(readonly) = ini;
85 if (PHAR_G(request_init) && PHAR_G(phar_fname_map.u.flags)) {
86 zend_hash_apply_with_argument(&(PHAR_G(phar_fname_map)), phar_set_writeable_bit, (void *)&ini);
87 }
88 } else {
89 PHAR_G(require_hash) = ini;
90 }
91
92 return SUCCESS;
93 }
94
95
96
97 HashTable cached_phars;
98 HashTable cached_alias;
99
100 static void phar_split_cache_list(void)
101 {
102 char *tmp;
103 char *key, *lasts, *end;
104 char ds[2];
105 phar_archive_data *phar;
106 uint i = 0;
107
108 if (!PHAR_G(cache_list) || !(PHAR_G(cache_list)[0])) {
109 return;
110 }
111
112 ds[0] = DEFAULT_DIR_SEPARATOR;
113 ds[1] = '\0';
114 tmp = estrdup(PHAR_G(cache_list));
115
116
117 PHAR_G(request_init) = 1;
118 zend_hash_init(&EG(regular_list), 0, NULL, NULL, 0);
119 EG(regular_list).nNextFreeElement=1;
120
121 PHAR_G(has_bz2) = zend_hash_str_exists(&module_registry, "bz2", sizeof("bz2")-1);
122 PHAR_G(has_zlib) = zend_hash_str_exists(&module_registry, "zlib", sizeof("zlib")-1);
123
124 zend_hash_init(&cached_phars, sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data, 1);
125 zend_hash_init(&cached_alias, sizeof(phar_archive_data*), zend_get_hash_value, NULL, 1);
126
127 zend_hash_init(&(PHAR_G(phar_fname_map)), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data, 1);
128 zend_hash_init(&(PHAR_G(phar_alias_map)), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 1);
129 PHAR_G(manifest_cached) = 1;
130 PHAR_G(persist) = 1;
131
132 for (key = php_strtok_r(tmp, ds, &lasts);
133 key;
134 key = php_strtok_r(NULL, ds, &lasts)) {
135 end = strchr(key, DEFAULT_DIR_SEPARATOR);
136
137 if (end) {
138 if (SUCCESS == phar_open_from_filename(key, end - key, NULL, 0, 0, &phar, NULL)) {
139 finish_up:
140 phar->phar_pos = i++;
141 php_stream_close(phar->fp);
142 phar->fp = NULL;
143 } else {
144 finish_error:
145 PHAR_G(persist) = 0;
146 PHAR_G(manifest_cached) = 0;
147 efree(tmp);
148 zend_hash_destroy(&(PHAR_G(phar_fname_map)));
149 PHAR_G(phar_fname_map.u.flags) = 0;
150 zend_hash_destroy(&(PHAR_G(phar_alias_map)));
151 PHAR_G(phar_alias_map.u.flags) = 0;
152 zend_hash_destroy(&cached_phars);
153 zend_hash_destroy(&cached_alias);
154 zend_hash_graceful_reverse_destroy(&EG(regular_list));
155 memset(&EG(regular_list), 0, sizeof(HashTable));
156
157 PHAR_G(request_init) = 0;
158 return;
159 }
160 } else {
161 if (SUCCESS == phar_open_from_filename(key, strlen(key), NULL, 0, 0, &phar, NULL)) {
162 goto finish_up;
163 } else {
164 goto finish_error;
165 }
166 }
167 }
168
169 PHAR_G(persist) = 0;
170 PHAR_G(request_init) = 0;
171
172 zend_hash_destroy(&cached_phars);
173 zend_hash_destroy(&cached_alias);
174 cached_phars = PHAR_G(phar_fname_map);
175 cached_alias = PHAR_G(phar_alias_map);
176 PHAR_G(phar_fname_map.u.flags) = 0;
177 PHAR_G(phar_alias_map.u.flags) = 0;
178 zend_hash_graceful_reverse_destroy(&EG(regular_list));
179 memset(&EG(regular_list), 0, sizeof(HashTable));
180 efree(tmp);
181 }
182
183
184 ZEND_INI_MH(phar_ini_cache_list)
185 {
186 PHAR_G(cache_list) = ZSTR_VAL(new_value);
187
188 if (stage == ZEND_INI_STAGE_STARTUP) {
189 phar_split_cache_list();
190 }
191
192 return SUCCESS;
193 }
194
195
196 PHP_INI_BEGIN()
197 STD_PHP_INI_BOOLEAN("phar.readonly", "1", PHP_INI_ALL, phar_ini_modify_handler, readonly, zend_phar_globals, phar_globals)
198 STD_PHP_INI_BOOLEAN("phar.require_hash", "1", PHP_INI_ALL, phar_ini_modify_handler, require_hash, zend_phar_globals, phar_globals)
199 STD_PHP_INI_ENTRY("phar.cache_list", "", PHP_INI_SYSTEM, phar_ini_cache_list, cache_list, zend_phar_globals, phar_globals)
200 PHP_INI_END()
201
202
203
204
205
206 void phar_destroy_phar_data(phar_archive_data *phar)
207 {
208 if (phar->alias && phar->alias != phar->fname) {
209 pefree(phar->alias, phar->is_persistent);
210 phar->alias = NULL;
211 }
212
213 if (phar->fname) {
214 pefree(phar->fname, phar->is_persistent);
215 phar->fname = NULL;
216 }
217
218 if (phar->signature) {
219 pefree(phar->signature, phar->is_persistent);
220 phar->signature = NULL;
221 }
222
223 if (phar->manifest.u.flags) {
224 zend_hash_destroy(&phar->manifest);
225 phar->manifest.u.flags = 0;
226 }
227
228 if (phar->mounted_dirs.u.flags) {
229 zend_hash_destroy(&phar->mounted_dirs);
230 phar->mounted_dirs.u.flags = 0;
231 }
232
233 if (phar->virtual_dirs.u.flags) {
234 zend_hash_destroy(&phar->virtual_dirs);
235 phar->virtual_dirs.u.flags = 0;
236 }
237
238 if (Z_TYPE(phar->metadata) != IS_UNDEF) {
239 if (phar->is_persistent) {
240 if (phar->metadata_len) {
241
242 free(Z_PTR(phar->metadata));
243 } else {
244 zval_internal_ptr_dtor(&phar->metadata);
245 }
246 } else {
247 zval_ptr_dtor(&phar->metadata);
248 }
249 phar->metadata_len = 0;
250 ZVAL_UNDEF(&phar->metadata);
251 }
252
253 if (phar->fp) {
254 php_stream_close(phar->fp);
255 phar->fp = 0;
256 }
257
258 if (phar->ufp) {
259 php_stream_close(phar->ufp);
260 phar->ufp = 0;
261 }
262
263 pefree(phar, phar->is_persistent);
264 }
265
266
267
268
269
270 int phar_archive_delref(phar_archive_data *phar)
271 {
272 if (phar->is_persistent) {
273 return 0;
274 }
275
276 if (--phar->refcount < 0) {
277 if (PHAR_G(request_done)
278 || zend_hash_str_del(&(PHAR_G(phar_fname_map)), phar->fname, phar->fname_len) != SUCCESS) {
279 phar_destroy_phar_data(phar);
280 }
281 return 1;
282 } else if (!phar->refcount) {
283
284 PHAR_G(last_phar) = NULL;
285 PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
286
287 if (phar->fp && !(phar->flags & PHAR_FILE_COMPRESSION_MASK)) {
288
289
290
291
292 php_stream_close(phar->fp);
293 phar->fp = NULL;
294 }
295
296 if (!zend_hash_num_elements(&phar->manifest)) {
297
298
299 if (zend_hash_str_del(&(PHAR_G(phar_fname_map)), phar->fname, phar->fname_len) != SUCCESS) {
300 phar_destroy_phar_data(phar);
301 }
302 return 1;
303 }
304 }
305 return 0;
306 }
307
308
309
310
311
312 static void destroy_phar_data_only(zval *zv)
313 {
314 phar_archive_data *phar_data = (phar_archive_data *) Z_PTR_P(zv);
315
316 if (EG(exception) || --phar_data->refcount < 0) {
317 phar_destroy_phar_data(phar_data);
318 }
319 }
320
321
322
323
324
325 static int phar_unalias_apply(zval *zv, void *argument)
326 {
327 return Z_PTR_P(zv) == argument ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_KEEP;
328 }
329
330
331
332
333
334 static int phar_tmpclose_apply(zval *zv)
335 {
336 phar_entry_info *entry = (phar_entry_info *) Z_PTR_P(zv);
337
338 if (entry->fp_type != PHAR_TMP) {
339 return ZEND_HASH_APPLY_KEEP;
340 }
341
342 if (entry->fp && !entry->fp_refcount) {
343 php_stream_close(entry->fp);
344 entry->fp = NULL;
345 }
346
347 return ZEND_HASH_APPLY_KEEP;
348 }
349
350
351
352
353
354 static void destroy_phar_data(zval *zv)
355 {
356 phar_archive_data *phar_data = (phar_archive_data *)Z_PTR_P(zv);
357
358 if (PHAR_G(request_ends)) {
359
360
361 zend_hash_apply(&(phar_data->manifest), phar_tmpclose_apply);
362 destroy_phar_data_only(zv);
363 return;
364 }
365
366 zend_hash_apply_with_argument(&(PHAR_G(phar_alias_map)), phar_unalias_apply, phar_data);
367
368 if (--phar_data->refcount < 0) {
369 phar_destroy_phar_data(phar_data);
370 }
371 }
372
373
374
375
376
377 void destroy_phar_manifest_entry_int(phar_entry_info *entry)
378 {
379
380 if (entry->cfp) {
381 php_stream_close(entry->cfp);
382 entry->cfp = 0;
383 }
384
385 if (entry->fp) {
386 php_stream_close(entry->fp);
387 entry->fp = 0;
388 }
389
390 if (Z_TYPE(entry->metadata) != IS_UNDEF) {
391 if (entry->is_persistent) {
392 if (entry->metadata_len) {
393
394 free(Z_PTR(entry->metadata));
395 } else {
396 zval_internal_ptr_dtor(&entry->metadata);
397 }
398 } else {
399 zval_ptr_dtor(&entry->metadata);
400 }
401 entry->metadata_len = 0;
402 ZVAL_UNDEF(&entry->metadata);
403 }
404
405 if (entry->metadata_str.s) {
406 smart_str_free(&entry->metadata_str);
407 entry->metadata_str.s = NULL;
408 }
409
410 pefree(entry->filename, entry->is_persistent);
411
412 if (entry->link) {
413 pefree(entry->link, entry->is_persistent);
414 entry->link = 0;
415 }
416
417 if (entry->tmp) {
418 pefree(entry->tmp, entry->is_persistent);
419 entry->tmp = 0;
420 }
421 }
422
423
424 void destroy_phar_manifest_entry(zval *zv)
425 {
426 phar_entry_info *entry = Z_PTR_P(zv);
427 destroy_phar_manifest_entry_int(entry);
428 pefree(entry, entry->is_persistent);
429 }
430
431
432 int phar_entry_delref(phar_entry_data *idata)
433 {
434 int ret = 0;
435
436 if (idata->internal_file && !idata->internal_file->is_persistent) {
437 if (--idata->internal_file->fp_refcount < 0) {
438 idata->internal_file->fp_refcount = 0;
439 }
440
441 if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
442 php_stream_close(idata->fp);
443 }
444
445 if (idata->internal_file->is_temp_dir) {
446 destroy_phar_manifest_entry_int(idata->internal_file);
447 efree(idata->internal_file);
448 }
449 }
450
451 phar_archive_delref(idata->phar);
452 efree(idata);
453 return ret;
454 }
455
456
457
458
459
460 void phar_entry_remove(phar_entry_data *idata, char **error)
461 {
462 phar_archive_data *phar;
463
464 phar = idata->phar;
465
466 if (idata->internal_file->fp_refcount < 2) {
467 if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
468 php_stream_close(idata->fp);
469 }
470 zend_hash_str_del(&idata->phar->manifest, idata->internal_file->filename, idata->internal_file->filename_len);
471 idata->phar->refcount--;
472 efree(idata);
473 } else {
474 idata->internal_file->is_deleted = 1;
475 phar_entry_delref(idata);
476 }
477
478 if (!phar->donotflush) {
479 phar_flush(phar, 0, 0, 0, error);
480 }
481 }
482
483
484 #define MAPPHAR_ALLOC_FAIL(msg) \
485 if (fp) {\
486 php_stream_close(fp);\
487 }\
488 if (error) {\
489 spprintf(error, 0, msg, fname);\
490 }\
491 return FAILURE;
492
493 #define MAPPHAR_FAIL(msg) \
494 efree(savebuf);\
495 if (mydata) {\
496 phar_destroy_phar_data(mydata);\
497 }\
498 if (signature) {\
499 pefree(signature, PHAR_G(persist));\
500 }\
501 MAPPHAR_ALLOC_FAIL(msg)
502
503 #ifdef WORDS_BIGENDIAN
504 # define PHAR_GET_32(buffer, var) \
505 var = ((((unsigned char*)(buffer))[3]) << 24) \
506 | ((((unsigned char*)(buffer))[2]) << 16) \
507 | ((((unsigned char*)(buffer))[1]) << 8) \
508 | (((unsigned char*)(buffer))[0]); \
509 (buffer) += 4
510 # define PHAR_GET_16(buffer, var) \
511 var = ((((unsigned char*)(buffer))[1]) << 8) \
512 | (((unsigned char*)(buffer))[0]); \
513 (buffer) += 2
514 #else
515 # define PHAR_GET_32(buffer, var) \
516 memcpy(&var, buffer, sizeof(var)); \
517 buffer += 4
518 # define PHAR_GET_16(buffer, var) \
519 var = *(php_uint16*)(buffer); \
520 buffer += 2
521 #endif
522 #define PHAR_ZIP_16(var) ((php_uint16)((((php_uint16)var[0]) & 0xff) | \
523 (((php_uint16)var[1]) & 0xff) << 8))
524 #define PHAR_ZIP_32(var) ((php_uint32)((((php_uint32)var[0]) & 0xff) | \
525 (((php_uint32)var[1]) & 0xff) << 8 | \
526 (((php_uint32)var[2]) & 0xff) << 16 | \
527 (((php_uint32)var[3]) & 0xff) << 24))
528
529
530
531
532 int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error)
533 {
534 phar_archive_data *phar;
535 #ifdef PHP_WIN32
536 char *unixfname;
537 #endif
538
539 if (error) {
540 *error = NULL;
541 }
542 #ifdef PHP_WIN32
543 unixfname = estrndup(fname, fname_len);
544 phar_unixify_path_separators(unixfname, fname_len);
545
546 if (SUCCESS == phar_get_archive(&phar, unixfname, fname_len, alias, alias_len, error)
547 && ((alias && fname_len == phar->fname_len
548 && !strncmp(unixfname, phar->fname, fname_len)) || !alias)
549 ) {
550 phar_entry_info *stub;
551 efree(unixfname);
552 #else
553 if (SUCCESS == phar_get_archive(&phar, fname, fname_len, alias, alias_len, error)
554 && ((alias && fname_len == phar->fname_len
555 && !strncmp(fname, phar->fname, fname_len)) || !alias)
556 ) {
557 phar_entry_info *stub;
558 #endif
559
560
561
562
563
564
565 if (!is_data) {
566
567 if (!phar->halt_offset && !phar->is_brandnew && (phar->is_tar || phar->is_zip)) {
568 if (PHAR_G(readonly) && NULL == (stub = zend_hash_str_find_ptr(&(phar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) {
569 if (error) {
570 spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
571 }
572 return FAILURE;
573 }
574 }
575 }
576
577 if (pphar) {
578 *pphar = phar;
579 }
580
581 return SUCCESS;
582 } else {
583 #ifdef PHP_WIN32
584 efree(unixfname);
585 #endif
586 if (pphar) {
587 *pphar = NULL;
588 }
589
590 if (phar && error && !(options & REPORT_ERRORS)) {
591 efree(error);
592 }
593
594 return FAILURE;
595 }
596 }
597
598
599
600
601
602
603
604
605
606
607 int phar_parse_metadata(char **buffer, zval *metadata, php_uint32 zip_metadata_len)
608 {
609 php_unserialize_data_t var_hash;
610
611 if (zip_metadata_len) {
612 const unsigned char *p;
613 unsigned char *p_buff = (unsigned char *)estrndup(*buffer, zip_metadata_len);
614 p = p_buff;
615 ZVAL_NULL(metadata);
616 PHP_VAR_UNSERIALIZE_INIT(var_hash);
617
618 if (!php_var_unserialize(metadata, &p, p + zip_metadata_len, &var_hash)) {
619 efree(p_buff);
620 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
621 zval_ptr_dtor(metadata);
622 ZVAL_UNDEF(metadata);
623 return FAILURE;
624 }
625 efree(p_buff);
626 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
627
628 if (PHAR_G(persist)) {
629
630 zval_ptr_dtor(metadata);
631 Z_PTR_P(metadata) = pemalloc(zip_metadata_len, 1);
632 memcpy(Z_PTR_P(metadata), *buffer, zip_metadata_len);
633 return SUCCESS;
634 }
635 } else {
636 ZVAL_UNDEF(metadata);
637 }
638
639 return SUCCESS;
640 }
641
642
643
644
645
646
647
648
649
650
651
652 static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, zend_long halt_offset, phar_archive_data** pphar, php_uint32 compression, char **error)
653 {
654 char b32[4], *buffer, *endbuffer, *savebuf;
655 phar_archive_data *mydata = NULL;
656 phar_entry_info entry;
657 php_uint32 manifest_len, manifest_count, manifest_flags, manifest_index, tmp_len, sig_flags;
658 php_uint16 manifest_ver;
659 php_uint32 len;
660 zend_long offset;
661 int sig_len, register_alias = 0, temp_alias = 0;
662 char *signature = NULL;
663
664 if (pphar) {
665 *pphar = NULL;
666 }
667
668 if (error) {
669 *error = NULL;
670 }
671
672
673 if (-1 == php_stream_seek(fp, halt_offset, SEEK_SET)) {
674 MAPPHAR_ALLOC_FAIL("cannot seek to __HALT_COMPILER(); location in phar \"%s\"")
675 }
676
677 buffer = b32;
678
679 if (3 != php_stream_read(fp, buffer, 3)) {
680 MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at stub end)")
681 }
682
683 if ((*buffer == ' ' || *buffer == '\n') && *(buffer + 1) == '?' && *(buffer + 2) == '>') {
684 int nextchar;
685 halt_offset += 3;
686 if (EOF == (nextchar = php_stream_getc(fp))) {
687 MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at stub end)")
688 }
689
690 if ((char) nextchar == '\r') {
691
692 if (EOF == (nextchar = php_stream_getc(fp)) || (char)nextchar != '\n') {
693 MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at stub end)")
694 }
695 ++halt_offset;
696 }
697
698 if ((char) nextchar == '\n') {
699 ++halt_offset;
700 }
701 }
702
703
704 if (-1 == php_stream_seek(fp, halt_offset, SEEK_SET)) {
705 MAPPHAR_ALLOC_FAIL("cannot seek to __HALT_COMPILER(); location in phar \"%s\"")
706 }
707
708
709 buffer = b32;
710
711 if (4 != php_stream_read(fp, buffer, 4)) {
712 MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated manifest at manifest length)")
713 }
714
715 PHAR_GET_32(buffer, manifest_len);
716
717 if (manifest_len > 1048576 * 100) {
718
719 MAPPHAR_ALLOC_FAIL("manifest cannot be larger than 100 MB in phar \"%s\"")
720 }
721
722 buffer = (char *)emalloc(manifest_len);
723 savebuf = buffer;
724 endbuffer = buffer + manifest_len;
725
726 if (manifest_len < 10 || manifest_len != php_stream_read(fp, buffer, manifest_len)) {
727 MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
728 }
729
730
731 PHAR_GET_32(buffer, manifest_count);
732
733 if (manifest_count == 0) {
734 MAPPHAR_FAIL("in phar \"%s\", manifest claims to have zero entries. Phars must have at least 1 entry");
735 }
736
737
738 manifest_ver = (((unsigned char)buffer[0]) << 8)
739 + ((unsigned char)buffer[1]);
740 buffer += 2;
741
742 if ((manifest_ver & PHAR_API_VER_MASK) < PHAR_API_MIN_READ) {
743 efree(savebuf);
744 php_stream_close(fp);
745 if (error) {
746 spprintf(error, 0, "phar \"%s\" is API version %1.u.%1.u.%1.u, and cannot be processed", fname, manifest_ver >> 12, (manifest_ver >> 8) & 0xF, (manifest_ver >> 4) & 0x0F);
747 }
748 return FAILURE;
749 }
750
751 PHAR_GET_32(buffer, manifest_flags);
752
753 manifest_flags &= ~PHAR_HDR_COMPRESSION_MASK;
754 manifest_flags &= ~PHAR_FILE_COMPRESSION_MASK;
755
756 manifest_flags |= compression;
757
758
759
760 if (manifest_flags & PHAR_HDR_SIGNATURE) {
761 char sig_buf[8], *sig_ptr = sig_buf;
762 zend_off_t read_len;
763 size_t end_of_phar;
764
765 if (-1 == php_stream_seek(fp, -8, SEEK_END)
766 || (read_len = php_stream_tell(fp)) < 20
767 || 8 != php_stream_read(fp, sig_buf, 8)
768 || memcmp(sig_buf+4, "GBMB", 4)) {
769 efree(savebuf);
770 php_stream_close(fp);
771 if (error) {
772 spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
773 }
774 return FAILURE;
775 }
776
777 PHAR_GET_32(sig_ptr, sig_flags);
778
779 switch(sig_flags) {
780 case PHAR_SIG_OPENSSL: {
781 php_uint32 signature_len;
782 char *sig;
783 zend_off_t whence;
784
785
786 if (-1 == php_stream_seek(fp, -12, SEEK_CUR)
787 || 4 != php_stream_read(fp, sig_buf, 4)) {
788 efree(savebuf);
789 php_stream_close(fp);
790 if (error) {
791 spprintf(error, 0, "phar \"%s\" openssl signature length could not be read", fname);
792 }
793 return FAILURE;
794 }
795
796 sig_ptr = sig_buf;
797 PHAR_GET_32(sig_ptr, signature_len);
798 sig = (char *) emalloc(signature_len);
799 whence = signature_len + 4;
800 whence = -whence;
801
802 if (-1 == php_stream_seek(fp, whence, SEEK_CUR)
803 || !(end_of_phar = php_stream_tell(fp))
804 || signature_len != php_stream_read(fp, sig, signature_len)) {
805 efree(savebuf);
806 efree(sig);
807 php_stream_close(fp);
808 if (error) {
809 spprintf(error, 0, "phar \"%s\" openssl signature could not be read", fname);
810 }
811 return FAILURE;
812 }
813
814 if (FAILURE == phar_verify_signature(fp, end_of_phar, PHAR_SIG_OPENSSL, sig, signature_len, fname, &signature, &sig_len, error)) {
815 efree(savebuf);
816 efree(sig);
817 php_stream_close(fp);
818 if (error) {
819 char *save = *error;
820 spprintf(error, 0, "phar \"%s\" openssl signature could not be verified: %s", fname, *error);
821 efree(save);
822 }
823 return FAILURE;
824 }
825 efree(sig);
826 }
827 break;
828 #if PHAR_HASH_OK
829 case PHAR_SIG_SHA512: {
830 unsigned char digest[64];
831
832 php_stream_seek(fp, -(8 + 64), SEEK_END);
833 read_len = php_stream_tell(fp);
834
835 if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
836 efree(savebuf);
837 php_stream_close(fp);
838 if (error) {
839 spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
840 }
841 return FAILURE;
842 }
843
844 if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA512, (char *)digest, 64, fname, &signature, &sig_len, error)) {
845 efree(savebuf);
846 php_stream_close(fp);
847 if (error) {
848 char *save = *error;
849 spprintf(error, 0, "phar \"%s\" SHA512 signature could not be verified: %s", fname, *error);
850 efree(save);
851 }
852 return FAILURE;
853 }
854 break;
855 }
856 case PHAR_SIG_SHA256: {
857 unsigned char digest[32];
858
859 php_stream_seek(fp, -(8 + 32), SEEK_END);
860 read_len = php_stream_tell(fp);
861
862 if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
863 efree(savebuf);
864 php_stream_close(fp);
865 if (error) {
866 spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
867 }
868 return FAILURE;
869 }
870
871 if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA256, (char *)digest, 32, fname, &signature, &sig_len, error)) {
872 efree(savebuf);
873 php_stream_close(fp);
874 if (error) {
875 char *save = *error;
876 spprintf(error, 0, "phar \"%s\" SHA256 signature could not be verified: %s", fname, *error);
877 efree(save);
878 }
879 return FAILURE;
880 }
881 break;
882 }
883 #else
884 case PHAR_SIG_SHA512:
885 case PHAR_SIG_SHA256:
886 efree(savebuf);
887 php_stream_close(fp);
888
889 if (error) {
890 spprintf(error, 0, "phar \"%s\" has a unsupported signature", fname);
891 }
892 return FAILURE;
893 #endif
894 case PHAR_SIG_SHA1: {
895 unsigned char digest[20];
896
897 php_stream_seek(fp, -(8 + 20), SEEK_END);
898 read_len = php_stream_tell(fp);
899
900 if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
901 efree(savebuf);
902 php_stream_close(fp);
903 if (error) {
904 spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
905 }
906 return FAILURE;
907 }
908
909 if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_SHA1, (char *)digest, 20, fname, &signature, &sig_len, error)) {
910 efree(savebuf);
911 php_stream_close(fp);
912 if (error) {
913 char *save = *error;
914 spprintf(error, 0, "phar \"%s\" SHA1 signature could not be verified: %s", fname, *error);
915 efree(save);
916 }
917 return FAILURE;
918 }
919 break;
920 }
921 case PHAR_SIG_MD5: {
922 unsigned char digest[16];
923
924 php_stream_seek(fp, -(8 + 16), SEEK_END);
925 read_len = php_stream_tell(fp);
926
927 if (php_stream_read(fp, (char*)digest, sizeof(digest)) != sizeof(digest)) {
928 efree(savebuf);
929 php_stream_close(fp);
930 if (error) {
931 spprintf(error, 0, "phar \"%s\" has a broken signature", fname);
932 }
933 return FAILURE;
934 }
935
936 if (FAILURE == phar_verify_signature(fp, read_len, PHAR_SIG_MD5, (char *)digest, 16, fname, &signature, &sig_len, error)) {
937 efree(savebuf);
938 php_stream_close(fp);
939 if (error) {
940 char *save = *error;
941 spprintf(error, 0, "phar \"%s\" MD5 signature could not be verified: %s", fname, *error);
942 efree(save);
943 }
944 return FAILURE;
945 }
946 break;
947 }
948 default:
949 efree(savebuf);
950 php_stream_close(fp);
951
952 if (error) {
953 spprintf(error, 0, "phar \"%s\" has a broken or unsupported signature", fname);
954 }
955 return FAILURE;
956 }
957 } else if (PHAR_G(require_hash)) {
958 efree(savebuf);
959 php_stream_close(fp);
960
961 if (error) {
962 spprintf(error, 0, "phar \"%s\" does not have a signature", fname);
963 }
964 return FAILURE;
965 } else {
966 sig_flags = 0;
967 sig_len = 0;
968 }
969
970
971 PHAR_GET_32(buffer, tmp_len);
972
973 if (buffer + tmp_len > endbuffer) {
974 MAPPHAR_FAIL("internal corruption of phar \"%s\" (buffer overrun)");
975 }
976
977 if (manifest_len < 10 + tmp_len) {
978 MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
979 }
980
981
982 if (tmp_len) {
983
984 if (alias && alias_len && (alias_len != (int)tmp_len || strncmp(alias, buffer, tmp_len)))
985 {
986 buffer[tmp_len] = '\0';
987 php_stream_close(fp);
988
989 if (signature) {
990 efree(signature);
991 }
992
993 if (error) {
994 spprintf(error, 0, "cannot load phar \"%s\" with implicit alias \"%s\" under different alias \"%s\"", fname, buffer, alias);
995 }
996
997 efree(savebuf);
998 return FAILURE;
999 }
1000
1001 alias_len = tmp_len;
1002 alias = buffer;
1003 buffer += tmp_len;
1004 register_alias = 1;
1005 } else if (!alias_len || !alias) {
1006
1007 alias = NULL;
1008 alias_len = 0;
1009 register_alias = 0;
1010 } else if (alias_len) {
1011 register_alias = 1;
1012 temp_alias = 1;
1013 }
1014
1015
1016 if (manifest_count > ((manifest_len - 10 - tmp_len) / (5 * 4 + 1))) {
1017
1018 MAPPHAR_FAIL("internal corruption of phar \"%s\" (too many manifest entries for size of manifest)")
1019 }
1020
1021 mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
1022 mydata->is_persistent = PHAR_G(persist);
1023
1024
1025 PHAR_GET_32(buffer, len);
1026 if (mydata->is_persistent) {
1027 mydata->metadata_len = len;
1028 if(!len) {
1029
1030 PHAR_GET_32(buffer, len);
1031 }
1032 }
1033 if(len > endbuffer - buffer) {
1034 MAPPHAR_FAIL("internal corruption of phar \"%s\" (trying to read past buffer end)");
1035 }
1036 if (phar_parse_metadata(&buffer, &mydata->metadata, len) == FAILURE) {
1037 MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\"");
1038 }
1039 buffer += len;
1040
1041
1042 zend_hash_init(&mydata->manifest, manifest_count,
1043 zend_get_hash_value, destroy_phar_manifest_entry, (zend_bool)mydata->is_persistent);
1044 zend_hash_init(&mydata->mounted_dirs, 5,
1045 zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
1046 zend_hash_init(&mydata->virtual_dirs, manifest_count * 2,
1047 zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
1048 mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent);
1049 #ifdef PHP_WIN32
1050 phar_unixify_path_separators(mydata->fname, fname_len);
1051 #endif
1052 mydata->fname_len = fname_len;
1053 offset = halt_offset + manifest_len + 4;
1054 memset(&entry, 0, sizeof(phar_entry_info));
1055 entry.phar = mydata;
1056 entry.fp_type = PHAR_FP;
1057 entry.is_persistent = mydata->is_persistent;
1058
1059 for (manifest_index = 0; manifest_index < manifest_count; ++manifest_index) {
1060 if (buffer + 4 > endbuffer) {
1061 MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)")
1062 }
1063
1064 PHAR_GET_32(buffer, entry.filename_len);
1065
1066 if (entry.filename_len == 0) {
1067 MAPPHAR_FAIL("zero-length filename encountered in phar \"%s\"");
1068 }
1069
1070 if (entry.is_persistent) {
1071 entry.manifest_pos = manifest_index;
1072 }
1073
1074 if (entry.filename_len + 20 > endbuffer - buffer) {
1075 MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)");
1076 }
1077
1078 if ((manifest_ver & PHAR_API_VER_MASK) >= PHAR_API_MIN_DIR && buffer[entry.filename_len - 1] == '/') {
1079 entry.is_dir = 1;
1080 } else {
1081 entry.is_dir = 0;
1082 }
1083
1084 phar_add_virtual_dirs(mydata, buffer, entry.filename_len);
1085 entry.filename = pestrndup(buffer, entry.filename_len, entry.is_persistent);
1086 buffer += entry.filename_len;
1087 PHAR_GET_32(buffer, entry.uncompressed_filesize);
1088 PHAR_GET_32(buffer, entry.timestamp);
1089
1090 if (offset == halt_offset + (int)manifest_len + 4) {
1091 mydata->min_timestamp = entry.timestamp;
1092 mydata->max_timestamp = entry.timestamp;
1093 } else {
1094 if (mydata->min_timestamp > entry.timestamp) {
1095 mydata->min_timestamp = entry.timestamp;
1096 } else if (mydata->max_timestamp < entry.timestamp) {
1097 mydata->max_timestamp = entry.timestamp;
1098 }
1099 }
1100
1101 PHAR_GET_32(buffer, entry.compressed_filesize);
1102 PHAR_GET_32(buffer, entry.crc32);
1103 PHAR_GET_32(buffer, entry.flags);
1104
1105 if (entry.is_dir) {
1106 entry.filename_len--;
1107 entry.flags |= PHAR_ENT_PERM_DEF_DIR;
1108 }
1109
1110 PHAR_GET_32(buffer, len);
1111 if (entry.is_persistent) {
1112 entry.metadata_len = len;
1113 } else {
1114 entry.metadata_len = 0;
1115 }
1116 if (len > endbuffer - buffer) {
1117 pefree(entry.filename, entry.is_persistent);
1118 MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)");
1119 }
1120 if (phar_parse_metadata(&buffer, &entry.metadata, len) == FAILURE) {
1121 pefree(entry.filename, entry.is_persistent);
1122 MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
1123 }
1124 buffer += len;
1125
1126 entry.offset = entry.offset_abs = offset;
1127 offset += entry.compressed_filesize;
1128
1129 switch (entry.flags & PHAR_ENT_COMPRESSION_MASK) {
1130 case PHAR_ENT_COMPRESSED_GZ:
1131 if (!PHAR_G(has_zlib)) {
1132 if (Z_TYPE(entry.metadata) != IS_UNDEF) {
1133 if (entry.is_persistent) {
1134 free(Z_PTR(entry.metadata));
1135 } else {
1136 zval_ptr_dtor(&entry.metadata);
1137 }
1138 }
1139 pefree(entry.filename, entry.is_persistent);
1140 MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
1141 }
1142 break;
1143 case PHAR_ENT_COMPRESSED_BZ2:
1144 if (!PHAR_G(has_bz2)) {
1145 if (Z_TYPE(entry.metadata) != IS_UNDEF) {
1146 if (entry.is_persistent) {
1147 free(Z_PTR(entry.metadata));
1148 } else {
1149 zval_ptr_dtor(&entry.metadata);
1150 }
1151 }
1152 pefree(entry.filename, entry.is_persistent);
1153 MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
1154 }
1155 break;
1156 default:
1157 if (entry.uncompressed_filesize != entry.compressed_filesize) {
1158 if (Z_TYPE(entry.metadata) != IS_UNDEF) {
1159 if (entry.is_persistent) {
1160 free(Z_PTR(entry.metadata));
1161 } else {
1162 zval_ptr_dtor(&entry.metadata);
1163 }
1164 }
1165 pefree(entry.filename, entry.is_persistent);
1166 MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)");
1167 }
1168 break;
1169 }
1170
1171 manifest_flags |= (entry.flags & PHAR_ENT_COMPRESSION_MASK);
1172
1173 entry.is_crc_checked = (manifest_flags & PHAR_HDR_SIGNATURE ? 1 : 0);
1174 phar_set_inode(&entry);
1175 zend_hash_str_add_mem(&mydata->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info));
1176 }
1177
1178 snprintf(mydata->version, sizeof(mydata->version), "%u.%u.%u", manifest_ver >> 12, (manifest_ver >> 8) & 0xF, (manifest_ver >> 4) & 0xF);
1179 mydata->internal_file_start = halt_offset + manifest_len + 4;
1180 mydata->halt_offset = halt_offset;
1181 mydata->flags = manifest_flags;
1182 endbuffer = strrchr(mydata->fname, '/');
1183
1184 if (endbuffer) {
1185 mydata->ext = memchr(endbuffer, '.', (mydata->fname + fname_len) - endbuffer);
1186 if (mydata->ext == endbuffer) {
1187 mydata->ext = memchr(endbuffer + 1, '.', (mydata->fname + fname_len) - endbuffer - 1);
1188 }
1189 if (mydata->ext) {
1190 mydata->ext_len = (mydata->fname + mydata->fname_len) - mydata->ext;
1191 }
1192 }
1193
1194 mydata->alias = alias ?
1195 pestrndup(alias, alias_len, mydata->is_persistent) :
1196 pestrndup(mydata->fname, fname_len, mydata->is_persistent);
1197 mydata->alias_len = alias ? alias_len : fname_len;
1198 mydata->sig_flags = sig_flags;
1199 mydata->fp = fp;
1200 mydata->sig_len = sig_len;
1201 mydata->signature = signature;
1202 phar_request_initialize();
1203
1204 if (register_alias) {
1205 phar_archive_data *fd_ptr;
1206
1207 mydata->is_temporary_alias = temp_alias;
1208
1209 if (!phar_validate_alias(mydata->alias, mydata->alias_len)) {
1210 signature = NULL;
1211 fp = NULL;
1212 MAPPHAR_FAIL("Cannot open archive \"%s\", invalid alias");
1213 }
1214
1215 if (NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
1216 if (SUCCESS != phar_free_alias(fd_ptr, alias, alias_len)) {
1217 signature = NULL;
1218 fp = NULL;
1219 MAPPHAR_FAIL("Cannot open archive \"%s\", alias is already in use by existing archive");
1220 }
1221 }
1222
1223 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata);
1224 } else {
1225 mydata->is_temporary_alias = 1;
1226 }
1227
1228 zend_hash_str_add_ptr(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len, mydata);
1229 efree(savebuf);
1230
1231 if (pphar) {
1232 *pphar = mydata;
1233 }
1234
1235 return SUCCESS;
1236 }
1237
1238
1239
1240
1241
1242 int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error)
1243 {
1244 const char *ext_str, *z;
1245 char *my_error;
1246 int ext_len;
1247 phar_archive_data **test, *unused = NULL;
1248
1249 test = &unused;
1250
1251 if (error) {
1252 *error = NULL;
1253 }
1254
1255
1256 if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, 1) == SUCCESS) {
1257 goto check_file;
1258 }
1259
1260
1261 if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, 1)) {
1262 if (error) {
1263 if (ext_len == -2) {
1264 spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", fname);
1265 } else {
1266 spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", fname);
1267 }
1268 }
1269 return FAILURE;
1270 }
1271 check_file:
1272 if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, test, &my_error) == SUCCESS) {
1273 if (pphar) {
1274 *pphar = *test;
1275 }
1276
1277 if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) {
1278 if (error) {
1279 spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname);
1280 }
1281 return FAILURE;
1282 }
1283
1284 if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) {
1285 phar_entry_info *stub;
1286 if (NULL == (stub = zend_hash_str_find_ptr(&((*test)->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) {
1287 spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
1288 return FAILURE;
1289 }
1290 }
1291
1292 if (!PHAR_G(readonly) || (*test)->is_data) {
1293 (*test)->is_writeable = 1;
1294 }
1295 return SUCCESS;
1296 } else if (my_error) {
1297 if (error) {
1298 *error = my_error;
1299 } else {
1300 efree(my_error);
1301 }
1302 return FAILURE;
1303 }
1304
1305 if (ext_len > 3 && (z = memchr(ext_str, 'z', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ip", 2)) {
1306
1307 return phar_open_or_create_zip(fname, fname_len, alias, alias_len, is_data, options, pphar, error);
1308 }
1309
1310 if (ext_len > 3 && (z = memchr(ext_str, 't', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ar", 2)) {
1311
1312 return phar_open_or_create_tar(fname, fname_len, alias, alias_len, is_data, options, pphar, error);
1313 }
1314
1315 return phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, pphar, error);
1316 }
1317
1318
1319 int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error)
1320 {
1321 phar_archive_data *mydata;
1322 php_stream *fp;
1323 zend_string *actual = NULL;
1324 char *p;
1325
1326 if (!pphar) {
1327 pphar = &mydata;
1328 }
1329 #if PHP_API_VERSION < 20100412
1330 if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
1331 return FAILURE;
1332 }
1333 #endif
1334 if (php_check_open_basedir(fname)) {
1335 return FAILURE;
1336 }
1337
1338
1339 fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual);
1340
1341 if (actual) {
1342 fname = ZSTR_VAL(actual);
1343 fname_len = ZSTR_LEN(actual);
1344 }
1345
1346 if (fp) {
1347 if (phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, is_data, error) == SUCCESS) {
1348 if ((*pphar)->is_data || !PHAR_G(readonly)) {
1349 (*pphar)->is_writeable = 1;
1350 }
1351 if (actual) {
1352 zend_string_release(actual);
1353 }
1354 return SUCCESS;
1355 } else {
1356
1357 if (actual) {
1358 zend_string_release(actual);
1359 }
1360 return FAILURE;
1361 }
1362 }
1363
1364 if (actual) {
1365 zend_string_release(actual);
1366 }
1367
1368 if (PHAR_G(readonly) && !is_data) {
1369 if (options & REPORT_ERRORS) {
1370 if (error) {
1371 spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", fname);
1372 }
1373 }
1374 return FAILURE;
1375 }
1376
1377
1378 mydata = ecalloc(1, sizeof(phar_archive_data));
1379 mydata->fname = expand_filepath(fname, NULL);
1380 fname_len = strlen(mydata->fname);
1381 #ifdef PHP_WIN32
1382 phar_unixify_path_separators(mydata->fname, fname_len);
1383 #endif
1384 p = strrchr(mydata->fname, '/');
1385
1386 if (p) {
1387 mydata->ext = memchr(p, '.', (mydata->fname + fname_len) - p);
1388 if (mydata->ext == p) {
1389 mydata->ext = memchr(p + 1, '.', (mydata->fname + fname_len) - p - 1);
1390 }
1391 if (mydata->ext) {
1392 mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
1393 }
1394 }
1395
1396 if (pphar) {
1397 *pphar = mydata;
1398 }
1399
1400 zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
1401 zend_get_hash_value, destroy_phar_manifest_entry, 0);
1402 zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
1403 zend_get_hash_value, NULL, 0);
1404 zend_hash_init(&mydata->virtual_dirs, sizeof(char *),
1405 zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
1406 mydata->fname_len = fname_len;
1407 snprintf(mydata->version, sizeof(mydata->version), "%s", PHP_PHAR_API_VERSION);
1408 mydata->is_temporary_alias = alias ? 0 : 1;
1409 mydata->internal_file_start = -1;
1410 mydata->fp = NULL;
1411 mydata->is_writeable = 1;
1412 mydata->is_brandnew = 1;
1413 phar_request_initialize();
1414 zend_hash_str_add_ptr(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len, mydata);
1415
1416 if (is_data) {
1417 alias = NULL;
1418 alias_len = 0;
1419 mydata->is_data = 1;
1420
1421 mydata->is_tar = 1;
1422 } else {
1423 phar_archive_data *fd_ptr;
1424
1425 if (alias && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
1426 if (SUCCESS != phar_free_alias(fd_ptr, alias, alias_len)) {
1427 if (error) {
1428 spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias);
1429 }
1430
1431 zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len);
1432
1433 if (pphar) {
1434 *pphar = NULL;
1435 }
1436
1437 return FAILURE;
1438 }
1439 }
1440
1441 mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
1442 mydata->alias_len = alias ? alias_len : fname_len;
1443 }
1444
1445 if (alias_len && alias) {
1446 if (NULL == zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, mydata)) {
1447 if (options & REPORT_ERRORS) {
1448 if (error) {
1449 spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias);
1450 }
1451 }
1452
1453 zend_hash_str_del(&(PHAR_G(phar_fname_map)), mydata->fname, fname_len);
1454
1455 if (pphar) {
1456 *pphar = NULL;
1457 }
1458
1459 return FAILURE;
1460 }
1461 }
1462
1463 return SUCCESS;
1464 }
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474 int phar_open_from_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error)
1475 {
1476 php_stream *fp;
1477 zend_string *actual;
1478 int ret, is_data = 0;
1479
1480 if (error) {
1481 *error = NULL;
1482 }
1483
1484 if (!strstr(fname, ".phar")) {
1485 is_data = 1;
1486 }
1487
1488 if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, pphar, error) == SUCCESS) {
1489 return SUCCESS;
1490 } else if (error && *error) {
1491 return FAILURE;
1492 }
1493 #if PHP_API_VERSION < 20100412
1494 if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
1495 return FAILURE;
1496 }
1497 #endif
1498 if (php_check_open_basedir(fname)) {
1499 return FAILURE;
1500 }
1501
1502 fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);
1503
1504 if (!fp) {
1505 if (options & REPORT_ERRORS) {
1506 if (error) {
1507 spprintf(error, 0, "unable to open phar for reading \"%s\"", fname);
1508 }
1509 }
1510 if (actual) {
1511 zend_string_release(actual);
1512 }
1513 return FAILURE;
1514 }
1515
1516 if (actual) {
1517 fname = ZSTR_VAL(actual);
1518 fname_len = ZSTR_LEN(actual);
1519 }
1520
1521 ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, is_data, error);
1522
1523 if (actual) {
1524 zend_string_release(actual);
1525 }
1526
1527 return ret;
1528 }
1529
1530
1531 static inline char *phar_strnstr(const char *buf, int buf_len, const char *search, int search_len)
1532 {
1533 const char *c;
1534 ptrdiff_t so_far = 0;
1535
1536 if (buf_len < search_len) {
1537 return NULL;
1538 }
1539
1540 c = buf - 1;
1541
1542 do {
1543 if (!(c = memchr(c + 1, search[0], buf_len - search_len - so_far))) {
1544 return (char *) NULL;
1545 }
1546
1547 so_far = c - buf;
1548
1549 if (so_far >= (buf_len - search_len)) {
1550 return (char *) NULL;
1551 }
1552
1553 if (!memcmp(c, search, search_len)) {
1554 return (char *) c;
1555 }
1556 } while (1);
1557 }
1558
1559
1560
1561
1562
1563
1564
1565 static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, int is_data, char **error)
1566 {
1567 const char token[] = "__HALT_COMPILER();";
1568 const char zip_magic[] = "PK\x03\x04";
1569 const char gz_magic[] = "\x1f\x8b\x08";
1570 const char bz_magic[] = "BZh";
1571 char *pos, test = '\0';
1572 const int window_size = 1024;
1573 char buffer[1024 + sizeof(token)];
1574 const zend_long readsize = sizeof(buffer) - sizeof(token);
1575 const zend_long tokenlen = sizeof(token) - 1;
1576 zend_long halt_offset;
1577 size_t got;
1578 php_uint32 compression = PHAR_FILE_COMPRESSED_NONE;
1579
1580 if (error) {
1581 *error = NULL;
1582 }
1583
1584 if (-1 == php_stream_rewind(fp)) {
1585 MAPPHAR_ALLOC_FAIL("cannot rewind phar \"%s\"")
1586 }
1587
1588 buffer[sizeof(buffer)-1] = '\0';
1589 memset(buffer, 32, sizeof(token));
1590 halt_offset = 0;
1591
1592
1593
1594 while(!php_stream_eof(fp)) {
1595 if ((got = php_stream_read(fp, buffer+tokenlen, readsize)) < (size_t) tokenlen) {
1596 MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)")
1597 }
1598
1599 if (!test) {
1600 test = '\1';
1601 pos = buffer+tokenlen;
1602 if (!memcmp(pos, gz_magic, 3)) {
1603 char err = 0;
1604 php_stream_filter *filter;
1605 php_stream *temp;
1606
1607 zval filterparams;
1608
1609 if (!PHAR_G(has_zlib)) {
1610 MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file, enable zlib extension in php.ini")
1611 }
1612 array_init(&filterparams);
1613
1614 #ifndef MAX_WBITS
1615 #define MAX_WBITS 15
1616 #endif
1617 add_assoc_long_ex(&filterparams, "window", sizeof("window") - 1, MAX_WBITS + 32);
1618
1619
1620 if (!(temp = php_stream_fopen_tmpfile())) {
1621 MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of gzipped phar archive \"%s\"")
1622 }
1623
1624 php_stream_rewind(fp);
1625 filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp));
1626
1627 if (!filter) {
1628 err = 1;
1629 add_assoc_long_ex(&filterparams, "window", sizeof("window") - 1, MAX_WBITS);
1630 filter = php_stream_filter_create("zlib.inflate", &filterparams, php_stream_is_persistent(fp));
1631 zval_dtor(&filterparams);
1632
1633 if (!filter) {
1634 php_stream_close(temp);
1635 MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\", ext/zlib is buggy in PHP versions older than 5.2.6")
1636 }
1637 } else {
1638 zval_dtor(&filterparams);
1639 }
1640
1641 php_stream_filter_append(&temp->writefilters, filter);
1642
1643 if (SUCCESS != php_stream_copy_to_stream_ex(fp, temp, PHP_STREAM_COPY_ALL, NULL)) {
1644 if (err) {
1645 php_stream_close(temp);
1646 MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\", ext/zlib is buggy in PHP versions older than 5.2.6")
1647 }
1648 php_stream_close(temp);
1649 MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\" to temporary file")
1650 }
1651
1652 php_stream_filter_flush(filter, 1);
1653 php_stream_filter_remove(filter, 1);
1654 php_stream_close(fp);
1655 fp = temp;
1656 php_stream_rewind(fp);
1657 compression = PHAR_FILE_COMPRESSED_GZ;
1658
1659
1660 test = '\0';
1661 continue;
1662 } else if (!memcmp(pos, bz_magic, 3)) {
1663 php_stream_filter *filter;
1664 php_stream *temp;
1665
1666 if (!PHAR_G(has_bz2)) {
1667 MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file, enable bz2 extension in php.ini")
1668 }
1669
1670
1671 if (!(temp = php_stream_fopen_tmpfile())) {
1672 MAPPHAR_ALLOC_FAIL("unable to create temporary file for decompression of bzipped phar archive \"%s\"")
1673 }
1674
1675 php_stream_rewind(fp);
1676 filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp));
1677
1678 if (!filter) {
1679 php_stream_close(temp);
1680 MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\", filter creation failed")
1681 }
1682
1683 php_stream_filter_append(&temp->writefilters, filter);
1684
1685 if (SUCCESS != php_stream_copy_to_stream_ex(fp, temp, PHP_STREAM_COPY_ALL, NULL)) {
1686 php_stream_close(temp);
1687 MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\" to temporary file")
1688 }
1689
1690 php_stream_filter_flush(filter, 1);
1691 php_stream_filter_remove(filter, 1);
1692 php_stream_close(fp);
1693 fp = temp;
1694 php_stream_rewind(fp);
1695 compression = PHAR_FILE_COMPRESSED_BZ2;
1696
1697
1698 test = '\0';
1699 continue;
1700 }
1701
1702 if (!memcmp(pos, zip_magic, 4)) {
1703 php_stream_seek(fp, 0, SEEK_END);
1704 return phar_parse_zipfile(fp, fname, fname_len, alias, alias_len, pphar, error);
1705 }
1706
1707 if (got > 512) {
1708 if (phar_is_tar(pos, fname)) {
1709 php_stream_rewind(fp);
1710 return phar_parse_tarfile(fp, fname, fname_len, alias, alias_len, pphar, is_data, compression, error);
1711 }
1712 }
1713 }
1714
1715 if (got > 0 && (pos = phar_strnstr(buffer, got + sizeof(token), token, sizeof(token)-1)) != NULL) {
1716 halt_offset += (pos - buffer);
1717 return phar_parse_pharfile(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, compression, error);
1718 }
1719
1720 halt_offset += got;
1721 memmove(buffer, buffer + window_size, tokenlen);
1722 }
1723
1724 MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (__HALT_COMPILER(); not found)")
1725 }
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737 static int phar_analyze_path(const char *fname, const char *ext, int ext_len, int for_create)
1738 {
1739 php_stream_statbuf ssb;
1740 char *realpath;
1741 char *filename = estrndup(fname, (ext - fname) + ext_len);
1742
1743 if ((realpath = expand_filepath(filename, NULL))) {
1744 #ifdef PHP_WIN32
1745 phar_unixify_path_separators(realpath, strlen(realpath));
1746 #endif
1747 if (zend_hash_str_exists(&(PHAR_G(phar_fname_map)), realpath, strlen(realpath))) {
1748 efree(realpath);
1749 efree(filename);
1750 return SUCCESS;
1751 }
1752
1753 if (PHAR_G(manifest_cached) && zend_hash_str_exists(&cached_phars, realpath, strlen(realpath))) {
1754 efree(realpath);
1755 efree(filename);
1756 return SUCCESS;
1757 }
1758 efree(realpath);
1759 }
1760
1761 if (SUCCESS == php_stream_stat_path((char *) filename, &ssb)) {
1762
1763 efree(filename);
1764
1765 if (ssb.sb.st_mode & S_IFDIR) {
1766 return FAILURE;
1767 }
1768
1769 if (for_create == 1) {
1770 return FAILURE;
1771 }
1772
1773 return SUCCESS;
1774 } else {
1775 char *slash;
1776
1777 if (!for_create) {
1778 efree(filename);
1779 return FAILURE;
1780 }
1781
1782 slash = (char *) strrchr(filename, '/');
1783
1784 if (slash) {
1785 *slash = '\0';
1786 }
1787
1788 if (SUCCESS != php_stream_stat_path((char *) filename, &ssb)) {
1789 if (!slash) {
1790 if (!(realpath = expand_filepath(filename, NULL))) {
1791 efree(filename);
1792 return FAILURE;
1793 }
1794 #ifdef PHP_WIN32
1795 phar_unixify_path_separators(realpath, strlen(realpath));
1796 #endif
1797 slash = strstr(realpath, filename);
1798 if (slash) {
1799 slash += ((ext - fname) + ext_len);
1800 *slash = '\0';
1801 }
1802 slash = strrchr(realpath, '/');
1803
1804 if (slash) {
1805 *slash = '\0';
1806 } else {
1807 efree(realpath);
1808 efree(filename);
1809 return FAILURE;
1810 }
1811
1812 if (SUCCESS != php_stream_stat_path(realpath, &ssb)) {
1813 efree(realpath);
1814 efree(filename);
1815 return FAILURE;
1816 }
1817
1818 efree(realpath);
1819
1820 if (ssb.sb.st_mode & S_IFDIR) {
1821 efree(filename);
1822 return SUCCESS;
1823 }
1824 }
1825
1826 efree(filename);
1827 return FAILURE;
1828 }
1829
1830 efree(filename);
1831
1832 if (ssb.sb.st_mode & S_IFDIR) {
1833 return SUCCESS;
1834 }
1835
1836 return FAILURE;
1837 }
1838 }
1839
1840
1841
1842 static int phar_check_str(const char *fname, const char *ext_str, int ext_len, int executable, int for_create)
1843 {
1844 char test[51];
1845 const char *pos;
1846
1847 if (ext_len >= 50) {
1848 return FAILURE;
1849 }
1850
1851 if (executable == 1) {
1852
1853 memcpy(test, ext_str - 1, ext_len + 1);
1854 test[ext_len + 1] = '\0';
1855
1856
1857 pos = strstr(test, ".phar");
1858
1859 if (pos && (*(pos - 1) != '/')
1860 && (pos += 5) && (*pos == '\0' || *pos == '/' || *pos == '.')) {
1861 return phar_analyze_path(fname, ext_str, ext_len, for_create);
1862 } else {
1863 return FAILURE;
1864 }
1865 }
1866
1867
1868 if (!executable) {
1869 pos = strstr(ext_str, ".phar");
1870 if (!(pos && (*(pos - 1) != '/')
1871 && (pos += 5) && (*pos == '\0' || *pos == '/' || *pos == '.')) && *(ext_str + 1) != '.' && *(ext_str + 1) != '/' && *(ext_str + 1) != '\0') {
1872 return phar_analyze_path(fname, ext_str, ext_len, for_create);
1873 }
1874 } else {
1875 if (*(ext_str + 1) != '.' && *(ext_str + 1) != '/' && *(ext_str + 1) != '\0') {
1876 return phar_analyze_path(fname, ext_str, ext_len, for_create);
1877 }
1878 }
1879
1880 return FAILURE;
1881 }
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897 int phar_detect_phar_fname_ext(const char *filename, int filename_len, const char **ext_str, int *ext_len, int executable, int for_create, int is_complete)
1898 {
1899 const char *pos, *slash;
1900
1901 *ext_str = NULL;
1902 *ext_len = 0;
1903
1904 if (!filename_len || filename_len == 1) {
1905 return FAILURE;
1906 }
1907
1908 phar_request_initialize();
1909
1910 pos = memchr(filename, '/', filename_len);
1911
1912 if (pos && pos != filename) {
1913
1914 if (*(pos - 1) == ':' && (pos - filename) < filename_len - 1 && *(pos + 1) == '/') {
1915 *ext_len = -2;
1916 *ext_str = NULL;
1917 return FAILURE;
1918 }
1919 if (zend_hash_str_exists(&(PHAR_G(phar_alias_map)), (char *) filename, pos - filename)) {
1920 *ext_str = pos;
1921 *ext_len = -1;
1922 return FAILURE;
1923 }
1924
1925 if (PHAR_G(manifest_cached) && zend_hash_str_exists(&cached_alias, (char *) filename, pos - filename)) {
1926 *ext_str = pos;
1927 *ext_len = -1;
1928 return FAILURE;
1929 }
1930 }
1931
1932 if (zend_hash_num_elements(&(PHAR_G(phar_fname_map))) || PHAR_G(manifest_cached)) {
1933 phar_archive_data *pphar;
1934
1935 if (is_complete) {
1936 if (NULL != (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), (char *) filename, filename_len))) {
1937 *ext_str = filename + (filename_len - pphar->ext_len);
1938 woohoo:
1939 *ext_len = pphar->ext_len;
1940
1941 if (executable == 2) {
1942 return SUCCESS;
1943 }
1944
1945 if (executable == 1 && !pphar->is_data) {
1946 return SUCCESS;
1947 }
1948
1949 if (!executable && pphar->is_data) {
1950 return SUCCESS;
1951 }
1952
1953 return FAILURE;
1954 }
1955
1956 if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, (char *) filename, filename_len))) {
1957 *ext_str = filename + (filename_len - pphar->ext_len);
1958 goto woohoo;
1959 }
1960 } else {
1961 zend_string *str_key;
1962 zend_ulong unused;
1963
1964 for (zend_hash_internal_pointer_reset(&(PHAR_G(phar_fname_map)));
1965 HASH_KEY_NON_EXISTENT != zend_hash_get_current_key(&(PHAR_G(phar_fname_map)), &str_key, &unused);
1966 zend_hash_move_forward(&(PHAR_G(phar_fname_map)))
1967 ) {
1968 if (ZSTR_LEN(str_key) > (uint) filename_len) {
1969 continue;
1970 }
1971
1972 if (!memcmp(filename, ZSTR_VAL(str_key), ZSTR_LEN(str_key)) && ((uint)filename_len == ZSTR_LEN(str_key)
1973 || filename[ZSTR_LEN(str_key)] == '/' || filename[ZSTR_LEN(str_key)] == '\0')) {
1974 if (NULL == (pphar = zend_hash_get_current_data_ptr(&(PHAR_G(phar_fname_map))))) {
1975 break;
1976 }
1977 *ext_str = filename + (ZSTR_LEN(str_key) - pphar->ext_len);
1978 goto woohoo;
1979 }
1980 }
1981
1982 if (PHAR_G(manifest_cached)) {
1983 for (zend_hash_internal_pointer_reset(&cached_phars);
1984 HASH_KEY_NON_EXISTENT != zend_hash_get_current_key(&cached_phars, &str_key, &unused);
1985 zend_hash_move_forward(&cached_phars)
1986 ) {
1987 if (ZSTR_LEN(str_key) > (uint) filename_len) {
1988 continue;
1989 }
1990
1991 if (!memcmp(filename, ZSTR_VAL(str_key), ZSTR_LEN(str_key)) && ((uint)filename_len == ZSTR_LEN(str_key)
1992 || filename[ZSTR_LEN(str_key)] == '/' || filename[ZSTR_LEN(str_key)] == '\0')) {
1993 if (NULL == (pphar = zend_hash_get_current_data_ptr(&cached_phars))) {
1994 break;
1995 }
1996 *ext_str = filename + (ZSTR_LEN(str_key) - pphar->ext_len);
1997 goto woohoo;
1998 }
1999 }
2000 }
2001 }
2002 }
2003
2004 pos = memchr(filename + 1, '.', filename_len);
2005 next_extension:
2006 if (!pos) {
2007 return FAILURE;
2008 }
2009
2010 while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) {
2011 pos = memchr(pos + 1, '.', filename_len - (pos - filename) + 1);
2012 if (!pos) {
2013 return FAILURE;
2014 }
2015 }
2016
2017 slash = memchr(pos, '/', filename_len - (pos - filename));
2018
2019 if (!slash) {
2020
2021 *ext_str = pos;
2022 *ext_len = strlen(pos);
2023
2024
2025 switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create)) {
2026 case SUCCESS:
2027 return SUCCESS;
2028 case FAILURE:
2029
2030 return FAILURE;
2031 }
2032 }
2033
2034
2035 *ext_str = pos;
2036 *ext_len = slash - pos;
2037
2038 switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create)) {
2039 case SUCCESS:
2040 return SUCCESS;
2041 case FAILURE:
2042
2043 pos = strchr(pos + 1, '.');
2044 if (pos) {
2045 *ext_str = NULL;
2046 *ext_len = 0;
2047 }
2048 goto next_extension;
2049 }
2050
2051 return FAILURE;
2052 }
2053
2054
2055 static int php_check_dots(const char *element, int n)
2056 {
2057 for(n--; n >= 0; --n) {
2058 if (element[n] != '.') {
2059 return 1;
2060 }
2061 }
2062 return 0;
2063 }
2064
2065
2066 #define IS_DIRECTORY_UP(element, len) \
2067 (len >= 2 && !php_check_dots(element, len))
2068
2069 #define IS_DIRECTORY_CURRENT(element, len) \
2070 (len == 1 && element[0] == '.')
2071
2072 #define IS_BACKSLASH(c) ((c) == '/')
2073
2074
2075
2076
2077 char *phar_fix_filepath(char *path, int *new_len, int use_cwd)
2078 {
2079 char *newpath;
2080 int newpath_len;
2081 char *ptr;
2082 char *tok;
2083 int ptr_length, path_length = *new_len;
2084
2085 if (PHAR_G(cwd_len) && use_cwd && path_length > 2 && path[0] == '.' && path[1] == '/') {
2086 newpath_len = PHAR_G(cwd_len);
2087 newpath = emalloc(strlen(path) + newpath_len + 1);
2088 memcpy(newpath, PHAR_G(cwd), newpath_len);
2089 } else {
2090 newpath = emalloc(strlen(path) + 2);
2091 newpath[0] = '/';
2092 newpath_len = 1;
2093 }
2094
2095 ptr = path;
2096
2097 if (*ptr == '/') {
2098 ++ptr;
2099 }
2100
2101 tok = ptr;
2102
2103 do {
2104 ptr = memchr(ptr, '/', path_length - (ptr - path));
2105 } while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);
2106
2107 if (!ptr && (path_length - (tok - path))) {
2108 switch (path_length - (tok - path)) {
2109 case 1:
2110 if (*tok == '.') {
2111 efree(path);
2112 *new_len = 1;
2113 efree(newpath);
2114 return estrndup("/", 1);
2115 }
2116 break;
2117 case 2:
2118 if (tok[0] == '.' && tok[1] == '.') {
2119 efree(path);
2120 *new_len = 1;
2121 efree(newpath);
2122 return estrndup("/", 1);
2123 }
2124 }
2125 efree(newpath);
2126 return path;
2127 }
2128
2129 while (ptr) {
2130 ptr_length = ptr - tok;
2131 last_time:
2132 if (IS_DIRECTORY_UP(tok, ptr_length)) {
2133 #define PREVIOUS newpath[newpath_len - 1]
2134
2135 while (newpath_len > 1 && !IS_BACKSLASH(PREVIOUS)) {
2136 newpath_len--;
2137 }
2138
2139 if (newpath[0] != '/') {
2140 newpath[newpath_len] = '\0';
2141 } else if (newpath_len > 1) {
2142 --newpath_len;
2143 }
2144 } else if (!IS_DIRECTORY_CURRENT(tok, ptr_length)) {
2145 if (newpath_len > 1) {
2146 newpath[newpath_len++] = '/';
2147 memcpy(newpath + newpath_len, tok, ptr_length+1);
2148 } else {
2149 memcpy(newpath + newpath_len, tok, ptr_length+1);
2150 }
2151
2152 newpath_len += ptr_length;
2153 }
2154
2155 if (ptr == path + path_length) {
2156 break;
2157 }
2158
2159 tok = ++ptr;
2160
2161 do {
2162 ptr = memchr(ptr, '/', path_length - (ptr - path));
2163 } while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);
2164
2165 if (!ptr && (path_length - (tok - path))) {
2166 ptr_length = path_length - (tok - path);
2167 ptr = path + path_length;
2168 goto last_time;
2169 }
2170 }
2171
2172 efree(path);
2173 *new_len = newpath_len;
2174 newpath[newpath_len] = '\0';
2175 return erealloc(newpath, newpath_len + 1);
2176 }
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191 int phar_split_fname(const char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create)
2192 {
2193 const char *ext_str;
2194 #ifdef PHP_WIN32
2195 char *save;
2196 #endif
2197 int ext_len;
2198
2199 if (CHECK_NULL_PATH(filename, filename_len)) {
2200 return FAILURE;
2201 }
2202
2203 if (CHECK_NULL_PATH(filename, filename_len)) {
2204 return FAILURE;
2205 }
2206
2207 if (!strncasecmp(filename, "phar://", 7)) {
2208 filename += 7;
2209 filename_len -= 7;
2210 }
2211
2212 ext_len = 0;
2213 #ifdef PHP_WIN32
2214 save = filename;
2215 filename = estrndup(filename, filename_len);
2216 phar_unixify_path_separators(filename, filename_len);
2217 #endif
2218 if (phar_detect_phar_fname_ext(filename, filename_len, &ext_str, &ext_len, executable, for_create, 0) == FAILURE) {
2219 if (ext_len != -1) {
2220 if (!ext_str) {
2221
2222 #ifdef PHP_WIN32
2223 *arch = save;
2224 #else
2225 *arch = (char*)filename;
2226 #endif
2227 }
2228
2229 #ifdef PHP_WIN32
2230 efree(filename);
2231 #endif
2232 return FAILURE;
2233 }
2234
2235 ext_len = 0;
2236
2237 }
2238
2239 *arch_len = ext_str - filename + ext_len;
2240 *arch = estrndup(filename, *arch_len);
2241
2242 if (ext_str[ext_len]) {
2243 *entry_len = filename_len - *arch_len;
2244 *entry = estrndup(ext_str+ext_len, *entry_len);
2245 #ifdef PHP_WIN32
2246 phar_unixify_path_separators(*entry, *entry_len);
2247 #endif
2248 *entry = phar_fix_filepath(*entry, entry_len, 0);
2249 } else {
2250 *entry_len = 1;
2251 *entry = estrndup("/", 1);
2252 }
2253
2254 #ifdef PHP_WIN32
2255 efree(filename);
2256 #endif
2257
2258 return SUCCESS;
2259 }
2260
2261
2262
2263
2264
2265
2266 int phar_open_executed_filename(char *alias, int alias_len, char **error)
2267 {
2268 char *fname;
2269 php_stream *fp;
2270 int fname_len;
2271 zend_string *actual = NULL;
2272 int ret;
2273
2274 if (error) {
2275 *error = NULL;
2276 }
2277
2278 fname = (char*)zend_get_executed_filename();
2279 fname_len = strlen(fname);
2280
2281 if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, 0, REPORT_ERRORS, NULL, 0) == SUCCESS) {
2282 return SUCCESS;
2283 }
2284
2285 if (!strcmp(fname, "[no active file]")) {
2286 if (error) {
2287 spprintf(error, 0, "cannot initialize a phar outside of PHP execution");
2288 }
2289 return FAILURE;
2290 }
2291
2292 if (0 == zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
2293 if (error) {
2294 spprintf(error, 0, "__HALT_COMPILER(); must be declared in a phar");
2295 }
2296 return FAILURE;
2297 }
2298
2299
2300 #if PHP_API_VERSION < 20100412
2301 if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
2302 return FAILURE;
2303 }
2304 #endif
2305
2306 if (php_check_open_basedir(fname)) {
2307 return FAILURE;
2308 }
2309
2310 fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, &actual);
2311
2312 if (!fp) {
2313 if (error) {
2314 spprintf(error, 0, "unable to open phar for reading \"%s\"", fname);
2315 }
2316 if (actual) {
2317 zend_string_release(actual);
2318 }
2319 return FAILURE;
2320 }
2321
2322 if (actual) {
2323 fname = ZSTR_VAL(actual);
2324 fname_len = ZSTR_LEN(actual);
2325 }
2326
2327 ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, 0, error);
2328
2329 if (actual) {
2330 zend_string_release(actual);
2331 }
2332
2333 return ret;
2334 }
2335
2336
2337
2338
2339
2340 int phar_postprocess_file(phar_entry_data *idata, php_uint32 crc32, char **error, int process_zip)
2341 {
2342 php_uint32 crc = ~0;
2343 int len = idata->internal_file->uncompressed_filesize;
2344 php_stream *fp = idata->fp;
2345 phar_entry_info *entry = idata->internal_file;
2346
2347 if (error) {
2348 *error = NULL;
2349 }
2350
2351 if (entry->is_zip && process_zip > 0) {
2352
2353 phar_zip_file_header local;
2354 phar_zip_data_desc desc;
2355
2356 if (SUCCESS != phar_open_archive_fp(idata->phar)) {
2357 spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"", idata->phar->fname, entry->filename);
2358 return FAILURE;
2359 }
2360 php_stream_seek(phar_get_entrypfp(idata->internal_file), entry->header_offset, SEEK_SET);
2361
2362 if (sizeof(local) != php_stream_read(phar_get_entrypfp(idata->internal_file), (char *) &local, sizeof(local))) {
2363
2364 spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", idata->phar->fname, entry->filename);
2365 return FAILURE;
2366 }
2367
2368
2369 if (((PHAR_ZIP_16(local.flags)) & 0x8) == 0x8) {
2370 php_stream_seek(phar_get_entrypfp(idata->internal_file),
2371 entry->header_offset + sizeof(local) +
2372 PHAR_ZIP_16(local.filename_len) +
2373 PHAR_ZIP_16(local.extra_len) +
2374 entry->compressed_filesize, SEEK_SET);
2375 if (sizeof(desc) != php_stream_read(phar_get_entrypfp(idata->internal_file),
2376 (char *) &desc, sizeof(desc))) {
2377 spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")", idata->phar->fname, entry->filename);
2378 return FAILURE;
2379 }
2380 if (desc.signature[0] == 'P' && desc.signature[1] == 'K') {
2381 memcpy(&(local.crc32), &(desc.crc32), 12);
2382 } else {
2383
2384 memcpy(&(local.crc32), &desc, 12);
2385 }
2386 }
2387
2388 if (entry->filename_len != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) {
2389 spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local header of file \"%s\" does not match central directory)", idata->phar->fname, entry->filename);
2390 return FAILURE;
2391 }
2392
2393
2394 entry->offset = entry->offset_abs =
2395 sizeof(local) + entry->header_offset + PHAR_ZIP_16(local.filename_len) + PHAR_ZIP_16(local.extra_len);
2396
2397 if (idata->zero && idata->zero != entry->offset_abs) {
2398 idata->zero = entry->offset_abs;
2399 }
2400 }
2401
2402 if (process_zip == 1) {
2403 return SUCCESS;
2404 }
2405
2406 php_stream_seek(fp, idata->zero, SEEK_SET);
2407
2408 while (len--) {
2409 CRC32(crc, php_stream_getc(fp));
2410 }
2411
2412 php_stream_seek(fp, idata->zero, SEEK_SET);
2413
2414 if (~crc == crc32) {
2415 entry->is_crc_checked = 1;
2416 return SUCCESS;
2417 } else {
2418 spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (crc32 mismatch on file \"%s\")", idata->phar->fname, entry->filename);
2419 return FAILURE;
2420 }
2421 }
2422
2423
2424 static inline void phar_set_32(char *buffer, int var)
2425 {
2426 #ifdef WORDS_BIGENDIAN
2427 *((buffer) + 3) = (unsigned char) (((var) >> 24) & 0xFF);
2428 *((buffer) + 2) = (unsigned char) (((var) >> 16) & 0xFF);
2429 *((buffer) + 1) = (unsigned char) (((var) >> 8) & 0xFF);
2430 *((buffer) + 0) = (unsigned char) ((var) & 0xFF);
2431 #else
2432 memcpy(buffer, &var, sizeof(var));
2433 #endif
2434 }
2435
2436 static int phar_flush_clean_deleted_apply(zval *zv)
2437 {
2438 phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
2439
2440 if (entry->fp_refcount <= 0 && entry->is_deleted) {
2441 return ZEND_HASH_APPLY_REMOVE;
2442 } else {
2443 return ZEND_HASH_APPLY_KEEP;
2444 }
2445 }
2446
2447
2448 #include "stub.h"
2449
2450 zend_string *phar_create_default_stub(const char *index_php, const char *web_index, char **error)
2451 {
2452 int index_len, web_len;
2453
2454 if (error) {
2455 *error = NULL;
2456 }
2457
2458 if (!index_php) {
2459 index_php = "index.php";
2460 }
2461
2462 if (!web_index) {
2463 web_index = "index.php";
2464 }
2465
2466 index_len = strlen(index_php);
2467 web_len = strlen(web_index);
2468
2469 if (index_len > 400) {
2470
2471 if (error) {
2472 spprintf(error, 0, "Illegal filename passed in for stub creation, was %d characters long, and only 400 or less is allowed", index_len);
2473 return NULL;
2474 }
2475 }
2476
2477 if (web_len > 400) {
2478
2479 if (error) {
2480 spprintf(error, 0, "Illegal web filename passed in for stub creation, was %d characters long, and only 400 or less is allowed", web_len);
2481 return NULL;
2482 }
2483 }
2484
2485 return phar_get_stub(index_php, web_index, index_len+1, web_len+1);
2486 }
2487
2488
2489
2490
2491
2492
2493
2494
2495 int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int convert, char **error)
2496 {
2497 char halt_stub[] = "__HALT_COMPILER();";
2498 zend_string *newstub;
2499 char *tmp;
2500 phar_entry_info *entry, *newentry;
2501 int halt_offset, restore_alias_len, global_flags = 0, closeoldfile;
2502 char *pos, has_dirs = 0;
2503 char manifest[18], entry_buffer[24];
2504 zend_off_t manifest_ftell;
2505 zend_long offset;
2506 size_t wrote;
2507 php_uint32 manifest_len, mytime, loc, new_manifest_count;
2508 php_uint32 newcrc32;
2509 php_stream *file, *oldfile, *newfile, *stubfile;
2510 php_stream_filter *filter;
2511 php_serialize_data_t metadata_hash;
2512 smart_str main_metadata_str = {0};
2513 int free_user_stub, free_fp = 1, free_ufp = 1;
2514 int manifest_hack = 0;
2515
2516 if (phar->is_persistent) {
2517 if (error) {
2518 spprintf(error, 0, "internal error: attempt to flush cached zip-based phar \"%s\"", phar->fname);
2519 }
2520 return EOF;
2521 }
2522
2523 if (error) {
2524 *error = NULL;
2525 }
2526
2527 if (!zend_hash_num_elements(&phar->manifest) && !user_stub) {
2528 return EOF;
2529 }
2530
2531 zend_hash_clean(&phar->virtual_dirs);
2532
2533 if (phar->is_zip) {
2534 return phar_zip_flush(phar, user_stub, len, convert, error);
2535 }
2536
2537 if (phar->is_tar) {
2538 return phar_tar_flush(phar, user_stub, len, convert, error);
2539 }
2540
2541 if (PHAR_G(readonly)) {
2542 return EOF;
2543 }
2544
2545 if (phar->fp && !phar->is_brandnew) {
2546 oldfile = phar->fp;
2547 closeoldfile = 0;
2548 php_stream_rewind(oldfile);
2549 } else {
2550 oldfile = php_stream_open_wrapper(phar->fname, "rb", 0, NULL);
2551 closeoldfile = oldfile != NULL;
2552 }
2553 newfile = php_stream_fopen_tmpfile();
2554 if (!newfile) {
2555 if (error) {
2556 spprintf(error, 0, "unable to create temporary file");
2557 }
2558 if (closeoldfile) {
2559 php_stream_close(oldfile);
2560 }
2561 return EOF;
2562 }
2563
2564 if (user_stub) {
2565 zend_string *suser_stub;
2566 if (len < 0) {
2567
2568 if (!(php_stream_from_zval_no_verify(stubfile, (zval *)user_stub))) {
2569 if (closeoldfile) {
2570 php_stream_close(oldfile);
2571 }
2572 php_stream_close(newfile);
2573 if (error) {
2574 spprintf(error, 0, "unable to access resource to copy stub to new phar \"%s\"", phar->fname);
2575 }
2576 return EOF;
2577 }
2578 if (len == -1) {
2579 len = PHP_STREAM_COPY_ALL;
2580 } else {
2581 len = -len;
2582 }
2583 user_stub = 0;
2584
2585 if (!(suser_stub = php_stream_copy_to_mem(stubfile, len, 0))) {
2586 if (closeoldfile) {
2587 php_stream_close(oldfile);
2588 }
2589 php_stream_close(newfile);
2590 if (error) {
2591 spprintf(error, 0, "unable to read resource to copy stub to new phar \"%s\"", phar->fname);
2592 }
2593 return EOF;
2594 }
2595 free_user_stub = 1;
2596 user_stub = ZSTR_VAL(suser_stub);
2597 len = ZSTR_LEN(suser_stub);
2598 } else {
2599 free_user_stub = 0;
2600 }
2601 tmp = estrndup(user_stub, len);
2602 if ((pos = php_stristr(tmp, halt_stub, len, sizeof(halt_stub) - 1)) == NULL) {
2603 efree(tmp);
2604 if (closeoldfile) {
2605 php_stream_close(oldfile);
2606 }
2607 php_stream_close(newfile);
2608 if (error) {
2609 spprintf(error, 0, "illegal stub for phar \"%s\"", phar->fname);
2610 }
2611 if (free_user_stub) {
2612 zend_string_free(suser_stub);
2613 }
2614 return EOF;
2615 }
2616 pos = user_stub + (pos - tmp);
2617 efree(tmp);
2618 len = pos - user_stub + 18;
2619 if ((size_t)len != php_stream_write(newfile, user_stub, len)
2620 || 5 != php_stream_write(newfile, " ?>\r\n", 5)) {
2621 if (closeoldfile) {
2622 php_stream_close(oldfile);
2623 }
2624 php_stream_close(newfile);
2625 if (error) {
2626 spprintf(error, 0, "unable to create stub from string in new phar \"%s\"", phar->fname);
2627 }
2628 if (free_user_stub) {
2629 zend_string_free(suser_stub);
2630 }
2631 return EOF;
2632 }
2633 phar->halt_offset = len + 5;
2634 if (free_user_stub) {
2635 zend_string_free(suser_stub);
2636 }
2637 } else {
2638 size_t written;
2639
2640 if (!user_stub && phar->halt_offset && oldfile && !phar->is_brandnew) {
2641 php_stream_copy_to_stream_ex(oldfile, newfile, phar->halt_offset, &written);
2642 newstub = NULL;
2643 } else {
2644
2645 newstub = phar_create_default_stub(NULL, NULL, NULL);
2646 phar->halt_offset = ZSTR_LEN(newstub);
2647 written = php_stream_write(newfile, ZSTR_VAL(newstub), phar->halt_offset);
2648 }
2649 if (phar->halt_offset != written) {
2650 if (closeoldfile) {
2651 php_stream_close(oldfile);
2652 }
2653 php_stream_close(newfile);
2654 if (error) {
2655 if (newstub) {
2656 spprintf(error, 0, "unable to create stub in new phar \"%s\"", phar->fname);
2657 } else {
2658 spprintf(error, 0, "unable to copy stub of old phar to new phar \"%s\"", phar->fname);
2659 }
2660 }
2661 if (newstub) {
2662 zend_string_free(newstub);
2663 }
2664 return EOF;
2665 }
2666 if (newstub) {
2667 zend_string_free(newstub);
2668 }
2669 }
2670 manifest_ftell = php_stream_tell(newfile);
2671 halt_offset = manifest_ftell;
2672
2673
2674
2675
2676 zend_hash_apply(&phar->manifest, phar_flush_clean_deleted_apply);
2677
2678
2679 main_metadata_str.s = NULL;
2680 if (Z_TYPE(phar->metadata) != IS_UNDEF) {
2681 PHP_VAR_SERIALIZE_INIT(metadata_hash);
2682 php_var_serialize(&main_metadata_str, &phar->metadata, &metadata_hash);
2683 PHP_VAR_SERIALIZE_DESTROY(metadata_hash);
2684 }
2685 new_manifest_count = 0;
2686 offset = 0;
2687 for (zend_hash_internal_pointer_reset(&phar->manifest);
2688 zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
2689 zend_hash_move_forward(&phar->manifest)) {
2690 if ((entry = zend_hash_get_current_data_ptr(&phar->manifest)) == NULL) {
2691 continue;
2692 }
2693 if (entry->cfp) {
2694
2695 php_stream_close(entry->cfp);
2696 entry->cfp = 0;
2697 }
2698 if (entry->is_deleted || entry->is_mounted) {
2699
2700 continue;
2701 }
2702 if (!entry->is_modified && entry->fp_refcount) {
2703
2704 switch (entry->fp_type) {
2705 case PHAR_FP:
2706 free_fp = 0;
2707 break;
2708 case PHAR_UFP:
2709 free_ufp = 0;
2710 default:
2711 break;
2712 }
2713 }
2714
2715 ++new_manifest_count;
2716 phar_add_virtual_dirs(phar, entry->filename, entry->filename_len);
2717
2718 if (entry->is_dir) {
2719
2720 has_dirs = 1;
2721 }
2722 if (Z_TYPE(entry->metadata) != IS_UNDEF) {
2723 if (entry->metadata_str.s) {
2724 smart_str_free(&entry->metadata_str);
2725 }
2726 entry->metadata_str.s = NULL;
2727 PHP_VAR_SERIALIZE_INIT(metadata_hash);
2728 php_var_serialize(&entry->metadata_str, &entry->metadata, &metadata_hash);
2729 PHP_VAR_SERIALIZE_DESTROY(metadata_hash);
2730 } else {
2731 if (entry->metadata_str.s) {
2732 smart_str_free(&entry->metadata_str);
2733 }
2734 entry->metadata_str.s = NULL;
2735 }
2736
2737
2738 offset += 4 + entry->filename_len + sizeof(entry_buffer) + (entry->metadata_str.s ? ZSTR_LEN(entry->metadata_str.s) : 0) + (entry->is_dir ? 1 : 0);
2739
2740
2741 if ((oldfile && !entry->is_modified) || entry->is_dir) {
2742 if (entry->fp_type == PHAR_UFP) {
2743
2744 entry->fp_type = PHAR_FP;
2745 }
2746 continue;
2747 }
2748 if (!phar_get_efp(entry, 0)) {
2749
2750 newentry = phar_open_jit(phar, entry, error);
2751 if (!newentry) {
2752
2753 efree(*error);
2754 *error = NULL;
2755 continue;
2756 }
2757 entry = newentry;
2758 }
2759 file = phar_get_efp(entry, 0);
2760 if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1)) {
2761 if (closeoldfile) {
2762 php_stream_close(oldfile);
2763 }
2764 php_stream_close(newfile);
2765 if (error) {
2766 spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
2767 }
2768 return EOF;
2769 }
2770 newcrc32 = ~0;
2771 mytime = entry->uncompressed_filesize;
2772 for (loc = 0;loc < mytime; ++loc) {
2773 CRC32(newcrc32, php_stream_getc(file));
2774 }
2775 entry->crc32 = ~newcrc32;
2776 entry->is_crc_checked = 1;
2777 if (!(entry->flags & PHAR_ENT_COMPRESSION_MASK)) {
2778
2779 entry->compressed_filesize = entry->uncompressed_filesize;
2780 continue;
2781 }
2782 filter = php_stream_filter_create(phar_compress_filter(entry, 0), NULL, 0);
2783 if (!filter) {
2784 if (closeoldfile) {
2785 php_stream_close(oldfile);
2786 }
2787 php_stream_close(newfile);
2788 if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
2789 if (error) {
2790 spprintf(error, 0, "unable to gzip compress file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
2791 }
2792 } else {
2793 if (error) {
2794 spprintf(error, 0, "unable to bzip2 compress file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
2795 }
2796 }
2797 return EOF;
2798 }
2799
2800
2801
2802
2803 entry->cfp = php_stream_fopen_tmpfile();
2804 if (!entry->cfp) {
2805 if (error) {
2806 spprintf(error, 0, "unable to create temporary file");
2807 }
2808 if (closeoldfile) {
2809 php_stream_close(oldfile);
2810 }
2811 php_stream_close(newfile);
2812 return EOF;
2813 }
2814 php_stream_flush(file);
2815 if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
2816 if (closeoldfile) {
2817 php_stream_close(oldfile);
2818 }
2819 php_stream_close(newfile);
2820 if (error) {
2821 spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
2822 }
2823 return EOF;
2824 }
2825 php_stream_filter_append((&entry->cfp->writefilters), filter);
2826 if (SUCCESS != php_stream_copy_to_stream_ex(file, entry->cfp, entry->uncompressed_filesize, NULL)) {
2827 if (closeoldfile) {
2828 php_stream_close(oldfile);
2829 }
2830 php_stream_close(newfile);
2831 if (error) {
2832 spprintf(error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
2833 }
2834 return EOF;
2835 }
2836 php_stream_filter_flush(filter, 1);
2837 php_stream_flush(entry->cfp);
2838 php_stream_filter_remove(filter, 1);
2839 php_stream_seek(entry->cfp, 0, SEEK_END);
2840 entry->compressed_filesize = (php_uint32) php_stream_tell(entry->cfp);
2841
2842 php_stream_rewind(entry->cfp);
2843 entry->old_flags = entry->flags;
2844 entry->is_modified = 1;
2845 global_flags |= (entry->flags & PHAR_ENT_COMPRESSION_MASK);
2846 }
2847 global_flags |= PHAR_HDR_SIGNATURE;
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859 restore_alias_len = phar->alias_len;
2860 if (phar->is_temporary_alias) {
2861 phar->alias_len = 0;
2862 }
2863
2864 manifest_len = offset + phar->alias_len + sizeof(manifest) + (main_metadata_str.s ? ZSTR_LEN(main_metadata_str.s) : 0);
2865 phar_set_32(manifest, manifest_len);
2866
2867 if(manifest[0] == '\r' || manifest[0] == '\n') {
2868 manifest_len++;
2869 phar_set_32(manifest, manifest_len);
2870 manifest_hack = 1;
2871 }
2872 phar_set_32(manifest+4, new_manifest_count);
2873 if (has_dirs) {
2874 *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF);
2875 *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION) & 0xF0));
2876 } else {
2877 *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION_NODIR) >> 8) & 0xFF);
2878 *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION_NODIR) & 0xF0));
2879 }
2880 phar_set_32(manifest+10, global_flags);
2881 phar_set_32(manifest+14, phar->alias_len);
2882
2883
2884 if (sizeof(manifest) != php_stream_write(newfile, manifest, sizeof(manifest))
2885 || (size_t)phar->alias_len != php_stream_write(newfile, phar->alias, phar->alias_len)) {
2886
2887 if (closeoldfile) {
2888 php_stream_close(oldfile);
2889 }
2890
2891 php_stream_close(newfile);
2892 phar->alias_len = restore_alias_len;
2893
2894 if (error) {
2895 spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname);
2896 }
2897
2898 return EOF;
2899 }
2900
2901 phar->alias_len = restore_alias_len;
2902
2903 phar_set_32(manifest, main_metadata_str.s ? ZSTR_LEN(main_metadata_str.s) : 0);
2904 if (4 != php_stream_write(newfile, manifest, 4) || ((main_metadata_str.s ? ZSTR_LEN(main_metadata_str.s) : 0)
2905 && ZSTR_LEN(main_metadata_str.s) != php_stream_write(newfile, ZSTR_VAL(main_metadata_str.s), ZSTR_LEN(main_metadata_str.s)))) {
2906 smart_str_free(&main_metadata_str);
2907
2908 if (closeoldfile) {
2909 php_stream_close(oldfile);
2910 }
2911
2912 php_stream_close(newfile);
2913 phar->alias_len = restore_alias_len;
2914
2915 if (error) {
2916 spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname);
2917 }
2918
2919 return EOF;
2920 }
2921 smart_str_free(&main_metadata_str);
2922
2923
2924 manifest_ftell = php_stream_tell(newfile);
2925
2926
2927 for (zend_hash_internal_pointer_reset(&phar->manifest);
2928 zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
2929 zend_hash_move_forward(&phar->manifest)) {
2930
2931 if ((entry = zend_hash_get_current_data_ptr(&phar->manifest)) == NULL) {
2932 continue;
2933 }
2934
2935 if (entry->is_deleted || entry->is_mounted) {
2936
2937 continue;
2938 }
2939
2940 if (entry->is_dir) {
2941
2942 phar_set_32(entry_buffer, entry->filename_len + 1);
2943 } else {
2944 phar_set_32(entry_buffer, entry->filename_len);
2945 }
2946
2947 if (4 != php_stream_write(newfile, entry_buffer, 4)
2948 || entry->filename_len != php_stream_write(newfile, entry->filename, entry->filename_len)
2949 || (entry->is_dir && 1 != php_stream_write(newfile, "/", 1))) {
2950 if (closeoldfile) {
2951 php_stream_close(oldfile);
2952 }
2953 php_stream_close(newfile);
2954 if (error) {
2955 if (entry->is_dir) {
2956 spprintf(error, 0, "unable to write filename of directory \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
2957 } else {
2958 spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
2959 }
2960 }
2961 return EOF;
2962 }
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973 mytime = time(NULL);
2974 phar_set_32(entry_buffer, entry->uncompressed_filesize);
2975 phar_set_32(entry_buffer+4, mytime);
2976 phar_set_32(entry_buffer+8, entry->compressed_filesize);
2977 phar_set_32(entry_buffer+12, entry->crc32);
2978 phar_set_32(entry_buffer+16, entry->flags);
2979 phar_set_32(entry_buffer+20, entry->metadata_str.s ? ZSTR_LEN(entry->metadata_str.s) : 0);
2980
2981 if (sizeof(entry_buffer) != php_stream_write(newfile, entry_buffer, sizeof(entry_buffer))
2982 || (entry->metadata_str.s &&
2983 ZSTR_LEN(entry->metadata_str.s) != php_stream_write(newfile, ZSTR_VAL(entry->metadata_str.s), ZSTR_LEN(entry->metadata_str.s)))) {
2984 if (closeoldfile) {
2985 php_stream_close(oldfile);
2986 }
2987
2988 php_stream_close(newfile);
2989
2990 if (error) {
2991 spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
2992 }
2993
2994 return EOF;
2995 }
2996 }
2997
2998 if(manifest_hack) {
2999 if(1 != php_stream_write(newfile, manifest, 1)) {
3000 if (closeoldfile) {
3001 php_stream_close(oldfile);
3002 }
3003
3004 php_stream_close(newfile);
3005
3006 if (error) {
3007 spprintf(error, 0, "unable to write manifest padding byte");
3008 }
3009
3010 return EOF;
3011 }
3012 }
3013
3014
3015 offset = php_stream_tell(newfile);
3016 for (zend_hash_internal_pointer_reset(&phar->manifest);
3017 zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
3018 zend_hash_move_forward(&phar->manifest)) {
3019
3020 if ((entry = zend_hash_get_current_data_ptr(&phar->manifest)) == NULL) {
3021 continue;
3022 }
3023
3024 if (entry->is_deleted || entry->is_dir || entry->is_mounted) {
3025 continue;
3026 }
3027
3028 if (entry->cfp) {
3029 file = entry->cfp;
3030 php_stream_rewind(file);
3031 } else {
3032 file = phar_get_efp(entry, 0);
3033 if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
3034 if (closeoldfile) {
3035 php_stream_close(oldfile);
3036 }
3037 php_stream_close(newfile);
3038 if (error) {
3039 spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
3040 }
3041 return EOF;
3042 }
3043 }
3044
3045 if (!file) {
3046 if (closeoldfile) {
3047 php_stream_close(oldfile);
3048 }
3049 php_stream_close(newfile);
3050 if (error) {
3051 spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
3052 }
3053 return EOF;
3054 }
3055
3056
3057 entry->offset = entry->offset_abs = offset;
3058 offset += entry->compressed_filesize;
3059 if (php_stream_copy_to_stream_ex(file, newfile, entry->compressed_filesize, &wrote) == FAILURE) {
3060 if (closeoldfile) {
3061 php_stream_close(oldfile);
3062 }
3063
3064 php_stream_close(newfile);
3065
3066 if (error) {
3067 spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
3068 }
3069
3070 return EOF;
3071 }
3072
3073 entry->is_modified = 0;
3074
3075 if (entry->cfp) {
3076 php_stream_close(entry->cfp);
3077 entry->cfp = NULL;
3078 }
3079
3080 if (entry->fp_type == PHAR_MOD) {
3081
3082 if (entry->fp_refcount == 0 && entry->fp != phar->fp && entry->fp != phar->ufp) {
3083 php_stream_close(entry->fp);
3084 }
3085
3086 entry->fp = NULL;
3087 entry->fp_type = PHAR_FP;
3088 } else if (entry->fp_type == PHAR_UFP) {
3089 entry->fp_type = PHAR_FP;
3090 }
3091 }
3092
3093
3094 if (global_flags & PHAR_HDR_SIGNATURE) {
3095 char sig_buf[4];
3096
3097 php_stream_rewind(newfile);
3098
3099 if (phar->signature) {
3100 efree(phar->signature);
3101 phar->signature = NULL;
3102 }
3103
3104 switch(phar->sig_flags) {
3105 #ifndef PHAR_HASH_OK
3106 case PHAR_SIG_SHA512:
3107 case PHAR_SIG_SHA256:
3108 if (closeoldfile) {
3109 php_stream_close(oldfile);
3110 }
3111 php_stream_close(newfile);
3112 if (error) {
3113 spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\" with requested hash type", entry->filename, phar->fname);
3114 }
3115 return EOF;
3116 #endif
3117 default: {
3118 char *digest = NULL;
3119 int digest_len;
3120
3121 if (FAILURE == phar_create_signature(phar, newfile, &digest, &digest_len, error)) {
3122 if (error) {
3123 char *save = *error;
3124 spprintf(error, 0, "phar error: unable to write signature: %s", save);
3125 efree(save);
3126 }
3127 if (digest) {
3128 efree(digest);
3129 }
3130 if (closeoldfile) {
3131 php_stream_close(oldfile);
3132 }
3133 php_stream_close(newfile);
3134 return EOF;
3135 }
3136
3137 php_stream_write(newfile, digest, digest_len);
3138 efree(digest);
3139 if (phar->sig_flags == PHAR_SIG_OPENSSL) {
3140 phar_set_32(sig_buf, digest_len);
3141 php_stream_write(newfile, sig_buf, 4);
3142 }
3143 break;
3144 }
3145 }
3146 phar_set_32(sig_buf, phar->sig_flags);
3147 php_stream_write(newfile, sig_buf, 4);
3148 php_stream_write(newfile, "GBMB", 4);
3149 }
3150
3151
3152
3153
3154 if (phar->fp && free_fp) {
3155 php_stream_close(phar->fp);
3156 }
3157
3158 if (phar->ufp) {
3159 if (free_ufp) {
3160 php_stream_close(phar->ufp);
3161 }
3162 phar->ufp = NULL;
3163 }
3164
3165 if (closeoldfile) {
3166 php_stream_close(oldfile);
3167 }
3168
3169 phar->internal_file_start = halt_offset + manifest_len + 4;
3170 phar->halt_offset = halt_offset;
3171 phar->is_brandnew = 0;
3172
3173 php_stream_rewind(newfile);
3174
3175 if (phar->donotflush) {
3176
3177 phar->fp = newfile;
3178 } else {
3179 phar->fp = php_stream_open_wrapper(phar->fname, "w+b", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, NULL);
3180 if (!phar->fp) {
3181 phar->fp = newfile;
3182 if (error) {
3183 spprintf(error, 4096, "unable to open new phar \"%s\" for writing", phar->fname);
3184 }
3185 return EOF;
3186 }
3187
3188 if (phar->flags & PHAR_FILE_COMPRESSED_GZ) {
3189
3190 zval filterparams;
3191
3192 array_init(&filterparams);
3193 add_assoc_long(&filterparams, "window", MAX_WBITS+16);
3194 filter = php_stream_filter_create("zlib.deflate", &filterparams, php_stream_is_persistent(phar->fp));
3195 zval_dtor(&filterparams);
3196
3197 if (!filter) {
3198 if (error) {
3199 spprintf(error, 4096, "unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->fname);
3200 }
3201 return EOF;
3202 }
3203
3204 php_stream_filter_append(&phar->fp->writefilters, filter);
3205 php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL);
3206 php_stream_filter_flush(filter, 1);
3207 php_stream_filter_remove(filter, 1);
3208 php_stream_close(phar->fp);
3209
3210 phar->fp = newfile;
3211 } else if (phar->flags & PHAR_FILE_COMPRESSED_BZ2) {
3212 filter = php_stream_filter_create("bzip2.compress", NULL, php_stream_is_persistent(phar->fp));
3213 php_stream_filter_append(&phar->fp->writefilters, filter);
3214 php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL);
3215 php_stream_filter_flush(filter, 1);
3216 php_stream_filter_remove(filter, 1);
3217 php_stream_close(phar->fp);
3218
3219 phar->fp = newfile;
3220 } else {
3221 php_stream_copy_to_stream_ex(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL);
3222
3223 php_stream_close(newfile);
3224 }
3225 }
3226
3227 if (-1 == php_stream_seek(phar->fp, phar->halt_offset, SEEK_SET)) {
3228 if (error) {
3229 spprintf(error, 0, "unable to seek to __HALT_COMPILER(); in new phar \"%s\"", phar->fname);
3230 }
3231 return EOF;
3232 }
3233
3234 return EOF;
3235 }
3236
3237
3238 #ifdef COMPILE_DL_PHAR
3239 #ifdef ZTS
3240 ZEND_TSRMLS_CACHE_DEFINE()
3241 #endif
3242 ZEND_GET_MODULE(phar)
3243 #endif
3244
3245
3246
3247
3248
3249 zend_function_entry phar_functions[] = {
3250 PHP_FE_END
3251 };
3252
3253
3254 static size_t phar_zend_stream_reader(void *handle, char *buf, size_t len)
3255 {
3256 return php_stream_read(phar_get_pharfp((phar_archive_data*)handle), buf, len);
3257 }
3258
3259
3260 static size_t phar_zend_stream_fsizer(void *handle)
3261 {
3262 return ((phar_archive_data*)handle)->halt_offset + 32;
3263 }
3264
3265 zend_op_array *(*phar_orig_compile_file)(zend_file_handle *file_handle, int type);
3266 #define phar_orig_zend_open zend_stream_open_function
3267
3268 static zend_string *phar_resolve_path(const char *filename, int filename_len)
3269 {
3270 return phar_find_in_include_path((char *) filename, filename_len, NULL);
3271 }
3272
3273 static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type)
3274 {
3275 zend_op_array *res;
3276 char *name = NULL;
3277 int failed;
3278 phar_archive_data *phar;
3279
3280 if (!file_handle || !file_handle->filename) {
3281 return phar_orig_compile_file(file_handle, type);
3282 }
3283 if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, "://")) {
3284 if (SUCCESS == phar_open_from_filename((char*)file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL)) {
3285 if (phar->is_zip || phar->is_tar) {
3286 zend_file_handle f = *file_handle;
3287
3288
3289 spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
3290 if (SUCCESS == phar_orig_zend_open((const char *)name, file_handle)) {
3291 efree(name);
3292 name = NULL;
3293 file_handle->filename = f.filename;
3294 if (file_handle->opened_path) {
3295 efree(file_handle->opened_path);
3296 }
3297 file_handle->opened_path = f.opened_path;
3298 file_handle->free_filename = f.free_filename;
3299 } else {
3300 *file_handle = f;
3301 }
3302 } else if (phar->flags & PHAR_FILE_COMPRESSION_MASK) {
3303
3304 file_handle->type = ZEND_HANDLE_STREAM;
3305
3306 file_handle->handle.stream.handle = phar;
3307 file_handle->handle.stream.reader = phar_zend_stream_reader;
3308 file_handle->handle.stream.closer = NULL;
3309 file_handle->handle.stream.fsizer = phar_zend_stream_fsizer;
3310 file_handle->handle.stream.isatty = 0;
3311 phar->is_persistent ?
3312 php_stream_rewind(PHAR_G(cached_fp)[phar->phar_pos].fp) :
3313 php_stream_rewind(phar->fp);
3314 memset(&file_handle->handle.stream.mmap, 0, sizeof(file_handle->handle.stream.mmap));
3315 }
3316 }
3317 }
3318
3319 zend_try {
3320 failed = 0;
3321 CG(zend_lineno) = 0;
3322 res = phar_orig_compile_file(file_handle, type);
3323 } zend_catch {
3324 failed = 1;
3325 res = NULL;
3326 } zend_end_try();
3327
3328 if (name) {
3329 efree(name);
3330 }
3331
3332 if (failed) {
3333 zend_bailout();
3334 }
3335
3336 return res;
3337 }
3338
3339
3340 typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int);
3341 typedef zend_compile_t* (compile_hook)(zend_compile_t *ptr);
3342
3343 static void mime_type_dtor(zval *zv)
3344 {
3345 free(Z_PTR_P(zv));
3346 }
3347
3348 PHP_GINIT_FUNCTION(phar)
3349 {
3350 #if defined(COMPILE_DL_PHAR) && defined(ZTS)
3351 ZEND_TSRMLS_CACHE_UPDATE();
3352 #endif
3353 phar_mime_type mime;
3354
3355 memset(phar_globals, 0, sizeof(zend_phar_globals));
3356 phar_globals->readonly = 1;
3357
3358 zend_hash_init(&phar_globals->mime_types, 0, NULL, mime_type_dtor, 1);
3359
3360 #define PHAR_SET_MIME(mimetype, ret, fileext) \
3361 mime.mime = mimetype; \
3362 mime.len = sizeof((mimetype))+1; \
3363 mime.type = ret; \
3364 zend_hash_str_add_mem(&phar_globals->mime_types, fileext, sizeof(fileext)-1, (void *)&mime, sizeof(phar_mime_type)); \
3365
3366 PHAR_SET_MIME("text/html", PHAR_MIME_PHPS, "phps")
3367 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "c")
3368 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "cc")
3369 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "cpp")
3370 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "c++")
3371 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "dtd")
3372 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "h")
3373 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "log")
3374 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "rng")
3375 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "txt")
3376 PHAR_SET_MIME("text/plain", PHAR_MIME_OTHER, "xsd")
3377 PHAR_SET_MIME("", PHAR_MIME_PHP, "php")
3378 PHAR_SET_MIME("", PHAR_MIME_PHP, "inc")
3379 PHAR_SET_MIME("video/avi", PHAR_MIME_OTHER, "avi")
3380 PHAR_SET_MIME("image/bmp", PHAR_MIME_OTHER, "bmp")
3381 PHAR_SET_MIME("text/css", PHAR_MIME_OTHER, "css")
3382 PHAR_SET_MIME("image/gif", PHAR_MIME_OTHER, "gif")
3383 PHAR_SET_MIME("text/html", PHAR_MIME_OTHER, "htm")
3384 PHAR_SET_MIME("text/html", PHAR_MIME_OTHER, "html")
3385 PHAR_SET_MIME("text/html", PHAR_MIME_OTHER, "htmls")
3386 PHAR_SET_MIME("image/x-ico", PHAR_MIME_OTHER, "ico")
3387 PHAR_SET_MIME("image/jpeg", PHAR_MIME_OTHER, "jpe")
3388 PHAR_SET_MIME("image/jpeg", PHAR_MIME_OTHER, "jpg")
3389 PHAR_SET_MIME("image/jpeg", PHAR_MIME_OTHER, "jpeg")
3390 PHAR_SET_MIME("application/x-javascript", PHAR_MIME_OTHER, "js")
3391 PHAR_SET_MIME("audio/midi", PHAR_MIME_OTHER, "midi")
3392 PHAR_SET_MIME("audio/midi", PHAR_MIME_OTHER, "mid")
3393 PHAR_SET_MIME("audio/mod", PHAR_MIME_OTHER, "mod")
3394 PHAR_SET_MIME("movie/quicktime", PHAR_MIME_OTHER, "mov")
3395 PHAR_SET_MIME("audio/mp3", PHAR_MIME_OTHER, "mp3")
3396 PHAR_SET_MIME("video/mpeg", PHAR_MIME_OTHER, "mpg")
3397 PHAR_SET_MIME("video/mpeg", PHAR_MIME_OTHER, "mpeg")
3398 PHAR_SET_MIME("application/pdf", PHAR_MIME_OTHER, "pdf")
3399 PHAR_SET_MIME("image/png", PHAR_MIME_OTHER, "png")
3400 PHAR_SET_MIME("application/shockwave-flash", PHAR_MIME_OTHER, "swf")
3401 PHAR_SET_MIME("image/tiff", PHAR_MIME_OTHER, "tif")
3402 PHAR_SET_MIME("image/tiff", PHAR_MIME_OTHER, "tiff")
3403 PHAR_SET_MIME("audio/wav", PHAR_MIME_OTHER, "wav")
3404 PHAR_SET_MIME("image/xbm", PHAR_MIME_OTHER, "xbm")
3405 PHAR_SET_MIME("text/xml", PHAR_MIME_OTHER, "xml")
3406
3407 phar_restore_orig_functions();
3408 }
3409
3410
3411 PHP_GSHUTDOWN_FUNCTION(phar)
3412 {
3413 zend_hash_destroy(&phar_globals->mime_types);
3414 }
3415
3416
3417 PHP_MINIT_FUNCTION(phar)
3418 {
3419 REGISTER_INI_ENTRIES();
3420
3421 phar_orig_compile_file = zend_compile_file;
3422 zend_compile_file = phar_compile_file;
3423
3424 phar_save_resolve_path = zend_resolve_path;
3425 zend_resolve_path = phar_resolve_path;
3426
3427 phar_object_init();
3428
3429 phar_intercept_functions_init();
3430 phar_save_orig_functions();
3431
3432 return php_register_url_stream_wrapper("phar", &php_stream_phar_wrapper);
3433 }
3434
3435
3436 PHP_MSHUTDOWN_FUNCTION(phar)
3437 {
3438 php_unregister_url_stream_wrapper("phar");
3439
3440 phar_intercept_functions_shutdown();
3441
3442 if (zend_compile_file == phar_compile_file) {
3443 zend_compile_file = phar_orig_compile_file;
3444 }
3445
3446 if (PHAR_G(manifest_cached)) {
3447 zend_hash_destroy(&(cached_phars));
3448 zend_hash_destroy(&(cached_alias));
3449 }
3450
3451 return SUCCESS;
3452 }
3453
3454
3455 void phar_request_initialize(void)
3456 {
3457 if (!PHAR_G(request_init))
3458 {
3459 PHAR_G(last_phar) = NULL;
3460 PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
3461 PHAR_G(has_bz2) = zend_hash_str_exists(&module_registry, "bz2", sizeof("bz2")-1);
3462 PHAR_G(has_zlib) = zend_hash_str_exists(&module_registry, "zlib", sizeof("zlib")-1);
3463 PHAR_G(request_init) = 1;
3464 PHAR_G(request_ends) = 0;
3465 PHAR_G(request_done) = 0;
3466 zend_hash_init(&(PHAR_G(phar_fname_map)), 5, zend_get_hash_value, destroy_phar_data, 0);
3467 zend_hash_init(&(PHAR_G(phar_persist_map)), 5, zend_get_hash_value, NULL, 0);
3468 zend_hash_init(&(PHAR_G(phar_alias_map)), 5, zend_get_hash_value, NULL, 0);
3469
3470 if (PHAR_G(manifest_cached)) {
3471 phar_archive_data *pphar;
3472 phar_entry_fp *stuff = (phar_entry_fp *) ecalloc(zend_hash_num_elements(&cached_phars), sizeof(phar_entry_fp));
3473
3474 for (zend_hash_internal_pointer_reset(&cached_phars);
3475 (pphar = zend_hash_get_current_data_ptr(&cached_phars)) != NULL;
3476 zend_hash_move_forward(&cached_phars)) {
3477 stuff[pphar->phar_pos].manifest = (phar_entry_fp_info *) ecalloc( zend_hash_num_elements(&(pphar->manifest)), sizeof(phar_entry_fp_info));
3478 }
3479
3480 PHAR_G(cached_fp) = stuff;
3481 }
3482
3483 PHAR_G(phar_SERVER_mung_list) = 0;
3484 PHAR_G(cwd) = NULL;
3485 PHAR_G(cwd_len) = 0;
3486 PHAR_G(cwd_init) = 0;
3487 }
3488 }
3489
3490
3491 PHP_RSHUTDOWN_FUNCTION(phar)
3492 {
3493 int i;
3494
3495 PHAR_G(request_ends) = 1;
3496
3497 if (PHAR_G(request_init))
3498 {
3499 phar_release_functions();
3500 zend_hash_destroy(&(PHAR_G(phar_alias_map)));
3501 PHAR_G(phar_alias_map.u.flags) = 0;
3502 zend_hash_destroy(&(PHAR_G(phar_fname_map)));
3503 PHAR_G(phar_fname_map.u.flags) = 0;
3504 zend_hash_destroy(&(PHAR_G(phar_persist_map)));
3505 PHAR_G(phar_persist_map.u.flags) = 0;
3506 PHAR_G(phar_SERVER_mung_list) = 0;
3507
3508 if (PHAR_G(cached_fp)) {
3509 for (i = 0; i < zend_hash_num_elements(&cached_phars); ++i) {
3510 if (PHAR_G(cached_fp)[i].fp) {
3511 php_stream_close(PHAR_G(cached_fp)[i].fp);
3512 }
3513 if (PHAR_G(cached_fp)[i].ufp) {
3514 php_stream_close(PHAR_G(cached_fp)[i].ufp);
3515 }
3516 efree(PHAR_G(cached_fp)[i].manifest);
3517 }
3518 efree(PHAR_G(cached_fp));
3519 PHAR_G(cached_fp) = 0;
3520 }
3521
3522 PHAR_G(request_init) = 0;
3523
3524 if (PHAR_G(cwd)) {
3525 efree(PHAR_G(cwd));
3526 }
3527
3528 PHAR_G(cwd) = NULL;
3529 PHAR_G(cwd_len) = 0;
3530 PHAR_G(cwd_init) = 0;
3531 }
3532
3533 PHAR_G(request_done) = 1;
3534 return SUCCESS;
3535 }
3536
3537
3538 PHP_MINFO_FUNCTION(phar)
3539 {
3540 phar_request_initialize();
3541 php_info_print_table_start();
3542 php_info_print_table_header(2, "Phar: PHP Archive support", "enabled");
3543 php_info_print_table_row(2, "Phar EXT version", PHP_PHAR_VERSION);
3544 php_info_print_table_row(2, "Phar API version", PHP_PHAR_API_VERSION);
3545 php_info_print_table_row(2, "SVN revision", "$Id: 860f5132d446a7b24c2bbf050ce6949381ea8db5 $");
3546 php_info_print_table_row(2, "Phar-based phar archives", "enabled");
3547 php_info_print_table_row(2, "Tar-based phar archives", "enabled");
3548 php_info_print_table_row(2, "ZIP-based phar archives", "enabled");
3549
3550 if (PHAR_G(has_zlib)) {
3551 php_info_print_table_row(2, "gzip compression", "enabled");
3552 } else {
3553 php_info_print_table_row(2, "gzip compression", "disabled (install ext/zlib)");
3554 }
3555
3556 if (PHAR_G(has_bz2)) {
3557 php_info_print_table_row(2, "bzip2 compression", "enabled");
3558 } else {
3559 php_info_print_table_row(2, "bzip2 compression", "disabled (install pecl/bz2)");
3560 }
3561 #ifdef PHAR_HAVE_OPENSSL
3562 php_info_print_table_row(2, "Native OpenSSL support", "enabled");
3563 #else
3564 if (zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) {
3565 php_info_print_table_row(2, "OpenSSL support", "enabled");
3566 } else {
3567 php_info_print_table_row(2, "OpenSSL support", "disabled (install ext/openssl)");
3568 }
3569 #endif
3570 php_info_print_table_end();
3571
3572 php_info_print_box_start(0);
3573 PUTS("Phar based on pear/PHP_Archive, original concept by Davey Shafik.");
3574 PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
3575 PUTS("Phar fully realized by Gregory Beaver and Marcus Boerger.");
3576 PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
3577 PUTS("Portions of tar implementation Copyright (c) 2003-2009 Tim Kientzle.");
3578 php_info_print_box_end();
3579
3580 DISPLAY_INI_ENTRIES();
3581 }
3582
3583
3584
3585
3586 static const zend_module_dep phar_deps[] = {
3587 ZEND_MOD_OPTIONAL("apc")
3588 ZEND_MOD_OPTIONAL("bz2")
3589 ZEND_MOD_OPTIONAL("openssl")
3590 ZEND_MOD_OPTIONAL("zlib")
3591 ZEND_MOD_OPTIONAL("standard")
3592 #if defined(HAVE_HASH) && !defined(COMPILE_DL_HASH)
3593 ZEND_MOD_REQUIRED("hash")
3594 #endif
3595 #if HAVE_SPL
3596 ZEND_MOD_REQUIRED("spl")
3597 #endif
3598 ZEND_MOD_END
3599 };
3600
3601 zend_module_entry phar_module_entry = {
3602 STANDARD_MODULE_HEADER_EX, NULL,
3603 phar_deps,
3604 "Phar",
3605 phar_functions,
3606 PHP_MINIT(phar),
3607 PHP_MSHUTDOWN(phar),
3608 NULL,
3609 PHP_RSHUTDOWN(phar),
3610 PHP_MINFO(phar),
3611 PHP_PHAR_VERSION,
3612 PHP_MODULE_GLOBALS(phar),
3613 PHP_GINIT(phar),
3614 PHP_GSHUTDOWN(phar),
3615 NULL,
3616 STANDARD_MODULE_PROPERTIES_EX
3617 };
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627