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