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