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