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