This source file includes following definitions.
- phar_file_type
- phar_mung_server_vars
- phar_file_action
- phar_do_403
- phar_do_404
- phar_postprocess_ru_web
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- phar_spl_foreign_dtor
- phar_spl_foreign_clone
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- phar_build
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- phar_copy_file_contents
- phar_rename_archive
- phar_convert_to_other
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- phar_set_compression
- phar_test_compression
- pharobj_set_compression
- pharobj_cancompress
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- phar_add_file
- phar_mkdir
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- phar_extract_file
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- phar_object_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "phar_internal.h"
23 #include "func_interceptors.h"
24
25 static zend_class_entry *phar_ce_archive;
26 static zend_class_entry *phar_ce_data;
27 static zend_class_entry *phar_ce_PharException;
28
29 #if HAVE_SPL
30 static zend_class_entry *phar_ce_entry;
31 #endif
32
33 #if PHP_VERSION_ID >= 50300
34 # define PHAR_ARG_INFO
35 #else
36 # define PHAR_ARG_INFO static
37 #endif
38
39 static int phar_file_type(HashTable *mimes, char *file, char **mime_type)
40 {
41 char *ext;
42 phar_mime_type *mime;
43 ext = strrchr(file, '.');
44 if (!ext) {
45 *mime_type = "text/plain";
46
47 return PHAR_MIME_OTHER;
48 }
49 ++ext;
50 if (NULL == (mime = zend_hash_str_find_ptr(mimes, ext, strlen(ext)))) {
51 *mime_type = "application/octet-stream";
52 return PHAR_MIME_OTHER;
53 }
54 *mime_type = mime->mime;
55 return mime->type;
56 }
57
58
59 static void phar_mung_server_vars(char *fname, char *entry, int entry_len, char *basename, int request_uri_len)
60 {
61 HashTable *_SERVER;
62 zval *stuff;
63 char *path_info;
64 int basename_len = strlen(basename);
65 int code;
66 zval temp;
67
68
69 if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_UNDEF) {
70 return;
71 }
72
73 _SERVER = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
74
75
76 if (NULL != (stuff = zend_hash_str_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO")-1))) {
77 path_info = Z_STRVAL_P(stuff);
78 code = Z_STRLEN_P(stuff);
79 if (code > entry_len && !memcmp(path_info, entry, entry_len)) {
80 ZVAL_STR(&temp, Z_STR_P(stuff));
81 ZVAL_STRINGL(stuff, path_info + entry_len, request_uri_len);
82 zend_hash_str_update(_SERVER, "PHAR_PATH_INFO", sizeof("PHAR_PATH_INFO")-1, &temp);
83 }
84 }
85
86 if (NULL != (stuff = zend_hash_str_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1))) {
87 zend_string *str = strpprintf(4096, "phar://%s%s", fname, entry);
88
89 ZVAL_STR(&temp, Z_STR_P(stuff));
90 ZVAL_NEW_STR(stuff, str);
91
92 zend_hash_str_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED")-1, &temp);
93 }
94
95 if (!PHAR_G(phar_SERVER_mung_list)) {
96 return;
97 }
98
99 if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_REQUEST_URI) {
100 if (NULL != (stuff = zend_hash_str_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI")-1))) {
101 path_info = Z_STRVAL_P(stuff);
102 code = Z_STRLEN_P(stuff);
103 if (code > basename_len && !memcmp(path_info, basename, basename_len)) {
104 ZVAL_STR(&temp, Z_STR_P(stuff));
105 ZVAL_STRINGL(stuff, path_info + basename_len, code - basename_len);
106 zend_hash_str_update(_SERVER, "PHAR_REQUEST_URI", sizeof("PHAR_REQUEST_URI")-1, &temp);
107 }
108 }
109 }
110
111 if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_PHP_SELF) {
112 if (NULL != (stuff = zend_hash_str_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF")-1))) {
113 path_info = Z_STRVAL_P(stuff);
114 code = Z_STRLEN_P(stuff);
115
116 if (code > basename_len && !memcmp(path_info, basename, basename_len)) {
117 ZVAL_STR(&temp, Z_STR_P(stuff));
118 ZVAL_STRINGL(stuff, path_info + basename_len, code - basename_len);
119 zend_hash_str_update(_SERVER, "PHAR_PHP_SELF", sizeof("PHAR_PHP_SELF")-1, &temp);
120 }
121 }
122 }
123
124 if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_SCRIPT_NAME) {
125 if (NULL != (stuff = zend_hash_str_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1))) {
126 ZVAL_STR(&temp, Z_STR_P(stuff));
127 ZVAL_STRINGL(stuff, entry, entry_len);
128 zend_hash_str_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME")-1, &temp);
129 }
130 }
131
132 if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_SCRIPT_FILENAME) {
133 if (NULL != (stuff = zend_hash_str_find(_SERVER, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1))) {
134 zend_string *str = strpprintf(4096, "phar://%s%s", fname, entry);
135
136 ZVAL_STR(&temp, Z_STR_P(stuff));
137 ZVAL_NEW_STR(stuff, str);
138
139 zend_hash_str_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME")-1, &temp);
140 }
141 }
142 }
143
144
145 static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char *mime_type, int code, char *entry, int entry_len, char *arch, char *basename, char *ru, int ru_len)
146 {
147 char *name = NULL, buf[8192];
148 const char *cwd;
149 zend_syntax_highlighter_ini syntax_highlighter_ini;
150 sapi_header_line ctr = {0};
151 size_t got;
152 zval dummy;
153 int name_len;
154 zend_file_handle file_handle;
155 zend_op_array *new_op_array;
156 zval result;
157 php_stream *fp;
158 zend_off_t position;
159
160 switch (code) {
161 case PHAR_MIME_PHPS:
162 efree(basename);
163
164 if (entry[0] == '/') {
165 name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
166 } else {
167 name_len = spprintf(&name, 4096, "phar://%s/%s", arch, entry);
168 }
169 php_get_highlight_struct(&syntax_highlighter_ini);
170
171 highlight_file(name, &syntax_highlighter_ini);
172
173 efree(name);
174 #ifdef PHP_WIN32
175 efree(arch);
176 #endif
177 zend_bailout();
178 case PHAR_MIME_OTHER:
179
180 efree(basename);
181 ctr.line_len = spprintf(&(ctr.line), 0, "Content-type: %s", mime_type);
182 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
183 efree(ctr.line);
184 ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %u", info->uncompressed_filesize);
185 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
186 efree(ctr.line);
187
188 if (FAILURE == sapi_send_headers()) {
189 zend_bailout();
190 }
191
192
193 fp = phar_get_efp(info, 1);
194
195 if (!fp) {
196 char *error;
197 if (!phar_open_jit(phar, info, &error)) {
198 if (error) {
199 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
200 efree(error);
201 }
202 return -1;
203 }
204 fp = phar_get_efp(info, 1);
205 }
206 position = 0;
207 phar_seek_efp(info, 0, SEEK_SET, 0, 1);
208
209 do {
210 got = php_stream_read(fp, buf, MIN(8192, info->uncompressed_filesize - position));
211 if (got > 0) {
212 PHPWRITE(buf, got);
213 position += got;
214 if (position == (zend_off_t) info->uncompressed_filesize) {
215 break;
216 }
217 }
218 } while (1);
219
220 zend_bailout();
221 case PHAR_MIME_PHP:
222 if (basename) {
223 phar_mung_server_vars(arch, entry, entry_len, basename, ru_len);
224 efree(basename);
225 }
226
227 if (entry[0] == '/') {
228 name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
229 } else {
230 name_len = spprintf(&name, 4096, "phar://%s/%s", arch, entry);
231 }
232
233 file_handle.type = ZEND_HANDLE_FILENAME;
234 file_handle.handle.fd = 0;
235 file_handle.filename = name;
236 file_handle.opened_path = NULL;
237 file_handle.free_filename = 0;
238
239 PHAR_G(cwd) = NULL;
240 PHAR_G(cwd_len) = 0;
241
242 ZVAL_NULL(&dummy);
243 if (zend_hash_str_add(&EG(included_files), name, name_len, &dummy) != NULL) {
244 if ((cwd = zend_memrchr(entry, '/', entry_len))) {
245 PHAR_G(cwd_init) = 1;
246 if (entry == cwd) {
247
248 PHAR_G(cwd_len) = 0;
249 PHAR_G(cwd) = NULL;
250 } else if (entry[0] == '/') {
251 PHAR_G(cwd_len) = cwd - (entry + 1);
252 PHAR_G(cwd) = estrndup(entry + 1, PHAR_G(cwd_len));
253 } else {
254 PHAR_G(cwd_len) = cwd - entry;
255 PHAR_G(cwd) = estrndup(entry, PHAR_G(cwd_len));
256 }
257 }
258
259 new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
260
261 if (!new_op_array) {
262 zend_hash_str_del(&EG(included_files), name, name_len);
263 }
264
265 zend_destroy_file_handle(&file_handle);
266
267 } else {
268 efree(name);
269 new_op_array = NULL;
270 }
271 #ifdef PHP_WIN32
272 efree(arch);
273 #endif
274 if (new_op_array) {
275 ZVAL_UNDEF(&result);
276
277 zend_try {
278 zend_execute(new_op_array, &result);
279 if (PHAR_G(cwd)) {
280 efree(PHAR_G(cwd));
281 PHAR_G(cwd) = NULL;
282 PHAR_G(cwd_len) = 0;
283 }
284
285 PHAR_G(cwd_init) = 0;
286 efree(name);
287 destroy_op_array(new_op_array);
288 efree(new_op_array);
289 zval_ptr_dtor(&result);
290 } zend_catch {
291 if (PHAR_G(cwd)) {
292 efree(PHAR_G(cwd));
293 PHAR_G(cwd) = NULL;
294 PHAR_G(cwd_len) = 0;
295 }
296
297 PHAR_G(cwd_init) = 0;
298 efree(name);
299 } zend_end_try();
300
301 zend_bailout();
302 }
303
304 return PHAR_MIME_PHP;
305 }
306 return -1;
307 }
308
309
310 static void phar_do_403(char *entry, int entry_len)
311 {
312 sapi_header_line ctr = {0};
313
314 ctr.response_code = 403;
315 ctr.line_len = sizeof("HTTP/1.0 403 Access Denied")-1;
316 ctr.line = "HTTP/1.0 403 Access Denied";
317 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
318 sapi_send_headers();
319 PHPWRITE("<html>\n <head>\n <title>Access Denied</title>\n </head>\n <body>\n <h1>403 - File ", sizeof("<html>\n <head>\n <title>Access Denied</title>\n </head>\n <body>\n <h1>403 - File ") - 1);
320 PHPWRITE(entry, entry_len);
321 PHPWRITE(" Access Denied</h1>\n </body>\n</html>", sizeof(" Access Denied</h1>\n </body>\n</html>") - 1);
322 }
323
324
325 static void phar_do_404(phar_archive_data *phar, char *fname, int fname_len, char *f404, size_t f404_len, char *entry, size_t entry_len)
326 {
327 sapi_header_line ctr = {0};
328 phar_entry_info *info;
329
330 if (phar && f404_len) {
331 info = phar_get_entry_info(phar, f404, f404_len, NULL, 1);
332
333 if (info) {
334 phar_file_action(phar, info, "text/html", PHAR_MIME_PHP, f404, f404_len, fname, NULL, NULL, 0);
335 return;
336 }
337 }
338
339 ctr.response_code = 404;
340 ctr.line_len = sizeof("HTTP/1.0 404 Not Found")-1;
341 ctr.line = "HTTP/1.0 404 Not Found";
342 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
343 sapi_send_headers();
344 PHPWRITE("<html>\n <head>\n <title>File Not Found</title>\n </head>\n <body>\n <h1>404 - File ", sizeof("<html>\n <head>\n <title>File Not Found</title>\n </head>\n <body>\n <h1>404 - File ") - 1);
345 PHPWRITE(entry, entry_len);
346 PHPWRITE(" Not Found</h1>\n </body>\n</html>", sizeof(" Not Found</h1>\n </body>\n</html>") - 1);
347 }
348
349
350
351
352
353 static void phar_postprocess_ru_web(char *fname, int fname_len, char **entry, int *entry_len, char **ru, int *ru_len)
354 {
355 char *e = *entry + 1, *u = NULL, *u1 = NULL, *saveu = NULL;
356 int e_len = *entry_len - 1, u_len = 0;
357 phar_archive_data *pphar;
358
359
360 pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len);
361
362 if (!pphar && PHAR_G(manifest_cached)) {
363 pphar = zend_hash_str_find_ptr(&cached_phars, fname, fname_len);
364 }
365
366 do {
367 if (zend_hash_str_exists(&(pphar->manifest), e, e_len)) {
368 if (u) {
369 u[0] = '/';
370 *ru = estrndup(u, u_len+1);
371 ++u_len;
372 u[0] = '\0';
373 } else {
374 *ru = NULL;
375 }
376 *ru_len = u_len;
377 *entry_len = e_len + 1;
378 return;
379 }
380
381 if (u) {
382 u1 = strrchr(e, '/');
383 u[0] = '/';
384 saveu = u;
385 e_len += u_len + 1;
386 u = u1;
387 if (!u) {
388 return;
389 }
390 } else {
391 u = strrchr(e, '/');
392 if (!u) {
393 if (saveu) {
394 saveu[0] = '/';
395 }
396 return;
397 }
398 }
399
400 u[0] = '\0';
401 u_len = strlen(u + 1);
402 e_len -= u_len + 1;
403
404 if (e_len < 0) {
405 if (saveu) {
406 saveu[0] = '/';
407 }
408 return;
409 }
410 } while (1);
411 }
412
413
414
415
416
417
418 PHP_METHOD(Phar, running)
419 {
420 char *fname, *arch, *entry;
421 int fname_len, arch_len, entry_len;
422 zend_bool retphar = 1;
423
424 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &retphar) == FAILURE) {
425 return;
426 }
427
428 fname = (char*)zend_get_executed_filename();
429 fname_len = strlen(fname);
430
431 if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
432 efree(entry);
433 if (retphar) {
434 RETVAL_STRINGL(fname, arch_len + 7);
435 efree(arch);
436 return;
437 } else {
438
439 RETVAL_STRINGL(arch, arch_len);
440 efree(arch);
441 return;
442 }
443 }
444
445 RETURN_EMPTY_STRING();
446 }
447
448
449
450
451
452
453
454
455 PHP_METHOD(Phar, mount)
456 {
457 char *fname, *arch = NULL, *entry = NULL, *path, *actual;
458 int fname_len, arch_len, entry_len;
459 size_t path_len, actual_len;
460 phar_archive_data *pphar;
461
462 if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &path, &path_len, &actual, &actual_len) == FAILURE) {
463 return;
464 }
465
466 fname = (char*)zend_get_executed_filename();
467 fname_len = strlen(fname);
468
469 #ifdef PHP_WIN32
470 phar_unixify_path_separators(fname, fname_len);
471 #endif
472
473 if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
474 efree(entry);
475 entry = NULL;
476
477 if (path_len > 7 && !memcmp(path, "phar://", 7)) {
478 zend_throw_exception_ex(phar_ce_PharException, 0, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path);
479 efree(arch);
480 return;
481 }
482 carry_on2:
483 if (NULL == (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), arch, arch_len))) {
484 if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, arch, arch_len))) {
485 if (SUCCESS == phar_copy_on_write(&pphar)) {
486 goto carry_on;
487 }
488 }
489
490 zend_throw_exception_ex(phar_ce_PharException, 0, "%s is not a phar archive, cannot mount", arch);
491
492 if (arch) {
493 efree(arch);
494 }
495 return;
496 }
497 carry_on:
498 if (SUCCESS != phar_mount_entry(pphar, actual, actual_len, path, path_len)) {
499 zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s within phar %s failed", path, actual, arch);
500 if (path && path == entry) {
501 efree(entry);
502 }
503
504 if (arch) {
505 efree(arch);
506 }
507
508 return;
509 }
510
511 if (entry && path && path == entry) {
512 efree(entry);
513 }
514
515 if (arch) {
516 efree(arch);
517 }
518
519 return;
520 } else if (PHAR_G(phar_fname_map.u.flags) && NULL != (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len))) {
521 goto carry_on;
522 } else if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) {
523 if (SUCCESS == phar_copy_on_write(&pphar)) {
524 goto carry_on;
525 }
526
527 goto carry_on;
528 } else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
529 path = entry;
530 path_len = entry_len;
531 goto carry_on2;
532 }
533
534 zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s failed", path, actual);
535 }
536
537
538
539
540
541
542
543
544
545 PHP_METHOD(Phar, webPhar)
546 {
547 zval *mimeoverride = NULL, *rewrite = NULL;
548 char *alias = NULL, *error, *index_php = NULL, *f404 = NULL, *ru = NULL;
549 size_t alias_len = 0, f404_len = 0, free_pathinfo = 0;
550 int ru_len = 0;
551 char *fname, *path_info, *mime_type = NULL, *entry, *pt;
552 const char *basename;
553 size_t fname_len, index_php_len = 0;
554 int entry_len, code, not_cgi;
555 phar_archive_data *phar = NULL;
556 phar_entry_info *info = NULL;
557 size_t sapi_mod_name_len = strlen(sapi_module.name);
558
559 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!saz", &alias, &alias_len, &index_php, &index_php_len, &f404, &f404_len, &mimeoverride, &rewrite) == FAILURE) {
560 return;
561 }
562
563 phar_request_initialize();
564 fname = (char*)zend_get_executed_filename();
565 fname_len = strlen(fname);
566
567 if (phar_open_executed_filename(alias, alias_len, &error) != SUCCESS) {
568 if (error) {
569 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
570 efree(error);
571 }
572 return;
573 }
574
575
576 if (!(SG(request_info).request_method && SG(request_info).request_uri && (!strcmp(SG(request_info).request_method, "GET") || !strcmp(SG(request_info).request_method, "POST")))) {
577 return;
578 }
579
580 #ifdef PHP_WIN32
581 fname = estrndup(fname, fname_len);
582 phar_unixify_path_separators(fname, fname_len);
583 #endif
584 basename = zend_memrchr(fname, '/', fname_len);
585
586 if (!basename) {
587 basename = fname;
588 } else {
589 ++basename;
590 }
591
592 if ((sapi_mod_name_len == sizeof("cgi-fcgi") - 1 && !strncmp(sapi_module.name, "cgi-fcgi", sizeof("cgi-fcgi") - 1))
593 || (sapi_mod_name_len == sizeof("fpm-fcgi") - 1 && !strncmp(sapi_module.name, "fpm-fcgi", sizeof("fpm-fcgi") - 1))
594 || (sapi_mod_name_len == sizeof("cgi") - 1 && !strncmp(sapi_module.name, "cgi", sizeof("cgi") - 1))) {
595
596 if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) != IS_UNDEF) {
597 HashTable *_server = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
598 zval *z_script_name, *z_path_info;
599
600 if (NULL == (z_script_name = zend_hash_str_find(_server, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) ||
601 IS_STRING != Z_TYPE_P(z_script_name) ||
602 !strstr(Z_STRVAL_P(z_script_name), basename)) {
603 return;
604 }
605
606 if (NULL != (z_path_info = zend_hash_str_find(_server, "PATH_INFO", sizeof("PATH_INFO")-1)) &&
607 IS_STRING == Z_TYPE_P(z_path_info)) {
608 entry_len = Z_STRLEN_P(z_path_info);
609 entry = estrndup(Z_STRVAL_P(z_path_info), entry_len);
610 path_info = emalloc(Z_STRLEN_P(z_script_name) + entry_len + 1);
611 memcpy(path_info, Z_STRVAL_P(z_script_name), Z_STRLEN_P(z_script_name));
612 memcpy(path_info + Z_STRLEN_P(z_script_name), entry, entry_len + 1);
613 free_pathinfo = 1;
614 } else {
615 entry_len = 0;
616 entry = estrndup("", 0);
617 path_info = Z_STRVAL_P(z_script_name);
618 }
619
620 pt = estrndup(Z_STRVAL_P(z_script_name), Z_STRLEN_P(z_script_name));
621
622 } else {
623 char *testit;
624
625 testit = sapi_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1);
626 if (!(pt = strstr(testit, basename))) {
627 efree(testit);
628 return;
629 }
630
631 path_info = sapi_getenv("PATH_INFO", sizeof("PATH_INFO")-1);
632
633 if (path_info) {
634 entry = path_info;
635 entry_len = strlen(entry);
636 spprintf(&path_info, 0, "%s%s", testit, path_info);
637 free_pathinfo = 1;
638 } else {
639 path_info = testit;
640 free_pathinfo = 1;
641 entry = estrndup("", 0);
642 entry_len = 0;
643 }
644
645 pt = estrndup(testit, (pt - testit) + (fname_len - (basename - fname)));
646 }
647 not_cgi = 0;
648 } else {
649 path_info = SG(request_info).request_uri;
650
651 if (!(pt = strstr(path_info, basename))) {
652
653 return;
654 }
655
656 entry_len = strlen(path_info);
657 entry_len -= (pt - path_info) + (fname_len - (basename - fname));
658 entry = estrndup(pt + (fname_len - (basename - fname)), entry_len);
659
660 pt = estrndup(path_info, (pt - path_info) + (fname_len - (basename - fname)));
661 not_cgi = 1;
662 }
663
664 if (rewrite) {
665 zend_fcall_info fci;
666 zend_fcall_info_cache fcc;
667 zval params, retval;
668
669 ZVAL_STRINGL(¶ms, entry, entry_len);
670
671 if (FAILURE == zend_fcall_info_init(rewrite, 0, &fci, &fcc, NULL, NULL)) {
672 zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: invalid rewrite callback");
673
674 if (free_pathinfo) {
675 efree(path_info);
676 }
677
678 return;
679 }
680
681 fci.param_count = 1;
682 fci.params = ¶ms;
683 Z_ADDREF(params);
684 fci.retval = &retval;
685
686 if (FAILURE == zend_call_function(&fci, &fcc)) {
687 if (!EG(exception)) {
688 zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: failed to call rewrite callback");
689 }
690
691 if (free_pathinfo) {
692 efree(path_info);
693 }
694
695 return;
696 }
697
698 if (Z_TYPE_P(fci.retval) == IS_UNDEF || Z_TYPE(retval) == IS_UNDEF) {
699 if (free_pathinfo) {
700 efree(path_info);
701 }
702 zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
703 return;
704 }
705
706 switch (Z_TYPE(retval)) {
707 case IS_STRING:
708 efree(entry);
709 entry = estrndup(Z_STRVAL_P(fci.retval), Z_STRLEN_P(fci.retval));
710 entry_len = Z_STRLEN_P(fci.retval);
711 break;
712 case IS_TRUE:
713 case IS_FALSE:
714 phar_do_403(entry, entry_len);
715
716 if (free_pathinfo) {
717 efree(path_info);
718 }
719
720 zend_bailout();
721 return;
722 default:
723 if (free_pathinfo) {
724 efree(path_info);
725 }
726
727 zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
728 return;
729 }
730 }
731
732 if (entry_len) {
733 phar_postprocess_ru_web(fname, fname_len, &entry, &entry_len, &ru, &ru_len);
734 }
735
736 if (!entry_len || (entry_len == 1 && entry[0] == '/')) {
737 efree(entry);
738
739 if (index_php_len) {
740 entry = index_php;
741 entry_len = index_php_len;
742 if (entry[0] != '/') {
743 spprintf(&entry, 0, "/%s", index_php);
744 ++entry_len;
745 }
746 } else {
747
748 entry = estrndup("/index.php", sizeof("/index.php"));
749 entry_len = sizeof("/index.php")-1;
750 }
751
752 if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) ||
753 (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) {
754 phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len);
755
756 if (free_pathinfo) {
757 efree(path_info);
758 }
759
760 zend_bailout();
761 } else {
762 char *tmp = NULL, sa = '\0';
763 sapi_header_line ctr = {0};
764 ctr.response_code = 301;
765 ctr.line_len = sizeof("HTTP/1.1 301 Moved Permanently")-1;
766 ctr.line = "HTTP/1.1 301 Moved Permanently";
767 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
768
769 if (not_cgi) {
770 tmp = strstr(path_info, basename) + fname_len;
771 sa = *tmp;
772 *tmp = '\0';
773 }
774
775 ctr.response_code = 0;
776
777 if (path_info[strlen(path_info)-1] == '/') {
778 ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry + 1);
779 } else {
780 ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry);
781 }
782
783 if (not_cgi) {
784 *tmp = sa;
785 }
786
787 if (free_pathinfo) {
788 efree(path_info);
789 }
790
791 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
792 sapi_send_headers();
793 efree(ctr.line);
794 zend_bailout();
795 }
796 }
797
798 if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) ||
799 (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) {
800 phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len);
801 #ifdef PHP_WIN32
802 efree(fname);
803 #endif
804 zend_bailout();
805 }
806
807 if (mimeoverride && zend_hash_num_elements(Z_ARRVAL_P(mimeoverride))) {
808 const char *ext = zend_memrchr(entry, '.', entry_len);
809 zval *val;
810
811 if (ext) {
812 ++ext;
813
814 if (NULL != (val = zend_hash_str_find(Z_ARRVAL_P(mimeoverride), ext, strlen(ext)))) {
815 switch (Z_TYPE_P(val)) {
816 case IS_LONG:
817 if (Z_LVAL_P(val) == PHAR_MIME_PHP || Z_LVAL_P(val) == PHAR_MIME_PHPS) {
818 mime_type = "";
819 code = Z_LVAL_P(val);
820 } else {
821 zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed");
822 if (free_pathinfo) {
823 efree(path_info);
824 }
825 efree(pt);
826 efree(entry);
827 #ifdef PHP_WIN32
828 efree(fname);
829 #endif
830 RETURN_FALSE;
831 }
832 break;
833 case IS_STRING:
834 mime_type = Z_STRVAL_P(val);
835 code = PHAR_MIME_OTHER;
836 break;
837 default:
838 zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed");
839 if (free_pathinfo) {
840 efree(path_info);
841 }
842 efree(pt);
843 efree(entry);
844 #ifdef PHP_WIN32
845 efree(fname);
846 #endif
847 RETURN_FALSE;
848 }
849 }
850 }
851 }
852
853 if (!mime_type) {
854 code = phar_file_type(&PHAR_G(mime_types), entry, &mime_type);
855 }
856 phar_file_action(phar, info, mime_type, code, entry, entry_len, fname, pt, ru, ru_len);
857 }
858
859
860
861
862
863
864
865
866 PHP_METHOD(Phar, mungServer)
867 {
868 zval *mungvalues, *data;
869
870 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &mungvalues) == FAILURE) {
871 return;
872 }
873
874 if (!zend_hash_num_elements(Z_ARRVAL_P(mungvalues))) {
875 zend_throw_exception_ex(phar_ce_PharException, 0, "No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
876 return;
877 }
878
879 if (zend_hash_num_elements(Z_ARRVAL_P(mungvalues)) > 4) {
880 zend_throw_exception_ex(phar_ce_PharException, 0, "Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
881 return;
882 }
883
884 phar_request_initialize();
885
886 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(mungvalues), data) {
887
888 if (Z_TYPE_P(data) != IS_STRING) {
889 zend_throw_exception_ex(phar_ce_PharException, 0, "Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
890 return;
891 }
892
893 if (Z_STRLEN_P(data) == sizeof("PHP_SELF")-1 && !strncmp(Z_STRVAL_P(data), "PHP_SELF", sizeof("PHP_SELF")-1)) {
894 PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_PHP_SELF;
895 }
896
897 if (Z_STRLEN_P(data) == sizeof("REQUEST_URI")-1) {
898 if (!strncmp(Z_STRVAL_P(data), "REQUEST_URI", sizeof("REQUEST_URI")-1)) {
899 PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_REQUEST_URI;
900 }
901 if (!strncmp(Z_STRVAL_P(data), "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) {
902 PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_NAME;
903 }
904 }
905
906 if (Z_STRLEN_P(data) == sizeof("SCRIPT_FILENAME")-1 && !strncmp(Z_STRVAL_P(data), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1)) {
907 PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_FILENAME;
908 }
909 } ZEND_HASH_FOREACH_END();
910 }
911
912
913
914
915
916
917
918
919
920
921 PHP_METHOD(Phar, interceptFileFuncs)
922 {
923 if (zend_parse_parameters_none() == FAILURE) {
924 return;
925 }
926 phar_intercept_functions();
927 }
928
929
930
931
932
933
934
935 PHP_METHOD(Phar, createDefaultStub)
936 {
937 char *index = NULL, *webindex = NULL, *error;
938 zend_string *stub;
939 size_t index_len = 0, webindex_len = 0;
940
941 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|pp", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
942 return;
943 }
944
945 stub = phar_create_default_stub(index, webindex, &error);
946
947 if (error) {
948 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
949 efree(error);
950 return;
951 }
952 RETURN_NEW_STR(stub);
953 }
954
955
956
957
958 PHP_METHOD(Phar, mapPhar)
959 {
960 char *alias = NULL, *error;
961 size_t alias_len = 0;
962 zend_long dataoffset = 0;
963
964 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) {
965 return;
966 }
967
968 phar_request_initialize();
969
970 RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error) == SUCCESS);
971
972 if (error) {
973 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
974 efree(error);
975 }
976 }
977
978
979
980 PHP_METHOD(Phar, loadPhar)
981 {
982 char *fname, *alias = NULL, *error;
983 size_t fname_len, alias_len = 0;
984
985 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!", &fname, &fname_len, &alias, &alias_len) == FAILURE) {
986 return;
987 }
988
989 phar_request_initialize();
990
991 RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error) == SUCCESS);
992
993 if (error) {
994 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
995 efree(error);
996 }
997 }
998
999
1000
1001 PHP_METHOD(Phar, apiVersion)
1002 {
1003 if (zend_parse_parameters_none() == FAILURE) {
1004 return;
1005 }
1006 RETURN_STRINGL(PHP_PHAR_API_VERSION, sizeof(PHP_PHAR_API_VERSION)-1);
1007 }
1008
1009
1010
1011
1012 PHP_METHOD(Phar, canCompress)
1013 {
1014 zend_long method = 0;
1015
1016 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &method) == FAILURE) {
1017 return;
1018 }
1019
1020 phar_request_initialize();
1021 switch (method) {
1022 case PHAR_ENT_COMPRESSED_GZ:
1023 if (PHAR_G(has_zlib)) {
1024 RETURN_TRUE;
1025 } else {
1026 RETURN_FALSE;
1027 }
1028 case PHAR_ENT_COMPRESSED_BZ2:
1029 if (PHAR_G(has_bz2)) {
1030 RETURN_TRUE;
1031 } else {
1032 RETURN_FALSE;
1033 }
1034 default:
1035 if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) {
1036 RETURN_TRUE;
1037 } else {
1038 RETURN_FALSE;
1039 }
1040 }
1041 }
1042
1043
1044
1045
1046 PHP_METHOD(Phar, canWrite)
1047 {
1048 if (zend_parse_parameters_none() == FAILURE) {
1049 return;
1050 }
1051 RETURN_BOOL(!PHAR_G(readonly));
1052 }
1053
1054
1055
1056
1057 PHP_METHOD(Phar, isValidPharFilename)
1058 {
1059 char *fname;
1060 const char *ext_str;
1061 size_t fname_len;
1062 int ext_len, is_executable;
1063 zend_bool executable = 1;
1064
1065 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &fname, &fname_len, &executable) == FAILURE) {
1066 return;
1067 }
1068
1069 is_executable = executable;
1070 RETVAL_BOOL(phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, is_executable, 2, 1) == SUCCESS);
1071 }
1072
1073
1074 #if HAVE_SPL
1075
1076
1077
1078 static void phar_spl_foreign_dtor(spl_filesystem_object *object)
1079 {
1080 phar_archive_data *phar = (phar_archive_data *) object->oth;
1081
1082 if (!phar->is_persistent) {
1083 phar_archive_delref(phar);
1084 }
1085
1086 object->oth = NULL;
1087 }
1088
1089
1090
1091
1092
1093 static void phar_spl_foreign_clone(spl_filesystem_object *src, spl_filesystem_object *dst)
1094 {
1095 phar_archive_data *phar_data = (phar_archive_data *) dst->oth;
1096
1097 if (!phar_data->is_persistent) {
1098 ++(phar_data->refcount);
1099 }
1100 }
1101
1102
1103 static spl_other_handler phar_spl_foreign_handler = {
1104 phar_spl_foreign_dtor,
1105 phar_spl_foreign_clone
1106 };
1107 #endif
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118 PHP_METHOD(Phar, __construct)
1119 {
1120 #if !HAVE_SPL
1121 zend_throw_exception_ex(zend_ce_exception, 0, "Cannot instantiate Phar object without SPL extension");
1122 #else
1123 char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname;
1124 size_t fname_len, alias_len = 0;
1125 int arch_len, entry_len, is_data;
1126 zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
1127 zend_long format = 0;
1128 phar_archive_object *phar_obj;
1129 phar_archive_data *phar_data;
1130 zval *zobj = getThis(), arg1, arg2;
1131
1132 phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
1133
1134 is_data = instanceof_function(Z_OBJCE_P(zobj), phar_ce_data);
1135
1136 if (is_data) {
1137 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) {
1138 return;
1139 }
1140 } else {
1141 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) {
1142 return;
1143 }
1144 }
1145
1146 if (phar_obj->archive) {
1147 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice");
1148 return;
1149 }
1150
1151 save_fname = fname;
1152 if (SUCCESS == phar_split_fname(fname, (int)fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2)) {
1153
1154
1155 #ifdef PHP_WIN32
1156 phar_unixify_path_separators(arch, arch_len);
1157 #endif
1158 fname = arch;
1159 fname_len = arch_len;
1160 #ifdef PHP_WIN32
1161 } else {
1162 arch = estrndup(fname, fname_len);
1163 arch_len = fname_len;
1164 fname = arch;
1165 phar_unixify_path_separators(arch, arch_len);
1166 #endif
1167 }
1168
1169 if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error) == FAILURE) {
1170
1171 if (fname == arch && fname != save_fname) {
1172 efree(arch);
1173 fname = save_fname;
1174 }
1175
1176 if (entry) {
1177 efree(entry);
1178 }
1179
1180 if (error) {
1181 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1182 "%s", error);
1183 efree(error);
1184 } else {
1185 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1186 "Phar creation or opening failed");
1187 }
1188
1189 return;
1190 }
1191
1192 if (is_data && phar_data->is_tar && phar_data->is_brandnew && format == PHAR_FORMAT_ZIP) {
1193 phar_data->is_zip = 1;
1194 phar_data->is_tar = 0;
1195 }
1196
1197 if (fname == arch) {
1198 efree(arch);
1199 fname = save_fname;
1200 }
1201
1202 if ((is_data && !phar_data->is_data) || (!is_data && phar_data->is_data)) {
1203 if (is_data) {
1204 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1205 "PharData class can only be used for non-executable tar and zip archives");
1206 } else {
1207 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1208 "Phar class can only be used for executable tar and zip archives");
1209 }
1210 efree(entry);
1211 return;
1212 }
1213
1214 is_data = phar_data->is_data;
1215
1216 if (!phar_data->is_persistent) {
1217 ++(phar_data->refcount);
1218 }
1219
1220 phar_obj->archive = phar_data;
1221 phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
1222
1223 if (entry) {
1224 fname_len = spprintf(&fname, 0, "phar://%s%s", phar_data->fname, entry);
1225 efree(entry);
1226 } else {
1227 fname_len = spprintf(&fname, 0, "phar://%s", phar_data->fname);
1228 }
1229
1230 ZVAL_STRINGL(&arg1, fname, fname_len);
1231 ZVAL_LONG(&arg2, flags);
1232
1233 zend_call_method_with_2_params(zobj, Z_OBJCE_P(zobj),
1234 &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
1235
1236 zval_ptr_dtor(&arg1);
1237
1238 if (!phar_data->is_persistent) {
1239 phar_obj->archive->is_data = is_data;
1240 } else if (!EG(exception)) {
1241
1242 zend_hash_str_add_ptr(&PHAR_G(phar_persist_map), (const char *) phar_obj->archive, sizeof(phar_obj->archive), phar_obj);
1243 }
1244
1245 phar_obj->spl.info_class = phar_ce_entry;
1246 efree(fname);
1247 #endif
1248 }
1249
1250
1251
1252
1253
1254 PHP_METHOD(Phar, getSupportedSignatures)
1255 {
1256 if (zend_parse_parameters_none() == FAILURE) {
1257 return;
1258 }
1259
1260 array_init(return_value);
1261
1262 add_next_index_stringl(return_value, "MD5", 3);
1263 add_next_index_stringl(return_value, "SHA-1", 5);
1264 #ifdef PHAR_HASH_OK
1265 add_next_index_stringl(return_value, "SHA-256", 7);
1266 add_next_index_stringl(return_value, "SHA-512", 7);
1267 #endif
1268 #if PHAR_HAVE_OPENSSL
1269 add_next_index_stringl(return_value, "OpenSSL", 7);
1270 #else
1271 if (zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) {
1272 add_next_index_stringl(return_value, "OpenSSL", 7);
1273 }
1274 #endif
1275 }
1276
1277
1278
1279
1280
1281 PHP_METHOD(Phar, getSupportedCompression)
1282 {
1283 if (zend_parse_parameters_none() == FAILURE) {
1284 return;
1285 }
1286
1287 array_init(return_value);
1288 phar_request_initialize();
1289
1290 if (PHAR_G(has_zlib)) {
1291 add_next_index_stringl(return_value, "GZ", 2);
1292 }
1293
1294 if (PHAR_G(has_bz2)) {
1295 add_next_index_stringl(return_value, "BZIP2", 5);
1296 }
1297 }
1298
1299
1300
1301
1302
1303 PHP_METHOD(Phar, unlinkArchive)
1304 {
1305 char *fname, *error, *zname, *arch, *entry;
1306 size_t fname_len;
1307 int zname_len, arch_len, entry_len;
1308 phar_archive_data *phar;
1309
1310 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
1311 RETURN_FALSE;
1312 }
1313
1314 if (!fname_len) {
1315 zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"\"");
1316 return;
1317 }
1318
1319 if (FAILURE == phar_open_from_filename(fname, fname_len, NULL, 0, REPORT_ERRORS, &phar, &error)) {
1320 if (error) {
1321 zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\": %s", fname, error);
1322 efree(error);
1323 } else {
1324 zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\"", fname);
1325 }
1326 return;
1327 }
1328
1329 zname = (char*)zend_get_executed_filename();
1330 zname_len = strlen(zname);
1331
1332 if (zname_len > 7 && !memcmp(zname, "phar://", 7) && SUCCESS == phar_split_fname(zname, zname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
1333 if (arch_len == fname_len && !memcmp(arch, fname, arch_len)) {
1334 zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" cannot be unlinked from within itself", fname);
1335 efree(arch);
1336 efree(entry);
1337 return;
1338 }
1339 efree(arch);
1340 efree(entry);
1341 }
1342
1343 if (phar->is_persistent) {
1344 zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" is in phar.cache_list, cannot unlinkArchive()", fname);
1345 return;
1346 }
1347
1348 if (phar->refcount) {
1349 zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname);
1350 return;
1351 }
1352
1353 fname = estrndup(phar->fname, phar->fname_len);
1354
1355
1356 PHAR_G(last_phar) = NULL;
1357 PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
1358
1359 phar_archive_delref(phar);
1360 unlink(fname);
1361 efree(fname);
1362 RETURN_TRUE;
1363 }
1364
1365
1366 #if HAVE_SPL
1367
1368 #define PHAR_ARCHIVE_OBJECT() \
1369 zval *zobj = getThis(); \
1370 phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \
1371 if (!phar_obj->archive) { \
1372 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
1373 "Cannot call method on an uninitialized Phar object"); \
1374 return; \
1375 }
1376
1377
1378
1379
1380 PHP_METHOD(Phar, __destruct)
1381 {
1382 zval *zobj = getThis();
1383 phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
1384
1385 if (phar_obj->archive && phar_obj->archive->is_persistent) {
1386 zend_hash_str_del(&PHAR_G(phar_persist_map), (const char *) phar_obj->archive, sizeof(phar_obj->archive));
1387 }
1388 }
1389
1390
1391 struct _phar_t {
1392 phar_archive_object *p;
1393 zend_class_entry *c;
1394 char *b;
1395 zval *ret;
1396 php_stream *fp;
1397 uint l;
1398 int count;
1399 };
1400
1401 static int phar_build(zend_object_iterator *iter, void *puser)
1402 {
1403 zval *value;
1404 zend_bool close_fp = 1;
1405 struct _phar_t *p_obj = (struct _phar_t*) puser;
1406 uint str_key_len, base_len = p_obj->l, fname_len;
1407 phar_entry_data *data;
1408 php_stream *fp;
1409 size_t contents_len;
1410 char *fname, *error = NULL, *base = p_obj->b, *save = NULL, *temp = NULL;
1411 zend_string *opened;
1412 char *str_key;
1413 zend_class_entry *ce = p_obj->c;
1414 phar_archive_object *phar_obj = p_obj->p;
1415
1416 value = iter->funcs->get_current_data(iter);
1417
1418 if (EG(exception)) {
1419 return ZEND_HASH_APPLY_STOP;
1420 }
1421
1422 if (!value) {
1423
1424 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned no value", ZSTR_VAL(ce->name));
1425 return ZEND_HASH_APPLY_STOP;
1426 }
1427
1428 switch (Z_TYPE_P(value)) {
1429 case IS_STRING:
1430 break;
1431 case IS_RESOURCE:
1432 php_stream_from_zval_no_verify(fp, value);
1433
1434 if (!fp) {
1435 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Iterator %v returned an invalid stream handle", ZSTR_VAL(ce->name));
1436 return ZEND_HASH_APPLY_STOP;
1437 }
1438
1439 if (iter->funcs->get_current_key) {
1440 zval key;
1441 iter->funcs->get_current_key(iter, &key);
1442
1443 if (EG(exception)) {
1444 return ZEND_HASH_APPLY_STOP;
1445 }
1446
1447 if (Z_TYPE(key) != IS_STRING) {
1448 zval_dtor(&key);
1449 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
1450 return ZEND_HASH_APPLY_STOP;
1451 }
1452
1453 str_key_len = Z_STRLEN(key);
1454 str_key = estrndup(Z_STRVAL(key), str_key_len);
1455
1456 save = str_key;
1457 zval_dtor(&key);
1458 } else {
1459 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
1460 return ZEND_HASH_APPLY_STOP;
1461 }
1462
1463 close_fp = 0;
1464 opened = zend_string_init("[stream]", sizeof("[stream]") - 1, 0);
1465 goto after_open_fp;
1466 case IS_OBJECT:
1467 if (instanceof_function(Z_OBJCE_P(value), spl_ce_SplFileInfo)) {
1468 char *test = NULL;
1469 zval dummy;
1470 spl_filesystem_object *intern = (spl_filesystem_object*)((char*)Z_OBJ_P(value) - Z_OBJ_P(value)->handlers->offset);
1471
1472 if (!base_len) {
1473 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Iterator %v returns an SplFileInfo object, so base directory must be specified", ZSTR_VAL(ce->name));
1474 return ZEND_HASH_APPLY_STOP;
1475 }
1476
1477 switch (intern->type) {
1478 case SPL_FS_DIR:
1479 test = spl_filesystem_object_get_path(intern, NULL);
1480 fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
1481 php_stat(fname, fname_len, FS_IS_DIR, &dummy);
1482
1483 if (Z_TYPE(dummy) == IS_TRUE) {
1484
1485 efree(fname);
1486 return ZEND_HASH_APPLY_KEEP;
1487 }
1488
1489 test = expand_filepath(fname, NULL);
1490 efree(fname);
1491
1492 if (test) {
1493 fname = test;
1494 fname_len = strlen(fname);
1495 } else {
1496 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
1497 return ZEND_HASH_APPLY_STOP;
1498 }
1499
1500 save = fname;
1501 goto phar_spl_fileinfo;
1502 case SPL_FS_INFO:
1503 case SPL_FS_FILE:
1504 fname = expand_filepath(intern->file_name, NULL);
1505 if (!fname) {
1506 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
1507 return ZEND_HASH_APPLY_STOP;
1508 }
1509
1510 fname_len = strlen(fname);
1511 save = fname;
1512 goto phar_spl_fileinfo;
1513 }
1514 }
1515
1516 default:
1517 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned an invalid value (must return a string)", ZSTR_VAL(ce->name));
1518 return ZEND_HASH_APPLY_STOP;
1519 }
1520
1521 fname = Z_STRVAL_P(value);
1522 fname_len = Z_STRLEN_P(value);
1523
1524 phar_spl_fileinfo:
1525 if (base_len) {
1526 temp = expand_filepath(base, NULL);
1527 if (!temp) {
1528 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
1529 if (save) {
1530 efree(save);
1531 }
1532 return ZEND_HASH_APPLY_STOP;
1533 }
1534
1535 base = temp;
1536 base_len = strlen(base);
1537
1538 if (strstr(fname, base)) {
1539 str_key_len = fname_len - base_len;
1540
1541 if (str_key_len <= 0) {
1542 if (save) {
1543 efree(save);
1544 efree(temp);
1545 }
1546 return ZEND_HASH_APPLY_KEEP;
1547 }
1548
1549 str_key = fname + base_len;
1550
1551 if (*str_key == '/' || *str_key == '\\') {
1552 str_key++;
1553 str_key_len--;
1554 }
1555
1556 } else {
1557 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned a path \"%s\" that is not in the base directory \"%s\"", ZSTR_VAL(ce->name), fname, base);
1558
1559 if (save) {
1560 efree(save);
1561 efree(temp);
1562 }
1563
1564 return ZEND_HASH_APPLY_STOP;
1565 }
1566 } else {
1567 if (iter->funcs->get_current_key) {
1568 zval key;
1569 iter->funcs->get_current_key(iter, &key);
1570
1571 if (EG(exception)) {
1572 return ZEND_HASH_APPLY_STOP;
1573 }
1574
1575 if (Z_TYPE(key) != IS_STRING) {
1576 zval_dtor(&key);
1577 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
1578 return ZEND_HASH_APPLY_STOP;
1579 }
1580
1581 str_key_len = Z_STRLEN(key);
1582 str_key = estrndup(Z_STRVAL(key), str_key_len);
1583
1584 save = str_key;
1585 zval_dtor(&key);
1586 } else {
1587 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
1588 return ZEND_HASH_APPLY_STOP;
1589 }
1590 }
1591 #if PHP_API_VERSION < 20100412
1592 if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
1593 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned a path \"%s\" that safe mode prevents opening", ZSTR_VAL(ce->name), fname);
1594
1595 if (save) {
1596 efree(save);
1597 }
1598
1599 if (temp) {
1600 efree(temp);
1601 }
1602
1603 return ZEND_HASH_APPLY_STOP;
1604 }
1605 #endif
1606
1607 if (php_check_open_basedir(fname)) {
1608 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned a path \"%s\" that open_basedir prevents opening", ZSTR_VAL(ce->name), fname);
1609
1610 if (save) {
1611 efree(save);
1612 }
1613
1614 if (temp) {
1615 efree(temp);
1616 }
1617
1618 return ZEND_HASH_APPLY_STOP;
1619 }
1620
1621
1622 fp = php_stream_open_wrapper(fname, "rb", STREAM_MUST_SEEK|0, &opened);
1623
1624 if (!fp) {
1625 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned a file that could not be opened \"%s\"", ZSTR_VAL(ce->name), fname);
1626
1627 if (save) {
1628 efree(save);
1629 }
1630
1631 if (temp) {
1632 efree(temp);
1633 }
1634
1635 return ZEND_HASH_APPLY_STOP;
1636 }
1637 after_open_fp:
1638 if (str_key_len >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
1639
1640 if (save) {
1641 efree(save);
1642 }
1643
1644 if (temp) {
1645 efree(temp);
1646 }
1647
1648 if (opened) {
1649 zend_string_release(opened);
1650 }
1651
1652 if (close_fp) {
1653 php_stream_close(fp);
1654 }
1655
1656 return ZEND_HASH_APPLY_KEEP;
1657 }
1658
1659 if (!(data = phar_get_or_create_entry_data(phar_obj->archive->fname, phar_obj->archive->fname_len, str_key, str_key_len, "w+b", 0, &error, 1))) {
1660 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s cannot be created: %s", str_key, error);
1661 efree(error);
1662
1663 if (save) {
1664 efree(save);
1665 }
1666
1667 if (opened) {
1668 zend_string_release(opened);
1669 }
1670
1671 if (temp) {
1672 efree(temp);
1673 }
1674
1675 if (close_fp) {
1676 php_stream_close(fp);
1677 }
1678
1679 return ZEND_HASH_APPLY_STOP;
1680
1681 } else {
1682 if (error) {
1683 efree(error);
1684 }
1685
1686 if (data->internal_file->fp_type == PHAR_MOD) {
1687 php_stream_close(data->internal_file->fp);
1688 }
1689
1690 data->internal_file->fp = NULL;
1691 data->internal_file->fp_type = PHAR_UFP;
1692 data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp);
1693 data->fp = NULL;
1694 php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len);
1695 data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
1696 php_stream_tell(p_obj->fp) - data->internal_file->offset;
1697 }
1698
1699 if (close_fp) {
1700 php_stream_close(fp);
1701 }
1702
1703 add_assoc_str(p_obj->ret, str_key, opened);
1704
1705 if (save) {
1706 efree(save);
1707 }
1708
1709 if (temp) {
1710 efree(temp);
1711 }
1712
1713 data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
1714 phar_entry_delref(data);
1715
1716 return ZEND_HASH_APPLY_KEEP;
1717 }
1718
1719
1720
1721
1722
1723
1724
1725
1726 PHP_METHOD(Phar, buildFromDirectory)
1727 {
1728 char *dir, *error, *regex = NULL;
1729 size_t dir_len, regex_len = 0;
1730 zend_bool apply_reg = 0;
1731 zval arg, arg2, iter, iteriter, regexiter;
1732 struct _phar_t pass;
1733
1734 PHAR_ARCHIVE_OBJECT();
1735
1736 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
1737 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1738 "Cannot write to archive - write operations restricted by INI setting");
1739 return;
1740 }
1741
1742 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s", &dir, &dir_len, ®ex, ®ex_len) == FAILURE) {
1743 RETURN_FALSE;
1744 }
1745
1746 if (SUCCESS != object_init_ex(&iter, spl_ce_RecursiveDirectoryIterator)) {
1747 zval_ptr_dtor(&iter);
1748 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
1749 RETURN_FALSE;
1750 }
1751
1752 ZVAL_STRINGL(&arg, dir, dir_len);
1753 ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
1754
1755 zend_call_method_with_2_params(&iter, spl_ce_RecursiveDirectoryIterator,
1756 &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2);
1757
1758 zval_ptr_dtor(&arg);
1759 if (EG(exception)) {
1760 zval_ptr_dtor(&iter);
1761 RETURN_FALSE;
1762 }
1763
1764 if (SUCCESS != object_init_ex(&iteriter, spl_ce_RecursiveIteratorIterator)) {
1765 zval_ptr_dtor(&iter);
1766 zval_ptr_dtor(&iteriter);
1767 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
1768 RETURN_FALSE;
1769 }
1770
1771 zend_call_method_with_1_params(&iteriter, spl_ce_RecursiveIteratorIterator,
1772 &spl_ce_RecursiveIteratorIterator->constructor, "__construct", NULL, &iter);
1773
1774 if (EG(exception)) {
1775 zval_ptr_dtor(&iter);
1776 zval_ptr_dtor(&iteriter);
1777 RETURN_FALSE;
1778 }
1779
1780 zval_ptr_dtor(&iter);
1781
1782 if (regex_len > 0) {
1783 apply_reg = 1;
1784
1785 if (SUCCESS != object_init_ex(®exiter, spl_ce_RegexIterator)) {
1786 zval_ptr_dtor(&iteriter);
1787 zval_dtor(®exiter);
1788 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate regex iterator for %s", phar_obj->archive->fname);
1789 RETURN_FALSE;
1790 }
1791
1792 ZVAL_STRINGL(&arg2, regex, regex_len);
1793
1794 zend_call_method_with_2_params(®exiter, spl_ce_RegexIterator,
1795 &spl_ce_RegexIterator->constructor, "__construct", NULL, &iteriter, &arg2);
1796 zval_ptr_dtor(&arg2);
1797 }
1798
1799 array_init(return_value);
1800
1801 pass.c = apply_reg ? Z_OBJCE(regexiter) : Z_OBJCE(iteriter);
1802 pass.p = phar_obj;
1803 pass.b = dir;
1804 pass.l = dir_len;
1805 pass.count = 0;
1806 pass.ret = return_value;
1807 pass.fp = php_stream_fopen_tmpfile();
1808 if (pass.fp == NULL) {
1809 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" unable to create temporary file", phar_obj->archive->fname);
1810 return;
1811 }
1812
1813 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
1814 zval_ptr_dtor(&iteriter);
1815 if (apply_reg) {
1816 zval_ptr_dtor(®exiter);
1817 }
1818 php_stream_close(pass.fp);
1819 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
1820 return;
1821 }
1822
1823 if (SUCCESS == spl_iterator_apply((apply_reg ? ®exiter : &iteriter), (spl_iterator_apply_func_t) phar_build, (void *) &pass)) {
1824 zval_ptr_dtor(&iteriter);
1825
1826 if (apply_reg) {
1827 zval_ptr_dtor(®exiter);
1828 }
1829
1830 phar_obj->archive->ufp = pass.fp;
1831 phar_flush(phar_obj->archive, 0, 0, 0, &error);
1832
1833 if (error) {
1834 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
1835 efree(error);
1836 }
1837
1838 } else {
1839 zval_ptr_dtor(&iteriter);
1840 if (apply_reg) {
1841 zval_ptr_dtor(®exiter);
1842 }
1843 php_stream_close(pass.fp);
1844 }
1845 }
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858 PHP_METHOD(Phar, buildFromIterator)
1859 {
1860 zval *obj;
1861 char *error;
1862 size_t base_len = 0;
1863 char *base = NULL;
1864 struct _phar_t pass;
1865
1866 PHAR_ARCHIVE_OBJECT();
1867
1868 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
1869 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1870 "Cannot write out phar archive, phar is read-only");
1871 return;
1872 }
1873
1874 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s", &obj, zend_ce_traversable, &base, &base_len) == FAILURE) {
1875 RETURN_FALSE;
1876 }
1877
1878 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
1879 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
1880 return;
1881 }
1882
1883 array_init(return_value);
1884
1885 pass.c = Z_OBJCE_P(obj);
1886 pass.p = phar_obj;
1887 pass.b = base;
1888 pass.l = base_len;
1889 pass.ret = return_value;
1890 pass.count = 0;
1891 pass.fp = php_stream_fopen_tmpfile();
1892 if (pass.fp == NULL) {
1893 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\": unable to create temporary file", phar_obj->archive->fname);
1894 return;
1895 }
1896
1897 if (SUCCESS == spl_iterator_apply(obj, (spl_iterator_apply_func_t) phar_build, (void *) &pass)) {
1898 phar_obj->archive->ufp = pass.fp;
1899 phar_flush(phar_obj->archive, 0, 0, 0, &error);
1900 if (error) {
1901 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
1902 efree(error);
1903 }
1904 } else {
1905 php_stream_close(pass.fp);
1906 }
1907 }
1908
1909
1910
1911
1912
1913 PHP_METHOD(Phar, count)
1914 {
1915
1916 zend_long mode;
1917 PHAR_ARCHIVE_OBJECT();
1918
1919 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &mode) == FAILURE) {
1920 RETURN_FALSE;
1921 }
1922
1923 RETURN_LONG(zend_hash_num_elements(&phar_obj->archive->manifest));
1924 }
1925
1926
1927
1928
1929
1930
1931 PHP_METHOD(Phar, isFileFormat)
1932 {
1933 zend_long type;
1934 PHAR_ARCHIVE_OBJECT();
1935
1936 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &type) == FAILURE) {
1937 RETURN_FALSE;
1938 }
1939
1940 switch (type) {
1941 case PHAR_FORMAT_TAR:
1942 RETURN_BOOL(phar_obj->archive->is_tar);
1943 case PHAR_FORMAT_ZIP:
1944 RETURN_BOOL(phar_obj->archive->is_zip);
1945 case PHAR_FORMAT_PHAR:
1946 RETURN_BOOL(!phar_obj->archive->is_tar && !phar_obj->archive->is_zip);
1947 default:
1948 zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown file format specified");
1949 }
1950 }
1951
1952
1953 static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp)
1954 {
1955 char *error;
1956 zend_off_t offset;
1957 phar_entry_info *link;
1958
1959 if (FAILURE == phar_open_entry_fp(entry, &error, 1)) {
1960 if (error) {
1961 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1962 "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents: %s", entry->phar->fname, entry->filename, error);
1963 efree(error);
1964 } else {
1965 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1966 "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents", entry->phar->fname, entry->filename);
1967 }
1968 return FAILURE;
1969 }
1970
1971
1972 phar_seek_efp(entry, 0, SEEK_SET, 0, 1);
1973 offset = php_stream_tell(fp);
1974 link = phar_get_link_source(entry);
1975
1976 if (!link) {
1977 link = entry;
1978 }
1979
1980 if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) {
1981 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
1982 "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename);
1983 return FAILURE;
1984 }
1985
1986 if (entry->fp_type == PHAR_MOD) {
1987
1988 entry->cfp = entry->fp;
1989 entry->fp = NULL;
1990 }
1991
1992
1993 entry->fp_type = PHAR_FP;
1994 entry->offset = offset;
1995 return SUCCESS;
1996 }
1997
1998
1999 static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext, zend_bool compress)
2000 {
2001 const char *oldname = NULL;
2002 phar_archive_data *phar = *sphar;
2003 char *oldpath = NULL;
2004 char *basename = NULL, *basepath = NULL;
2005 char *newname = NULL, *newpath = NULL;
2006 zval ret, arg1;
2007 zend_class_entry *ce;
2008 char *error;
2009 const char *pcr_error;
2010 int ext_len = ext ? strlen(ext) : 0;
2011 int oldname_len;
2012 phar_archive_data *pphar = NULL;
2013 php_stream_statbuf ssb;
2014
2015 if (!ext) {
2016 if (phar->is_zip) {
2017
2018 if (phar->is_data) {
2019 ext = "zip";
2020 } else {
2021 ext = "phar.zip";
2022 }
2023
2024 } else if (phar->is_tar) {
2025
2026 switch (phar->flags) {
2027 case PHAR_FILE_COMPRESSED_GZ:
2028 if (phar->is_data) {
2029 ext = "tar.gz";
2030 } else {
2031 ext = "phar.tar.gz";
2032 }
2033 break;
2034 case PHAR_FILE_COMPRESSED_BZ2:
2035 if (phar->is_data) {
2036 ext = "tar.bz2";
2037 } else {
2038 ext = "phar.tar.bz2";
2039 }
2040 break;
2041 default:
2042 if (phar->is_data) {
2043 ext = "tar";
2044 } else {
2045 ext = "phar.tar";
2046 }
2047 }
2048 } else {
2049
2050 switch (phar->flags) {
2051 case PHAR_FILE_COMPRESSED_GZ:
2052 ext = "phar.gz";
2053 break;
2054 case PHAR_FILE_COMPRESSED_BZ2:
2055 ext = "phar.bz2";
2056 break;
2057 default:
2058 ext = "phar";
2059 }
2060 }
2061 } else if (phar_path_check(&ext, &ext_len, &pcr_error) > pcr_is_ok) {
2062
2063 if (phar->is_data) {
2064 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "data phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
2065 } else {
2066 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
2067 }
2068 return NULL;
2069 }
2070
2071 if (ext[0] == '.') {
2072 ++ext;
2073 }
2074
2075 oldpath = estrndup(phar->fname, phar->fname_len);
2076 if ((oldname = zend_memrchr(phar->fname, '/', phar->fname_len))) {
2077 ++oldname;
2078 } else {
2079 oldname = phar->fname;
2080 }
2081 oldname_len = strlen(oldname);
2082
2083 basename = estrndup(oldname, oldname_len);
2084 spprintf(&newname, 0, "%s.%s", strtok(basename, "."), ext);
2085 efree(basename);
2086
2087
2088
2089 basepath = estrndup(oldpath, (strlen(oldpath) - oldname_len));
2090 phar->fname_len = spprintf(&newpath, 0, "%s%s", basepath, newname);
2091 phar->fname = newpath;
2092 phar->ext = newpath + phar->fname_len - strlen(ext) - 1;
2093 efree(basepath);
2094 efree(newname);
2095
2096 if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, newpath, phar->fname_len))) {
2097 efree(oldpath);
2098 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars, new phar name is in phar.cache_list", phar->fname);
2099 return NULL;
2100 }
2101
2102 if (NULL != (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len))) {
2103 if (pphar->fname_len == phar->fname_len && !memcmp(pphar->fname, phar->fname, phar->fname_len)) {
2104 if (!zend_hash_num_elements(&phar->manifest)) {
2105 pphar->is_tar = phar->is_tar;
2106 pphar->is_zip = phar->is_zip;
2107 pphar->is_data = phar->is_data;
2108 pphar->flags = phar->flags;
2109 pphar->fp = phar->fp;
2110 phar->fp = NULL;
2111 phar_destroy_phar_data(phar);
2112 *sphar = NULL;
2113 phar = pphar;
2114 phar->refcount++;
2115 newpath = oldpath;
2116 goto its_ok;
2117 }
2118 }
2119
2120 efree(oldpath);
2121 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars, a phar with that name already exists", phar->fname);
2122 return NULL;
2123 }
2124 its_ok:
2125 if (SUCCESS == php_stream_stat_path(newpath, &ssb)) {
2126 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar \"%s\" exists and must be unlinked prior to conversion", newpath);
2127 efree(oldpath);
2128 return NULL;
2129 }
2130 if (!phar->is_data) {
2131 if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 1, 1, 1)) {
2132 efree(oldpath);
2133 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar \"%s\" has invalid extension %s", phar->fname, ext);
2134 return NULL;
2135 }
2136
2137 if (phar->alias) {
2138 if (phar->is_temporary_alias) {
2139 phar->alias = NULL;
2140 phar->alias_len = 0;
2141 } else {
2142 phar->alias = estrndup(newpath, strlen(newpath));
2143 phar->alias_len = strlen(newpath);
2144 phar->is_temporary_alias = 1;
2145 zend_hash_str_update_ptr(&(PHAR_G(phar_alias_map)), newpath, phar->fname_len, phar);
2146 }
2147 }
2148
2149 } else {
2150
2151 if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 0, 1, 1)) {
2152 efree(oldpath);
2153 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
2154 return NULL;
2155 }
2156
2157 phar->alias = NULL;
2158 phar->alias_len = 0;
2159 }
2160
2161 if ((!pphar || phar == pphar) && NULL == zend_hash_str_update_ptr(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len, phar)) {
2162 efree(oldpath);
2163 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars", phar->fname);
2164 return NULL;
2165 }
2166
2167 phar_flush(phar, 0, 0, 1, &error);
2168
2169 if (error) {
2170 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
2171 efree(error);
2172 efree(oldpath);
2173 return NULL;
2174 }
2175
2176 efree(oldpath);
2177
2178 if (phar->is_data) {
2179 ce = phar_ce_data;
2180 } else {
2181 ce = phar_ce_archive;
2182 }
2183
2184 ZVAL_NULL(&ret);
2185 if (SUCCESS != object_init_ex(&ret, ce)) {
2186 zval_dtor(&ret);
2187 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname);
2188 return NULL;
2189 }
2190
2191 ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len);
2192
2193 zend_call_method_with_1_params(&ret, ce, &ce->constructor, "__construct", NULL, &arg1);
2194 zval_ptr_dtor(&arg1);
2195 return Z_OBJ(ret);
2196 }
2197
2198
2199 static zend_object *phar_convert_to_other(phar_archive_data *source, int convert, char *ext, php_uint32 flags)
2200 {
2201 phar_archive_data *phar;
2202 phar_entry_info *entry, newentry;
2203 zend_object *ret;
2204
2205
2206 PHAR_G(last_phar) = NULL;
2207 PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
2208
2209 phar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
2210
2211 phar->flags = flags;
2212 phar->is_data = source->is_data;
2213
2214 switch (convert) {
2215 case PHAR_FORMAT_TAR:
2216 phar->is_tar = 1;
2217 break;
2218 case PHAR_FORMAT_ZIP:
2219 phar->is_zip = 1;
2220 break;
2221 default:
2222 phar->is_data = 0;
2223 break;
2224 }
2225
2226 zend_hash_init(&(phar->manifest), sizeof(phar_entry_info),
2227 zend_get_hash_value, destroy_phar_manifest_entry, 0);
2228 zend_hash_init(&phar->mounted_dirs, sizeof(char *),
2229 zend_get_hash_value, NULL, 0);
2230 zend_hash_init(&phar->virtual_dirs, sizeof(char *),
2231 zend_get_hash_value, NULL, 0);
2232
2233 phar->fp = php_stream_fopen_tmpfile();
2234 if (phar->fp == NULL) {
2235 zend_throw_exception_ex(phar_ce_PharException, 0, "unable to create temporary file");
2236 return NULL;
2237 }
2238 phar->fname = source->fname;
2239 phar->fname_len = source->fname_len;
2240 phar->is_temporary_alias = source->is_temporary_alias;
2241 phar->alias = source->alias;
2242
2243 if (Z_TYPE(source->metadata) != IS_UNDEF) {
2244 ZVAL_DUP(&phar->metadata, &source->metadata);
2245 phar->metadata_len = 0;
2246 }
2247
2248
2249 ZEND_HASH_FOREACH_PTR(&source->manifest, entry) {
2250
2251 newentry = *entry;
2252
2253 if (newentry.link) {
2254 newentry.link = estrdup(newentry.link);
2255 goto no_copy;
2256 }
2257
2258 if (newentry.tmp) {
2259 newentry.tmp = estrdup(newentry.tmp);
2260 goto no_copy;
2261 }
2262
2263 newentry.metadata_str.s = NULL;
2264
2265 if (FAILURE == phar_copy_file_contents(&newentry, phar->fp)) {
2266 zend_hash_destroy(&(phar->manifest));
2267 php_stream_close(phar->fp);
2268 efree(phar);
2269
2270 return NULL;
2271 }
2272 no_copy:
2273 newentry.filename = estrndup(newentry.filename, newentry.filename_len);
2274
2275 if (Z_TYPE(newentry.metadata) != IS_UNDEF) {
2276 zval_copy_ctor(&newentry.metadata);
2277 newentry.metadata_str.s = NULL;
2278 }
2279
2280 newentry.is_zip = phar->is_zip;
2281 newentry.is_tar = phar->is_tar;
2282
2283 if (newentry.is_tar) {
2284 newentry.tar_type = (entry->is_dir ? TAR_DIR : TAR_FILE);
2285 }
2286
2287 newentry.is_modified = 1;
2288 newentry.phar = phar;
2289 newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK;
2290 phar_set_inode(&newentry);
2291 zend_hash_str_add_mem(&(phar->manifest), newentry.filename, newentry.filename_len, (void*)&newentry, sizeof(phar_entry_info));
2292 phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len);
2293 } ZEND_HASH_FOREACH_END();
2294
2295 if ((ret = phar_rename_archive(&phar, ext, 0))) {
2296 return ret;
2297 } else {
2298 if(phar != NULL) {
2299 zend_hash_destroy(&(phar->manifest));
2300 zend_hash_destroy(&(phar->mounted_dirs));
2301 zend_hash_destroy(&(phar->virtual_dirs));
2302 if (phar->fp) {
2303 php_stream_close(phar->fp);
2304 }
2305 efree(phar->fname);
2306 efree(phar);
2307 }
2308 return NULL;
2309 }
2310 }
2311
2312
2313
2314
2315
2316
2317
2318 PHP_METHOD(Phar, convertToExecutable)
2319 {
2320 char *ext = NULL;
2321 int is_data;
2322 size_t ext_len = 0;
2323 php_uint32 flags;
2324 zend_object *ret;
2325
2326 zend_long format = 9021976, method = 9021976;
2327 PHAR_ARCHIVE_OBJECT();
2328
2329 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
2330 return;
2331 }
2332
2333 if (PHAR_G(readonly)) {
2334 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2335 "Cannot write out executable phar archive, phar is read-only");
2336 return;
2337 }
2338
2339 switch (format) {
2340 case 9021976:
2341 case PHAR_FORMAT_SAME:
2342
2343 if (phar_obj->archive->is_tar) {
2344 format = PHAR_FORMAT_TAR;
2345 } else if (phar_obj->archive->is_zip) {
2346 format = PHAR_FORMAT_ZIP;
2347 } else {
2348 format = PHAR_FORMAT_PHAR;
2349 }
2350 break;
2351 case PHAR_FORMAT_PHAR:
2352 case PHAR_FORMAT_TAR:
2353 case PHAR_FORMAT_ZIP:
2354 break;
2355 default:
2356 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2357 "Unknown file format specified, please pass one of Phar::PHAR, Phar::TAR or Phar::ZIP");
2358 return;
2359 }
2360
2361 switch (method) {
2362 case 9021976:
2363 flags = phar_obj->archive->flags & PHAR_FILE_COMPRESSION_MASK;
2364 break;
2365 case 0:
2366 flags = PHAR_FILE_COMPRESSED_NONE;
2367 break;
2368 case PHAR_ENT_COMPRESSED_GZ:
2369 if (format == PHAR_FORMAT_ZIP) {
2370 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2371 "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
2372 return;
2373 }
2374
2375 if (!PHAR_G(has_zlib)) {
2376 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2377 "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
2378 return;
2379 }
2380
2381 flags = PHAR_FILE_COMPRESSED_GZ;
2382 break;
2383 case PHAR_ENT_COMPRESSED_BZ2:
2384 if (format == PHAR_FORMAT_ZIP) {
2385 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2386 "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
2387 return;
2388 }
2389
2390 if (!PHAR_G(has_bz2)) {
2391 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2392 "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
2393 return;
2394 }
2395
2396 flags = PHAR_FILE_COMPRESSED_BZ2;
2397 break;
2398 default:
2399 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2400 "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
2401 return;
2402 }
2403
2404 is_data = phar_obj->archive->is_data;
2405 phar_obj->archive->is_data = 0;
2406 ret = phar_convert_to_other(phar_obj->archive, format, ext, flags);
2407 phar_obj->archive->is_data = is_data;
2408
2409 if (ret) {
2410 ZVAL_OBJ(return_value, ret);
2411 } else {
2412 RETURN_NULL();
2413 }
2414 }
2415
2416
2417
2418
2419
2420
2421
2422 PHP_METHOD(Phar, convertToData)
2423 {
2424 char *ext = NULL;
2425 int is_data;
2426 size_t ext_len = 0;
2427 php_uint32 flags;
2428 zend_object *ret;
2429
2430 zend_long format = 9021976, method = 9021976;
2431 PHAR_ARCHIVE_OBJECT();
2432
2433 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
2434 return;
2435 }
2436
2437 switch (format) {
2438 case 9021976:
2439 case PHAR_FORMAT_SAME:
2440
2441 if (phar_obj->archive->is_tar) {
2442 format = PHAR_FORMAT_TAR;
2443 } else if (phar_obj->archive->is_zip) {
2444 format = PHAR_FORMAT_ZIP;
2445 } else {
2446 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2447 "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
2448 return;
2449 }
2450 break;
2451 case PHAR_FORMAT_PHAR:
2452 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2453 "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
2454 return;
2455 case PHAR_FORMAT_TAR:
2456 case PHAR_FORMAT_ZIP:
2457 break;
2458 default:
2459 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2460 "Unknown file format specified, please pass one of Phar::TAR or Phar::ZIP");
2461 return;
2462 }
2463
2464 switch (method) {
2465 case 9021976:
2466 flags = phar_obj->archive->flags & PHAR_FILE_COMPRESSION_MASK;
2467 break;
2468 case 0:
2469 flags = PHAR_FILE_COMPRESSED_NONE;
2470 break;
2471 case PHAR_ENT_COMPRESSED_GZ:
2472 if (format == PHAR_FORMAT_ZIP) {
2473 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2474 "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
2475 return;
2476 }
2477
2478 if (!PHAR_G(has_zlib)) {
2479 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2480 "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
2481 return;
2482 }
2483
2484 flags = PHAR_FILE_COMPRESSED_GZ;
2485 break;
2486 case PHAR_ENT_COMPRESSED_BZ2:
2487 if (format == PHAR_FORMAT_ZIP) {
2488 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2489 "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
2490 return;
2491 }
2492
2493 if (!PHAR_G(has_bz2)) {
2494 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2495 "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
2496 return;
2497 }
2498
2499 flags = PHAR_FILE_COMPRESSED_BZ2;
2500 break;
2501 default:
2502 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
2503 "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
2504 return;
2505 }
2506
2507 is_data = phar_obj->archive->is_data;
2508 phar_obj->archive->is_data = 1;
2509 ret = phar_convert_to_other(phar_obj->archive, format, ext, flags);
2510 phar_obj->archive->is_data = is_data;
2511
2512 if (ret) {
2513 ZVAL_OBJ(return_value, ret);
2514 } else {
2515 RETURN_NULL();
2516 }
2517 }
2518
2519
2520
2521
2522
2523
2524 PHP_METHOD(Phar, isCompressed)
2525 {
2526 PHAR_ARCHIVE_OBJECT();
2527
2528 if (zend_parse_parameters_none() == FAILURE) {
2529 return;
2530 }
2531
2532 if (phar_obj->archive->flags & PHAR_FILE_COMPRESSED_GZ) {
2533 RETURN_LONG(PHAR_ENT_COMPRESSED_GZ);
2534 }
2535
2536 if (phar_obj->archive->flags & PHAR_FILE_COMPRESSED_BZ2) {
2537 RETURN_LONG(PHAR_ENT_COMPRESSED_BZ2);
2538 }
2539
2540 RETURN_FALSE;
2541 }
2542
2543
2544
2545
2546
2547 PHP_METHOD(Phar, isWritable)
2548 {
2549 php_stream_statbuf ssb;
2550 PHAR_ARCHIVE_OBJECT();
2551
2552 if (zend_parse_parameters_none() == FAILURE) {
2553 return;
2554 }
2555
2556 if (!phar_obj->archive->is_writeable) {
2557 RETURN_FALSE;
2558 }
2559
2560 if (SUCCESS != php_stream_stat_path(phar_obj->archive->fname, &ssb)) {
2561 if (phar_obj->archive->is_brandnew) {
2562
2563 RETURN_TRUE;
2564 }
2565 RETURN_FALSE;
2566 }
2567
2568 RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0);
2569 }
2570
2571
2572
2573
2574
2575 PHP_METHOD(Phar, delete)
2576 {
2577 char *fname;
2578 size_t fname_len;
2579 char *error;
2580 phar_entry_info *entry;
2581 PHAR_ARCHIVE_OBJECT();
2582
2583 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
2584 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2585 "Cannot write out phar archive, phar is read-only");
2586 return;
2587 }
2588
2589 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
2590 RETURN_FALSE;
2591 }
2592
2593 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
2594 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
2595 return;
2596 }
2597 if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint) fname_len)) {
2598 if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint) fname_len))) {
2599 if (entry->is_deleted) {
2600
2601 RETURN_TRUE;
2602 } else {
2603 entry->is_deleted = 1;
2604 entry->is_modified = 1;
2605 phar_obj->archive->is_modified = 1;
2606 }
2607 }
2608 } else {
2609 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be deleted", fname);
2610 RETURN_FALSE;
2611 }
2612
2613 phar_flush(phar_obj->archive, NULL, 0, 0, &error);
2614 if (error) {
2615 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
2616 efree(error);
2617 }
2618
2619 RETURN_TRUE;
2620 }
2621
2622
2623
2624
2625
2626 PHP_METHOD(Phar, getAlias)
2627 {
2628 PHAR_ARCHIVE_OBJECT();
2629
2630 if (zend_parse_parameters_none() == FAILURE) {
2631 return;
2632 }
2633
2634 if (phar_obj->archive->alias && phar_obj->archive->alias != phar_obj->archive->fname) {
2635 RETURN_STRINGL(phar_obj->archive->alias, phar_obj->archive->alias_len);
2636 }
2637 }
2638
2639
2640
2641
2642
2643 PHP_METHOD(Phar, getPath)
2644 {
2645 PHAR_ARCHIVE_OBJECT();
2646
2647 if (zend_parse_parameters_none() == FAILURE) {
2648 return;
2649 }
2650
2651 RETURN_STRINGL(phar_obj->archive->fname, phar_obj->archive->fname_len);
2652 }
2653
2654
2655
2656
2657
2658
2659 PHP_METHOD(Phar, setAlias)
2660 {
2661 char *alias, *error, *oldalias;
2662 phar_archive_data *fd_ptr;
2663 size_t alias_len, oldalias_len;
2664 int old_temp, readd = 0;
2665
2666 PHAR_ARCHIVE_OBJECT();
2667
2668 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
2669 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2670 "Cannot write out phar archive, phar is read-only");
2671 RETURN_FALSE;
2672 }
2673
2674
2675 PHAR_G(last_phar) = NULL;
2676 PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
2677
2678 if (phar_obj->archive->is_data) {
2679 if (phar_obj->archive->is_tar) {
2680 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2681 "A Phar alias cannot be set in a plain tar archive");
2682 } else {
2683 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2684 "A Phar alias cannot be set in a plain zip archive");
2685 }
2686 RETURN_FALSE;
2687 }
2688
2689 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &alias, &alias_len) == SUCCESS) {
2690 if (alias_len == phar_obj->archive->alias_len && memcmp(phar_obj->archive->alias, alias, alias_len) == 0) {
2691 RETURN_TRUE;
2692 }
2693 if (alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
2694 spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", alias, fd_ptr->fname);
2695 if (SUCCESS == phar_free_alias(fd_ptr, alias, alias_len)) {
2696 efree(error);
2697 goto valid_alias;
2698 }
2699 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
2700 efree(error);
2701 RETURN_FALSE;
2702 }
2703 if (!phar_validate_alias(alias, alias_len)) {
2704 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2705 "Invalid alias \"%s\" specified for phar \"%s\"", alias, phar_obj->archive->fname);
2706 RETURN_FALSE;
2707 }
2708 valid_alias:
2709 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
2710 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
2711 return;
2712 }
2713 if (phar_obj->archive->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len))) {
2714 zend_hash_str_del(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len);
2715 readd = 1;
2716 }
2717
2718 oldalias = phar_obj->archive->alias;
2719 oldalias_len = phar_obj->archive->alias_len;
2720 old_temp = phar_obj->archive->is_temporary_alias;
2721
2722 if (alias_len) {
2723 phar_obj->archive->alias = estrndup(alias, alias_len);
2724 } else {
2725 phar_obj->archive->alias = NULL;
2726 }
2727
2728 phar_obj->archive->alias_len = alias_len;
2729 phar_obj->archive->is_temporary_alias = 0;
2730 phar_flush(phar_obj->archive, NULL, 0, 0, &error);
2731
2732 if (error) {
2733 phar_obj->archive->alias = oldalias;
2734 phar_obj->archive->alias_len = oldalias_len;
2735 phar_obj->archive->is_temporary_alias = old_temp;
2736 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
2737 if (readd) {
2738 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), oldalias, oldalias_len, phar_obj->archive);
2739 }
2740 efree(error);
2741 RETURN_FALSE;
2742 }
2743
2744 zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, phar_obj->archive);
2745
2746 if (oldalias) {
2747 efree(oldalias);
2748 }
2749
2750 RETURN_TRUE;
2751 }
2752
2753 RETURN_FALSE;
2754 }
2755
2756
2757
2758
2759
2760 PHP_METHOD(Phar, getVersion)
2761 {
2762 PHAR_ARCHIVE_OBJECT();
2763
2764 if (zend_parse_parameters_none() == FAILURE) {
2765 return;
2766 }
2767
2768 RETURN_STRING(phar_obj->archive->version);
2769 }
2770
2771
2772
2773
2774
2775 PHP_METHOD(Phar, startBuffering)
2776 {
2777 PHAR_ARCHIVE_OBJECT();
2778
2779 if (zend_parse_parameters_none() == FAILURE) {
2780 return;
2781 }
2782
2783 phar_obj->archive->donotflush = 1;
2784 }
2785
2786
2787
2788
2789
2790 PHP_METHOD(Phar, isBuffering)
2791 {
2792 PHAR_ARCHIVE_OBJECT();
2793
2794 if (zend_parse_parameters_none() == FAILURE) {
2795 return;
2796 }
2797
2798 RETURN_BOOL(phar_obj->archive->donotflush);
2799 }
2800
2801
2802
2803
2804
2805 PHP_METHOD(Phar, stopBuffering)
2806 {
2807 char *error;
2808
2809 PHAR_ARCHIVE_OBJECT();
2810
2811 if (zend_parse_parameters_none() == FAILURE) {
2812 return;
2813 }
2814
2815 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
2816 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2817 "Cannot write out phar archive, phar is read-only");
2818 return;
2819 }
2820
2821 phar_obj->archive->donotflush = 0;
2822 phar_flush(phar_obj->archive, 0, 0, 0, &error);
2823
2824 if (error) {
2825 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
2826 efree(error);
2827 }
2828 }
2829
2830
2831
2832
2833
2834
2835 PHP_METHOD(Phar, setStub)
2836 {
2837 zval *zstub;
2838 char *stub, *error;
2839 size_t stub_len;
2840 zend_long len = -1;
2841 php_stream *stream;
2842 PHAR_ARCHIVE_OBJECT();
2843
2844 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
2845 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2846 "Cannot change stub, phar is read-only");
2847 return;
2848 }
2849
2850 if (phar_obj->archive->is_data) {
2851 if (phar_obj->archive->is_tar) {
2852 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2853 "A Phar stub cannot be set in a plain tar archive");
2854 } else {
2855 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2856 "A Phar stub cannot be set in a plain zip archive");
2857 }
2858 return;
2859 }
2860
2861 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "r|l", &zstub, &len) == SUCCESS) {
2862 if ((php_stream_from_zval_no_verify(stream, zstub)) != NULL) {
2863 if (len > 0) {
2864 len = -len;
2865 } else {
2866 len = -1;
2867 }
2868 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
2869 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
2870 return;
2871 }
2872 phar_flush(phar_obj->archive, (char *) zstub, len, 0, &error);
2873 if (error) {
2874 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
2875 efree(error);
2876 }
2877 RETURN_TRUE;
2878 } else {
2879 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2880 "Cannot change stub, unable to read from input stream");
2881 }
2882 } else if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &stub, &stub_len) == SUCCESS) {
2883 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
2884 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
2885 return;
2886 }
2887 phar_flush(phar_obj->archive, stub, stub_len, 0, &error);
2888
2889 if (error) {
2890 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
2891 efree(error);
2892 }
2893
2894 RETURN_TRUE;
2895 }
2896
2897 RETURN_FALSE;
2898 }
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914 PHP_METHOD(Phar, setDefaultStub)
2915 {
2916 char *index = NULL, *webindex = NULL, *error = NULL;
2917 zend_string *stub = NULL;
2918 size_t index_len = 0, webindex_len = 0;
2919 int created_stub = 0;
2920 PHAR_ARCHIVE_OBJECT();
2921
2922 if (phar_obj->archive->is_data) {
2923 if (phar_obj->archive->is_tar) {
2924 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2925 "A Phar stub cannot be set in a plain tar archive");
2926 } else {
2927 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2928 "A Phar stub cannot be set in a plain zip archive");
2929 }
2930 return;
2931 }
2932
2933 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
2934 RETURN_FALSE;
2935 }
2936
2937 if (ZEND_NUM_ARGS() > 0 && (phar_obj->archive->is_tar || phar_obj->archive->is_zip)) {
2938 php_error_docref(NULL, E_WARNING, "method accepts no arguments for a tar- or zip-based phar stub, %d given", ZEND_NUM_ARGS());
2939 RETURN_FALSE;
2940 }
2941
2942 if (PHAR_G(readonly)) {
2943 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2944 "Cannot change stub: phar.readonly=1");
2945 RETURN_FALSE;
2946 }
2947
2948 if (!phar_obj->archive->is_tar && !phar_obj->archive->is_zip) {
2949 stub = phar_create_default_stub(index, webindex, &error);
2950
2951 if (error) {
2952 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "%s", error);
2953 efree(error);
2954 if (stub) {
2955 zend_string_free(stub);
2956 }
2957 RETURN_FALSE;
2958 }
2959
2960 created_stub = 1;
2961 }
2962
2963 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
2964 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
2965 return;
2966 }
2967 phar_flush(phar_obj->archive, stub ? ZSTR_VAL(stub) : 0, stub ? ZSTR_LEN(stub) : 0, 1, &error);
2968
2969 if (created_stub) {
2970 zend_string_free(stub);
2971 }
2972
2973 if (error) {
2974 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
2975 efree(error);
2976 RETURN_FALSE;
2977 }
2978
2979 RETURN_TRUE;
2980 }
2981
2982
2983
2984
2985
2986
2987
2988
2989 PHP_METHOD(Phar, setSignatureAlgorithm)
2990 {
2991 zend_long algo;
2992 char *error, *key = NULL;
2993 size_t key_len = 0;
2994
2995 PHAR_ARCHIVE_OBJECT();
2996
2997 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
2998 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
2999 "Cannot set signature algorithm, phar is read-only");
3000 return;
3001 }
3002
3003 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "l|s", &algo, &key, &key_len) != SUCCESS) {
3004 return;
3005 }
3006
3007 switch (algo) {
3008 case PHAR_SIG_SHA256:
3009 case PHAR_SIG_SHA512:
3010 #ifndef PHAR_HASH_OK
3011 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3012 "SHA-256 and SHA-512 signatures are only supported if the hash extension is enabled and built non-shared");
3013 return;
3014 #endif
3015 case PHAR_SIG_MD5:
3016 case PHAR_SIG_SHA1:
3017 case PHAR_SIG_OPENSSL:
3018 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
3019 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
3020 return;
3021 }
3022 phar_obj->archive->sig_flags = algo;
3023 phar_obj->archive->is_modified = 1;
3024 PHAR_G(openssl_privatekey) = key;
3025 PHAR_G(openssl_privatekey_len) = key_len;
3026
3027 phar_flush(phar_obj->archive, 0, 0, 0, &error);
3028 if (error) {
3029 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
3030 efree(error);
3031 }
3032 break;
3033 default:
3034 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3035 "Unknown signature algorithm specified");
3036 }
3037 }
3038
3039
3040
3041
3042
3043 PHP_METHOD(Phar, getSignature)
3044 {
3045 PHAR_ARCHIVE_OBJECT();
3046
3047 if (zend_parse_parameters_none() == FAILURE) {
3048 return;
3049 }
3050
3051 if (phar_obj->archive->signature) {
3052 zend_string *unknown;
3053
3054 array_init(return_value);
3055 add_assoc_stringl(return_value, "hash", phar_obj->archive->signature, phar_obj->archive->sig_len);
3056 switch(phar_obj->archive->sig_flags) {
3057 case PHAR_SIG_MD5:
3058 add_assoc_stringl(return_value, "hash_type", "MD5", 3);
3059 break;
3060 case PHAR_SIG_SHA1:
3061 add_assoc_stringl(return_value, "hash_type", "SHA-1", 5);
3062 break;
3063 case PHAR_SIG_SHA256:
3064 add_assoc_stringl(return_value, "hash_type", "SHA-256", 7);
3065 break;
3066 case PHAR_SIG_SHA512:
3067 add_assoc_stringl(return_value, "hash_type", "SHA-512", 7);
3068 break;
3069 case PHAR_SIG_OPENSSL:
3070 add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7);
3071 break;
3072 default:
3073 unknown = strpprintf(0, "Unknown (%u)", phar_obj->archive->sig_flags);
3074 add_assoc_str(return_value, "hash_type", unknown);
3075 break;
3076 }
3077 } else {
3078 RETURN_FALSE;
3079 }
3080 }
3081
3082
3083
3084
3085
3086 PHP_METHOD(Phar, getModified)
3087 {
3088 PHAR_ARCHIVE_OBJECT();
3089
3090 if (zend_parse_parameters_none() == FAILURE) {
3091 return;
3092 }
3093
3094 RETURN_BOOL(phar_obj->archive->is_modified);
3095 }
3096
3097
3098 static int phar_set_compression(zval *zv, void *argument)
3099 {
3100 phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
3101 php_uint32 compress = *(php_uint32 *)argument;
3102
3103 if (entry->is_deleted) {
3104 return ZEND_HASH_APPLY_KEEP;
3105 }
3106
3107 entry->old_flags = entry->flags;
3108 entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
3109 entry->flags |= compress;
3110 entry->is_modified = 1;
3111 return ZEND_HASH_APPLY_KEEP;
3112 }
3113
3114
3115 static int phar_test_compression(zval *zv, void *argument)
3116 {
3117 phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
3118
3119 if (entry->is_deleted) {
3120 return ZEND_HASH_APPLY_KEEP;
3121 }
3122
3123 if (!PHAR_G(has_bz2)) {
3124 if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
3125 *(int *) argument = 0;
3126 }
3127 }
3128
3129 if (!PHAR_G(has_zlib)) {
3130 if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
3131 *(int *) argument = 0;
3132 }
3133 }
3134
3135 return ZEND_HASH_APPLY_KEEP;
3136 }
3137
3138
3139 static void pharobj_set_compression(HashTable *manifest, php_uint32 compress)
3140 {
3141 zend_hash_apply_with_argument(manifest, phar_set_compression, &compress);
3142 }
3143
3144
3145 static int pharobj_cancompress(HashTable *manifest)
3146 {
3147 int test;
3148
3149 test = 1;
3150 zend_hash_apply_with_argument(manifest, phar_test_compression, &test);
3151 return test;
3152 }
3153
3154
3155
3156
3157
3158
3159
3160 PHP_METHOD(Phar, compress)
3161 {
3162 zend_long method;
3163 char *ext = NULL;
3164 size_t ext_len = 0;
3165 php_uint32 flags;
3166 zend_object *ret;
3167 PHAR_ARCHIVE_OBJECT();
3168
3169 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|s", &method, &ext, &ext_len) == FAILURE) {
3170 return;
3171 }
3172
3173 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3174 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3175 "Cannot compress phar archive, phar is read-only");
3176 return;
3177 }
3178
3179 if (phar_obj->archive->is_zip) {
3180 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3181 "Cannot compress zip-based archives with whole-archive compression");
3182 return;
3183 }
3184
3185 switch (method) {
3186 case 0:
3187 flags = PHAR_FILE_COMPRESSED_NONE;
3188 break;
3189 case PHAR_ENT_COMPRESSED_GZ:
3190 if (!PHAR_G(has_zlib)) {
3191 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3192 "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
3193 return;
3194 }
3195 flags = PHAR_FILE_COMPRESSED_GZ;
3196 break;
3197
3198 case PHAR_ENT_COMPRESSED_BZ2:
3199 if (!PHAR_G(has_bz2)) {
3200 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3201 "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
3202 return;
3203 }
3204 flags = PHAR_FILE_COMPRESSED_BZ2;
3205 break;
3206 default:
3207 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3208 "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
3209 return;
3210 }
3211
3212 if (phar_obj->archive->is_tar) {
3213 ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_TAR, ext, flags);
3214 } else {
3215 ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_PHAR, ext, flags);
3216 }
3217
3218 if (ret) {
3219 ZVAL_OBJ(return_value, ret);
3220 } else {
3221 RETURN_NULL();
3222 }
3223 }
3224
3225
3226
3227
3228
3229 PHP_METHOD(Phar, decompress)
3230 {
3231 char *ext = NULL;
3232 size_t ext_len = 0;
3233 zend_object *ret;
3234 PHAR_ARCHIVE_OBJECT();
3235
3236 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &ext, &ext_len) == FAILURE) {
3237 return;
3238 }
3239
3240 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3241 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3242 "Cannot decompress phar archive, phar is read-only");
3243 return;
3244 }
3245
3246 if (phar_obj->archive->is_zip) {
3247 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3248 "Cannot decompress zip-based archives with whole-archive compression");
3249 return;
3250 }
3251
3252 if (phar_obj->archive->is_tar) {
3253 ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_TAR, ext, PHAR_FILE_COMPRESSED_NONE);
3254 } else {
3255 ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_PHAR, ext, PHAR_FILE_COMPRESSED_NONE);
3256 }
3257
3258 if (ret) {
3259 ZVAL_OBJ(return_value, ret);
3260 } else {
3261 RETURN_NULL();
3262 }
3263 }
3264
3265
3266
3267
3268
3269
3270
3271 PHP_METHOD(Phar, compressFiles)
3272 {
3273 char *error;
3274 php_uint32 flags;
3275 zend_long method;
3276 PHAR_ARCHIVE_OBJECT();
3277
3278 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &method) == FAILURE) {
3279 return;
3280 }
3281
3282 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3283 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3284 "Phar is readonly, cannot change compression");
3285 return;
3286 }
3287
3288 switch (method) {
3289 case PHAR_ENT_COMPRESSED_GZ:
3290 if (!PHAR_G(has_zlib)) {
3291 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3292 "Cannot compress files within archive with gzip, enable ext/zlib in php.ini");
3293 return;
3294 }
3295 flags = PHAR_ENT_COMPRESSED_GZ;
3296 break;
3297
3298 case PHAR_ENT_COMPRESSED_BZ2:
3299 if (!PHAR_G(has_bz2)) {
3300 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3301 "Cannot compress files within archive with bz2, enable ext/bz2 in php.ini");
3302 return;
3303 }
3304 flags = PHAR_ENT_COMPRESSED_BZ2;
3305 break;
3306 default:
3307 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3308 "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
3309 return;
3310 }
3311
3312 if (phar_obj->archive->is_tar) {
3313 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3314 "Cannot compress with Gzip compression, tar archives cannot compress individual files, use compress() to compress the whole archive");
3315 return;
3316 }
3317
3318 if (!pharobj_cancompress(&phar_obj->archive->manifest)) {
3319 if (flags == PHAR_FILE_COMPRESSED_GZ) {
3320 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3321 "Cannot compress all files as Gzip, some are compressed as bzip2 and cannot be decompressed");
3322 } else {
3323 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3324 "Cannot compress all files as Bzip2, some are compressed as gzip and cannot be decompressed");
3325 }
3326 return;
3327 }
3328
3329 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
3330 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
3331 return;
3332 }
3333 pharobj_set_compression(&phar_obj->archive->manifest, flags);
3334 phar_obj->archive->is_modified = 1;
3335 phar_flush(phar_obj->archive, 0, 0, 0, &error);
3336
3337 if (error) {
3338 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
3339 efree(error);
3340 }
3341 }
3342
3343
3344
3345
3346
3347 PHP_METHOD(Phar, decompressFiles)
3348 {
3349 char *error;
3350 PHAR_ARCHIVE_OBJECT();
3351
3352 if (zend_parse_parameters_none() == FAILURE) {
3353 return;
3354 }
3355
3356 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3357 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3358 "Phar is readonly, cannot change compression");
3359 return;
3360 }
3361
3362 if (!pharobj_cancompress(&phar_obj->archive->manifest)) {
3363 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
3364 "Cannot decompress all files, some are compressed as bzip2 or gzip and cannot be decompressed");
3365 return;
3366 }
3367
3368 if (phar_obj->archive->is_tar) {
3369 RETURN_TRUE;
3370 } else {
3371 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
3372 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
3373 return;
3374 }
3375 pharobj_set_compression(&phar_obj->archive->manifest, PHAR_ENT_COMPRESSED_NONE);
3376 }
3377
3378 phar_obj->archive->is_modified = 1;
3379 phar_flush(phar_obj->archive, 0, 0, 0, &error);
3380
3381 if (error) {
3382 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
3383 efree(error);
3384 }
3385
3386 RETURN_TRUE;
3387 }
3388
3389
3390
3391
3392
3393 PHP_METHOD(Phar, copy)
3394 {
3395 char *oldfile, *newfile, *error;
3396 const char *pcr_error;
3397 size_t oldfile_len, newfile_len;
3398 phar_entry_info *oldentry, newentry = {0}, *temp;
3399 int tmp_len = 0;
3400
3401 PHAR_ARCHIVE_OBJECT();
3402
3403 if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &oldfile, &oldfile_len, &newfile, &newfile_len) == FAILURE) {
3404 return;
3405 }
3406
3407 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3408 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3409 "Cannot copy \"%s\" to \"%s\", phar is read-only", oldfile, newfile);
3410 RETURN_FALSE;
3411 }
3412
3413 if (oldfile_len >= sizeof(".phar")-1 && !memcmp(oldfile, ".phar", sizeof(".phar")-1)) {
3414
3415 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3416 "file \"%s\" cannot be copied to file \"%s\", cannot copy Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname);
3417 RETURN_FALSE;
3418 }
3419
3420 if (newfile_len >= sizeof(".phar")-1 && !memcmp(newfile, ".phar", sizeof(".phar")-1)) {
3421
3422 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3423 "file \"%s\" cannot be copied to file \"%s\", cannot copy to Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname);
3424 RETURN_FALSE;
3425 }
3426
3427 if (!zend_hash_str_exists(&phar_obj->archive->manifest, oldfile, (uint) oldfile_len) || NULL == (oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint) oldfile_len)) || oldentry->is_deleted) {
3428 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3429 "file \"%s\" cannot be copied to file \"%s\", file does not exist in %s", oldfile, newfile, phar_obj->archive->fname);
3430 RETURN_FALSE;
3431 }
3432
3433 if (zend_hash_str_exists(&phar_obj->archive->manifest, newfile, (uint) newfile_len)) {
3434 if (NULL != (temp = zend_hash_str_find_ptr(&phar_obj->archive->manifest, newfile, (uint) newfile_len)) || !temp->is_deleted) {
3435 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3436 "file \"%s\" cannot be copied to file \"%s\", file must not already exist in phar %s", oldfile, newfile, phar_obj->archive->fname);
3437 RETURN_FALSE;
3438 }
3439 }
3440
3441 tmp_len = (int)newfile_len;
3442 if (phar_path_check(&newfile, &tmp_len, &pcr_error) > pcr_is_ok) {
3443 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
3444 "file \"%s\" contains invalid characters %s, cannot be copied from \"%s\" in phar %s", newfile, pcr_error, oldfile, phar_obj->archive->fname);
3445 RETURN_FALSE;
3446 }
3447 newfile_len = tmp_len;
3448
3449 if (phar_obj->archive->is_persistent) {
3450 if (FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
3451 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
3452 return;
3453 }
3454
3455 oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint) oldfile_len);
3456 }
3457
3458 memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info));
3459
3460 if (Z_TYPE(newentry.metadata) != IS_UNDEF) {
3461 zval_copy_ctor(&newentry.metadata);
3462 newentry.metadata_str.s = NULL;
3463 }
3464
3465 newentry.filename = estrndup(newfile, newfile_len);
3466 newentry.filename_len = newfile_len;
3467 newentry.fp_refcount = 0;
3468
3469 if (oldentry->fp_type != PHAR_FP) {
3470 if (FAILURE == phar_copy_entry_fp(oldentry, &newentry, &error)) {
3471 efree(newentry.filename);
3472 php_stream_close(newentry.fp);
3473 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
3474 efree(error);
3475 return;
3476 }
3477 }
3478
3479 zend_hash_str_add_mem(&oldentry->phar->manifest, newfile, newfile_len, &newentry, sizeof(phar_entry_info));
3480 phar_obj->archive->is_modified = 1;
3481 phar_flush(phar_obj->archive, 0, 0, 0, &error);
3482
3483 if (error) {
3484 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
3485 efree(error);
3486 }
3487
3488 RETURN_TRUE;
3489 }
3490
3491
3492
3493
3494
3495 PHP_METHOD(Phar, offsetExists)
3496 {
3497 char *fname;
3498 size_t fname_len;
3499 phar_entry_info *entry;
3500
3501 PHAR_ARCHIVE_OBJECT();
3502
3503 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
3504 return;
3505 }
3506
3507 if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint) fname_len)) {
3508 if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint) fname_len))) {
3509 if (entry->is_deleted) {
3510
3511 RETURN_FALSE;
3512 }
3513 }
3514
3515 if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
3516
3517 RETURN_FALSE;
3518 }
3519 RETURN_TRUE;
3520 } else {
3521 if (zend_hash_str_exists(&phar_obj->archive->virtual_dirs, fname, (uint) fname_len)) {
3522 RETURN_TRUE;
3523 }
3524 RETURN_FALSE;
3525 }
3526 }
3527
3528
3529
3530
3531
3532 PHP_METHOD(Phar, offsetGet)
3533 {
3534 char *fname, *error;
3535 size_t fname_len;
3536 zval zfname;
3537 phar_entry_info *entry;
3538 zend_string *sfname;
3539 PHAR_ARCHIVE_OBJECT();
3540
3541 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
3542 return;
3543 }
3544
3545
3546 if (!(entry = phar_get_entry_info_dir(phar_obj->archive, fname, fname_len, 1, &error, 0))) {
3547 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:"");
3548 } else {
3549 if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
3550 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use getStub", phar_obj->archive->fname);
3551 return;
3552 }
3553
3554 if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
3555 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use getAlias", phar_obj->archive->fname);
3556 return;
3557 }
3558
3559 if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
3560 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot directly get any files or directories in magic \".phar\" directory", phar_obj->archive->fname);
3561 return;
3562 }
3563
3564 if (entry->is_temp_dir) {
3565 efree(entry->filename);
3566 efree(entry);
3567 }
3568
3569 sfname = strpprintf(0, "phar://%s/%s", phar_obj->archive->fname, fname);
3570 ZVAL_NEW_STR(&zfname, sfname);
3571 spl_instantiate_arg_ex1(phar_obj->spl.info_class, return_value, &zfname);
3572 zval_ptr_dtor(&zfname);
3573 }
3574 }
3575
3576
3577
3578
3579 static void phar_add_file(phar_archive_data **pphar, char *filename, int filename_len, char *cont_str, size_t cont_len, zval *zresource)
3580 {
3581 char *error;
3582 size_t contents_len;
3583 phar_entry_data *data;
3584 php_stream *contents_file;
3585
3586 if (filename_len >= sizeof(".phar")-1 && !memcmp(filename, ".phar", sizeof(".phar")-1) && (filename[5] == '/' || filename[5] == '\\' || filename[5] == '\0')) {
3587 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create any files in magic \".phar\" directory", (*pphar)->fname);
3588 return;
3589 }
3590
3591 if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, filename, filename_len, "w+b", 0, &error, 1))) {
3592 if (error) {
3593 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created: %s", filename, error);
3594 efree(error);
3595 } else {
3596 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created", filename);
3597 }
3598 return;
3599 } else {
3600 if (error) {
3601 efree(error);
3602 }
3603
3604 if (!data->internal_file->is_dir) {
3605 if (cont_str) {
3606 contents_len = php_stream_write(data->fp, cont_str, cont_len);
3607 if (contents_len != cont_len) {
3608 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s could not be written to", filename);
3609 return;
3610 }
3611 } else {
3612 if (!(php_stream_from_zval_no_verify(contents_file, zresource))) {
3613 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s could not be written to", filename);
3614 return;
3615 }
3616 php_stream_copy_to_stream_ex(contents_file, data->fp, PHP_STREAM_COPY_ALL, &contents_len);
3617 }
3618
3619 data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
3620 }
3621
3622
3623 if (pphar[0] != data->phar) {
3624 *pphar = data->phar;
3625 }
3626 phar_entry_delref(data);
3627 phar_flush(*pphar, 0, 0, 0, &error);
3628
3629 if (error) {
3630 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
3631 efree(error);
3632 }
3633 }
3634 }
3635
3636
3637
3638
3639 static void phar_mkdir(phar_archive_data **pphar, char *dirname, int dirname_len)
3640 {
3641 char *error;
3642 phar_entry_data *data;
3643
3644 if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, dirname, dirname_len, "w+b", 2, &error, 1))) {
3645 if (error) {
3646 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created: %s", dirname, error);
3647 efree(error);
3648 } else {
3649 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created", dirname);
3650 }
3651
3652 return;
3653 } else {
3654 if (error) {
3655 efree(error);
3656 }
3657
3658
3659 if (data->phar != *pphar) {
3660 *pphar = data->phar;
3661 }
3662 phar_entry_delref(data);
3663 phar_flush(*pphar, 0, 0, 0, &error);
3664
3665 if (error) {
3666 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
3667 efree(error);
3668 }
3669 }
3670 }
3671
3672
3673
3674
3675
3676 PHP_METHOD(Phar, offsetSet)
3677 {
3678 char *fname, *cont_str = NULL;
3679 size_t fname_len, cont_len;
3680 zval *zresource;
3681 PHAR_ARCHIVE_OBJECT();
3682
3683 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3684 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
3685 return;
3686 }
3687
3688 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "pr", &fname, &fname_len, &zresource) == FAILURE
3689 && zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &fname, &fname_len, &cont_str, &cont_len) == FAILURE) {
3690 return;
3691 }
3692
3693 if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
3694 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set stub \".phar/stub.php\" directly in phar \"%s\", use setStub", phar_obj->archive->fname);
3695 return;
3696 }
3697
3698 if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
3699 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set alias \".phar/alias.txt\" directly in phar \"%s\", use setAlias", phar_obj->archive->fname);
3700 return;
3701 }
3702
3703 if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
3704 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set any files or directories in magic \".phar\" directory", phar_obj->archive->fname);
3705 return;
3706 }
3707
3708 phar_add_file(&(phar_obj->archive), fname, fname_len, cont_str, cont_len, zresource);
3709 }
3710
3711
3712
3713
3714
3715 PHP_METHOD(Phar, offsetUnset)
3716 {
3717 char *fname, *error;
3718 size_t fname_len;
3719 phar_entry_info *entry;
3720 PHAR_ARCHIVE_OBJECT();
3721
3722 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3723 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
3724 return;
3725 }
3726
3727 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
3728 return;
3729 }
3730
3731 if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint) fname_len)) {
3732 if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint) fname_len))) {
3733 if (entry->is_deleted) {
3734
3735 return;
3736 }
3737
3738 if (phar_obj->archive->is_persistent) {
3739 if (FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
3740 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
3741 return;
3742 }
3743
3744 entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint) fname_len);
3745 }
3746 entry->is_modified = 0;
3747 entry->is_deleted = 1;
3748
3749 phar_flush(phar_obj->archive, 0, 0, 0, &error);
3750
3751 if (error) {
3752 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
3753 efree(error);
3754 }
3755
3756 RETURN_TRUE;
3757 }
3758 } else {
3759 RETURN_FALSE;
3760 }
3761 }
3762
3763
3764
3765
3766
3767 PHP_METHOD(Phar, addEmptyDir)
3768 {
3769 char *dirname;
3770 size_t dirname_len;
3771
3772 PHAR_ARCHIVE_OBJECT();
3773
3774 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &dirname, &dirname_len) == FAILURE) {
3775 return;
3776 }
3777
3778 if (dirname_len >= sizeof(".phar")-1 && !memcmp(dirname, ".phar", sizeof(".phar")-1)) {
3779 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create a directory in magic \".phar\" directory");
3780 return;
3781 }
3782
3783 phar_mkdir(&phar_obj->archive, dirname, dirname_len);
3784 }
3785
3786
3787
3788
3789
3790 PHP_METHOD(Phar, addFile)
3791 {
3792 char *fname, *localname = NULL;
3793 size_t fname_len, localname_len = 0;
3794 php_stream *resource;
3795 zval zresource;
3796
3797 PHAR_ARCHIVE_OBJECT();
3798
3799 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s", &fname, &fname_len, &localname, &localname_len) == FAILURE) {
3800 return;
3801 }
3802
3803 #if PHP_API_VERSION < 20100412
3804 if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
3805 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, safe_mode restrictions prevent this", fname);
3806 return;
3807 }
3808 #endif
3809
3810 if (!strstr(fname, "://") && php_check_open_basedir(fname)) {
3811 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, open_basedir restrictions prevent this", fname);
3812 return;
3813 }
3814
3815 if (!(resource = php_stream_open_wrapper(fname, "rb", 0, NULL))) {
3816 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive", fname);
3817 return;
3818 }
3819
3820 if (localname) {
3821 fname = localname;
3822 fname_len = localname_len;
3823 }
3824
3825 php_stream_to_zval(resource, &zresource);
3826 phar_add_file(&(phar_obj->archive), fname, fname_len, NULL, 0, &zresource);
3827 zval_ptr_dtor(&zresource);
3828 }
3829
3830
3831
3832
3833
3834 PHP_METHOD(Phar, addFromString)
3835 {
3836 char *localname, *cont_str;
3837 size_t localname_len, cont_len;
3838
3839 PHAR_ARCHIVE_OBJECT();
3840
3841 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &localname, &localname_len, &cont_str, &cont_len) == FAILURE) {
3842 return;
3843 }
3844
3845 phar_add_file(&(phar_obj->archive), localname, localname_len, cont_str, cont_len, NULL);
3846 }
3847
3848
3849
3850
3851
3852 PHP_METHOD(Phar, getStub)
3853 {
3854 size_t len;
3855 zend_string *buf;
3856 php_stream *fp;
3857 php_stream_filter *filter = NULL;
3858 phar_entry_info *stub;
3859
3860 PHAR_ARCHIVE_OBJECT();
3861
3862 if (zend_parse_parameters_none() == FAILURE) {
3863 return;
3864 }
3865
3866 if (phar_obj->archive->is_tar || phar_obj->archive->is_zip) {
3867
3868 if (NULL != (stub = zend_hash_str_find_ptr(&(phar_obj->archive->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) {
3869 if (phar_obj->archive->fp && !phar_obj->archive->is_brandnew && !(stub->flags & PHAR_ENT_COMPRESSION_MASK)) {
3870 fp = phar_obj->archive->fp;
3871 } else {
3872 if (!(fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", 0, NULL))) {
3873 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to open phar \"%s\"", phar_obj->archive->fname);
3874 return;
3875 }
3876 if (stub->flags & PHAR_ENT_COMPRESSION_MASK) {
3877 char *filter_name;
3878
3879 if ((filter_name = phar_decompress_filter(stub, 0)) != NULL) {
3880 filter = php_stream_filter_create(filter_name, NULL, php_stream_is_persistent(fp));
3881 } else {
3882 filter = NULL;
3883 }
3884 if (!filter) {
3885 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to read stub of phar \"%s\" (cannot create %s filter)", phar_obj->archive->fname, phar_decompress_filter(stub, 1));
3886 return;
3887 }
3888 php_stream_filter_append(&fp->readfilters, filter);
3889 }
3890 }
3891
3892 if (!fp) {
3893 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
3894 "Unable to read stub");
3895 return;
3896 }
3897
3898 php_stream_seek(fp, stub->offset_abs, SEEK_SET);
3899 len = stub->uncompressed_filesize;
3900 goto carry_on;
3901 } else {
3902 RETURN_EMPTY_STRING();
3903 }
3904 }
3905 len = phar_obj->archive->halt_offset;
3906
3907 if (phar_obj->archive->fp && !phar_obj->archive->is_brandnew) {
3908 fp = phar_obj->archive->fp;
3909 } else {
3910 fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", 0, NULL);
3911 }
3912
3913 if (!fp) {
3914 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
3915 "Unable to read stub");
3916 return;
3917 }
3918
3919 php_stream_rewind(fp);
3920 carry_on:
3921 buf = zend_string_alloc(len, 0);
3922
3923 if (len != php_stream_read(fp, ZSTR_VAL(buf), len)) {
3924 if (fp != phar_obj->archive->fp) {
3925 php_stream_close(fp);
3926 }
3927 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
3928 "Unable to read stub");
3929 zend_string_release(buf);
3930 return;
3931 }
3932
3933 if (filter) {
3934 php_stream_filter_flush(filter, 1);
3935 php_stream_filter_remove(filter, 1);
3936 }
3937
3938 if (fp != phar_obj->archive->fp) {
3939 php_stream_close(fp);
3940 }
3941
3942 ZSTR_VAL(buf)[len] = '\0';
3943 ZSTR_LEN(buf) = len;
3944 RETVAL_STR(buf);
3945 }
3946
3947
3948
3949
3950
3951 PHP_METHOD(Phar, hasMetadata)
3952 {
3953 PHAR_ARCHIVE_OBJECT();
3954
3955 RETURN_BOOL(Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF);
3956 }
3957
3958
3959
3960
3961
3962 PHP_METHOD(Phar, getMetadata)
3963 {
3964 PHAR_ARCHIVE_OBJECT();
3965
3966 if (zend_parse_parameters_none() == FAILURE) {
3967 return;
3968 }
3969
3970 if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
3971 if (phar_obj->archive->is_persistent) {
3972 char *buf = estrndup((char *) Z_PTR(phar_obj->archive->metadata), phar_obj->archive->metadata_len);
3973
3974 phar_parse_metadata(&buf, return_value, phar_obj->archive->metadata_len);
3975 efree(buf);
3976 } else {
3977 ZVAL_COPY(return_value, &phar_obj->archive->metadata);
3978 }
3979 }
3980 }
3981
3982
3983
3984
3985
3986 PHP_METHOD(Phar, setMetadata)
3987 {
3988 char *error;
3989 zval *metadata;
3990
3991 PHAR_ARCHIVE_OBJECT();
3992
3993 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
3994 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
3995 return;
3996 }
3997
3998 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &metadata) == FAILURE) {
3999 return;
4000 }
4001
4002 if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
4003 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
4004 return;
4005 }
4006 if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
4007 zval_ptr_dtor(&phar_obj->archive->metadata);
4008 ZVAL_UNDEF(&phar_obj->archive->metadata);
4009 }
4010
4011 ZVAL_COPY(&phar_obj->archive->metadata, metadata);
4012 phar_obj->archive->is_modified = 1;
4013 phar_flush(phar_obj->archive, 0, 0, 0, &error);
4014
4015 if (error) {
4016 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
4017 efree(error);
4018 }
4019 }
4020
4021
4022
4023
4024
4025 PHP_METHOD(Phar, delMetadata)
4026 {
4027 char *error;
4028
4029 PHAR_ARCHIVE_OBJECT();
4030
4031 if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
4032 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
4033 return;
4034 }
4035
4036 if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
4037 zval_ptr_dtor(&phar_obj->archive->metadata);
4038 ZVAL_UNDEF(&phar_obj->archive->metadata);
4039 phar_obj->archive->is_modified = 1;
4040 phar_flush(phar_obj->archive, 0, 0, 0, &error);
4041
4042 if (error) {
4043 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
4044 efree(error);
4045 RETURN_FALSE;
4046 } else {
4047 RETURN_TRUE;
4048 }
4049
4050 } else {
4051 RETURN_TRUE;
4052 }
4053 }
4054
4055 #if PHP_API_VERSION < 20100412
4056 #define PHAR_OPENBASEDIR_CHECKPATH(filename) \
4057 (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename)
4058 #else
4059 #define PHAR_OPENBASEDIR_CHECKPATH(filename) \
4060 php_check_open_basedir(filename)
4061 #endif
4062
4063 static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *dest, int dest_len, char **error)
4064 {
4065 php_stream_statbuf ssb;
4066 int len;
4067 php_stream *fp;
4068 char *fullpath;
4069 const char *slash;
4070 mode_t mode;
4071 cwd_state new_state;
4072 char *filename;
4073 size_t filename_len;
4074
4075 if (entry->is_mounted) {
4076
4077 return SUCCESS;
4078 }
4079
4080 if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
4081 return SUCCESS;
4082 }
4083
4084 new_state.cwd = (char*)emalloc(2);
4085 new_state.cwd[0] = DEFAULT_SLASH;
4086 new_state.cwd[1] = '\0';
4087 new_state.cwd_length = 1;
4088 if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND) != 0 ||
4089 new_state.cwd_length <= 1) {
4090 if (EINVAL == errno && entry->filename_len > 50) {
4091 char *tmp = estrndup(entry->filename, 50);
4092 spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, dest);
4093 efree(tmp);
4094 } else {
4095 spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
4096 }
4097 efree(new_state.cwd);
4098 return FAILURE;
4099 }
4100 filename = new_state.cwd + 1;
4101 filename_len = new_state.cwd_length - 1;
4102 #ifdef PHP_WIN32
4103
4104 {
4105 int cnt = filename_len;
4106
4107 do {
4108 if ('\\' == filename[cnt]) {
4109 filename[cnt] = '/';
4110 }
4111 } while (cnt-- >= 0);
4112 }
4113 #endif
4114
4115 len = spprintf(&fullpath, 0, "%s/%s", dest, filename);
4116
4117 if (len >= MAXPATHLEN) {
4118 char *tmp;
4119
4120 fullpath[50] = '\0';
4121 if (entry->filename_len > 50) {
4122 tmp = estrndup(entry->filename, 50);
4123 spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, fullpath);
4124 efree(tmp);
4125 } else {
4126 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath);
4127 }
4128 efree(fullpath);
4129 efree(new_state.cwd);
4130 return FAILURE;
4131 }
4132
4133 if (!len) {
4134 spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
4135 efree(fullpath);
4136 efree(new_state.cwd);
4137 return FAILURE;
4138 }
4139
4140 if (PHAR_OPENBASEDIR_CHECKPATH(fullpath)) {
4141 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath);
4142 efree(fullpath);
4143 efree(new_state.cwd);
4144 return FAILURE;
4145 }
4146
4147
4148 if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) {
4149 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath);
4150 efree(fullpath);
4151 efree(new_state.cwd);
4152 return FAILURE;
4153 }
4154
4155
4156 slash = zend_memrchr(filename, '/', filename_len);
4157
4158 if (slash) {
4159 fullpath[dest_len + (slash - filename) + 1] = '\0';
4160 } else {
4161 fullpath[dest_len] = '\0';
4162 }
4163
4164 if (FAILURE == php_stream_stat_path(fullpath, &ssb)) {
4165 if (entry->is_dir) {
4166 if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
4167 spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
4168 efree(fullpath);
4169 free(new_state.cwd);
4170 return FAILURE;
4171 }
4172 } else {
4173 if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
4174 spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
4175 efree(fullpath);
4176 free(new_state.cwd);
4177 return FAILURE;
4178 }
4179 }
4180 }
4181
4182 if (slash) {
4183 fullpath[dest_len + (slash - filename) + 1] = '/';
4184 } else {
4185 fullpath[dest_len] = '/';
4186 }
4187
4188 filename = NULL;
4189 efree(new_state.cwd);
4190
4191 if (entry->is_dir) {
4192 efree(fullpath);
4193 return SUCCESS;
4194 }
4195
4196 #if PHP_API_VERSION < 20100412
4197 fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
4198 #else
4199 fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
4200 #endif
4201
4202 if (!fp) {
4203 spprintf(error, 4096, "Cannot extract \"%s\", could not open for writing \"%s\"", entry->filename, fullpath);
4204 efree(fullpath);
4205 return FAILURE;
4206 }
4207
4208 if (!phar_get_efp(entry, 0)) {
4209 if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
4210 if (error) {
4211 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error);
4212 } else {
4213 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer", entry->filename, fullpath);
4214 }
4215 efree(fullpath);
4216 php_stream_close(fp);
4217 return FAILURE;
4218 }
4219 }
4220
4221 if (FAILURE == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
4222 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", entry->filename, fullpath);
4223 efree(fullpath);
4224 php_stream_close(fp);
4225 return FAILURE;
4226 }
4227
4228 if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) {
4229 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", entry->filename, fullpath);
4230 efree(fullpath);
4231 php_stream_close(fp);
4232 return FAILURE;
4233 }
4234
4235 php_stream_close(fp);
4236 mode = (mode_t) entry->flags & PHAR_ENT_PERM_MASK;
4237
4238 if (FAILURE == VCWD_CHMOD(fullpath, mode)) {
4239 spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", setting file permissions failed", entry->filename, fullpath);
4240 efree(fullpath);
4241 return FAILURE;
4242 }
4243
4244 efree(fullpath);
4245 return SUCCESS;
4246 }
4247
4248
4249
4250
4251
4252 PHP_METHOD(Phar, extractTo)
4253 {
4254 char *error = NULL;
4255 php_stream *fp;
4256 php_stream_statbuf ssb;
4257 phar_entry_info *entry;
4258 char *pathto, *filename;
4259 size_t pathto_len, filename_len;
4260 int ret, i;
4261 int nelems;
4262 zval *zval_files = NULL;
4263 zend_bool overwrite = 0;
4264
4265 PHAR_ARCHIVE_OBJECT();
4266
4267 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z!b", &pathto, &pathto_len, &zval_files, &overwrite) == FAILURE) {
4268 return;
4269 }
4270
4271 fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, NULL);
4272
4273 if (!fp) {
4274 zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
4275 "Invalid argument, %s cannot be found", phar_obj->archive->fname);
4276 return;
4277 }
4278
4279 php_stream_close(fp);
4280
4281 if (pathto_len < 1) {
4282 zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
4283 "Invalid argument, extraction path must be non-zero length");
4284 return;
4285 }
4286
4287 if (pathto_len >= MAXPATHLEN) {
4288 char *tmp = estrndup(pathto, 50);
4289
4290 zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%s...\", destination directory is too long for filesystem", tmp);
4291 efree(tmp);
4292 return;
4293 }
4294
4295 if (php_stream_stat_path(pathto, &ssb) < 0) {
4296 ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
4297 if (!ret) {
4298 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
4299 "Unable to create path \"%s\" for extraction", pathto);
4300 return;
4301 }
4302 } else if (!(ssb.sb.st_mode & S_IFDIR)) {
4303 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
4304 "Unable to use path \"%s\" for extraction, it is a file, must be a directory", pathto);
4305 return;
4306 }
4307
4308 if (zval_files) {
4309 switch (Z_TYPE_P(zval_files)) {
4310 case IS_NULL:
4311 goto all_files;
4312 case IS_STRING:
4313 filename = Z_STRVAL_P(zval_files);
4314 filename_len = Z_STRLEN_P(zval_files);
4315 break;
4316 case IS_ARRAY:
4317 nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
4318 if (nelems == 0 ) {
4319 RETURN_FALSE;
4320 }
4321 for (i = 0; i < nelems; i++) {
4322 zval *zval_file;
4323 if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(zval_files), i)) != NULL) {
4324 switch (Z_TYPE_P(zval_file)) {
4325 case IS_STRING:
4326 break;
4327 default:
4328 zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
4329 "Invalid argument, array of filenames to extract contains non-string value");
4330 return;
4331 }
4332 if (NULL == (entry = zend_hash_find_ptr(&phar_obj->archive->manifest, Z_STR_P(zval_file)))) {
4333 zend_throw_exception_ex(phar_ce_PharException, 0,
4334 "Phar Error: attempted to extract non-existent file \"%s\" from phar \"%s\"", Z_STRVAL_P(zval_file), phar_obj->archive->fname);
4335 }
4336 if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error)) {
4337 zend_throw_exception_ex(phar_ce_PharException, 0,
4338 "Extraction from phar \"%s\" failed: %s", phar_obj->archive->fname, error);
4339 efree(error);
4340 return;
4341 }
4342 }
4343 }
4344 RETURN_TRUE;
4345 default:
4346 zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
4347 "Invalid argument, expected a filename (string) or array of filenames");
4348 return;
4349 }
4350
4351 if (NULL == (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, filename, filename_len))) {
4352 zend_throw_exception_ex(phar_ce_PharException, 0,
4353 "Phar Error: attempted to extract non-existent file \"%s\" from phar \"%s\"", filename, phar_obj->archive->fname);
4354 return;
4355 }
4356
4357 if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error)) {
4358 zend_throw_exception_ex(phar_ce_PharException, 0,
4359 "Extraction from phar \"%s\" failed: %s", phar_obj->archive->fname, error);
4360 efree(error);
4361 return;
4362 }
4363 } else {
4364 phar_archive_data *phar;
4365 all_files:
4366 phar = phar_obj->archive;
4367
4368 if (!zend_hash_num_elements(&(phar->manifest))) {
4369 RETURN_TRUE;
4370 }
4371
4372 ZEND_HASH_FOREACH_PTR(&phar->manifest, entry) {
4373 if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error)) {
4374 zend_throw_exception_ex(phar_ce_PharException, 0,
4375 "Extraction from phar \"%s\" failed: %s", phar->fname, error);
4376 efree(error);
4377 return;
4378 }
4379 } ZEND_HASH_FOREACH_END();
4380 }
4381 RETURN_TRUE;
4382 }
4383
4384
4385
4386
4387
4388
4389 PHP_METHOD(PharFileInfo, __construct)
4390 {
4391 char *fname, *arch, *entry, *error;
4392 size_t fname_len;
4393 int arch_len, entry_len;
4394 phar_entry_object *entry_obj;
4395 phar_entry_info *entry_info;
4396 phar_archive_data *phar_data;
4397 zval *zobj = getThis(), arg1;
4398
4399 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
4400 return;
4401 }
4402
4403 entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
4404
4405 if (entry_obj->entry) {
4406 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice");
4407 return;
4408 }
4409
4410 if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, (int)fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0) == FAILURE) {
4411 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
4412 "'%s' is not a valid phar archive URL (must have at least phar://filename.phar)", fname);
4413 return;
4414 }
4415
4416 if (phar_open_from_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data, &error) == FAILURE) {
4417 efree(arch);
4418 efree(entry);
4419 if (error) {
4420 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
4421 "Cannot open phar file '%s': %s", fname, error);
4422 efree(error);
4423 } else {
4424 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
4425 "Cannot open phar file '%s'", fname);
4426 }
4427 return;
4428 }
4429
4430 if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, 1)) == NULL) {
4431 zend_throw_exception_ex(spl_ce_RuntimeException, 0,
4432 "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : "");
4433 efree(arch);
4434 efree(entry);
4435 return;
4436 }
4437
4438 efree(arch);
4439 efree(entry);
4440
4441 entry_obj->entry = entry_info;
4442
4443 ZVAL_STRINGL(&arg1, fname, fname_len);
4444
4445 zend_call_method_with_1_params(zobj, Z_OBJCE_P(zobj),
4446 &spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1);
4447
4448 zval_ptr_dtor(&arg1);
4449 }
4450
4451
4452 #define PHAR_ENTRY_OBJECT() \
4453 zval *zobj = getThis(); \
4454 phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \
4455 if (!entry_obj->entry) { \
4456 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4457 "Cannot call method on an uninitialized PharFileInfo object"); \
4458 return; \
4459 }
4460
4461
4462
4463
4464 PHP_METHOD(PharFileInfo, __destruct)
4465 {
4466 zval *zobj = getThis();
4467 phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
4468
4469 if (entry_obj->entry && entry_obj->entry->is_temp_dir) {
4470 if (entry_obj->entry->filename) {
4471 efree(entry_obj->entry->filename);
4472 entry_obj->entry->filename = NULL;
4473 }
4474
4475 efree(entry_obj->entry);
4476 entry_obj->entry = NULL;
4477 }
4478 }
4479
4480
4481
4482
4483
4484 PHP_METHOD(PharFileInfo, getCompressedSize)
4485 {
4486 PHAR_ENTRY_OBJECT();
4487
4488 if (zend_parse_parameters_none() == FAILURE) {
4489 return;
4490 }
4491
4492 RETURN_LONG(entry_obj->entry->compressed_filesize);
4493 }
4494
4495
4496
4497
4498
4499 PHP_METHOD(PharFileInfo, isCompressed)
4500 {
4501
4502 zend_long method = 9021976;
4503 PHAR_ENTRY_OBJECT();
4504
4505 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &method) == FAILURE) {
4506 return;
4507 }
4508
4509 switch (method) {
4510 case 9021976:
4511 RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK);
4512 case PHAR_ENT_COMPRESSED_GZ:
4513 RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ);
4514 case PHAR_ENT_COMPRESSED_BZ2:
4515 RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2);
4516 default:
4517 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4518 "Unknown compression type specified"); \
4519 }
4520 }
4521
4522
4523
4524
4525
4526 PHP_METHOD(PharFileInfo, getCRC32)
4527 {
4528 PHAR_ENTRY_OBJECT();
4529
4530 if (zend_parse_parameters_none() == FAILURE) {
4531 return;
4532 }
4533
4534 if (entry_obj->entry->is_dir) {
4535 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4536 "Phar entry is a directory, does not have a CRC"); \
4537 return;
4538 }
4539
4540 if (entry_obj->entry->is_crc_checked) {
4541 RETURN_LONG(entry_obj->entry->crc32);
4542 } else {
4543 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4544 "Phar entry was not CRC checked"); \
4545 }
4546 }
4547
4548
4549
4550
4551
4552 PHP_METHOD(PharFileInfo, isCRCChecked)
4553 {
4554 PHAR_ENTRY_OBJECT();
4555
4556 if (zend_parse_parameters_none() == FAILURE) {
4557 return;
4558 }
4559
4560 RETURN_BOOL(entry_obj->entry->is_crc_checked);
4561 }
4562
4563
4564
4565
4566
4567 PHP_METHOD(PharFileInfo, getPharFlags)
4568 {
4569 PHAR_ENTRY_OBJECT();
4570
4571 if (zend_parse_parameters_none() == FAILURE) {
4572 return;
4573 }
4574
4575 RETURN_LONG(entry_obj->entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
4576 }
4577
4578
4579
4580
4581
4582 PHP_METHOD(PharFileInfo, chmod)
4583 {
4584 char *error;
4585 zend_long perms;
4586 PHAR_ENTRY_OBJECT();
4587
4588 if (entry_obj->entry->is_temp_dir) {
4589 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4590 "Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", entry_obj->entry->filename); \
4591 return;
4592 }
4593
4594 if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
4595 zend_throw_exception_ex(phar_ce_PharException, 0, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", entry_obj->entry->filename, entry_obj->entry->phar->fname);
4596 return;
4597 }
4598
4599 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &perms) == FAILURE) {
4600 return;
4601 }
4602
4603 if (entry_obj->entry->is_persistent) {
4604 phar_archive_data *phar = entry_obj->entry->phar;
4605
4606 if (FAILURE == phar_copy_on_write(&phar)) {
4607 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
4608 return;
4609 }
4610
4611 entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
4612 }
4613
4614 entry_obj->entry->flags &= ~PHAR_ENT_PERM_MASK;
4615 perms &= 0777;
4616 entry_obj->entry->flags |= perms;
4617 entry_obj->entry->old_flags = entry_obj->entry->flags;
4618 entry_obj->entry->phar->is_modified = 1;
4619 entry_obj->entry->is_modified = 1;
4620
4621
4622
4623 if (BG(CurrentLStatFile)) {
4624 efree(BG(CurrentLStatFile));
4625 }
4626
4627 if (BG(CurrentStatFile)) {
4628 efree(BG(CurrentStatFile));
4629 }
4630
4631 BG(CurrentLStatFile) = NULL;
4632 BG(CurrentStatFile) = NULL;
4633 phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
4634
4635 if (error) {
4636 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
4637 efree(error);
4638 }
4639 }
4640
4641
4642
4643
4644
4645 PHP_METHOD(PharFileInfo, hasMetadata)
4646 {
4647 PHAR_ENTRY_OBJECT();
4648
4649 if (zend_parse_parameters_none() == FAILURE) {
4650 return;
4651 }
4652
4653 RETURN_BOOL(Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF);
4654 }
4655
4656
4657
4658
4659
4660 PHP_METHOD(PharFileInfo, getMetadata)
4661 {
4662 PHAR_ENTRY_OBJECT();
4663
4664 if (zend_parse_parameters_none() == FAILURE) {
4665 return;
4666 }
4667
4668 if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
4669 if (entry_obj->entry->is_persistent) {
4670 char *buf = estrndup((char *) Z_PTR(entry_obj->entry->metadata), entry_obj->entry->metadata_len);
4671
4672 phar_parse_metadata(&buf, return_value, entry_obj->entry->metadata_len);
4673 efree(buf);
4674 } else {
4675 ZVAL_COPY(return_value, &entry_obj->entry->metadata);
4676 }
4677 }
4678 }
4679
4680
4681
4682
4683
4684 PHP_METHOD(PharFileInfo, setMetadata)
4685 {
4686 char *error;
4687 zval *metadata;
4688
4689 PHAR_ENTRY_OBJECT();
4690
4691 if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
4692 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
4693 return;
4694 }
4695
4696 if (entry_obj->entry->is_temp_dir) {
4697 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4698 "Phar entry is a temporary directory (not an actual entry in the archive), cannot set metadata"); \
4699 return;
4700 }
4701
4702 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &metadata) == FAILURE) {
4703 return;
4704 }
4705
4706 if (entry_obj->entry->is_persistent) {
4707 phar_archive_data *phar = entry_obj->entry->phar;
4708
4709 if (FAILURE == phar_copy_on_write(&phar)) {
4710 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
4711 return;
4712 }
4713
4714 entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
4715 }
4716 if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
4717 zval_ptr_dtor(&entry_obj->entry->metadata);
4718 ZVAL_UNDEF(&entry_obj->entry->metadata);
4719 }
4720
4721 ZVAL_COPY(&entry_obj->entry->metadata, metadata);
4722
4723 entry_obj->entry->is_modified = 1;
4724 entry_obj->entry->phar->is_modified = 1;
4725 phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
4726
4727 if (error) {
4728 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
4729 efree(error);
4730 }
4731 }
4732
4733
4734
4735
4736
4737 PHP_METHOD(PharFileInfo, delMetadata)
4738 {
4739 char *error;
4740
4741 PHAR_ENTRY_OBJECT();
4742
4743 if (zend_parse_parameters_none() == FAILURE) {
4744 return;
4745 }
4746
4747 if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
4748 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
4749 return;
4750 }
4751
4752 if (entry_obj->entry->is_temp_dir) {
4753 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4754 "Phar entry is a temporary directory (not an actual entry in the archive), cannot delete metadata"); \
4755 return;
4756 }
4757
4758 if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
4759 if (entry_obj->entry->is_persistent) {
4760 phar_archive_data *phar = entry_obj->entry->phar;
4761
4762 if (FAILURE == phar_copy_on_write(&phar)) {
4763 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
4764 return;
4765 }
4766
4767 entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
4768 }
4769 zval_ptr_dtor(&entry_obj->entry->metadata);
4770 ZVAL_UNDEF(&entry_obj->entry->metadata);
4771 entry_obj->entry->is_modified = 1;
4772 entry_obj->entry->phar->is_modified = 1;
4773
4774 phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
4775
4776 if (error) {
4777 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
4778 efree(error);
4779 RETURN_FALSE;
4780 } else {
4781 RETURN_TRUE;
4782 }
4783
4784 } else {
4785 RETURN_TRUE;
4786 }
4787 }
4788
4789
4790
4791
4792
4793 PHP_METHOD(PharFileInfo, getContent)
4794 {
4795 char *error;
4796 php_stream *fp;
4797 phar_entry_info *link;
4798 zend_string *str;
4799
4800 PHAR_ENTRY_OBJECT();
4801
4802 if (zend_parse_parameters_none() == FAILURE) {
4803 return;
4804 }
4805
4806 if (entry_obj->entry->is_dir) {
4807 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4808 "Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", entry_obj->entry->filename, entry_obj->entry->phar->fname);
4809 return;
4810 }
4811
4812 link = phar_get_link_source(entry_obj->entry);
4813
4814 if (!link) {
4815 link = entry_obj->entry;
4816 }
4817
4818 if (SUCCESS != phar_open_entry_fp(link, &error, 0)) {
4819 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4820 "Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
4821 efree(error);
4822 return;
4823 }
4824
4825 if (!(fp = phar_get_efp(link, 0))) {
4826 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4827 "Phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", entry_obj->entry->filename, entry_obj->entry->phar->fname);
4828 return;
4829 }
4830
4831 phar_seek_efp(link, 0, SEEK_SET, 0, 0);
4832 str = php_stream_copy_to_mem(fp, link->uncompressed_filesize, 0);
4833 if (str) {
4834 RETURN_STR(str);
4835 } else {
4836 RETURN_EMPTY_STRING();
4837 }
4838 }
4839
4840
4841
4842
4843
4844 PHP_METHOD(PharFileInfo, compress)
4845 {
4846 zend_long method;
4847 char *error;
4848 PHAR_ENTRY_OBJECT();
4849
4850 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &method) == FAILURE) {
4851 return;
4852 }
4853
4854 if (entry_obj->entry->is_tar) {
4855 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4856 "Cannot compress with Gzip compression, not possible with tar-based phar archives");
4857 return;
4858 }
4859
4860 if (entry_obj->entry->is_dir) {
4861 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4862 "Phar entry is a directory, cannot set compression"); \
4863 return;
4864 }
4865
4866 if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
4867 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4868 "Phar is readonly, cannot change compression");
4869 return;
4870 }
4871
4872 if (entry_obj->entry->is_deleted) {
4873 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4874 "Cannot compress deleted file");
4875 return;
4876 }
4877
4878 if (entry_obj->entry->is_persistent) {
4879 phar_archive_data *phar = entry_obj->entry->phar;
4880
4881 if (FAILURE == phar_copy_on_write(&phar)) {
4882 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
4883 return;
4884 }
4885
4886 entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
4887 }
4888 switch (method) {
4889 case PHAR_ENT_COMPRESSED_GZ:
4890 if (entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) {
4891 RETURN_TRUE;
4892 }
4893
4894 if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0) {
4895 if (!PHAR_G(has_bz2)) {
4896 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4897 "Cannot compress with gzip compression, file is already compressed with bzip2 compression and bz2 extension is not enabled, cannot decompress");
4898 return;
4899 }
4900
4901
4902 if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
4903 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4904 "Phar error: Cannot decompress bzip2-compressed file \"%s\" in phar \"%s\" in order to compress with gzip: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
4905 efree(error);
4906 return;
4907 }
4908 }
4909
4910 if (!PHAR_G(has_zlib)) {
4911 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4912 "Cannot compress with gzip compression, zlib extension is not enabled");
4913 return;
4914 }
4915
4916 entry_obj->entry->old_flags = entry_obj->entry->flags;
4917 entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
4918 entry_obj->entry->flags |= PHAR_ENT_COMPRESSED_GZ;
4919 break;
4920 case PHAR_ENT_COMPRESSED_BZ2:
4921 if (entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
4922 RETURN_TRUE;
4923 }
4924
4925 if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0) {
4926 if (!PHAR_G(has_zlib)) {
4927 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4928 "Cannot compress with bzip2 compression, file is already compressed with gzip compression and zlib extension is not enabled, cannot decompress");
4929 return;
4930 }
4931
4932
4933 if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
4934 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4935 "Phar error: Cannot decompress gzip-compressed file \"%s\" in phar \"%s\" in order to compress with bzip2: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
4936 efree(error);
4937 return;
4938 }
4939 }
4940
4941 if (!PHAR_G(has_bz2)) {
4942 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4943 "Cannot compress with bzip2 compression, bz2 extension is not enabled");
4944 return;
4945 }
4946 entry_obj->entry->old_flags = entry_obj->entry->flags;
4947 entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
4948 entry_obj->entry->flags |= PHAR_ENT_COMPRESSED_BZ2;
4949 break;
4950 default:
4951 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4952 "Unknown compression type specified"); \
4953 }
4954
4955 entry_obj->entry->phar->is_modified = 1;
4956 entry_obj->entry->is_modified = 1;
4957 phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
4958
4959 if (error) {
4960 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
4961 efree(error);
4962 }
4963
4964 RETURN_TRUE;
4965 }
4966
4967
4968
4969
4970
4971 PHP_METHOD(PharFileInfo, decompress)
4972 {
4973 char *error;
4974 PHAR_ENTRY_OBJECT();
4975
4976 if (zend_parse_parameters_none() == FAILURE) {
4977 return;
4978 }
4979
4980 if (entry_obj->entry->is_dir) {
4981 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
4982 "Phar entry is a directory, cannot set compression"); \
4983 return;
4984 }
4985
4986 if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) {
4987 RETURN_TRUE;
4988 }
4989
4990 if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
4991 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4992 "Phar is readonly, cannot decompress");
4993 return;
4994 }
4995
4996 if (entry_obj->entry->is_deleted) {
4997 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
4998 "Cannot compress deleted file");
4999 return;
5000 }
5001
5002 if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0 && !PHAR_G(has_zlib)) {
5003 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
5004 "Cannot decompress Gzip-compressed file, zlib extension is not enabled");
5005 return;
5006 }
5007
5008 if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0 && !PHAR_G(has_bz2)) {
5009 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
5010 "Cannot decompress Bzip2-compressed file, bz2 extension is not enabled");
5011 return;
5012 }
5013
5014 if (entry_obj->entry->is_persistent) {
5015 phar_archive_data *phar = entry_obj->entry->phar;
5016
5017 if (FAILURE == phar_copy_on_write(&phar)) {
5018 zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
5019 return;
5020 }
5021
5022 entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
5023 }
5024 if (!entry_obj->entry->fp) {
5025 if (FAILURE == phar_open_archive_fp(entry_obj->entry->phar)) {
5026 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot decompress entry \"%s\", phar error: Cannot open phar archive \"%s\" for reading", entry_obj->entry->filename, entry_obj->entry->phar->fname);
5027 return;
5028 }
5029 entry_obj->entry->fp_type = PHAR_FP;
5030 }
5031
5032 entry_obj->entry->old_flags = entry_obj->entry->flags;
5033 entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
5034 entry_obj->entry->phar->is_modified = 1;
5035 entry_obj->entry->is_modified = 1;
5036 phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
5037
5038 if (error) {
5039 zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
5040 efree(error);
5041 }
5042 RETURN_TRUE;
5043 }
5044
5045
5046 #endif
5047
5048
5049 PHAR_ARG_INFO
5050 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1)
5051 ZEND_ARG_INFO(0, filename)
5052 ZEND_ARG_INFO(0, flags)
5053 ZEND_ARG_INFO(0, alias)
5054 ZEND_ARG_INFO(0, fileformat)
5055 ZEND_END_ARG_INFO()
5056
5057 PHAR_ARG_INFO
5058 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_createDS, 0, 0, 0)
5059 ZEND_ARG_INFO(0, index)
5060 ZEND_ARG_INFO(0, webindex)
5061 ZEND_END_ARG_INFO()
5062
5063 PHAR_ARG_INFO
5064 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_cancompress, 0, 0, 0)
5065 ZEND_ARG_INFO(0, method)
5066 ZEND_END_ARG_INFO()
5067
5068 PHAR_ARG_INFO
5069 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isvalidpharfilename, 0, 0, 1)
5070 ZEND_ARG_INFO(0, filename)
5071 ZEND_ARG_INFO(0, executable)
5072 ZEND_END_ARG_INFO()
5073
5074 PHAR_ARG_INFO
5075 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_loadPhar, 0, 0, 1)
5076 ZEND_ARG_INFO(0, filename)
5077 ZEND_ARG_INFO(0, alias)
5078 ZEND_END_ARG_INFO()
5079
5080 PHAR_ARG_INFO
5081 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mapPhar, 0, 0, 0)
5082 ZEND_ARG_INFO(0, alias)
5083 ZEND_ARG_INFO(0, offset)
5084 ZEND_END_ARG_INFO()
5085
5086 PHAR_ARG_INFO
5087 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mount, 0, 0, 2)
5088 ZEND_ARG_INFO(0, inphar)
5089 ZEND_ARG_INFO(0, externalfile)
5090 ZEND_END_ARG_INFO()
5091
5092 PHAR_ARG_INFO
5093 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mungServer, 0, 0, 1)
5094 ZEND_ARG_INFO(0, munglist)
5095 ZEND_END_ARG_INFO()
5096
5097 PHAR_ARG_INFO
5098 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_webPhar, 0, 0, 0)
5099 ZEND_ARG_INFO(0, alias)
5100 ZEND_ARG_INFO(0, index)
5101 ZEND_ARG_INFO(0, f404)
5102 ZEND_ARG_INFO(0, mimetypes)
5103 ZEND_ARG_INFO(0, rewrites)
5104 ZEND_END_ARG_INFO()
5105
5106 PHAR_ARG_INFO
5107 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_running, 0, 0, 1)
5108 ZEND_ARG_INFO(0, retphar)
5109 ZEND_END_ARG_INFO()
5110
5111 PHAR_ARG_INFO
5112 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_ua, 0, 0, 1)
5113 ZEND_ARG_INFO(0, archive)
5114 ZEND_END_ARG_INFO()
5115
5116 #if HAVE_SPL
5117 PHAR_ARG_INFO
5118 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_build, 0, 0, 1)
5119 ZEND_ARG_INFO(0, iterator)
5120 ZEND_ARG_INFO(0, base_directory)
5121 ZEND_END_ARG_INFO()
5122
5123 PHAR_ARG_INFO
5124 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_conv, 0, 0, 0)
5125 ZEND_ARG_INFO(0, format)
5126 ZEND_ARG_INFO(0, compression_type)
5127 ZEND_ARG_INFO(0, file_ext)
5128 ZEND_END_ARG_INFO()
5129
5130 PHAR_ARG_INFO
5131 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comps, 0, 0, 1)
5132 ZEND_ARG_INFO(0, compression_type)
5133 ZEND_ARG_INFO(0, file_ext)
5134 ZEND_END_ARG_INFO()
5135
5136 PHAR_ARG_INFO
5137 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_decomp, 0, 0, 0)
5138 ZEND_ARG_INFO(0, file_ext)
5139 ZEND_END_ARG_INFO()
5140
5141 PHAR_ARG_INFO
5142 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comp, 0, 0, 1)
5143 ZEND_ARG_INFO(0, compression_type)
5144 ZEND_END_ARG_INFO()
5145
5146 PHAR_ARG_INFO
5147 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_compo, 0, 0, 0)
5148 ZEND_ARG_INFO(0, compression_type)
5149 ZEND_END_ARG_INFO()
5150
5151 PHAR_ARG_INFO
5152 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_copy, 0, 0, 2)
5153 ZEND_ARG_INFO(0, newfile)
5154 ZEND_ARG_INFO(0, oldfile)
5155 ZEND_END_ARG_INFO()
5156
5157 PHAR_ARG_INFO
5158 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_delete, 0, 0, 1)
5159 ZEND_ARG_INFO(0, entry)
5160 ZEND_END_ARG_INFO()
5161
5162 PHAR_ARG_INFO
5163 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromdir, 0, 0, 1)
5164 ZEND_ARG_INFO(0, base_dir)
5165 ZEND_ARG_INFO(0, regex)
5166 ZEND_END_ARG_INFO()
5167
5168 PHAR_ARG_INFO
5169 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetExists, 0, 0, 1)
5170 ZEND_ARG_INFO(0, entry)
5171 ZEND_END_ARG_INFO()
5172
5173 PHAR_ARG_INFO
5174 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetSet, 0, 0, 2)
5175 ZEND_ARG_INFO(0, entry)
5176 ZEND_ARG_INFO(0, value)
5177 ZEND_END_ARG_INFO()
5178
5179 PHAR_ARG_INFO
5180 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setAlias, 0, 0, 1)
5181 ZEND_ARG_INFO(0, alias)
5182 ZEND_END_ARG_INFO()
5183
5184 PHAR_ARG_INFO
5185 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setMetadata, 0, 0, 1)
5186 ZEND_ARG_INFO(0, metadata)
5187 ZEND_END_ARG_INFO()
5188
5189 PHAR_ARG_INFO
5190 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setSigAlgo, 0, 0, 1)
5191 ZEND_ARG_INFO(0, algorithm)
5192 ZEND_ARG_INFO(0, privatekey)
5193 ZEND_END_ARG_INFO()
5194
5195 PHAR_ARG_INFO
5196 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setStub, 0, 0, 1)
5197 ZEND_ARG_INFO(0, newstub)
5198 ZEND_ARG_INFO(0, maxlen)
5199 ZEND_END_ARG_INFO()
5200
5201 PHAR_ARG_INFO
5202 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_emptydir, 0, 0, 0)
5203 ZEND_ARG_INFO(0, dirname)
5204 ZEND_END_ARG_INFO()
5205
5206 PHAR_ARG_INFO
5207 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_extract, 0, 0, 1)
5208 ZEND_ARG_INFO(0, pathto)
5209 ZEND_ARG_INFO(0, files)
5210 ZEND_ARG_INFO(0, overwrite)
5211 ZEND_END_ARG_INFO()
5212
5213 PHAR_ARG_INFO
5214 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_addfile, 0, 0, 1)
5215 ZEND_ARG_INFO(0, filename)
5216 ZEND_ARG_INFO(0, localname)
5217 ZEND_END_ARG_INFO()
5218
5219 PHAR_ARG_INFO
5220 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromstring, 0, 0, 1)
5221 ZEND_ARG_INFO(0, localname)
5222 ZEND_ARG_INFO(0, contents)
5223 ZEND_END_ARG_INFO()
5224
5225 PHAR_ARG_INFO
5226 ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isff, 0, 0, 1)
5227 ZEND_ARG_INFO(0, fileformat)
5228 ZEND_END_ARG_INFO()
5229
5230 PHAR_ARG_INFO
5231 ZEND_BEGIN_ARG_INFO(arginfo_phar__void, 0)
5232 ZEND_END_ARG_INFO()
5233
5234
5235 #endif
5236
5237 zend_function_entry php_archive_methods[] = {
5238 #if !HAVE_SPL
5239 PHP_ME(Phar, __construct, arginfo_phar___construct, ZEND_ACC_PRIVATE)
5240 #else
5241 PHP_ME(Phar, __construct, arginfo_phar___construct, ZEND_ACC_PUBLIC)
5242 PHP_ME(Phar, __destruct, arginfo_phar__void, ZEND_ACC_PUBLIC)
5243 PHP_ME(Phar, addEmptyDir, arginfo_phar_emptydir, ZEND_ACC_PUBLIC)
5244 PHP_ME(Phar, addFile, arginfo_phar_addfile, ZEND_ACC_PUBLIC)
5245 PHP_ME(Phar, addFromString, arginfo_phar_fromstring, ZEND_ACC_PUBLIC)
5246 PHP_ME(Phar, buildFromDirectory, arginfo_phar_fromdir, ZEND_ACC_PUBLIC)
5247 PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC)
5248 PHP_ME(Phar, compressFiles, arginfo_phar_comp, ZEND_ACC_PUBLIC)
5249 PHP_ME(Phar, decompressFiles, arginfo_phar__void, ZEND_ACC_PUBLIC)
5250 PHP_ME(Phar, compress, arginfo_phar_comps, ZEND_ACC_PUBLIC)
5251 PHP_ME(Phar, decompress, arginfo_phar_decomp, ZEND_ACC_PUBLIC)
5252 PHP_ME(Phar, convertToExecutable, arginfo_phar_conv, ZEND_ACC_PUBLIC)
5253 PHP_ME(Phar, convertToData, arginfo_phar_conv, ZEND_ACC_PUBLIC)
5254 PHP_ME(Phar, copy, arginfo_phar_copy, ZEND_ACC_PUBLIC)
5255 PHP_ME(Phar, count, arginfo_phar__void, ZEND_ACC_PUBLIC)
5256 PHP_ME(Phar, delete, arginfo_phar_delete, ZEND_ACC_PUBLIC)
5257 PHP_ME(Phar, delMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
5258 PHP_ME(Phar, extractTo, arginfo_phar_extract, ZEND_ACC_PUBLIC)
5259 PHP_ME(Phar, getAlias, arginfo_phar__void, ZEND_ACC_PUBLIC)
5260 PHP_ME(Phar, getPath, arginfo_phar__void, ZEND_ACC_PUBLIC)
5261 PHP_ME(Phar, getMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
5262 PHP_ME(Phar, getModified, arginfo_phar__void, ZEND_ACC_PUBLIC)
5263 PHP_ME(Phar, getSignature, arginfo_phar__void, ZEND_ACC_PUBLIC)
5264 PHP_ME(Phar, getStub, arginfo_phar__void, ZEND_ACC_PUBLIC)
5265 PHP_ME(Phar, getVersion, arginfo_phar__void, ZEND_ACC_PUBLIC)
5266 PHP_ME(Phar, hasMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
5267 PHP_ME(Phar, isBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
5268 PHP_ME(Phar, isCompressed, arginfo_phar__void, ZEND_ACC_PUBLIC)
5269 PHP_ME(Phar, isFileFormat, arginfo_phar_isff, ZEND_ACC_PUBLIC)
5270 PHP_ME(Phar, isWritable, arginfo_phar__void, ZEND_ACC_PUBLIC)
5271 PHP_ME(Phar, offsetExists, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
5272 PHP_ME(Phar, offsetGet, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
5273 PHP_ME(Phar, offsetSet, arginfo_phar_offsetSet, ZEND_ACC_PUBLIC)
5274 PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
5275 PHP_ME(Phar, setAlias, arginfo_phar_setAlias, ZEND_ACC_PUBLIC)
5276 PHP_ME(Phar, setDefaultStub, arginfo_phar_createDS, ZEND_ACC_PUBLIC)
5277 PHP_ME(Phar, setMetadata, arginfo_phar_setMetadata, ZEND_ACC_PUBLIC)
5278 PHP_ME(Phar, setSignatureAlgorithm, arginfo_phar_setSigAlgo, ZEND_ACC_PUBLIC)
5279 PHP_ME(Phar, setStub, arginfo_phar_setStub, ZEND_ACC_PUBLIC)
5280 PHP_ME(Phar, startBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
5281 PHP_ME(Phar, stopBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
5282 #endif
5283
5284 PHP_ME(Phar, apiVersion, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5285 PHP_ME(Phar, canCompress, arginfo_phar_cancompress, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5286 PHP_ME(Phar, canWrite, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5287 PHP_ME(Phar, createDefaultStub, arginfo_phar_createDS, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5288 PHP_ME(Phar, getSupportedCompression,arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5289 PHP_ME(Phar, getSupportedSignatures,arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5290 PHP_ME(Phar, interceptFileFuncs, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5291 PHP_ME(Phar, isValidPharFilename, arginfo_phar_isvalidpharfilename, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5292 PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5293 PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5294 PHP_ME(Phar, running, arginfo_phar_running, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5295 PHP_ME(Phar, mount, arginfo_phar_mount, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5296 PHP_ME(Phar, mungServer, arginfo_phar_mungServer, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5297 PHP_ME(Phar, unlinkArchive, arginfo_phar_ua, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5298 PHP_ME(Phar, webPhar, arginfo_phar_webPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
5299 PHP_FE_END
5300 };
5301
5302 #if HAVE_SPL
5303 PHAR_ARG_INFO
5304 ZEND_BEGIN_ARG_INFO_EX(arginfo_entry___construct, 0, 0, 1)
5305 ZEND_ARG_INFO(0, filename)
5306 ZEND_END_ARG_INFO()
5307
5308 PHAR_ARG_INFO
5309 ZEND_BEGIN_ARG_INFO_EX(arginfo_entry_chmod, 0, 0, 1)
5310 ZEND_ARG_INFO(0, perms)
5311 ZEND_END_ARG_INFO()
5312
5313 zend_function_entry php_entry_methods[] = {
5314 PHP_ME(PharFileInfo, __construct, arginfo_entry___construct, ZEND_ACC_PUBLIC)
5315 PHP_ME(PharFileInfo, __destruct, arginfo_phar__void, ZEND_ACC_PUBLIC)
5316 PHP_ME(PharFileInfo, chmod, arginfo_entry_chmod, ZEND_ACC_PUBLIC)
5317 PHP_ME(PharFileInfo, compress, arginfo_phar_comp, ZEND_ACC_PUBLIC)
5318 PHP_ME(PharFileInfo, decompress, arginfo_phar__void, ZEND_ACC_PUBLIC)
5319 PHP_ME(PharFileInfo, delMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
5320 PHP_ME(PharFileInfo, getCompressedSize, arginfo_phar__void, ZEND_ACC_PUBLIC)
5321 PHP_ME(PharFileInfo, getCRC32, arginfo_phar__void, ZEND_ACC_PUBLIC)
5322 PHP_ME(PharFileInfo, getContent, arginfo_phar__void, ZEND_ACC_PUBLIC)
5323 PHP_ME(PharFileInfo, getMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
5324 PHP_ME(PharFileInfo, getPharFlags, arginfo_phar__void, ZEND_ACC_PUBLIC)
5325 PHP_ME(PharFileInfo, hasMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
5326 PHP_ME(PharFileInfo, isCompressed, arginfo_phar_compo, ZEND_ACC_PUBLIC)
5327 PHP_ME(PharFileInfo, isCRCChecked, arginfo_phar__void, ZEND_ACC_PUBLIC)
5328 PHP_ME(PharFileInfo, setMetadata, arginfo_phar_setMetadata, ZEND_ACC_PUBLIC)
5329 PHP_FE_END
5330 };
5331 #endif
5332
5333 zend_function_entry phar_exception_methods[] = {
5334 PHP_FE_END
5335 };
5336
5337
5338 #define REGISTER_PHAR_CLASS_CONST_LONG(class_name, const_name, value) \
5339 zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (zend_long)value);
5340
5341 void phar_object_init(void)
5342 {
5343 zend_class_entry ce;
5344
5345 INIT_CLASS_ENTRY(ce, "PharException", phar_exception_methods);
5346 phar_ce_PharException = zend_register_internal_class_ex(&ce, zend_ce_exception);
5347
5348 #if HAVE_SPL
5349 INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
5350 phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator);
5351
5352 zend_class_implements(phar_ce_archive, 2, spl_ce_Countable, zend_ce_arrayaccess);
5353
5354 INIT_CLASS_ENTRY(ce, "PharData", php_archive_methods);
5355 phar_ce_data = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator);
5356
5357 zend_class_implements(phar_ce_data, 2, spl_ce_Countable, zend_ce_arrayaccess);
5358
5359 INIT_CLASS_ENTRY(ce, "PharFileInfo", php_entry_methods);
5360 phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo);
5361 #else
5362 INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
5363 phar_ce_archive = zend_register_internal_class(&ce);
5364 phar_ce_archive->ce_flags |= ZEND_ACC_FINAL;
5365
5366 INIT_CLASS_ENTRY(ce, "PharData", php_archive_methods);
5367 phar_ce_data = zend_register_internal_class(&ce);
5368 phar_ce_data->ce_flags |= ZEND_ACC_FINAL;
5369 #endif
5370
5371 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2)
5372 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ)
5373 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "NONE", PHAR_ENT_COMPRESSED_NONE)
5374 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHAR", PHAR_FORMAT_PHAR)
5375 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "TAR", PHAR_FORMAT_TAR)
5376 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "ZIP", PHAR_FORMAT_ZIP)
5377 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "COMPRESSED", PHAR_ENT_COMPRESSION_MASK)
5378 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHP", PHAR_MIME_PHP)
5379 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHPS", PHAR_MIME_PHPS)
5380 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "MD5", PHAR_SIG_MD5)
5381 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "OPENSSL", PHAR_SIG_OPENSSL)
5382 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA1", PHAR_SIG_SHA1)
5383 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA256", PHAR_SIG_SHA256)
5384 REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA512", PHAR_SIG_SHA512)
5385 }
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395