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