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