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