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