1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2014 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 | Author: Piere-Alain Joye <pierre@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id: 6c872ebfb022206b0cc2a183c7a388c7b6ad8685 $ */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "ext/standard/file.h"
29 #include "ext/standard/php_string.h"
30 #include "ext/pcre/php_pcre.h"
31 #include "ext/standard/php_filestat.h"
32 #include "php_zip.h"
33 #include "lib/zip.h"
34 #include "lib/zipint.h"
35
36 /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */
37 static PHP_NAMED_FUNCTION(zif_zip_open);
38 static PHP_NAMED_FUNCTION(zif_zip_read);
39 static PHP_NAMED_FUNCTION(zif_zip_close);
40 static PHP_NAMED_FUNCTION(zif_zip_entry_read);
41 static PHP_NAMED_FUNCTION(zif_zip_entry_filesize);
42 static PHP_NAMED_FUNCTION(zif_zip_entry_name);
43 static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize);
44 static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod);
45 static PHP_NAMED_FUNCTION(zif_zip_entry_open);
46 static PHP_NAMED_FUNCTION(zif_zip_entry_close);
47
48 #ifdef HAVE_GLOB
49 #ifndef PHP_WIN32
50 #include <glob.h>
51 #else
52 #include "win32/glob.h"
53 #endif
54 #endif
55
56 /* {{{ Resource le */
57 static int le_zip_dir;
58 #define le_zip_dir_name "Zip Directory"
59 static int le_zip_entry;
60 #define le_zip_entry_name "Zip Entry"
61 /* }}} */
62
63 /* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
64 #define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
65 if (zip_stat_index(za, index, flags, &sb) != 0) { \
66 RETURN_FALSE; \
67 }
68 /* }}} */
69
70 /* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */
71 #define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
72 if (path_len < 1) { \
73 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); \
74 RETURN_FALSE; \
75 } \
76 if (zip_stat(za, path, flags, &sb) != 0) { \
77 RETURN_FALSE; \
78 }
79 /* }}} */
80
81 /* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
82 #define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
83 if (comment_len == 0) { \
84 /* Passing NULL remove the existing comment */ \
85 if (zip_set_file_comment(intern, index, NULL, 0) < 0) { \
86 RETURN_FALSE; \
87 } \
88 } else if (zip_set_file_comment(intern, index, comment, comment_len) < 0) { \
89 RETURN_FALSE; \
90 } \
91 RETURN_TRUE;
92 /* }}} */
93
94 #if (PHP_MAJOR_VERSION < 6)
95 # define add_ascii_assoc_string add_assoc_string
96 # define add_ascii_assoc_long add_assoc_long
97 #endif
98
99 /* Flatten a path by making a relative path (to .)*/
php_zip_make_relative_path(char * path,int path_len)100 static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
101 {
102 char *path_begin = path;
103 size_t i;
104
105 if (path_len < 1 || path == NULL) {
106 return NULL;
107 }
108
109 if (IS_SLASH(path[0])) {
110 return path + 1;
111 }
112
113 i = path_len;
114
115 while (1) {
116 while (i > 0 && !IS_SLASH(path[i])) {
117 i--;
118 }
119
120 if (!i) {
121 return path;
122 }
123
124 if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) {
125 /* i is the position of . or :, add 1 for / */
126 path_begin = path + i + 1;
127 break;
128 }
129 i--;
130 }
131
132 return path_begin;
133 }
134 /* }}} */
135
136 #ifdef PHP_ZIP_USE_OO
137 /* {{{ php_zip_extract_file */
php_zip_extract_file(struct zip * za,char * dest,char * file,int file_len TSRMLS_DC)138 static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC)
139 {
140 php_stream_statbuf ssb;
141 struct zip_file *zf;
142 struct zip_stat sb;
143 char b[8192];
144 int n, len, ret;
145 php_stream *stream;
146 char *fullpath;
147 char *file_dirname_fullpath;
148 char file_dirname[MAXPATHLEN];
149 size_t dir_len;
150 char *file_basename;
151 size_t file_basename_len;
152 int is_dir_only = 0;
153 char *path_cleaned;
154 size_t path_cleaned_len;
155 cwd_state new_state;
156
157 new_state.cwd = (char*)malloc(1);
158 new_state.cwd[0] = '\0';
159 new_state.cwd_length = 0;
160
161 /* Clean/normlize the path and then transform any path (absolute or relative)
162 to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
163 */
164 virtual_file_ex(&new_state, file, NULL, CWD_EXPAND TSRMLS_CC);
165 path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
166 if(!path_cleaned) {
167 return 0;
168 }
169 path_cleaned_len = strlen(path_cleaned);
170
171 if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
172 return 0;
173 }
174
175 /* it is a directory only, see #40228 */
176 if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
177 len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, path_cleaned);
178 is_dir_only = 1;
179 } else {
180 memcpy(file_dirname, path_cleaned, path_cleaned_len);
181 dir_len = php_dirname(file_dirname, path_cleaned_len);
182
183 if (dir_len <= 0 || (dir_len == 1 && file_dirname[0] == '.')) {
184 len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
185 } else {
186 len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
187 }
188
189 php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (size_t *)&file_basename_len TSRMLS_CC);
190
191 if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
192 efree(file_dirname_fullpath);
193 efree(file_basename);
194 free(new_state.cwd);
195 return 0;
196 }
197 }
198
199 /* let see if the path already exists */
200 if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
201
202 #if defined(PHP_WIN32) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1)
203 char *e;
204 e = file_dirname_fullpath;
205 while (*e) {
206 if (*e == '/') {
207 *e = DEFAULT_SLASH;
208 }
209 e++;
210 }
211 #endif
212
213 ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
214 if (!ret) {
215 efree(file_dirname_fullpath);
216 if (!is_dir_only) {
217 efree(file_basename);
218 free(new_state.cwd);
219 }
220 return 0;
221 }
222 }
223
224 /* it is a standalone directory, job done */
225 if (is_dir_only) {
226 efree(file_dirname_fullpath);
227 free(new_state.cwd);
228 return 1;
229 }
230
231 len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, file_basename);
232 if (!len) {
233 efree(file_dirname_fullpath);
234 efree(file_basename);
235 free(new_state.cwd);
236 return 0;
237 } else if (len > MAXPATHLEN) {
238 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
239 efree(file_dirname_fullpath);
240 efree(file_basename);
241 free(new_state.cwd);
242 return 0;
243 }
244
245 /* check again the full path, not sure if it
246 * is required, does a file can have a different
247 * safemode status as its parent folder?
248 */
249 if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
250 efree(fullpath);
251 efree(file_dirname_fullpath);
252 efree(file_basename);
253 free(new_state.cwd);
254 return 0;
255 }
256
257 #if PHP_API_VERSION < 20100412
258 stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
259 #else
260 stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
261 #endif
262
263 if (stream == NULL) {
264 n = -1;
265 goto done;
266 }
267
268 zf = zip_fopen(za, file, 0);
269 if (zf == NULL) {
270 n = -1;
271 php_stream_close(stream);
272 goto done;
273 }
274
275 n = 0;
276
277 while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
278 php_stream_write(stream, b, n);
279 }
280
281 php_stream_close(stream);
282 n = zip_fclose(zf);
283
284 done:
285 efree(fullpath);
286 efree(file_basename);
287 efree(file_dirname_fullpath);
288 free(new_state.cwd);
289
290 if (n<0) {
291 return 0;
292 } else {
293 return 1;
294 }
295 }
296 /* }}} */
297
php_zip_add_file(struct zip * za,const char * filename,size_t filename_len,char * entry_name,size_t entry_name_len,long offset_start,long offset_len TSRMLS_DC)298 static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len,
299 char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */
300 {
301 struct zip_source *zs;
302 int cur_idx;
303 char resolved_path[MAXPATHLEN];
304 zval exists_flag;
305
306
307 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
308 return -1;
309 }
310
311 if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
312 return -1;
313 }
314
315 php_stat(resolved_path, strlen(resolved_path), FS_EXISTS, &exists_flag TSRMLS_CC);
316 if (!Z_BVAL(exists_flag)) {
317 return -1;
318 }
319
320 zs = zip_source_file(za, resolved_path, offset_start, offset_len);
321 if (!zs) {
322 return -1;
323 }
324
325 cur_idx = zip_name_locate(za, (const char *)entry_name, 0);
326 /* TODO: fix _zip_replace */
327 if (cur_idx<0) {
328 /* reset the error */
329 if (za->error.str) {
330 _zip_error_fini(&za->error);
331 }
332 _zip_error_init(&za->error);
333 } else {
334 if (zip_delete(za, cur_idx) == -1) {
335 zip_source_free(zs);
336 return -1;
337 }
338 }
339
340 if (zip_add(za, entry_name, zs) == -1) {
341 return -1;
342 } else {
343 return 1;
344 }
345 }
346 /* }}} */
347
php_zip_parse_options(zval * options,long * remove_all_path,char ** remove_path,int * remove_path_len,char ** add_path,int * add_path_len TSRMLS_DC)348 static int php_zip_parse_options(zval *options, long *remove_all_path,
349 char **remove_path, int *remove_path_len, char **add_path, int *add_path_len TSRMLS_DC) /* {{{ */
350 {
351 zval **option;
352 if (zend_hash_find(HASH_OF(options), "remove_all_path", sizeof("remove_all_path"), (void **)&option) == SUCCESS) {
353 long opt;
354 if (Z_TYPE_PP(option) != IS_LONG) {
355 zval tmp = **option;
356 zval_copy_ctor(&tmp);
357 convert_to_long(&tmp);
358 opt = Z_LVAL(tmp);
359 } else {
360 opt = Z_LVAL_PP(option);
361 }
362 *remove_all_path = opt;
363 }
364
365 /* If I add more options, it would make sense to create a nice static struct and loop over it. */
366 if (zend_hash_find(HASH_OF(options), "remove_path", sizeof("remove_path"), (void **)&option) == SUCCESS) {
367 if (Z_TYPE_PP(option) != IS_STRING) {
368 php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path option expected to be a string");
369 return -1;
370 }
371
372 if (Z_STRLEN_PP(option) < 1) {
373 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as remove_path option");
374 return -1;
375 }
376
377 if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
378 php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)",
379 MAXPATHLEN - 1, Z_STRLEN_PP(option));
380 return -1;
381 }
382 *remove_path_len = Z_STRLEN_PP(option);
383 *remove_path = Z_STRVAL_PP(option);
384 }
385
386 if (zend_hash_find(HASH_OF(options), "add_path", sizeof("add_path"), (void **)&option) == SUCCESS) {
387 if (Z_TYPE_PP(option) != IS_STRING) {
388 php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path option expected to be a string");
389 return -1;
390 }
391
392 if (Z_STRLEN_PP(option) < 1) {
393 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as the add_path option");
394 return -1;
395 }
396
397 if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
398 php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
399 MAXPATHLEN - 1, Z_STRLEN_PP(option));
400 return -1;
401 }
402 *add_path_len = Z_STRLEN_PP(option);
403 *add_path = Z_STRVAL_PP(option);
404 }
405 return 1;
406 }
407 /* }}} */
408
409 /* {{{ REGISTER_ZIP_CLASS_CONST_LONG */
410 #define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \
411 zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
412 /* }}} */
413
414 /* {{{ ZIP_FROM_OBJECT */
415 #define ZIP_FROM_OBJECT(intern, object) \
416 { \
417 ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \
418 intern = obj->za; \
419 if (!intern) { \
420 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized Zip object"); \
421 RETURN_FALSE; \
422 } \
423 }
424 /* }}} */
425
426 /* {{{ RETURN_SB(sb) */
427 #define RETURN_SB(sb) \
428 { \
429 array_init(return_value); \
430 add_ascii_assoc_string(return_value, "name", (char *)(sb)->name, 1); \
431 add_ascii_assoc_long(return_value, "index", (long) (sb)->index); \
432 add_ascii_assoc_long(return_value, "crc", (long) (sb)->crc); \
433 add_ascii_assoc_long(return_value, "size", (long) (sb)->size); \
434 add_ascii_assoc_long(return_value, "mtime", (long) (sb)->mtime); \
435 add_ascii_assoc_long(return_value, "comp_size", (long) (sb)->comp_size); \
436 add_ascii_assoc_long(return_value, "comp_method", (long) (sb)->comp_method); \
437 }
438 /* }}} */
439
php_zip_status(struct zip * za TSRMLS_DC)440 static int php_zip_status(struct zip *za TSRMLS_DC) /* {{{ */
441 {
442 int zep, syp;
443
444 zip_error_get(za, &zep, &syp);
445 return zep;
446 }
447 /* }}} */
448
php_zip_status_sys(struct zip * za TSRMLS_DC)449 static int php_zip_status_sys(struct zip *za TSRMLS_DC) /* {{{ */
450 {
451 int zep, syp;
452
453 zip_error_get(za, &zep, &syp);
454 return syp;
455 }
456 /* }}} */
457
php_zip_get_num_files(struct zip * za TSRMLS_DC)458 static int php_zip_get_num_files(struct zip *za TSRMLS_DC) /* {{{ */
459 {
460 return zip_get_num_files(za);
461 }
462 /* }}} */
463
php_zipobj_get_filename(ze_zip_object * obj TSRMLS_DC)464 static char * php_zipobj_get_filename(ze_zip_object *obj TSRMLS_DC) /* {{{ */
465 {
466
467 if (!obj) {
468 return NULL;
469 }
470
471 if (obj->filename) {
472 return obj->filename;
473 }
474 return NULL;
475 }
476 /* }}} */
477
php_zipobj_get_zip_comment(struct zip * za,int * len TSRMLS_DC)478 static char * php_zipobj_get_zip_comment(struct zip *za, int *len TSRMLS_DC) /* {{{ */
479 {
480 if (za) {
481 return (char *)zip_get_archive_comment(za, len, 0);
482 }
483 return NULL;
484 }
485 /* }}} */
486
487 #ifdef HAVE_GLOB /* {{{ */
488 #ifndef GLOB_ONLYDIR
489 #define GLOB_ONLYDIR (1<<30)
490 #define GLOB_EMULATE_ONLYDIR
491 #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
492 #else
493 #define GLOB_FLAGMASK (~0)
494 #endif
495 #ifndef GLOB_BRACE
496 # define GLOB_BRACE 0
497 #endif
498 #ifndef GLOB_MARK
499 # define GLOB_MARK 0
500 #endif
501 #ifndef GLOB_NOSORT
502 # define GLOB_NOSORT 0
503 #endif
504 #ifndef GLOB_NOCHECK
505 # define GLOB_NOCHECK 0
506 #endif
507 #ifndef GLOB_NOESCAPE
508 # define GLOB_NOESCAPE 0
509 #endif
510 #ifndef GLOB_ERR
511 # define GLOB_ERR 0
512 #endif
513
514 /* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
515 #define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
516
517 #endif /* }}} */
518
php_zip_glob(char * pattern,int pattern_len,long flags,zval * return_value TSRMLS_DC)519 int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value TSRMLS_DC) /* {{{ */
520 {
521 #ifdef HAVE_GLOB
522 char cwd[MAXPATHLEN];
523 int cwd_skip = 0;
524 #ifdef ZTS
525 char work_pattern[MAXPATHLEN];
526 char *result;
527 #endif
528 glob_t globbuf;
529 int n;
530 int ret;
531
532 if (pattern_len >= MAXPATHLEN) {
533 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
534 return -1;
535 }
536
537 if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
538 php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
539 return -1;
540 }
541
542 #ifdef ZTS
543 if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
544 result = VCWD_GETCWD(cwd, MAXPATHLEN);
545 if (!result) {
546 cwd[0] = '\0';
547 }
548 #ifdef PHP_WIN32
549 if (IS_SLASH(*pattern)) {
550 cwd[2] = '\0';
551 }
552 #endif
553 cwd_skip = strlen(cwd)+1;
554
555 snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
556 pattern = work_pattern;
557 }
558 #endif
559
560 globbuf.gl_offs = 0;
561 if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
562 #ifdef GLOB_NOMATCH
563 if (GLOB_NOMATCH == ret) {
564 /* Some glob implementation simply return no data if no matches
565 were found, others return the GLOB_NOMATCH error code.
566 We don't want to treat GLOB_NOMATCH as an error condition
567 so that PHP glob() behaves the same on both types of
568 implementations and so that 'foreach (glob() as ...'
569 can be used for simple glob() calls without further error
570 checking.
571 */
572 array_init(return_value);
573 return 0;
574 }
575 #endif
576 return 0;
577 }
578
579 /* now catch the FreeBSD style of "no matches" */
580 if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
581 array_init(return_value);
582 return 0;
583 }
584
585 /* we assume that any glob pattern will match files from one directory only
586 so checking the dirname of the first match should be sufficient */
587 strncpy(cwd, globbuf.gl_pathv[0], MAXPATHLEN);
588 if (ZIP_OPENBASEDIR_CHECKPATH(cwd)) {
589 return -1;
590 }
591
592 array_init(return_value);
593 for (n = 0; n < globbuf.gl_pathc; n++) {
594 /* we need to do this everytime since GLOB_ONLYDIR does not guarantee that
595 * all directories will be filtered. GNU libc documentation states the
596 * following:
597 * If the information about the type of the file is easily available
598 * non-directories will be rejected but no extra work will be done to
599 * determine the information for each file. I.e., the caller must still be
600 * able to filter directories out.
601 */
602 if (flags & GLOB_ONLYDIR) {
603 struct stat s;
604
605 if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
606 continue;
607 }
608
609 if (S_IFDIR != (s.st_mode & S_IFMT)) {
610 continue;
611 }
612 }
613 add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip, 1);
614 }
615
616 globfree(&globbuf);
617 return globbuf.gl_pathc;
618 #else
619 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Glob support is not available");
620 return 0;
621 #endif /* HAVE_GLOB */
622 }
623 /* }}} */
624
php_zip_pcre(char * regexp,int regexp_len,char * path,int path_len,zval * return_value TSRMLS_DC)625 int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *return_value TSRMLS_DC) /* {{{ */
626 {
627 #ifdef ZTS
628 char cwd[MAXPATHLEN];
629 int cwd_skip = 0;
630 char work_path[MAXPATHLEN];
631 char *result;
632 #endif
633 int files_cnt;
634 char **namelist;
635
636 #ifdef ZTS
637 if (!IS_ABSOLUTE_PATH(path, path_len)) {
638 result = VCWD_GETCWD(cwd, MAXPATHLEN);
639 if (!result) {
640 cwd[0] = '\0';
641 }
642 #ifdef PHP_WIN32
643 if (IS_SLASH(*path)) {
644 cwd[2] = '\0';
645 }
646 #endif
647 cwd_skip = strlen(cwd)+1;
648
649 snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
650 path = work_path;
651 }
652 #endif
653
654 if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
655 return -1;
656 }
657
658 files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
659
660 if (files_cnt > 0) {
661 pcre *re = NULL;
662 pcre_extra *pcre_extra = NULL;
663 int preg_options = 0, i;
664
665 re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
666 if (!re) {
667 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid expression");
668 return -1;
669 }
670
671 array_init(return_value);
672
673 /* only the files, directories are ignored */
674 for (i = 0; i < files_cnt; i++) {
675 struct stat s;
676 char fullpath[MAXPATHLEN];
677 int ovector[3];
678 int matches;
679 int namelist_len = strlen(namelist[i]);
680
681
682 if ((namelist_len == 1 && namelist[i][0] == '.') ||
683 (namelist_len == 2 && namelist[i][0] == '.' && namelist[i][1] == '.')) {
684 efree(namelist[i]);
685 continue;
686 }
687
688 if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
689 php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
690 MAXPATHLEN - 1, (path_len + namelist_len + 1));
691 efree(namelist[i]);
692 break;
693 }
694
695 snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, namelist[i]);
696
697 if (0 != VCWD_STAT(fullpath, &s)) {
698 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot read <%s>", fullpath);
699 efree(namelist[i]);
700 continue;
701 }
702
703 if (S_IFDIR == (s.st_mode & S_IFMT)) {
704 efree(namelist[i]);
705 continue;
706 }
707
708 matches = pcre_exec(re, NULL, namelist[i], strlen(namelist[i]), 0, 0, ovector, 3);
709 /* 0 means that the vector is too small to hold all the captured substring offsets */
710 if (matches < 0) {
711 efree(namelist[i]);
712 continue;
713 }
714
715 add_next_index_string(return_value, fullpath, 1);
716 efree(namelist[i]);
717 }
718 efree(namelist);
719 }
720 return files_cnt;
721 }
722 /* }}} */
723
724 #endif
725
726 /* {{{ arginfo */
727 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1)
728 ZEND_ARG_INFO(0, filename)
729 ZEND_END_ARG_INFO()
730
731 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_close, 0, 0, 1)
732 ZEND_ARG_INFO(0, zip)
733 ZEND_END_ARG_INFO()
734
735 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_read, 0, 0, 1)
736 ZEND_ARG_INFO(0, zip)
737 ZEND_END_ARG_INFO()
738
739 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_open, 0, 0, 2)
740 ZEND_ARG_INFO(0, zip_dp)
741 ZEND_ARG_INFO(0, zip_entry)
742 ZEND_ARG_INFO(0, mode)
743 ZEND_END_ARG_INFO()
744
745 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_close, 0, 0, 1)
746 ZEND_ARG_INFO(0, zip_ent)
747 ZEND_END_ARG_INFO()
748
749 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_read, 0, 0, 1)
750 ZEND_ARG_INFO(0, zip_entry)
751 ZEND_ARG_INFO(0, len)
752 ZEND_END_ARG_INFO()
753
754 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_name, 0, 0, 1)
755 ZEND_ARG_INFO(0, zip_entry)
756 ZEND_END_ARG_INFO()
757
758 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressedsize, 0, 0, 1)
759 ZEND_ARG_INFO(0, zip_entry)
760 ZEND_END_ARG_INFO()
761
762 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_filesize, 0, 0, 1)
763 ZEND_ARG_INFO(0, zip_entry)
764 ZEND_END_ARG_INFO()
765
766 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressionmethod, 0, 0, 1)
767 ZEND_ARG_INFO(0, zip_entry)
768 ZEND_END_ARG_INFO()
769 /* }}} */
770
771 /* {{{ zend_function_entry */
772 static const zend_function_entry zip_functions[] = {
773 ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0)
774 ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0)
775 ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0)
776 PHP_FE(zip_entry_open, arginfo_zip_entry_open)
777 PHP_FE(zip_entry_close, arginfo_zip_entry_close)
778 PHP_FE(zip_entry_read, arginfo_zip_entry_read)
779 PHP_FE(zip_entry_filesize, arginfo_zip_entry_filesize)
780 PHP_FE(zip_entry_name, arginfo_zip_entry_name)
781 PHP_FE(zip_entry_compressedsize, arginfo_zip_entry_compressedsize)
782 PHP_FE(zip_entry_compressionmethod, arginfo_zip_entry_compressionmethod)
783 PHP_FE_END
784 };
785 /* }}} */
786
787 /* {{{ ZE2 OO definitions */
788 #ifdef PHP_ZIP_USE_OO
789 static zend_class_entry *zip_class_entry;
790 static zend_object_handlers zip_object_handlers;
791
792 static HashTable zip_prop_handlers;
793
794 typedef int (*zip_read_int_t)(struct zip *za TSRMLS_DC);
795 typedef char *(*zip_read_const_char_t)(struct zip *za, int *len TSRMLS_DC);
796 typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj TSRMLS_DC);
797
798 typedef struct _zip_prop_handler {
799 zip_read_int_t read_int_func;
800 zip_read_const_char_t read_const_char_func;
801 zip_read_const_char_from_ze_t read_const_char_from_obj_func;
802
803 int type;
804 } zip_prop_handler;
805 #endif
806 /* }}} */
807
808 #ifdef PHP_ZIP_USE_OO
php_zip_register_prop_handler(HashTable * prop_handler,char * name,zip_read_int_t read_int_func,zip_read_const_char_t read_char_func,zip_read_const_char_from_ze_t read_char_from_obj_func,int rettype TSRMLS_DC)809 static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, zip_read_int_t read_int_func, zip_read_const_char_t read_char_func, zip_read_const_char_from_ze_t read_char_from_obj_func, int rettype TSRMLS_DC) /* {{{ */
810 {
811 zip_prop_handler hnd;
812
813 hnd.read_const_char_func = read_char_func;
814 hnd.read_int_func = read_int_func;
815 hnd.read_const_char_from_obj_func = read_char_from_obj_func;
816 hnd.type = rettype;
817 zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(zip_prop_handler), NULL);
818 }
819 /* }}} */
820
php_zip_property_reader(ze_zip_object * obj,zip_prop_handler * hnd,zval ** retval,int newzval TSRMLS_DC)821 static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval **retval, int newzval TSRMLS_DC) /* {{{ */
822 {
823 const char *retchar = NULL;
824 int retint = 0;
825 int len = 0;
826
827 if (obj && obj->za != NULL) {
828 if (hnd->read_const_char_func) {
829 retchar = hnd->read_const_char_func(obj->za, &len TSRMLS_CC);
830 } else {
831 if (hnd->read_int_func) {
832 retint = hnd->read_int_func(obj->za TSRMLS_CC);
833 if (retint == -1) {
834 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal zip error returned");
835 return FAILURE;
836 }
837 } else {
838 if (hnd->read_const_char_from_obj_func) {
839 retchar = hnd->read_const_char_from_obj_func(obj TSRMLS_CC);
840 len = strlen(retchar);
841 }
842 }
843 }
844 }
845
846 if (newzval) {
847 ALLOC_ZVAL(*retval);
848 }
849
850 switch (hnd->type) {
851 case IS_STRING:
852 if (retchar) {
853 ZVAL_STRINGL(*retval, (char *) retchar, len, 1);
854 } else {
855 ZVAL_EMPTY_STRING(*retval);
856 }
857 break;
858 case IS_BOOL:
859 ZVAL_BOOL(*retval, (long)retint);
860 break;
861 case IS_LONG:
862 ZVAL_LONG(*retval, (long)retint);
863 break;
864 default:
865 ZVAL_NULL(*retval);
866 }
867
868 return SUCCESS;
869 }
870 /* }}} */
871
php_zip_get_property_ptr_ptr(zval * object,zval * member,const zend_literal * key TSRMLS_DC)872 static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
873 {
874 ze_zip_object *obj;
875 zval tmp_member;
876 zval **retval = NULL;
877
878 zip_prop_handler *hnd;
879 zend_object_handlers *std_hnd;
880 int ret;
881
882 if (member->type != IS_STRING) {
883 tmp_member = *member;
884 zval_copy_ctor(&tmp_member);
885 convert_to_string(&tmp_member);
886 member = &tmp_member;
887 key = NULL;
888 }
889
890 ret = FAILURE;
891 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
892
893 if (obj->prop_handler != NULL) {
894 if (key) {
895 ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
896 } else {
897 ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
898 }
899 }
900
901
902 if (ret == FAILURE) {
903 std_hnd = zend_get_std_object_handlers();
904 retval = std_hnd->get_property_ptr_ptr(object, member, key TSRMLS_CC);
905 }
906
907 if (member == &tmp_member) {
908 zval_dtor(member);
909 }
910 return retval;
911 }
912 /* }}} */
913
php_zip_read_property(zval * object,zval * member,int type,const zend_literal * key TSRMLS_DC)914 static zval* php_zip_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
915 {
916 ze_zip_object *obj;
917 zval tmp_member;
918 zval *retval;
919 zip_prop_handler *hnd;
920 zend_object_handlers *std_hnd;
921 int ret;
922
923 if (member->type != IS_STRING) {
924 tmp_member = *member;
925 zval_copy_ctor(&tmp_member);
926 convert_to_string(&tmp_member);
927 member = &tmp_member;
928 key = NULL;
929 }
930
931 ret = FAILURE;
932 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
933
934 if (obj->prop_handler != NULL) {
935 if (key) {
936 ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
937 } else {
938 ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
939 }
940 }
941
942 if (ret == SUCCESS) {
943 ret = php_zip_property_reader(obj, hnd, &retval, 1 TSRMLS_CC);
944 if (ret == SUCCESS) {
945 /* ensure we're creating a temporary variable */
946 Z_SET_REFCOUNT_P(retval, 0);
947 } else {
948 retval = EG(uninitialized_zval_ptr);
949 }
950 } else {
951 std_hnd = zend_get_std_object_handlers();
952 retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
953 }
954
955 if (member == &tmp_member) {
956 zval_dtor(member);
957 }
958 return retval;
959 }
960 /* }}} */
961
php_zip_has_property(zval * object,zval * member,int type,const zend_literal * key TSRMLS_DC)962 static int php_zip_has_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
963 {
964 ze_zip_object *obj;
965 zval tmp_member;
966 zip_prop_handler *hnd;
967 zend_object_handlers *std_hnd;
968 int ret, retval = 0;
969
970 if (member->type != IS_STRING) {
971 tmp_member = *member;
972 zval_copy_ctor(&tmp_member);
973 convert_to_string(&tmp_member);
974 member = &tmp_member;
975 key = NULL;
976 }
977
978 ret = FAILURE;
979 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
980
981 if (obj->prop_handler != NULL) {
982 if (key) {
983 ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
984 } else {
985 ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
986 }
987 }
988
989 if (ret == SUCCESS) {
990 zval *tmp;
991 ALLOC_INIT_ZVAL(tmp);
992
993 if (type == 2) {
994 retval = 1;
995 } else if (php_zip_property_reader(obj, hnd, &tmp, 0 TSRMLS_CC) == SUCCESS) {
996 Z_SET_REFCOUNT_P(tmp, 1);
997 Z_UNSET_ISREF_P(tmp);
998 if (type == 1) {
999 retval = zend_is_true(tmp);
1000 } else if (type == 0) {
1001 retval = (Z_TYPE_P(tmp) != IS_NULL);
1002 }
1003 }
1004
1005 zval_ptr_dtor(&tmp);
1006 } else {
1007 std_hnd = zend_get_std_object_handlers();
1008 retval = std_hnd->has_property(object, member, type, key TSRMLS_CC);
1009 }
1010
1011 if (member == &tmp_member) {
1012 zval_dtor(member);
1013 }
1014 return retval;
1015 }
1016 /* }}} */
1017
php_zip_get_properties(zval * object TSRMLS_DC)1018 static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
1019 {
1020 ze_zip_object *obj;
1021 zip_prop_handler *hnd;
1022 HashTable *props;
1023 zval *val;
1024 int ret;
1025 char *key;
1026 uint key_len;
1027 HashPosition pos;
1028 ulong num_key;
1029
1030 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
1031 props = zend_std_get_properties(object TSRMLS_CC);
1032
1033 if (obj->prop_handler == NULL) {
1034 return NULL;
1035 }
1036 zend_hash_internal_pointer_reset_ex(obj->prop_handler, &pos);
1037
1038 while (zend_hash_get_current_data_ex(obj->prop_handler, (void**)&hnd, &pos) == SUCCESS) {
1039 zend_hash_get_current_key_ex(obj->prop_handler, &key, &key_len, &num_key, 0, &pos);
1040 MAKE_STD_ZVAL(val);
1041 ret = php_zip_property_reader(obj, hnd, &val, 0 TSRMLS_CC);
1042 if (ret != SUCCESS) {
1043 val = EG(uninitialized_zval_ptr);
1044 }
1045 zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
1046 zend_hash_move_forward_ex(obj->prop_handler, &pos);
1047 }
1048 return props;
1049 }
1050 /* }}} */
1051
php_zip_object_free_storage(void * object TSRMLS_DC)1052 static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
1053 {
1054 ze_zip_object * intern = (ze_zip_object *) object;
1055 int i;
1056
1057 if (!intern) {
1058 return;
1059 }
1060 if (intern->za) {
1061 if (zip_close(intern->za) != 0) {
1062 _zip_free(intern->za);
1063 }
1064 intern->za = NULL;
1065 }
1066
1067 if (intern->buffers_cnt>0) {
1068 for (i=0; i<intern->buffers_cnt; i++) {
1069 efree(intern->buffers[i]);
1070 }
1071 efree(intern->buffers);
1072 }
1073
1074 intern->za = NULL;
1075
1076 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
1077 zend_object_std_dtor(&intern->zo TSRMLS_CC);
1078 #else
1079 if (intern->zo.guards) {
1080 zend_hash_destroy(intern->zo.guards);
1081 FREE_HASHTABLE(intern->zo.guards);
1082 }
1083
1084 if (intern->zo.properties) {
1085 zend_hash_destroy(intern->zo.properties);
1086 FREE_HASHTABLE(intern->zo.properties);
1087 }
1088 #endif
1089
1090 if (intern->filename) {
1091 efree(intern->filename);
1092 }
1093 efree(intern);
1094 }
1095 /* }}} */
1096
php_zip_object_new(zend_class_entry * class_type TSRMLS_DC)1097 static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
1098 {
1099 ze_zip_object *intern;
1100 zend_object_value retval;
1101
1102 intern = emalloc(sizeof(ze_zip_object));
1103 memset(&intern->zo, 0, sizeof(zend_object));
1104
1105 intern->za = NULL;
1106 intern->buffers = NULL;
1107 intern->filename = NULL;
1108 intern->buffers_cnt = 0;
1109 intern->prop_handler = &zip_prop_handlers;
1110
1111 #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2))
1112 zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
1113 #else
1114 ALLOC_HASHTABLE(intern->zo.properties);
1115 zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
1116 intern->zo.ce = class_type;
1117 #endif
1118
1119 object_properties_init(&intern->zo, class_type);
1120
1121 retval.handle = zend_objects_store_put(intern,
1122 NULL,
1123 (zend_objects_free_object_storage_t) php_zip_object_free_storage,
1124 NULL TSRMLS_CC);
1125
1126 retval.handlers = (zend_object_handlers *) & zip_object_handlers;
1127
1128 return retval;
1129 }
1130 /* }}} */
1131 #endif
1132
1133 /* {{{ Resource dtors */
1134
1135 /* {{{ php_zip_free_dir */
php_zip_free_dir(zend_rsrc_list_entry * rsrc TSRMLS_DC)1136 static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1137 {
1138 zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
1139
1140 if (zip_int) {
1141 if (zip_int->za) {
1142 if (zip_close(zip_int->za) != 0) {
1143 _zip_free(zip_int->za);
1144 }
1145 zip_int->za = NULL;
1146 }
1147
1148 efree(rsrc->ptr);
1149
1150 rsrc->ptr = NULL;
1151 }
1152 }
1153 /* }}} */
1154
1155 /* {{{ php_zip_free_entry */
php_zip_free_entry(zend_rsrc_list_entry * rsrc TSRMLS_DC)1156 static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1157 {
1158 zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
1159
1160 if (zr_rsrc) {
1161 if (zr_rsrc->zf) {
1162 if (zr_rsrc->zf->za) {
1163 zip_fclose(zr_rsrc->zf);
1164 } else {
1165 if (zr_rsrc->zf->src)
1166 zip_source_free(zr_rsrc->zf->src);
1167 free(zr_rsrc->zf);
1168 }
1169 zr_rsrc->zf = NULL;
1170 }
1171 efree(zr_rsrc);
1172 rsrc->ptr = NULL;
1173 }
1174 }
1175 /* }}} */
1176
1177 /* }}}*/
1178
1179 /* reset macro */
1180
1181 /* {{{ function prototypes */
1182 static PHP_MINIT_FUNCTION(zip);
1183 static PHP_MSHUTDOWN_FUNCTION(zip);
1184 static PHP_MINFO_FUNCTION(zip);
1185 /* }}} */
1186
1187 /* {{{ zip_module_entry
1188 */
1189 zend_module_entry zip_module_entry = {
1190 STANDARD_MODULE_HEADER,
1191 "zip",
1192 zip_functions,
1193 PHP_MINIT(zip),
1194 PHP_MSHUTDOWN(zip),
1195 NULL,
1196 NULL,
1197 PHP_MINFO(zip),
1198 PHP_ZIP_VERSION_STRING,
1199 STANDARD_MODULE_PROPERTIES
1200 };
1201 /* }}} */
1202
1203 #ifdef COMPILE_DL_ZIP
1204 ZEND_GET_MODULE(zip)
1205 #endif
1206 /* set macro */
1207
1208 /* {{{ proto resource zip_open(string filename)
1209 Create new zip using source uri for output */
PHP_NAMED_FUNCTION(zif_zip_open)1210 static PHP_NAMED_FUNCTION(zif_zip_open)
1211 {
1212 char *filename;
1213 int filename_len;
1214 char resolved_path[MAXPATHLEN + 1];
1215 zip_rsrc *rsrc_int;
1216 int err = 0;
1217
1218 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
1219 return;
1220 }
1221
1222 if (filename_len == 0) {
1223 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
1224 RETURN_FALSE;
1225 }
1226
1227 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
1228 RETURN_FALSE;
1229 }
1230
1231 if(!expand_filepath(filename, resolved_path TSRMLS_CC)) {
1232 RETURN_FALSE;
1233 }
1234
1235 rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
1236
1237 rsrc_int->za = zip_open(resolved_path, 0, &err);
1238 if (rsrc_int->za == NULL) {
1239 efree(rsrc_int);
1240 RETURN_LONG((long)err);
1241 }
1242
1243 rsrc_int->index_current = 0;
1244 rsrc_int->num_files = zip_get_num_files(rsrc_int->za);
1245
1246 ZEND_REGISTER_RESOURCE(return_value, rsrc_int, le_zip_dir);
1247 }
1248 /* }}} */
1249
1250 /* {{{ proto void zip_close(resource zip)
1251 Close a Zip archive */
PHP_NAMED_FUNCTION(zif_zip_close)1252 static PHP_NAMED_FUNCTION(zif_zip_close)
1253 {
1254 zval * zip;
1255 zip_rsrc *z_rsrc = NULL;
1256
1257 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip) == FAILURE) {
1258 return;
1259 }
1260 ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
1261
1262 /* really close the zip will break BC :-D */
1263 zend_list_delete(Z_LVAL_P(zip));
1264 }
1265 /* }}} */
1266
1267 /* {{{ proto resource zip_read(resource zip)
1268 Returns the next file in the archive */
PHP_NAMED_FUNCTION(zif_zip_read)1269 static PHP_NAMED_FUNCTION(zif_zip_read)
1270 {
1271 zval *zip_dp;
1272 zip_read_rsrc *zr_rsrc;
1273 int ret;
1274 zip_rsrc *rsrc_int;
1275
1276 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_dp) == FAILURE) {
1277 return;
1278 }
1279 ZEND_FETCH_RESOURCE(rsrc_int, zip_rsrc *, &zip_dp, -1, le_zip_dir_name, le_zip_dir);
1280
1281 if (rsrc_int && rsrc_int->za) {
1282 if (rsrc_int->index_current >= rsrc_int->num_files) {
1283 RETURN_FALSE;
1284 }
1285
1286 zr_rsrc = emalloc(sizeof(zip_read_rsrc));
1287
1288 ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
1289
1290 if (ret != 0) {
1291 efree(zr_rsrc);
1292 RETURN_FALSE;
1293 }
1294
1295 zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
1296 if (zr_rsrc->zf) {
1297 rsrc_int->index_current++;
1298 ZEND_REGISTER_RESOURCE(return_value, zr_rsrc, le_zip_entry);
1299 } else {
1300 efree(zr_rsrc);
1301 RETURN_FALSE;
1302 }
1303
1304 } else {
1305 RETURN_FALSE;
1306 }
1307 }
1308 /* }}} */
1309
1310 /* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode])
1311 Open a Zip File, pointed by the resource entry */
1312 /* Dummy function to follow the old API */
PHP_NAMED_FUNCTION(zif_zip_entry_open)1313 static PHP_NAMED_FUNCTION(zif_zip_entry_open)
1314 {
1315 zval * zip;
1316 zval * zip_entry;
1317 char *mode = NULL;
1318 int mode_len = 0;
1319 zip_read_rsrc * zr_rsrc;
1320 zip_rsrc *z_rsrc;
1321
1322 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
1323 return;
1324 }
1325
1326 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1327 ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
1328
1329 if (zr_rsrc->zf != NULL) {
1330 RETURN_TRUE;
1331 } else {
1332 RETURN_FALSE;
1333 }
1334 }
1335 /* }}} */
1336
1337 /* {{{ proto bool zip_entry_close(resource zip_ent)
1338 Close a zip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_close)1339 static PHP_NAMED_FUNCTION(zif_zip_entry_close)
1340 {
1341 zval * zip_entry;
1342 zip_read_rsrc * zr_rsrc;
1343
1344 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
1345 return;
1346 }
1347
1348 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1349
1350 RETURN_BOOL(SUCCESS == zend_list_delete(Z_LVAL_P(zip_entry)));
1351 }
1352 /* }}} */
1353
1354 /* {{{ proto mixed zip_entry_read(resource zip_entry [, int len])
1355 Read from an open directory entry */
PHP_NAMED_FUNCTION(zif_zip_entry_read)1356 static PHP_NAMED_FUNCTION(zif_zip_entry_read)
1357 {
1358 zval * zip_entry;
1359 long len = 0;
1360 zip_read_rsrc * zr_rsrc;
1361 char *buffer;
1362 int n = 0;
1363
1364 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zip_entry, &len) == FAILURE) {
1365 return;
1366 }
1367
1368 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1369
1370 if (len <= 0) {
1371 len = 1024;
1372 }
1373
1374 if (zr_rsrc->zf) {
1375 buffer = safe_emalloc(len, 1, 1);
1376 n = zip_fread(zr_rsrc->zf, buffer, len);
1377 if (n > 0) {
1378 buffer[n] = 0;
1379 RETURN_STRINGL(buffer, n, 0);
1380 } else {
1381 efree(buffer);
1382 RETURN_EMPTY_STRING()
1383 }
1384 } else {
1385 RETURN_FALSE;
1386 }
1387 }
1388 /* }}} */
1389
php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS,int opt)1390 static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
1391 {
1392 zval * zip_entry;
1393 zip_read_rsrc * zr_rsrc;
1394
1395 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
1396 return;
1397 }
1398
1399 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1400
1401 if (!zr_rsrc->zf) {
1402 RETURN_FALSE;
1403 }
1404
1405 switch (opt) {
1406 case 0:
1407 RETURN_STRING((char *)zr_rsrc->sb.name, 1);
1408 break;
1409 case 1:
1410 RETURN_LONG((long) (zr_rsrc->sb.comp_size));
1411 break;
1412 case 2:
1413 RETURN_LONG((long) (zr_rsrc->sb.size));
1414 break;
1415 case 3:
1416 switch (zr_rsrc->sb.comp_method) {
1417 case 0:
1418 RETURN_STRING("stored", 1);
1419 break;
1420 case 1:
1421 RETURN_STRING("shrunk", 1);
1422 break;
1423 case 2:
1424 case 3:
1425 case 4:
1426 case 5:
1427 RETURN_STRING("reduced", 1);
1428 break;
1429 case 6:
1430 RETURN_STRING("imploded", 1);
1431 break;
1432 case 7:
1433 RETURN_STRING("tokenized", 1);
1434 break;
1435 case 8:
1436 RETURN_STRING("deflated", 1);
1437 break;
1438 case 9:
1439 RETURN_STRING("deflatedX", 1);
1440 break;
1441 case 10:
1442 RETURN_STRING("implodedX", 1);
1443 break;
1444 default:
1445 RETURN_FALSE;
1446 }
1447 RETURN_LONG((long) (zr_rsrc->sb.comp_method));
1448 break;
1449 }
1450
1451 }
1452 /* }}} */
1453
1454 /* {{{ proto string zip_entry_name(resource zip_entry)
1455 Return the name given a ZZip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_name)1456 static PHP_NAMED_FUNCTION(zif_zip_entry_name)
1457 {
1458 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1459 }
1460 /* }}} */
1461
1462 /* {{{ proto int zip_entry_compressedsize(resource zip_entry)
1463 Return the compressed size of a ZZip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)1464 static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)
1465 {
1466 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1467 }
1468 /* }}} */
1469
1470 /* {{{ proto int zip_entry_filesize(resource zip_entry)
1471 Return the actual filesize of a ZZip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_filesize)1472 static PHP_NAMED_FUNCTION(zif_zip_entry_filesize)
1473 {
1474 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1475 }
1476 /* }}} */
1477
1478 /* {{{ proto string zip_entry_compressionmethod(resource zip_entry)
1479 Return a string containing the compression method used on a particular entry */
PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)1480 static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
1481 {
1482 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
1483 }
1484 /* }}} */
1485
1486 #ifdef PHP_ZIP_USE_OO
1487 /* {{{ proto mixed ZipArchive::open(string source [, int flags])
1488 Create new zip using source uri for output, return TRUE on success or the error code */
ZIPARCHIVE_METHOD(open)1489 static ZIPARCHIVE_METHOD(open)
1490 {
1491 struct zip *intern;
1492 char *filename;
1493 int filename_len;
1494 int err = 0;
1495 long flags = 0;
1496 char resolved_path[MAXPATHLEN];
1497
1498 zval *this = getThis();
1499 ze_zip_object *ze_obj = NULL;
1500
1501 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) {
1502 return;
1503 }
1504
1505 if (this) {
1506 /* We do not use ZIP_FROM_OBJECT, zip init function here */
1507 ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1508 }
1509
1510 if (filename_len == 0) {
1511 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
1512 RETURN_FALSE;
1513 }
1514
1515 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
1516 RETURN_FALSE;
1517 }
1518
1519 if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
1520 RETURN_FALSE;
1521 }
1522
1523 if (ze_obj->za) {
1524 /* we already have an opened zip, free it */
1525 if (zip_close(ze_obj->za) != 0) {
1526 _zip_free(ze_obj->za);
1527 }
1528 ze_obj->za = NULL;
1529 }
1530 if (ze_obj->filename) {
1531 efree(ze_obj->filename);
1532 ze_obj->filename = NULL;
1533 }
1534
1535 intern = zip_open(resolved_path, flags, &err);
1536 if (!intern || err) {
1537 RETURN_LONG((long)err);
1538 }
1539 ze_obj->filename = estrdup(resolved_path);
1540 ze_obj->filename_len = strlen(resolved_path);
1541 ze_obj->za = intern;
1542 RETURN_TRUE;
1543 }
1544 /* }}} */
1545
1546 /* {{{ proto bool ZipArchive::close()
1547 close the zip archive */
ZIPARCHIVE_METHOD(close)1548 static ZIPARCHIVE_METHOD(close)
1549 {
1550 struct zip *intern;
1551 zval *this = getThis();
1552 ze_zip_object *ze_obj;
1553
1554 if (!this) {
1555 RETURN_FALSE;
1556 }
1557
1558 ZIP_FROM_OBJECT(intern, this);
1559
1560 ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1561
1562 if (zip_close(intern)) {
1563 RETURN_FALSE;
1564 }
1565
1566 efree(ze_obj->filename);
1567 ze_obj->filename = NULL;
1568 ze_obj->filename_len = 0;
1569 ze_obj->za = NULL;
1570
1571 RETURN_TRUE;
1572 }
1573 /* }}} */
1574
1575 /* {{{ proto string ZipArchive::getStatusString()
1576 * Returns the status error message, system and/or zip messages */
ZIPARCHIVE_METHOD(getStatusString)1577 static ZIPARCHIVE_METHOD(getStatusString)
1578 {
1579 struct zip *intern;
1580 zval *this = getThis();
1581 int zep, syp, len;
1582 char error_string[128];
1583
1584 if (!this) {
1585 RETURN_FALSE;
1586 }
1587
1588 ZIP_FROM_OBJECT(intern, this);
1589
1590 zip_error_get(intern, &zep, &syp);
1591
1592 len = zip_error_to_str(error_string, 128, zep, syp);
1593 RETVAL_STRINGL(error_string, len, 1);
1594 }
1595 /* }}} */
1596
1597 /* {{{ proto bool ZipArchive::createEmptyDir(string dirname)
1598 Returns the index of the entry named filename in the archive */
ZIPARCHIVE_METHOD(addEmptyDir)1599 static ZIPARCHIVE_METHOD(addEmptyDir)
1600 {
1601 struct zip *intern;
1602 zval *this = getThis();
1603 char *dirname;
1604 int dirname_len;
1605 int idx;
1606 struct zip_stat sb;
1607 char *s;
1608
1609 if (!this) {
1610 RETURN_FALSE;
1611 }
1612
1613 ZIP_FROM_OBJECT(intern, this);
1614
1615 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
1616 &dirname, &dirname_len) == FAILURE) {
1617 return;
1618 }
1619
1620 if (dirname_len<1) {
1621 RETURN_FALSE;
1622 }
1623
1624 if (dirname[dirname_len-1] != '/') {
1625 s=(char *)emalloc(dirname_len+2);
1626 strcpy(s, dirname);
1627 s[dirname_len] = '/';
1628 s[dirname_len+1] = '\0';
1629 } else {
1630 s = dirname;
1631 }
1632
1633 idx = zip_stat(intern, s, 0, &sb);
1634 if (idx >= 0) {
1635 RETVAL_FALSE;
1636 } else {
1637 if (zip_add_dir(intern, (const char *)s) == -1) {
1638 RETVAL_FALSE;
1639 }
1640 RETVAL_TRUE;
1641 }
1642
1643 if (s != dirname) {
1644 efree(s);
1645 }
1646 }
1647 /* }}} */
1648
php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS,int type)1649 static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1650 {
1651 struct zip *intern;
1652 zval *this = getThis();
1653 char *pattern;
1654 char *path = NULL;
1655 char *remove_path = NULL;
1656 char *add_path = NULL;
1657 int pattern_len, add_path_len = 0, remove_path_len = 0, path_len = 0;
1658 long remove_all_path = 0;
1659 long flags = 0;
1660 zval *options = NULL;
1661 int found;
1662
1663 if (!this) {
1664 RETURN_FALSE;
1665 }
1666
1667 ZIP_FROM_OBJECT(intern, this);
1668 /* 1 == glob, 2==pcre */
1669 if (type == 1) {
1670 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
1671 &pattern, &pattern_len, &flags, &options) == FAILURE) {
1672 return;
1673 }
1674 } else {
1675 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
1676 &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
1677 return;
1678 }
1679 }
1680
1681 if (pattern_len == 0) {
1682 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as pattern");
1683 RETURN_FALSE;
1684 }
1685 if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len,
1686 &add_path, &add_path_len TSRMLS_CC) < 0)) {
1687 RETURN_FALSE;
1688 }
1689
1690 if (remove_path && remove_path_len > 1 && (remove_path[strlen(remove_path) - 1] == '/' ||
1691 remove_path[strlen(remove_path) - 1] == '\\')) {
1692 remove_path[strlen(remove_path) - 1] = '\0';
1693 }
1694
1695 if (type == 1) {
1696 found = php_zip_glob(pattern, pattern_len, flags, return_value TSRMLS_CC);
1697 } else {
1698 found = php_zip_pcre(pattern, pattern_len, path, path_len, return_value TSRMLS_CC);
1699 }
1700
1701 if (found > 0) {
1702 int i;
1703 zval **zval_file = NULL;
1704
1705 for (i = 0; i < found; i++) {
1706 char *file, *file_stripped, *entry_name;
1707 size_t entry_name_len, file_stripped_len;
1708 char entry_name_buf[MAXPATHLEN];
1709 char *basename = NULL;
1710
1711 if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) {
1712 file = Z_STRVAL_PP(zval_file);
1713 if (remove_all_path) {
1714 php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0,
1715 &basename, (size_t *)&file_stripped_len TSRMLS_CC);
1716 file_stripped = basename;
1717 } else if (remove_path && strstr(Z_STRVAL_PP(zval_file), remove_path) != NULL) {
1718 file_stripped = Z_STRVAL_PP(zval_file) + remove_path_len + 1;
1719 file_stripped_len = Z_STRLEN_PP(zval_file) - remove_path_len - 1;
1720 } else {
1721 file_stripped = Z_STRVAL_PP(zval_file);
1722 file_stripped_len = Z_STRLEN_PP(zval_file);
1723 }
1724
1725 if (add_path) {
1726 if ((add_path_len + file_stripped_len) > MAXPATHLEN) {
1727 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)",
1728 MAXPATHLEN - 1, (add_path_len + file_stripped_len));
1729 zval_dtor(return_value);
1730 RETURN_FALSE;
1731 }
1732
1733 snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped);
1734 entry_name = entry_name_buf;
1735 entry_name_len = strlen(entry_name);
1736 } else {
1737 entry_name = Z_STRVAL_PP(zval_file);
1738 entry_name_len = Z_STRLEN_PP(zval_file);
1739 }
1740 if (basename) {
1741 efree(basename);
1742 basename = NULL;
1743 }
1744 if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file),
1745 entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
1746 zval_dtor(return_value);
1747 RETURN_FALSE;
1748 }
1749 }
1750 }
1751 }
1752 }
1753 /* }}} */
1754
1755 /* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]])
1756 Add files matching the glob pattern. See php's glob for the pattern syntax. */
ZIPARCHIVE_METHOD(addGlob)1757 static ZIPARCHIVE_METHOD(addGlob)
1758 {
1759 php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1760 }
1761 /* }}} */
1762
1763 /* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]])
1764 Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
ZIPARCHIVE_METHOD(addPattern)1765 static ZIPARCHIVE_METHOD(addPattern)
1766 {
1767 php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1768 }
1769 /* }}} */
1770
1771 /* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]])
1772 Add a file in a Zip archive using its path and the name to use. */
ZIPARCHIVE_METHOD(addFile)1773 static ZIPARCHIVE_METHOD(addFile)
1774 {
1775 struct zip *intern;
1776 zval *this = getThis();
1777 char *filename;
1778 int filename_len;
1779 char *entry_name = NULL;
1780 int entry_name_len = 0;
1781 long offset_start = 0, offset_len = 0;
1782
1783 if (!this) {
1784 RETURN_FALSE;
1785 }
1786
1787 ZIP_FROM_OBJECT(intern, this);
1788
1789 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll",
1790 &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
1791 return;
1792 }
1793
1794 if (filename_len == 0) {
1795 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as filename");
1796 RETURN_FALSE;
1797 }
1798
1799 if (entry_name_len == 0) {
1800 entry_name = filename;
1801 entry_name_len = filename_len;
1802 }
1803
1804 if (php_zip_add_file(intern, filename, filename_len,
1805 entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
1806 RETURN_FALSE;
1807 } else {
1808 RETURN_TRUE;
1809 }
1810 }
1811 /* }}} */
1812
1813 /* {{{ proto bool ZipArchive::addFromString(string name, string content)
1814 Add a file using content and the entry name */
ZIPARCHIVE_METHOD(addFromString)1815 static ZIPARCHIVE_METHOD(addFromString)
1816 {
1817 struct zip *intern;
1818 zval *this = getThis();
1819 char *buffer, *name;
1820 int buffer_len, name_len;
1821 ze_zip_object *ze_obj;
1822 struct zip_source *zs;
1823 int pos = 0;
1824 int cur_idx;
1825
1826 if (!this) {
1827 RETURN_FALSE;
1828 }
1829
1830 ZIP_FROM_OBJECT(intern, this);
1831
1832 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
1833 &name, &name_len, &buffer, &buffer_len) == FAILURE) {
1834 return;
1835 }
1836
1837 ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1838 if (ze_obj->buffers_cnt) {
1839 ze_obj->buffers = (char **)erealloc(ze_obj->buffers, sizeof(char *) * (ze_obj->buffers_cnt+1));
1840 pos = ze_obj->buffers_cnt++;
1841 } else {
1842 ze_obj->buffers = (char **)emalloc(sizeof(char *));
1843 ze_obj->buffers_cnt++;
1844 pos = 0;
1845 }
1846 ze_obj->buffers[pos] = (char *)emalloc(buffer_len + 1);
1847 memcpy(ze_obj->buffers[pos], buffer, buffer_len + 1);
1848
1849 zs = zip_source_buffer(intern, ze_obj->buffers[pos], buffer_len, 0);
1850
1851 if (zs == NULL) {
1852 RETURN_FALSE;
1853 }
1854
1855 cur_idx = zip_name_locate(intern, (const char *)name, 0);
1856 /* TODO: fix _zip_replace */
1857 if (cur_idx >= 0) {
1858 if (zip_delete(intern, cur_idx) == -1) {
1859 goto fail;
1860 }
1861 }
1862
1863 if (zip_add(intern, name, zs) != -1) {
1864 RETURN_TRUE;
1865 }
1866 fail:
1867 zip_source_free(zs);
1868 RETURN_FALSE;
1869 }
1870 /* }}} */
1871
1872 /* {{{ proto array ZipArchive::statName(string filename[, int flags])
1873 Returns the information about a the zip entry filename */
ZIPARCHIVE_METHOD(statName)1874 static ZIPARCHIVE_METHOD(statName)
1875 {
1876 struct zip *intern;
1877 zval *this = getThis();
1878 char *name;
1879 int name_len;
1880 long flags = 0;
1881 struct zip_stat sb;
1882
1883 if (!this) {
1884 RETURN_FALSE;
1885 }
1886
1887 ZIP_FROM_OBJECT(intern, this);
1888
1889 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
1890 &name, &name_len, &flags) == FAILURE) {
1891 return;
1892 }
1893
1894 PHP_ZIP_STAT_PATH(intern, name, name_len, flags, sb);
1895
1896 RETURN_SB(&sb);
1897 }
1898 /* }}} */
1899
1900 /* {{{ proto resource ZipArchive::statIndex(int index[, int flags])
1901 Returns the zip entry informations using its index */
ZIPARCHIVE_METHOD(statIndex)1902 static ZIPARCHIVE_METHOD(statIndex)
1903 {
1904 struct zip *intern;
1905 zval *this = getThis();
1906 long index, flags = 0;
1907
1908 struct zip_stat sb;
1909
1910 if (!this) {
1911 RETURN_FALSE;
1912 }
1913
1914 ZIP_FROM_OBJECT(intern, this);
1915
1916 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
1917 &index, &flags) == FAILURE) {
1918 return;
1919 }
1920
1921 if (zip_stat_index(intern, index, flags, &sb) != 0) {
1922 RETURN_FALSE;
1923 }
1924 RETURN_SB(&sb);
1925 }
1926 /* }}} */
1927
1928 /* {{{ proto int ZipArchive::locateName(string filename[, int flags])
1929 Returns the index of the entry named filename in the archive */
ZIPARCHIVE_METHOD(locateName)1930 static ZIPARCHIVE_METHOD(locateName)
1931 {
1932 struct zip *intern;
1933 zval *this = getThis();
1934 char *name;
1935 int name_len;
1936 long flags = 0;
1937 long idx = -1;
1938
1939 if (!this) {
1940 RETURN_FALSE;
1941 }
1942
1943 ZIP_FROM_OBJECT(intern, this);
1944
1945 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
1946 &name, &name_len, &flags) == FAILURE) {
1947 return;
1948 }
1949 if (name_len<1) {
1950 RETURN_FALSE;
1951 }
1952
1953 idx = (long)zip_name_locate(intern, (const char *)name, flags);
1954
1955 if (idx >= 0) {
1956 RETURN_LONG(idx);
1957 } else {
1958 RETURN_FALSE;
1959 }
1960 }
1961 /* }}} */
1962
1963 /* {{{ proto string ZipArchive::getNameIndex(int index [, int flags])
1964 Returns the name of the file at position index */
ZIPARCHIVE_METHOD(getNameIndex)1965 static ZIPARCHIVE_METHOD(getNameIndex)
1966 {
1967 struct zip *intern;
1968 zval *this = getThis();
1969 const char *name;
1970 long flags = 0, index = 0;
1971
1972 if (!this) {
1973 RETURN_FALSE;
1974 }
1975
1976 ZIP_FROM_OBJECT(intern, this);
1977
1978 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
1979 &index, &flags) == FAILURE) {
1980 return;
1981 }
1982
1983 name = zip_get_name(intern, (int) index, flags);
1984
1985 if (name) {
1986 RETVAL_STRING((char *)name, 1);
1987 } else {
1988 RETURN_FALSE;
1989 }
1990 }
1991 /* }}} */
1992
1993 /* {{{ proto bool ZipArchive::setArchiveComment(string comment)
1994 Set or remove (NULL/'') the comment of the archive */
ZIPARCHIVE_METHOD(setArchiveComment)1995 static ZIPARCHIVE_METHOD(setArchiveComment)
1996 {
1997 struct zip *intern;
1998 zval *this = getThis();
1999 int comment_len;
2000 char * comment;
2001
2002 if (!this) {
2003 RETURN_FALSE;
2004 }
2005
2006 ZIP_FROM_OBJECT(intern, this);
2007
2008 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &comment, &comment_len) == FAILURE) {
2009 return;
2010 }
2011 if (zip_set_archive_comment(intern, (const char *)comment, (int)comment_len)) {
2012 RETURN_FALSE;
2013 } else {
2014 RETURN_TRUE;
2015 }
2016 }
2017 /* }}} */
2018
2019 /* {{{ proto string ZipArchive::getArchiveComment([int flags])
2020 Returns the comment of an entry using its index */
ZIPARCHIVE_METHOD(getArchiveComment)2021 static ZIPARCHIVE_METHOD(getArchiveComment)
2022 {
2023 struct zip *intern;
2024 zval *this = getThis();
2025 long flags = 0;
2026 const char * comment;
2027 int comment_len = 0;
2028
2029 if (!this) {
2030 RETURN_FALSE;
2031 }
2032
2033 ZIP_FROM_OBJECT(intern, this);
2034
2035 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
2036 return;
2037 }
2038
2039 comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
2040 if(comment==NULL) {
2041 RETURN_FALSE;
2042 }
2043 RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2044 }
2045 /* }}} */
2046
2047 /* {{{ proto bool ZipArchive::setCommentName(string name, string comment)
2048 Set or remove (NULL/'') the comment of an entry using its Name */
ZIPARCHIVE_METHOD(setCommentName)2049 static ZIPARCHIVE_METHOD(setCommentName)
2050 {
2051 struct zip *intern;
2052 zval *this = getThis();
2053 int comment_len, name_len;
2054 char * comment, *name;
2055 int idx;
2056
2057 if (!this) {
2058 RETURN_FALSE;
2059 }
2060
2061 ZIP_FROM_OBJECT(intern, this);
2062
2063 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
2064 &name, &name_len, &comment, &comment_len) == FAILURE) {
2065 return;
2066 }
2067
2068 if (name_len < 1) {
2069 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
2070 }
2071
2072 idx = zip_name_locate(intern, name, 0);
2073 if (idx < 0) {
2074 RETURN_FALSE;
2075 }
2076 PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
2077 }
2078 /* }}} */
2079
2080 /* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment)
2081 Set or remove (NULL/'') the comment of an entry using its index */
ZIPARCHIVE_METHOD(setCommentIndex)2082 static ZIPARCHIVE_METHOD(setCommentIndex)
2083 {
2084 struct zip *intern;
2085 zval *this = getThis();
2086 long index;
2087 int comment_len;
2088 char * comment;
2089 struct zip_stat sb;
2090
2091 if (!this) {
2092 RETURN_FALSE;
2093 }
2094
2095 ZIP_FROM_OBJECT(intern, this);
2096
2097 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls",
2098 &index, &comment, &comment_len) == FAILURE) {
2099 return;
2100 }
2101
2102 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2103 PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
2104 }
2105 /* }}} */
2106
2107 /* {{{ proto string ZipArchive::getCommentName(string name[, int flags])
2108 Returns the comment of an entry using its name */
ZIPARCHIVE_METHOD(getCommentName)2109 static ZIPARCHIVE_METHOD(getCommentName)
2110 {
2111 struct zip *intern;
2112 zval *this = getThis();
2113 int name_len, idx;
2114 long flags = 0;
2115 int comment_len = 0;
2116 const char * comment;
2117 char *name;
2118
2119 if (!this) {
2120 RETURN_FALSE;
2121 }
2122
2123 ZIP_FROM_OBJECT(intern, this);
2124
2125 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
2126 &name, &name_len, &flags) == FAILURE) {
2127 return;
2128 }
2129 if (name_len < 1) {
2130 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
2131 RETURN_FALSE;
2132 }
2133
2134 idx = zip_name_locate(intern, name, 0);
2135 if (idx < 0) {
2136 RETURN_FALSE;
2137 }
2138
2139 comment = zip_get_file_comment(intern, idx, &comment_len, (int)flags);
2140 RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2141 }
2142 /* }}} */
2143
2144 /* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags])
2145 Returns the comment of an entry using its index */
ZIPARCHIVE_METHOD(getCommentIndex)2146 static ZIPARCHIVE_METHOD(getCommentIndex)
2147 {
2148 struct zip *intern;
2149 zval *this = getThis();
2150 long index, flags = 0;
2151 const char * comment;
2152 int comment_len = 0;
2153 struct zip_stat sb;
2154
2155 if (!this) {
2156 RETURN_FALSE;
2157 }
2158
2159 ZIP_FROM_OBJECT(intern, this);
2160
2161 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
2162 &index, &flags) == FAILURE) {
2163 return;
2164 }
2165
2166 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2167 comment = zip_get_file_comment(intern, index, &comment_len, (int)flags);
2168 RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2169 }
2170 /* }}} */
2171
2172 /* {{{ proto bool ZipArchive::deleteIndex(int index)
2173 Delete a file using its index */
ZIPARCHIVE_METHOD(deleteIndex)2174 static ZIPARCHIVE_METHOD(deleteIndex)
2175 {
2176 struct zip *intern;
2177 zval *this = getThis();
2178 long index;
2179
2180 if (!this) {
2181 RETURN_FALSE;
2182 }
2183
2184 ZIP_FROM_OBJECT(intern, this);
2185
2186 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
2187 return;
2188 }
2189
2190 if (index < 0) {
2191 RETURN_FALSE;
2192 }
2193
2194 if (zip_delete(intern, index) < 0) {
2195 RETURN_FALSE;
2196 }
2197
2198 RETURN_TRUE;
2199 }
2200 /* }}} */
2201
2202 /* {{{ proto bool ZipArchive::deleteName(string name)
2203 Delete a file using its index */
ZIPARCHIVE_METHOD(deleteName)2204 static ZIPARCHIVE_METHOD(deleteName)
2205 {
2206 struct zip *intern;
2207 zval *this = getThis();
2208 int name_len;
2209 char *name;
2210 struct zip_stat sb;
2211
2212 if (!this) {
2213 RETURN_FALSE;
2214 }
2215
2216 ZIP_FROM_OBJECT(intern, this);
2217
2218 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
2219 return;
2220 }
2221 if (name_len < 1) {
2222 RETURN_FALSE;
2223 }
2224
2225 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2226 if (zip_delete(intern, sb.index)) {
2227 RETURN_FALSE;
2228 }
2229 RETURN_TRUE;
2230 }
2231 /* }}} */
2232
2233 /* {{{ proto bool ZipArchive::renameIndex(int index, string new_name)
2234 Rename an entry selected by its index to new_name */
ZIPARCHIVE_METHOD(renameIndex)2235 static ZIPARCHIVE_METHOD(renameIndex)
2236 {
2237 struct zip *intern;
2238 zval *this = getThis();
2239
2240 char *new_name;
2241 int new_name_len;
2242 long index;
2243
2244 if (!this) {
2245 RETURN_FALSE;
2246 }
2247
2248 ZIP_FROM_OBJECT(intern, this);
2249
2250 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &index, &new_name, &new_name_len) == FAILURE) {
2251 return;
2252 }
2253
2254 if (index < 0) {
2255 RETURN_FALSE;
2256 }
2257
2258 if (new_name_len < 1) {
2259 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
2260 RETURN_FALSE;
2261 }
2262 if (zip_rename(intern, index, (const char *)new_name) != 0) {
2263 RETURN_FALSE;
2264 }
2265 RETURN_TRUE;
2266 }
2267 /* }}} */
2268
2269 /* {{{ proto bool ZipArchive::renameName(string name, string new_name)
2270 Rename an entry selected by its name to new_name */
ZIPARCHIVE_METHOD(renameName)2271 static ZIPARCHIVE_METHOD(renameName)
2272 {
2273 struct zip *intern;
2274 zval *this = getThis();
2275 struct zip_stat sb;
2276 char *name, *new_name;
2277 int name_len, new_name_len;
2278
2279 if (!this) {
2280 RETURN_FALSE;
2281 }
2282
2283 ZIP_FROM_OBJECT(intern, this);
2284
2285 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
2286 return;
2287 }
2288
2289 if (new_name_len < 1) {
2290 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
2291 RETURN_FALSE;
2292 }
2293
2294 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2295
2296 if (zip_rename(intern, sb.index, (const char *)new_name)) {
2297 RETURN_FALSE;
2298 }
2299 RETURN_TRUE;
2300 }
2301 /* }}} */
2302
2303 /* {{{ proto bool ZipArchive::unchangeIndex(int index)
2304 Changes to the file at position index are reverted */
ZIPARCHIVE_METHOD(unchangeIndex)2305 static ZIPARCHIVE_METHOD(unchangeIndex)
2306 {
2307 struct zip *intern;
2308 zval *this = getThis();
2309 long index;
2310
2311 if (!this) {
2312 RETURN_FALSE;
2313 }
2314
2315 ZIP_FROM_OBJECT(intern, this);
2316
2317 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
2318 return;
2319 }
2320
2321 if (index < 0) {
2322 RETURN_FALSE;
2323 }
2324
2325 if (zip_unchange(intern, index) != 0) {
2326 RETURN_FALSE;
2327 } else {
2328 RETURN_TRUE;
2329 }
2330 }
2331 /* }}} */
2332
2333 /* {{{ proto bool ZipArchive::unchangeName(string name)
2334 Changes to the file named 'name' are reverted */
ZIPARCHIVE_METHOD(unchangeName)2335 static ZIPARCHIVE_METHOD(unchangeName)
2336 {
2337 struct zip *intern;
2338 zval *this = getThis();
2339 struct zip_stat sb;
2340 char *name;
2341 int name_len;
2342
2343 if (!this) {
2344 RETURN_FALSE;
2345 }
2346
2347 ZIP_FROM_OBJECT(intern, this);
2348
2349 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
2350 return;
2351 }
2352
2353 if (name_len < 1) {
2354 RETURN_FALSE;
2355 }
2356
2357 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2358
2359 if (zip_unchange(intern, sb.index) != 0) {
2360 RETURN_FALSE;
2361 } else {
2362 RETURN_TRUE;
2363 }
2364 }
2365 /* }}} */
2366
2367 /* {{{ proto bool ZipArchive::unchangeAll()
2368 All changes to files and global information in archive are reverted */
ZIPARCHIVE_METHOD(unchangeAll)2369 static ZIPARCHIVE_METHOD(unchangeAll)
2370 {
2371 struct zip *intern;
2372 zval *this = getThis();
2373
2374 if (!this) {
2375 RETURN_FALSE;
2376 }
2377
2378 ZIP_FROM_OBJECT(intern, this);
2379
2380 if (zip_unchange_all(intern) != 0) {
2381 RETURN_FALSE;
2382 } else {
2383 RETURN_TRUE;
2384 }
2385 }
2386 /* }}} */
2387
2388 /* {{{ proto bool ZipArchive::unchangeArchive()
2389 Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */
ZIPARCHIVE_METHOD(unchangeArchive)2390 static ZIPARCHIVE_METHOD(unchangeArchive)
2391 {
2392 struct zip *intern;
2393 zval *this = getThis();
2394
2395 if (!this) {
2396 RETURN_FALSE;
2397 }
2398
2399 ZIP_FROM_OBJECT(intern, this);
2400
2401 if (zip_unchange_archive(intern) != 0) {
2402 RETURN_FALSE;
2403 } else {
2404 RETURN_TRUE;
2405 }
2406 }
2407 /* }}} */
2408
2409 /* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files])
2410 Extract one or more file from a zip archive */
2411 /* TODO:
2412 * - allow index or array of indeces
2413 * - replace path
2414 * - patterns
2415 */
ZIPARCHIVE_METHOD(extractTo)2416 static ZIPARCHIVE_METHOD(extractTo)
2417 {
2418 struct zip *intern;
2419
2420 zval *this = getThis();
2421 zval *zval_files = NULL;
2422 zval **zval_file = NULL;
2423 php_stream_statbuf ssb;
2424 char *pathto;
2425 int pathto_len;
2426 int ret, i;
2427
2428 int nelems;
2429
2430 if (!this) {
2431 RETURN_FALSE;
2432 }
2433
2434 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &pathto, &pathto_len, &zval_files) == FAILURE) {
2435 return;
2436 }
2437
2438 if (pathto_len < 1) {
2439 RETURN_FALSE;
2440 }
2441
2442 if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
2443 ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
2444 if (!ret) {
2445 RETURN_FALSE;
2446 }
2447 }
2448
2449 ZIP_FROM_OBJECT(intern, this);
2450 if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) {
2451 switch (Z_TYPE_P(zval_files)) {
2452 case IS_STRING:
2453 if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files) TSRMLS_CC)) {
2454 RETURN_FALSE;
2455 }
2456 break;
2457 case IS_ARRAY:
2458 nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
2459 if (nelems == 0 ) {
2460 RETURN_FALSE;
2461 }
2462 for (i = 0; i < nelems; i++) {
2463 if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
2464 switch (Z_TYPE_PP(zval_file)) {
2465 case IS_LONG:
2466 break;
2467 case IS_STRING:
2468 if (!php_zip_extract_file(intern, pathto, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file) TSRMLS_CC)) {
2469 RETURN_FALSE;
2470 }
2471 break;
2472 }
2473 }
2474 }
2475 break;
2476 case IS_LONG:
2477 default:
2478 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings");
2479 break;
2480 }
2481 } else {
2482 /* Extract all files */
2483 int filecount = zip_get_num_files(intern);
2484
2485 if (filecount == -1) {
2486 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive");
2487 RETURN_FALSE;
2488 }
2489
2490 for (i = 0; i < filecount; i++) {
2491 char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
2492 if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) {
2493 RETURN_FALSE;
2494 }
2495 }
2496 }
2497 RETURN_TRUE;
2498 }
2499 /* }}} */
2500
php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS,int type)2501 static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
2502 {
2503 struct zip *intern;
2504 zval *this = getThis();
2505
2506 struct zip_stat sb;
2507 struct zip_file *zf;
2508
2509 char *filename;
2510 int filename_len;
2511 long index = -1;
2512 long flags = 0;
2513 long len = 0;
2514
2515 char *buffer;
2516 int n = 0;
2517
2518 if (!this) {
2519 RETURN_FALSE;
2520 }
2521
2522 ZIP_FROM_OBJECT(intern, this);
2523
2524 if (type == 1) {
2525 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
2526 return;
2527 }
2528 PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb);
2529 } else {
2530 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &index, &len, &flags) == FAILURE) {
2531 return;
2532 }
2533 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2534 }
2535
2536 if (sb.size < 1) {
2537 RETURN_EMPTY_STRING();
2538 }
2539
2540 if (len < 1) {
2541 len = sb.size;
2542 }
2543 if (index >= 0) {
2544 zf = zip_fopen_index(intern, index, flags);
2545 } else {
2546 zf = zip_fopen(intern, filename, flags);
2547 }
2548
2549 if (zf == NULL) {
2550 RETURN_FALSE;
2551 }
2552
2553 buffer = safe_emalloc(len, 1, 2);
2554 n = zip_fread(zf, buffer, len);
2555 if (n < 1) {
2556 efree(buffer);
2557 RETURN_EMPTY_STRING();
2558 }
2559
2560 zip_fclose(zf);
2561 buffer[n] = 0;
2562 RETURN_STRINGL(buffer, n, 0);
2563 }
2564 /* }}} */
2565
2566 /* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]])
2567 get the contents of an entry using its name */
ZIPARCHIVE_METHOD(getFromName)2568 static ZIPARCHIVE_METHOD(getFromName)
2569 {
2570 php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2571 }
2572 /* }}} */
2573
2574 /* {{{ proto string ZipArchive::getFromIndex(int index[, int len [, int flags]])
2575 get the contents of an entry using its index */
ZIPARCHIVE_METHOD(getFromIndex)2576 static ZIPARCHIVE_METHOD(getFromIndex)
2577 {
2578 php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2579 }
2580 /* }}} */
2581
2582 /* {{{ proto resource ZipArchive::getStream(string entryname)
2583 get a stream for an entry using its name */
ZIPARCHIVE_METHOD(getStream)2584 static ZIPARCHIVE_METHOD(getStream)
2585 {
2586 struct zip *intern;
2587 zval *this = getThis();
2588 struct zip_stat sb;
2589 char *filename;
2590 int filename_len;
2591 char *mode = "rb";
2592 php_stream *stream;
2593 ze_zip_object *obj;
2594
2595 if (!this) {
2596 RETURN_FALSE;
2597 }
2598
2599 ZIP_FROM_OBJECT(intern, this);
2600
2601 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
2602 return;
2603 }
2604
2605 if (zip_stat(intern, filename, 0, &sb) != 0) {
2606 RETURN_FALSE;
2607 }
2608
2609 obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
2610
2611 stream = php_stream_zip_open(obj->filename, filename, mode STREAMS_CC TSRMLS_CC);
2612 if (stream) {
2613 php_stream_to_zval(stream, return_value);
2614 }
2615 }
2616 /* }}} */
2617
2618 /* {{{ arginfo */
2619 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1)
2620 ZEND_ARG_INFO(0, filename)
2621 ZEND_ARG_INFO(0, flags)
2622 ZEND_END_ARG_INFO()
2623
2624 ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0)
2625 ZEND_END_ARG_INFO()
2626
2627 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addemptydir, 0, 0, 1)
2628 ZEND_ARG_INFO(0, dirname)
2629 ZEND_END_ARG_INFO()
2630
2631 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addglob, 0, 0, 1)
2632 ZEND_ARG_INFO(0, pattern)
2633 ZEND_ARG_INFO(0, flags)
2634 ZEND_ARG_INFO(0, options)
2635 ZEND_END_ARG_INFO()
2636
2637 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addpattern, 0, 0, 1)
2638 ZEND_ARG_INFO(0, pattern)
2639 ZEND_ARG_INFO(0, path)
2640 ZEND_ARG_INFO(0, options)
2641 ZEND_END_ARG_INFO()
2642
2643 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfile, 0, 0, 1)
2644 ZEND_ARG_INFO(0, filepath)
2645 ZEND_ARG_INFO(0, entryname)
2646 ZEND_ARG_INFO(0, start)
2647 ZEND_ARG_INFO(0, length)
2648 ZEND_END_ARG_INFO()
2649
2650 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfromstring, 0, 0, 2)
2651 ZEND_ARG_INFO(0, name)
2652 ZEND_ARG_INFO(0, content)
2653 ZEND_END_ARG_INFO()
2654
2655 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statname, 0, 0, 1)
2656 ZEND_ARG_INFO(0, filename)
2657 ZEND_ARG_INFO(0, flags)
2658 ZEND_END_ARG_INFO()
2659
2660 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statindex, 0, 0, 1)
2661 ZEND_ARG_INFO(0, index)
2662 ZEND_ARG_INFO(0, flags)
2663 ZEND_END_ARG_INFO()
2664
2665 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setarchivecomment, 0, 0, 1)
2666 ZEND_ARG_INFO(0, comment)
2667 ZEND_END_ARG_INFO()
2668
2669 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentindex, 0, 0, 2)
2670 ZEND_ARG_INFO(0, index)
2671 ZEND_ARG_INFO(0, comment)
2672 ZEND_END_ARG_INFO()
2673
2674 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentname, 0, 0, 1)
2675 ZEND_ARG_INFO(0, name)
2676 ZEND_ARG_INFO(0, flags)
2677 ZEND_END_ARG_INFO()
2678
2679 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentindex, 0, 0, 1)
2680 ZEND_ARG_INFO(0, index)
2681 ZEND_ARG_INFO(0, flags)
2682 ZEND_END_ARG_INFO()
2683
2684 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renameindex, 0, 0, 2)
2685 ZEND_ARG_INFO(0, index)
2686 ZEND_ARG_INFO(0, new_name)
2687 ZEND_END_ARG_INFO()
2688
2689 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renamename, 0, 0, 2)
2690 ZEND_ARG_INFO(0, name)
2691 ZEND_ARG_INFO(0, new_name)
2692 ZEND_END_ARG_INFO()
2693
2694 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangeindex, 0, 0, 1)
2695 ZEND_ARG_INFO(0, index)
2696 ZEND_END_ARG_INFO()
2697
2698 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangename, 0, 0, 1)
2699 ZEND_ARG_INFO(0, name)
2700 ZEND_END_ARG_INFO()
2701
2702 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_extractto, 0, 0, 1)
2703 ZEND_ARG_INFO(0, pathto)
2704 ZEND_ARG_INFO(0, files)
2705 ZEND_END_ARG_INFO()
2706
2707 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromname, 0, 0, 1)
2708 ZEND_ARG_INFO(0, entryname)
2709 ZEND_ARG_INFO(0, len)
2710 ZEND_ARG_INFO(0, flags)
2711 ZEND_END_ARG_INFO()
2712
2713 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromindex, 0, 0, 1)
2714 ZEND_ARG_INFO(0, index)
2715 ZEND_ARG_INFO(0, len)
2716 ZEND_ARG_INFO(0, flags)
2717 ZEND_END_ARG_INFO()
2718
2719 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getarchivecomment, 0, 0, 0)
2720 ZEND_ARG_INFO(0, flags)
2721 ZEND_END_ARG_INFO()
2722
2723 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentname, 0, 0, 2)
2724 ZEND_ARG_INFO(0, name)
2725 ZEND_ARG_INFO(0, comment)
2726 ZEND_END_ARG_INFO()
2727
2728 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getstream, 0, 0, 1)
2729 ZEND_ARG_INFO(0, entryname)
2730 ZEND_END_ARG_INFO()
2731 /* }}} */
2732
2733 /* {{{ ze_zip_object_class_functions */
2734 static const zend_function_entry zip_class_functions[] = {
2735 ZIPARCHIVE_ME(open, arginfo_ziparchive_open, ZEND_ACC_PUBLIC)
2736 ZIPARCHIVE_ME(close, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2737 ZIPARCHIVE_ME(getStatusString, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2738 ZIPARCHIVE_ME(addEmptyDir, arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC)
2739 ZIPARCHIVE_ME(addFromString, arginfo_ziparchive_addfromstring, ZEND_ACC_PUBLIC)
2740 ZIPARCHIVE_ME(addFile, arginfo_ziparchive_addfile, ZEND_ACC_PUBLIC)
2741 ZIPARCHIVE_ME(addGlob, arginfo_ziparchive_addglob, ZEND_ACC_PUBLIC)
2742 ZIPARCHIVE_ME(addPattern, arginfo_ziparchive_addpattern, ZEND_ACC_PUBLIC)
2743 ZIPARCHIVE_ME(renameIndex, arginfo_ziparchive_renameindex, ZEND_ACC_PUBLIC)
2744 ZIPARCHIVE_ME(renameName, arginfo_ziparchive_renamename, ZEND_ACC_PUBLIC)
2745 ZIPARCHIVE_ME(setArchiveComment, arginfo_ziparchive_setarchivecomment, ZEND_ACC_PUBLIC)
2746 ZIPARCHIVE_ME(getArchiveComment, arginfo_ziparchive_getarchivecomment, ZEND_ACC_PUBLIC)
2747 ZIPARCHIVE_ME(setCommentIndex, arginfo_ziparchive_setcommentindex, ZEND_ACC_PUBLIC)
2748 ZIPARCHIVE_ME(setCommentName, arginfo_ziparchive_setcommentname, ZEND_ACC_PUBLIC)
2749 ZIPARCHIVE_ME(getCommentIndex, arginfo_ziparchive_getcommentindex, ZEND_ACC_PUBLIC)
2750 ZIPARCHIVE_ME(getCommentName, arginfo_ziparchive_getcommentname, ZEND_ACC_PUBLIC)
2751 ZIPARCHIVE_ME(deleteIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
2752 ZIPARCHIVE_ME(deleteName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
2753 ZIPARCHIVE_ME(statName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
2754 ZIPARCHIVE_ME(statIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
2755 ZIPARCHIVE_ME(locateName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
2756 ZIPARCHIVE_ME(getNameIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
2757 ZIPARCHIVE_ME(unchangeArchive, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2758 ZIPARCHIVE_ME(unchangeAll, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2759 ZIPARCHIVE_ME(unchangeIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
2760 ZIPARCHIVE_ME(unchangeName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
2761 ZIPARCHIVE_ME(extractTo, arginfo_ziparchive_extractto, ZEND_ACC_PUBLIC)
2762 ZIPARCHIVE_ME(getFromName, arginfo_ziparchive_getfromname, ZEND_ACC_PUBLIC)
2763 ZIPARCHIVE_ME(getFromIndex, arginfo_ziparchive_getfromindex, ZEND_ACC_PUBLIC)
2764 ZIPARCHIVE_ME(getStream, arginfo_ziparchive_getstream, ZEND_ACC_PUBLIC)
2765 {NULL, NULL, NULL}
2766 };
2767 /* }}} */
2768 #endif
2769
2770 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(zip)2771 static PHP_MINIT_FUNCTION(zip)
2772 {
2773 #ifdef PHP_ZIP_USE_OO
2774 zend_class_entry ce;
2775
2776 memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2777 zip_object_handlers.clone_obj = NULL;
2778 zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
2779
2780 zip_object_handlers.get_properties = php_zip_get_properties;
2781 zip_object_handlers.read_property = php_zip_read_property;
2782 zip_object_handlers.has_property = php_zip_has_property;
2783
2784 INIT_CLASS_ENTRY(ce, "ZipArchive", zip_class_functions);
2785 ce.create_object = php_zip_object_new;
2786 zip_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
2787
2788 zend_hash_init(&zip_prop_handlers, 0, NULL, NULL, 1);
2789 php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, NULL, IS_LONG TSRMLS_CC);
2790 php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG TSRMLS_CC);
2791 php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, NULL, IS_LONG TSRMLS_CC);
2792 php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC);
2793 php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC);
2794
2795 REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
2796 REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL);
2797 REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS);
2798 REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE);
2799
2800 REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE);
2801 REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
2802 REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
2803 REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
2804 REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
2805 REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);
2806 REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK);
2807 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1);
2808 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2);
2809 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3);
2810 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4);
2811 REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE);
2812 REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE);
2813 REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64);
2814 REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE);
2815 REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2);
2816 REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA);
2817 REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE);
2818 REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77);
2819 REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK);
2820 REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD);
2821
2822 /* Error code */
2823 REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */
2824 REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */
2825 REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */
2826 REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */
2827 REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */
2828 REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */
2829 REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */
2830 REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */
2831 REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */
2832 REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */
2833 REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */
2834 REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */
2835 REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */
2836 REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */
2837 REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */
2838 REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */
2839 REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */
2840 REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */
2841 REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */
2842 REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */
2843 REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */
2844 REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */
2845 REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */
2846 REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */
2847
2848 php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC);
2849 #endif
2850
2851 le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number);
2852 le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
2853
2854 return SUCCESS;
2855 }
2856 /* }}} */
2857
2858 /* {{{ PHP_MSHUTDOWN_FUNCTION
2859 */
PHP_MSHUTDOWN_FUNCTION(zip)2860 static PHP_MSHUTDOWN_FUNCTION(zip)
2861 {
2862 #ifdef PHP_ZIP_USE_OO
2863 zend_hash_destroy(&zip_prop_handlers);
2864 php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
2865 #endif
2866 return SUCCESS;
2867 }
2868 /* }}} */
2869
2870 /* {{{ PHP_MINFO_FUNCTION
2871 */
PHP_MINFO_FUNCTION(zip)2872 static PHP_MINFO_FUNCTION(zip)
2873 {
2874 php_info_print_table_start();
2875
2876 php_info_print_table_row(2, "Zip", "enabled");
2877 php_info_print_table_row(2, "Extension Version","$Id: 6c872ebfb022206b0cc2a183c7a388c7b6ad8685 $");
2878 php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING);
2879 php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
2880
2881 php_info_print_table_end();
2882 }
2883 /* }}} */
2884
2885 /*
2886 * Local variables:
2887 * tab-width: 4
2888 * c-basic-offset: 4
2889 * End:
2890 * vim600: noet sw=4 ts=4 fdm=marker
2891 * vim<600: noet sw=4 ts=4
2892 */
2893