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