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