xref: /PHP-5.4/ext/zip/php_zip.c (revision f9c2bf73)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2014 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: 6c872ebfb022206b0cc2a183c7a388c7b6ad8685 $ */
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 unitialized 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,const zend_literal * key TSRMLS_DC)872 static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, 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, 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_properties(zval * object TSRMLS_DC)1018 static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
1019 {
1020 	ze_zip_object *obj;
1021 	zip_prop_handler *hnd;
1022 	HashTable *props;
1023 	zval *val;
1024 	int ret;
1025 	char *key;
1026 	uint key_len;
1027 	HashPosition pos;
1028 	ulong num_key;
1029 
1030 	obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
1031 	props = zend_std_get_properties(object TSRMLS_CC);
1032 
1033 	if (obj->prop_handler == NULL) {
1034 		return NULL;
1035 	}
1036 	zend_hash_internal_pointer_reset_ex(obj->prop_handler, &pos);
1037 
1038 	while (zend_hash_get_current_data_ex(obj->prop_handler, (void**)&hnd, &pos) == SUCCESS) {
1039 		zend_hash_get_current_key_ex(obj->prop_handler, &key, &key_len, &num_key, 0, &pos);
1040 		MAKE_STD_ZVAL(val);
1041 		ret = php_zip_property_reader(obj, hnd, &val, 0 TSRMLS_CC);
1042 		if (ret != SUCCESS) {
1043 			val = EG(uninitialized_zval_ptr);
1044 		}
1045 		zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
1046 		zend_hash_move_forward_ex(obj->prop_handler, &pos);
1047 	}
1048 	return props;
1049 }
1050 /* }}} */
1051 
php_zip_object_free_storage(void * object TSRMLS_DC)1052 static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
1053 {
1054 	ze_zip_object * intern = (ze_zip_object *) object;
1055 	int i;
1056 
1057 	if (!intern) {
1058 		return;
1059 	}
1060 	if (intern->za) {
1061 		if (zip_close(intern->za) != 0) {
1062 			_zip_free(intern->za);
1063 		}
1064 		intern->za = NULL;
1065 	}
1066 
1067 	if (intern->buffers_cnt>0) {
1068 		for (i=0; i<intern->buffers_cnt; i++) {
1069 			efree(intern->buffers[i]);
1070 		}
1071 		efree(intern->buffers);
1072 	}
1073 
1074 	intern->za = NULL;
1075 
1076 #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)
1077 	zend_object_std_dtor(&intern->zo TSRMLS_CC);
1078 #else
1079 	if (intern->zo.guards) {
1080 		zend_hash_destroy(intern->zo.guards);
1081 		FREE_HASHTABLE(intern->zo.guards);
1082 	}
1083 
1084 	if (intern->zo.properties) {
1085 		zend_hash_destroy(intern->zo.properties);
1086 		FREE_HASHTABLE(intern->zo.properties);
1087 	}
1088 #endif
1089 
1090 	if (intern->filename) {
1091 		efree(intern->filename);
1092 	}
1093 	efree(intern);
1094 }
1095 /* }}} */
1096 
php_zip_object_new(zend_class_entry * class_type TSRMLS_DC)1097 static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
1098 {
1099 	ze_zip_object *intern;
1100 	zend_object_value retval;
1101 
1102 	intern = emalloc(sizeof(ze_zip_object));
1103 	memset(&intern->zo, 0, sizeof(zend_object));
1104 
1105 	intern->za = NULL;
1106 	intern->buffers = NULL;
1107 	intern->filename = NULL;
1108 	intern->buffers_cnt = 0;
1109 	intern->prop_handler = &zip_prop_handlers;
1110 
1111 #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2))
1112 	zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
1113 #else
1114 	ALLOC_HASHTABLE(intern->zo.properties);
1115   	zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
1116 	intern->zo.ce = class_type;
1117 #endif
1118 
1119 	object_properties_init(&intern->zo, class_type);
1120 
1121 	retval.handle = zend_objects_store_put(intern,
1122 						NULL,
1123 						(zend_objects_free_object_storage_t) php_zip_object_free_storage,
1124 						NULL TSRMLS_CC);
1125 
1126 	retval.handlers = (zend_object_handlers *) & zip_object_handlers;
1127 
1128 	return retval;
1129 }
1130 /* }}} */
1131 #endif
1132 
1133 /* {{{ Resource dtors */
1134 
1135 /* {{{ php_zip_free_dir */
php_zip_free_dir(zend_rsrc_list_entry * rsrc TSRMLS_DC)1136 static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1137 {
1138 	zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
1139 
1140 	if (zip_int) {
1141 		if (zip_int->za) {
1142 			if (zip_close(zip_int->za) != 0) {
1143 				_zip_free(zip_int->za);
1144 			}
1145 			zip_int->za = NULL;
1146 		}
1147 
1148 		efree(rsrc->ptr);
1149 
1150 		rsrc->ptr = NULL;
1151 	}
1152 }
1153 /* }}} */
1154 
1155 /* {{{ php_zip_free_entry */
php_zip_free_entry(zend_rsrc_list_entry * rsrc TSRMLS_DC)1156 static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1157 {
1158 	zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
1159 
1160 	if (zr_rsrc) {
1161 		if (zr_rsrc->zf) {
1162 			if (zr_rsrc->zf->za) {
1163 				zip_fclose(zr_rsrc->zf);
1164 			} else {
1165 				if (zr_rsrc->zf->src)
1166 					zip_source_free(zr_rsrc->zf->src);
1167 				free(zr_rsrc->zf);
1168 			}
1169 			zr_rsrc->zf = NULL;
1170 		}
1171 		efree(zr_rsrc);
1172 		rsrc->ptr = NULL;
1173 	}
1174 }
1175 /* }}} */
1176 
1177 /* }}}*/
1178 
1179 /* reset macro */
1180 
1181 /* {{{ function prototypes */
1182 static PHP_MINIT_FUNCTION(zip);
1183 static PHP_MSHUTDOWN_FUNCTION(zip);
1184 static PHP_MINFO_FUNCTION(zip);
1185 /* }}} */
1186 
1187 /* {{{ zip_module_entry
1188  */
1189 zend_module_entry zip_module_entry = {
1190 	STANDARD_MODULE_HEADER,
1191 	"zip",
1192 	zip_functions,
1193 	PHP_MINIT(zip),
1194 	PHP_MSHUTDOWN(zip),
1195 	NULL,
1196 	NULL,
1197 	PHP_MINFO(zip),
1198 	PHP_ZIP_VERSION_STRING,
1199 	STANDARD_MODULE_PROPERTIES
1200 };
1201 /* }}} */
1202 
1203 #ifdef COMPILE_DL_ZIP
1204 ZEND_GET_MODULE(zip)
1205 #endif
1206 /* set macro */
1207 
1208 /* {{{ proto resource zip_open(string filename)
1209 Create new zip using source uri for output */
PHP_NAMED_FUNCTION(zif_zip_open)1210 static PHP_NAMED_FUNCTION(zif_zip_open)
1211 {
1212 	char     *filename;
1213 	int       filename_len;
1214 	char resolved_path[MAXPATHLEN + 1];
1215 	zip_rsrc *rsrc_int;
1216 	int err = 0;
1217 
1218 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
1219 		return;
1220 	}
1221 
1222 	if (filename_len == 0) {
1223 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
1224 		RETURN_FALSE;
1225 	}
1226 
1227 	if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
1228 		RETURN_FALSE;
1229 	}
1230 
1231 	if(!expand_filepath(filename, resolved_path TSRMLS_CC)) {
1232 		RETURN_FALSE;
1233 	}
1234 
1235 	rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
1236 
1237 	rsrc_int->za = zip_open(resolved_path, 0, &err);
1238 	if (rsrc_int->za == NULL) {
1239 		efree(rsrc_int);
1240 		RETURN_LONG((long)err);
1241 	}
1242 
1243 	rsrc_int->index_current = 0;
1244 	rsrc_int->num_files = zip_get_num_files(rsrc_int->za);
1245 
1246 	ZEND_REGISTER_RESOURCE(return_value, rsrc_int, le_zip_dir);
1247 }
1248 /* }}} */
1249 
1250 /* {{{ proto void zip_close(resource zip)
1251    Close a Zip archive */
PHP_NAMED_FUNCTION(zif_zip_close)1252 static PHP_NAMED_FUNCTION(zif_zip_close)
1253 {
1254 	zval * zip;
1255 	zip_rsrc *z_rsrc = NULL;
1256 
1257 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip) == FAILURE) {
1258 		return;
1259 	}
1260 	ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
1261 
1262 	/* really close the zip will break BC :-D */
1263 	zend_list_delete(Z_LVAL_P(zip));
1264 }
1265 /* }}} */
1266 
1267 /* {{{ proto resource zip_read(resource zip)
1268    Returns the next file in the archive */
PHP_NAMED_FUNCTION(zif_zip_read)1269 static PHP_NAMED_FUNCTION(zif_zip_read)
1270 {
1271 	zval *zip_dp;
1272 	zip_read_rsrc *zr_rsrc;
1273 	int ret;
1274 	zip_rsrc *rsrc_int;
1275 
1276 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_dp) == FAILURE) {
1277 		return;
1278 	}
1279 	ZEND_FETCH_RESOURCE(rsrc_int, zip_rsrc *, &zip_dp, -1, le_zip_dir_name, le_zip_dir);
1280 
1281 	if (rsrc_int && rsrc_int->za) {
1282 		if (rsrc_int->index_current >= rsrc_int->num_files) {
1283 			RETURN_FALSE;
1284 		}
1285 
1286 		zr_rsrc = emalloc(sizeof(zip_read_rsrc));
1287 
1288 		ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
1289 
1290 		if (ret != 0) {
1291 			efree(zr_rsrc);
1292 			RETURN_FALSE;
1293 		}
1294 
1295 		zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
1296 		if (zr_rsrc->zf) {
1297 			rsrc_int->index_current++;
1298 			ZEND_REGISTER_RESOURCE(return_value, zr_rsrc, le_zip_entry);
1299 		} else {
1300 			efree(zr_rsrc);
1301 			RETURN_FALSE;
1302 		}
1303 
1304 	} else {
1305 		RETURN_FALSE;
1306 	}
1307 }
1308 /* }}} */
1309 
1310 /* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode])
1311    Open a Zip File, pointed by the resource entry */
1312 /* Dummy function to follow the old API */
PHP_NAMED_FUNCTION(zif_zip_entry_open)1313 static PHP_NAMED_FUNCTION(zif_zip_entry_open)
1314 {
1315 	zval * zip;
1316 	zval * zip_entry;
1317 	char *mode = NULL;
1318 	int mode_len = 0;
1319 	zip_read_rsrc * zr_rsrc;
1320 	zip_rsrc *z_rsrc;
1321 
1322 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
1323 		return;
1324 	}
1325 
1326 	ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1327 	ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
1328 
1329 	if (zr_rsrc->zf != NULL) {
1330 		RETURN_TRUE;
1331 	} else {
1332 		RETURN_FALSE;
1333 	}
1334 }
1335 /* }}} */
1336 
1337 /* {{{ proto bool zip_entry_close(resource zip_ent)
1338    Close a zip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_close)1339 static PHP_NAMED_FUNCTION(zif_zip_entry_close)
1340 {
1341 	zval * zip_entry;
1342 	zip_read_rsrc * zr_rsrc;
1343 
1344 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
1345 		return;
1346 	}
1347 
1348 	ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1349 
1350 	RETURN_BOOL(SUCCESS == zend_list_delete(Z_LVAL_P(zip_entry)));
1351 }
1352 /* }}} */
1353 
1354 /* {{{ proto mixed zip_entry_read(resource zip_entry [, int len])
1355    Read from an open directory entry */
PHP_NAMED_FUNCTION(zif_zip_entry_read)1356 static PHP_NAMED_FUNCTION(zif_zip_entry_read)
1357 {
1358 	zval * zip_entry;
1359 	long len = 0;
1360 	zip_read_rsrc * zr_rsrc;
1361 	char *buffer;
1362 	int n = 0;
1363 
1364 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zip_entry, &len) == FAILURE) {
1365 		return;
1366 	}
1367 
1368 	ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1369 
1370 	if (len <= 0) {
1371 		len = 1024;
1372 	}
1373 
1374 	if (zr_rsrc->zf) {
1375 		buffer = safe_emalloc(len, 1, 1);
1376 		n = zip_fread(zr_rsrc->zf, buffer, len);
1377 		if (n > 0) {
1378 			buffer[n] = 0;
1379 			RETURN_STRINGL(buffer, n, 0);
1380 		} else {
1381 			efree(buffer);
1382 			RETURN_EMPTY_STRING()
1383 		}
1384 	} else {
1385 		RETURN_FALSE;
1386 	}
1387 }
1388 /* }}} */
1389 
php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS,int opt)1390 static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
1391 {
1392 	zval * zip_entry;
1393 	zip_read_rsrc * zr_rsrc;
1394 
1395 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
1396 		return;
1397 	}
1398 
1399 	ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1400 
1401 	if (!zr_rsrc->zf) {
1402 		RETURN_FALSE;
1403 	}
1404 
1405 	switch (opt) {
1406 		case 0:
1407 			RETURN_STRING((char *)zr_rsrc->sb.name, 1);
1408 			break;
1409 		case 1:
1410 			RETURN_LONG((long) (zr_rsrc->sb.comp_size));
1411 			break;
1412 		case 2:
1413 			RETURN_LONG((long) (zr_rsrc->sb.size));
1414 			break;
1415 		case 3:
1416 			switch (zr_rsrc->sb.comp_method) {
1417 				case 0:
1418 					RETURN_STRING("stored", 1);
1419 					break;
1420 				case 1:
1421 					RETURN_STRING("shrunk", 1);
1422 					break;
1423 				case 2:
1424 				case 3:
1425 				case 4:
1426 				case 5:
1427 					RETURN_STRING("reduced", 1);
1428 					break;
1429 				case 6:
1430 					RETURN_STRING("imploded", 1);
1431 					break;
1432 				case 7:
1433 					RETURN_STRING("tokenized", 1);
1434 					break;
1435 				case 8:
1436 					RETURN_STRING("deflated", 1);
1437 					break;
1438 				case 9:
1439 					RETURN_STRING("deflatedX", 1);
1440 					break;
1441 				case 10:
1442 					RETURN_STRING("implodedX", 1);
1443 					break;
1444 				default:
1445 					RETURN_FALSE;
1446 			}
1447 			RETURN_LONG((long) (zr_rsrc->sb.comp_method));
1448 			break;
1449 	}
1450 
1451 }
1452 /* }}} */
1453 
1454 /* {{{ proto string zip_entry_name(resource zip_entry)
1455    Return the name given a ZZip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_name)1456 static PHP_NAMED_FUNCTION(zif_zip_entry_name)
1457 {
1458 	php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1459 }
1460 /* }}} */
1461 
1462 /* {{{ proto int zip_entry_compressedsize(resource zip_entry)
1463    Return the compressed size of a ZZip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)1464 static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)
1465 {
1466 	php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1467 }
1468 /* }}} */
1469 
1470 /* {{{ proto int zip_entry_filesize(resource zip_entry)
1471    Return the actual filesize of a ZZip entry */
PHP_NAMED_FUNCTION(zif_zip_entry_filesize)1472 static PHP_NAMED_FUNCTION(zif_zip_entry_filesize)
1473 {
1474 	php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1475 }
1476 /* }}} */
1477 
1478 /* {{{ proto string zip_entry_compressionmethod(resource zip_entry)
1479    Return a string containing the compression method used on a particular entry */
PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)1480 static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
1481 {
1482 	php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
1483 }
1484 /* }}} */
1485 
1486 #ifdef PHP_ZIP_USE_OO
1487 /* {{{ proto mixed ZipArchive::open(string source [, int flags])
1488 Create new zip using source uri for output, return TRUE on success or the error code */
ZIPARCHIVE_METHOD(open)1489 static ZIPARCHIVE_METHOD(open)
1490 {
1491 	struct zip *intern;
1492 	char *filename;
1493 	int filename_len;
1494 	int err = 0;
1495 	long flags = 0;
1496 	char resolved_path[MAXPATHLEN];
1497 
1498 	zval *this = getThis();
1499 	ze_zip_object *ze_obj = NULL;
1500 
1501 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) {
1502 		return;
1503 	}
1504 
1505 	if (this) {
1506 		/* We do not use ZIP_FROM_OBJECT, zip init function here */
1507 		ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1508 	}
1509 
1510 	if (filename_len == 0) {
1511 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
1512 		RETURN_FALSE;
1513 	}
1514 
1515 	if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
1516 		RETURN_FALSE;
1517 	}
1518 
1519 	if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
1520 		RETURN_FALSE;
1521 	}
1522 
1523 	if (ze_obj->za) {
1524 		/* we already have an opened zip, free it */
1525 		if (zip_close(ze_obj->za) != 0) {
1526 			_zip_free(ze_obj->za);
1527 		}
1528 		ze_obj->za = NULL;
1529 	}
1530 	if (ze_obj->filename) {
1531 		efree(ze_obj->filename);
1532 		ze_obj->filename = NULL;
1533 	}
1534 
1535 	intern = zip_open(resolved_path, flags, &err);
1536 	if (!intern || err) {
1537 		RETURN_LONG((long)err);
1538 	}
1539 	ze_obj->filename = estrdup(resolved_path);
1540 	ze_obj->filename_len = strlen(resolved_path);
1541 	ze_obj->za = intern;
1542 	RETURN_TRUE;
1543 }
1544 /* }}} */
1545 
1546 /* {{{ proto bool ZipArchive::close()
1547 close the zip archive */
ZIPARCHIVE_METHOD(close)1548 static ZIPARCHIVE_METHOD(close)
1549 {
1550 	struct zip *intern;
1551 	zval *this = getThis();
1552 	ze_zip_object *ze_obj;
1553 
1554 	if (!this) {
1555 			RETURN_FALSE;
1556 	}
1557 
1558 	ZIP_FROM_OBJECT(intern, this);
1559 
1560 	ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1561 
1562 	if (zip_close(intern)) {
1563 		RETURN_FALSE;
1564 	}
1565 
1566 	efree(ze_obj->filename);
1567 	ze_obj->filename = NULL;
1568 	ze_obj->filename_len = 0;
1569 	ze_obj->za = NULL;
1570 
1571 	RETURN_TRUE;
1572 }
1573 /* }}} */
1574 
1575 /* {{{ proto string ZipArchive::getStatusString()
1576  * Returns the status error message, system and/or zip messages */
ZIPARCHIVE_METHOD(getStatusString)1577 static ZIPARCHIVE_METHOD(getStatusString)
1578 {
1579 	struct zip *intern;
1580 	zval *this = getThis();
1581 	int zep, syp, len;
1582 	char error_string[128];
1583 
1584 	if (!this) {
1585 		RETURN_FALSE;
1586 	}
1587 
1588 	ZIP_FROM_OBJECT(intern, this);
1589 
1590 	zip_error_get(intern, &zep, &syp);
1591 
1592 	len = zip_error_to_str(error_string, 128, zep, syp);
1593 	RETVAL_STRINGL(error_string, len, 1);
1594 }
1595 /* }}} */
1596 
1597 /* {{{ proto bool ZipArchive::createEmptyDir(string dirname)
1598 Returns the index of the entry named filename in the archive */
ZIPARCHIVE_METHOD(addEmptyDir)1599 static ZIPARCHIVE_METHOD(addEmptyDir)
1600 {
1601 	struct zip *intern;
1602 	zval *this = getThis();
1603 	char *dirname;
1604 	int   dirname_len;
1605 	int idx;
1606 	struct zip_stat sb;
1607 	char *s;
1608 
1609 	if (!this) {
1610 		RETURN_FALSE;
1611 	}
1612 
1613 	ZIP_FROM_OBJECT(intern, this);
1614 
1615 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
1616 				&dirname, &dirname_len) == FAILURE) {
1617 		return;
1618 	}
1619 
1620 	if (dirname_len<1) {
1621 		RETURN_FALSE;
1622 	}
1623 
1624 	if (dirname[dirname_len-1] != '/') {
1625 		s=(char *)emalloc(dirname_len+2);
1626 		strcpy(s, dirname);
1627 		s[dirname_len] = '/';
1628 		s[dirname_len+1] = '\0';
1629 	} else {
1630 		s = dirname;
1631 	}
1632 
1633 	idx = zip_stat(intern, s, 0, &sb);
1634 	if (idx >= 0) {
1635 		RETVAL_FALSE;
1636 	} else {
1637 		if (zip_add_dir(intern, (const char *)s) == -1) {
1638 			RETVAL_FALSE;
1639 		}
1640 		RETVAL_TRUE;
1641 	}
1642 
1643 	if (s != dirname) {
1644 		efree(s);
1645 	}
1646 }
1647 /* }}} */
1648 
php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS,int type)1649 static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1650 {
1651 	struct zip *intern;
1652 	zval *this = getThis();
1653 	char *pattern;
1654 	char *path = NULL;
1655 	char *remove_path = NULL;
1656 	char *add_path = NULL;
1657 	int pattern_len, add_path_len = 0, remove_path_len = 0, path_len = 0;
1658 	long remove_all_path = 0;
1659 	long flags = 0;
1660 	zval *options = NULL;
1661 	int found;
1662 
1663 	if (!this) {
1664 		RETURN_FALSE;
1665 	}
1666 
1667 	ZIP_FROM_OBJECT(intern, this);
1668 	/* 1 == glob, 2==pcre */
1669 	if (type == 1) {
1670 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
1671 					&pattern, &pattern_len, &flags, &options) == FAILURE) {
1672 			return;
1673 		}
1674 	} else {
1675 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
1676 					&pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
1677 			return;
1678 		}
1679 	}
1680 
1681 	if (pattern_len == 0) {
1682 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as pattern");
1683 		RETURN_FALSE;
1684 	}
1685 	if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len,
1686 			&add_path, &add_path_len TSRMLS_CC) < 0)) {
1687 		RETURN_FALSE;
1688 	}
1689 
1690 	if (remove_path && remove_path_len > 1 && (remove_path[strlen(remove_path) - 1] == '/' ||
1691 		remove_path[strlen(remove_path) - 1] == '\\')) {
1692 		remove_path[strlen(remove_path) - 1] = '\0';
1693 	}
1694 
1695 	if (type == 1) {
1696 		found = php_zip_glob(pattern, pattern_len, flags, return_value TSRMLS_CC);
1697 	} else {
1698 		found = php_zip_pcre(pattern, pattern_len, path, path_len, return_value TSRMLS_CC);
1699 	}
1700 
1701 	if (found > 0) {
1702 		int i;
1703 		zval **zval_file = NULL;
1704 
1705 		for (i = 0; i < found; i++) {
1706 			char *file, *file_stripped, *entry_name;
1707 			size_t entry_name_len, file_stripped_len;
1708 			char entry_name_buf[MAXPATHLEN];
1709 			char *basename = NULL;
1710 
1711 			if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) {
1712 				file = Z_STRVAL_PP(zval_file);
1713 				if (remove_all_path) {
1714 					php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0,
1715 									&basename, (size_t *)&file_stripped_len TSRMLS_CC);
1716 					file_stripped = basename;
1717 				} else if (remove_path && strstr(Z_STRVAL_PP(zval_file), remove_path) != NULL) {
1718 					file_stripped = Z_STRVAL_PP(zval_file) + remove_path_len + 1;
1719 					file_stripped_len = Z_STRLEN_PP(zval_file) - remove_path_len - 1;
1720 				} else {
1721 					file_stripped = Z_STRVAL_PP(zval_file);
1722 					file_stripped_len = Z_STRLEN_PP(zval_file);
1723 				}
1724 
1725 				if (add_path) {
1726 					if ((add_path_len + file_stripped_len) > MAXPATHLEN) {
1727 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)",
1728 						MAXPATHLEN - 1, (add_path_len + file_stripped_len));
1729 						zval_dtor(return_value);
1730 						RETURN_FALSE;
1731 					}
1732 
1733 					snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped);
1734 					entry_name = entry_name_buf;
1735 					entry_name_len = strlen(entry_name);
1736 				} else {
1737 					entry_name = Z_STRVAL_PP(zval_file);
1738 					entry_name_len = Z_STRLEN_PP(zval_file);
1739 				}
1740 				if (basename) {
1741 					efree(basename);
1742 					basename = NULL;
1743 				}
1744 				if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file),
1745 					entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
1746 					zval_dtor(return_value);
1747 					RETURN_FALSE;
1748 				}
1749 			}
1750 		}
1751 	}
1752 }
1753 /* }}} */
1754 
1755 /* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]])
1756 Add files matching the glob pattern. See php's glob for the pattern syntax. */
ZIPARCHIVE_METHOD(addGlob)1757 static ZIPARCHIVE_METHOD(addGlob)
1758 {
1759 	php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1760 }
1761 /* }}} */
1762 
1763 /* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]])
1764 Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
ZIPARCHIVE_METHOD(addPattern)1765 static ZIPARCHIVE_METHOD(addPattern)
1766 {
1767 	php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1768 }
1769 /* }}} */
1770 
1771 /* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]])
1772 Add a file in a Zip archive using its path and the name to use. */
ZIPARCHIVE_METHOD(addFile)1773 static ZIPARCHIVE_METHOD(addFile)
1774 {
1775 	struct zip *intern;
1776 	zval *this = getThis();
1777 	char *filename;
1778 	int filename_len;
1779 	char *entry_name = NULL;
1780 	int entry_name_len = 0;
1781 	long offset_start = 0, offset_len = 0;
1782 
1783 	if (!this) {
1784 		RETURN_FALSE;
1785 	}
1786 
1787 	ZIP_FROM_OBJECT(intern, this);
1788 
1789 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll",
1790 			&filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
1791 		return;
1792 	}
1793 
1794 	if (filename_len == 0) {
1795 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as filename");
1796 		RETURN_FALSE;
1797 	}
1798 
1799 	if (entry_name_len == 0) {
1800 		entry_name = filename;
1801 		entry_name_len = filename_len;
1802 	}
1803 
1804 	if (php_zip_add_file(intern, filename, filename_len,
1805 		entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
1806 		RETURN_FALSE;
1807 	} else {
1808 		RETURN_TRUE;
1809 	}
1810 }
1811 /* }}} */
1812 
1813 /* {{{ proto bool ZipArchive::addFromString(string name, string content)
1814 Add a file using content and the entry name */
ZIPARCHIVE_METHOD(addFromString)1815 static ZIPARCHIVE_METHOD(addFromString)
1816 {
1817 	struct zip *intern;
1818 	zval *this = getThis();
1819 	char *buffer, *name;
1820 	int buffer_len, name_len;
1821 	ze_zip_object *ze_obj;
1822 	struct zip_source *zs;
1823 	int pos = 0;
1824 	int cur_idx;
1825 
1826 	if (!this) {
1827 		RETURN_FALSE;
1828 	}
1829 
1830 	ZIP_FROM_OBJECT(intern, this);
1831 
1832 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
1833 			&name, &name_len, &buffer, &buffer_len) == FAILURE) {
1834 		return;
1835 	}
1836 
1837 	ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1838 	if (ze_obj->buffers_cnt) {
1839 		ze_obj->buffers = (char **)erealloc(ze_obj->buffers, sizeof(char *) * (ze_obj->buffers_cnt+1));
1840 		pos = ze_obj->buffers_cnt++;
1841 	} else {
1842 		ze_obj->buffers = (char **)emalloc(sizeof(char *));
1843 		ze_obj->buffers_cnt++;
1844 		pos = 0;
1845 	}
1846 	ze_obj->buffers[pos] = (char *)emalloc(buffer_len + 1);
1847 	memcpy(ze_obj->buffers[pos], buffer, buffer_len + 1);
1848 
1849 	zs = zip_source_buffer(intern, ze_obj->buffers[pos], buffer_len, 0);
1850 
1851 	if (zs == NULL) {
1852 		RETURN_FALSE;
1853 	}
1854 
1855 	cur_idx = zip_name_locate(intern, (const char *)name, 0);
1856 	/* TODO: fix  _zip_replace */
1857 	if (cur_idx >= 0) {
1858 		if (zip_delete(intern, cur_idx) == -1) {
1859 			goto fail;
1860 		}
1861 	}
1862 
1863 	if (zip_add(intern, name, zs) != -1) {
1864 		RETURN_TRUE;
1865 	}
1866 fail:
1867 	zip_source_free(zs);
1868 	RETURN_FALSE;
1869 }
1870 /* }}} */
1871 
1872 /* {{{ proto array ZipArchive::statName(string filename[, int flags])
1873 Returns the information about a the zip entry filename */
ZIPARCHIVE_METHOD(statName)1874 static ZIPARCHIVE_METHOD(statName)
1875 {
1876 	struct zip *intern;
1877 	zval *this = getThis();
1878 	char *name;
1879 	int name_len;
1880 	long flags = 0;
1881 	struct zip_stat sb;
1882 
1883 	if (!this) {
1884 		RETURN_FALSE;
1885 	}
1886 
1887 	ZIP_FROM_OBJECT(intern, this);
1888 
1889 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
1890 			&name, &name_len, &flags) == FAILURE) {
1891 		return;
1892 	}
1893 
1894 	PHP_ZIP_STAT_PATH(intern, name, name_len, flags, sb);
1895 
1896 	RETURN_SB(&sb);
1897 }
1898 /* }}} */
1899 
1900 /* {{{ proto resource ZipArchive::statIndex(int index[, int flags])
1901 Returns the zip entry informations using its index */
ZIPARCHIVE_METHOD(statIndex)1902 static ZIPARCHIVE_METHOD(statIndex)
1903 {
1904 	struct zip *intern;
1905 	zval *this = getThis();
1906 	long index, flags = 0;
1907 
1908 	struct zip_stat sb;
1909 
1910 	if (!this) {
1911 		RETURN_FALSE;
1912 	}
1913 
1914 	ZIP_FROM_OBJECT(intern, this);
1915 
1916 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
1917 			&index, &flags) == FAILURE) {
1918 		return;
1919 	}
1920 
1921 	if (zip_stat_index(intern, index, flags, &sb) != 0) {
1922 		RETURN_FALSE;
1923 	}
1924 	RETURN_SB(&sb);
1925 }
1926 /* }}} */
1927 
1928 /* {{{ proto int ZipArchive::locateName(string filename[, int flags])
1929 Returns the index of the entry named filename in the archive */
ZIPARCHIVE_METHOD(locateName)1930 static ZIPARCHIVE_METHOD(locateName)
1931 {
1932 	struct zip *intern;
1933 	zval *this = getThis();
1934 	char *name;
1935 	int name_len;
1936 	long flags = 0;
1937 	long idx = -1;
1938 
1939 	if (!this) {
1940 		RETURN_FALSE;
1941 	}
1942 
1943 	ZIP_FROM_OBJECT(intern, this);
1944 
1945 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
1946 			&name, &name_len, &flags) == FAILURE) {
1947 		return;
1948 	}
1949 	if (name_len<1) {
1950 		RETURN_FALSE;
1951 	}
1952 
1953 	idx = (long)zip_name_locate(intern, (const char *)name, flags);
1954 
1955 	if (idx >= 0) {
1956 		RETURN_LONG(idx);
1957 	} else {
1958 		RETURN_FALSE;
1959 	}
1960 }
1961 /* }}} */
1962 
1963 /* {{{ proto string ZipArchive::getNameIndex(int index [, int flags])
1964 Returns the name of the file at position index */
ZIPARCHIVE_METHOD(getNameIndex)1965 static ZIPARCHIVE_METHOD(getNameIndex)
1966 {
1967 	struct zip *intern;
1968 	zval *this = getThis();
1969 	const char *name;
1970 	long flags = 0, index = 0;
1971 
1972 	if (!this) {
1973 		RETURN_FALSE;
1974 	}
1975 
1976 	ZIP_FROM_OBJECT(intern, this);
1977 
1978 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
1979 			&index, &flags) == FAILURE) {
1980 		return;
1981 	}
1982 
1983 	name = zip_get_name(intern, (int) index, flags);
1984 
1985 	if (name) {
1986 		RETVAL_STRING((char *)name, 1);
1987 	} else {
1988 		RETURN_FALSE;
1989 	}
1990 }
1991 /* }}} */
1992 
1993 /* {{{ proto bool ZipArchive::setArchiveComment(string comment)
1994 Set or remove (NULL/'') the comment of the archive */
ZIPARCHIVE_METHOD(setArchiveComment)1995 static ZIPARCHIVE_METHOD(setArchiveComment)
1996 {
1997 	struct zip *intern;
1998 	zval *this = getThis();
1999 	int comment_len;
2000 	char * comment;
2001 
2002 	if (!this) {
2003 		RETURN_FALSE;
2004 	}
2005 
2006 	ZIP_FROM_OBJECT(intern, this);
2007 
2008 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &comment, &comment_len) == FAILURE) {
2009 		return;
2010 	}
2011 	if (zip_set_archive_comment(intern, (const char *)comment, (int)comment_len)) {
2012 		RETURN_FALSE;
2013 	} else {
2014 		RETURN_TRUE;
2015 	}
2016 }
2017 /* }}} */
2018 
2019 /* {{{ proto string ZipArchive::getArchiveComment([int flags])
2020 Returns the comment of an entry using its index */
ZIPARCHIVE_METHOD(getArchiveComment)2021 static ZIPARCHIVE_METHOD(getArchiveComment)
2022 {
2023 	struct zip *intern;
2024 	zval *this = getThis();
2025 	long flags = 0;
2026 	const char * comment;
2027 	int comment_len = 0;
2028 
2029 	if (!this) {
2030 		RETURN_FALSE;
2031 	}
2032 
2033 	ZIP_FROM_OBJECT(intern, this);
2034 
2035 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
2036 		return;
2037 	}
2038 
2039 	comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
2040 	if(comment==NULL) {
2041 		RETURN_FALSE;
2042 	}
2043 	RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2044 }
2045 /* }}} */
2046 
2047 /* {{{ proto bool ZipArchive::setCommentName(string name, string comment)
2048 Set or remove (NULL/'') the comment of an entry using its Name */
ZIPARCHIVE_METHOD(setCommentName)2049 static ZIPARCHIVE_METHOD(setCommentName)
2050 {
2051 	struct zip *intern;
2052 	zval *this = getThis();
2053 	int comment_len, name_len;
2054 	char * comment, *name;
2055 	int idx;
2056 
2057 	if (!this) {
2058 		RETURN_FALSE;
2059 	}
2060 
2061 	ZIP_FROM_OBJECT(intern, this);
2062 
2063 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
2064 			&name, &name_len, &comment, &comment_len) == FAILURE) {
2065 		return;
2066 	}
2067 
2068 	if (name_len < 1) {
2069 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
2070 	}
2071 
2072 	idx = zip_name_locate(intern, name, 0);
2073 	if (idx < 0) {
2074 		RETURN_FALSE;
2075 	}
2076 	PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
2077 }
2078 /* }}} */
2079 
2080 /* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment)
2081 Set or remove (NULL/'') the comment of an entry using its index */
ZIPARCHIVE_METHOD(setCommentIndex)2082 static ZIPARCHIVE_METHOD(setCommentIndex)
2083 {
2084 	struct zip *intern;
2085 	zval *this = getThis();
2086 	long index;
2087 	int comment_len;
2088 	char * comment;
2089 	struct zip_stat sb;
2090 
2091 	if (!this) {
2092 		RETURN_FALSE;
2093 	}
2094 
2095 	ZIP_FROM_OBJECT(intern, this);
2096 
2097 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls",
2098 			&index, &comment, &comment_len) == FAILURE) {
2099 		return;
2100 	}
2101 
2102 	PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2103 	PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
2104 }
2105 /* }}} */
2106 
2107 /* {{{ proto string ZipArchive::getCommentName(string name[, int flags])
2108 Returns the comment of an entry using its name */
ZIPARCHIVE_METHOD(getCommentName)2109 static ZIPARCHIVE_METHOD(getCommentName)
2110 {
2111 	struct zip *intern;
2112 	zval *this = getThis();
2113 	int name_len, idx;
2114 	long flags = 0;
2115 	int comment_len = 0;
2116 	const char * comment;
2117 	char *name;
2118 
2119 	if (!this) {
2120 		RETURN_FALSE;
2121 	}
2122 
2123 	ZIP_FROM_OBJECT(intern, this);
2124 
2125 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
2126 			&name, &name_len, &flags) == FAILURE) {
2127 		return;
2128 	}
2129 	if (name_len < 1) {
2130 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
2131 		RETURN_FALSE;
2132 	}
2133 
2134 	idx = zip_name_locate(intern, name, 0);
2135 	if (idx < 0) {
2136 		RETURN_FALSE;
2137 	}
2138 
2139 	comment = zip_get_file_comment(intern, idx, &comment_len, (int)flags);
2140 	RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2141 }
2142 /* }}} */
2143 
2144 /* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags])
2145 Returns the comment of an entry using its index */
ZIPARCHIVE_METHOD(getCommentIndex)2146 static ZIPARCHIVE_METHOD(getCommentIndex)
2147 {
2148 	struct zip *intern;
2149 	zval *this = getThis();
2150 	long index, flags = 0;
2151 	const char * comment;
2152 	int comment_len = 0;
2153 	struct zip_stat sb;
2154 
2155 	if (!this) {
2156 		RETURN_FALSE;
2157 	}
2158 
2159 	ZIP_FROM_OBJECT(intern, this);
2160 
2161 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
2162 				&index, &flags) == FAILURE) {
2163 		return;
2164 	}
2165 
2166 	PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2167 	comment = zip_get_file_comment(intern, index, &comment_len, (int)flags);
2168 	RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2169 }
2170 /* }}} */
2171 
2172 /* {{{ proto bool ZipArchive::deleteIndex(int index)
2173 Delete a file using its index */
ZIPARCHIVE_METHOD(deleteIndex)2174 static ZIPARCHIVE_METHOD(deleteIndex)
2175 {
2176 	struct zip *intern;
2177 	zval *this = getThis();
2178 	long index;
2179 
2180 	if (!this) {
2181 		RETURN_FALSE;
2182 	}
2183 
2184 	ZIP_FROM_OBJECT(intern, this);
2185 
2186 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
2187 		return;
2188 	}
2189 
2190 	if (index < 0) {
2191 		RETURN_FALSE;
2192 	}
2193 
2194 	if (zip_delete(intern, index) < 0) {
2195 		RETURN_FALSE;
2196 	}
2197 
2198 	RETURN_TRUE;
2199 }
2200 /* }}} */
2201 
2202 /* {{{ proto bool ZipArchive::deleteName(string name)
2203 Delete a file using its index */
ZIPARCHIVE_METHOD(deleteName)2204 static ZIPARCHIVE_METHOD(deleteName)
2205 {
2206 	struct zip *intern;
2207 	zval *this = getThis();
2208 	int name_len;
2209 	char *name;
2210 	struct zip_stat sb;
2211 
2212 	if (!this) {
2213 		RETURN_FALSE;
2214 	}
2215 
2216 	ZIP_FROM_OBJECT(intern, this);
2217 
2218 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
2219 		return;
2220 	}
2221 	if (name_len < 1) {
2222 		RETURN_FALSE;
2223 	}
2224 
2225 	PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2226 	if (zip_delete(intern, sb.index)) {
2227 		RETURN_FALSE;
2228 	}
2229 	RETURN_TRUE;
2230 }
2231 /* }}} */
2232 
2233 /* {{{ proto bool ZipArchive::renameIndex(int index, string new_name)
2234 Rename an entry selected by its index to new_name */
ZIPARCHIVE_METHOD(renameIndex)2235 static ZIPARCHIVE_METHOD(renameIndex)
2236 {
2237 	struct zip *intern;
2238 	zval *this = getThis();
2239 
2240 	char *new_name;
2241 	int new_name_len;
2242 	long index;
2243 
2244 	if (!this) {
2245 		RETURN_FALSE;
2246 	}
2247 
2248 	ZIP_FROM_OBJECT(intern, this);
2249 
2250 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &index, &new_name, &new_name_len) == FAILURE) {
2251 		return;
2252 	}
2253 
2254 	if (index < 0) {
2255 		RETURN_FALSE;
2256 	}
2257 
2258 	if (new_name_len < 1) {
2259 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
2260 		RETURN_FALSE;
2261 	}
2262 	if (zip_rename(intern, index, (const char *)new_name) != 0) {
2263 		RETURN_FALSE;
2264 	}
2265 	RETURN_TRUE;
2266 }
2267 /* }}} */
2268 
2269 /* {{{ proto bool ZipArchive::renameName(string name, string new_name)
2270 Rename an entry selected by its name to new_name */
ZIPARCHIVE_METHOD(renameName)2271 static ZIPARCHIVE_METHOD(renameName)
2272 {
2273 	struct zip *intern;
2274 	zval *this = getThis();
2275 	struct zip_stat sb;
2276 	char *name, *new_name;
2277 	int name_len, new_name_len;
2278 
2279 	if (!this) {
2280 		RETURN_FALSE;
2281 	}
2282 
2283 	ZIP_FROM_OBJECT(intern, this);
2284 
2285 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
2286 		return;
2287 	}
2288 
2289 	if (new_name_len < 1) {
2290 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
2291 		RETURN_FALSE;
2292 	}
2293 
2294 	PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2295 
2296 	if (zip_rename(intern, sb.index, (const char *)new_name)) {
2297 		RETURN_FALSE;
2298 	}
2299 	RETURN_TRUE;
2300 }
2301 /* }}} */
2302 
2303 /* {{{ proto bool ZipArchive::unchangeIndex(int index)
2304 Changes to the file at position index are reverted */
ZIPARCHIVE_METHOD(unchangeIndex)2305 static ZIPARCHIVE_METHOD(unchangeIndex)
2306 {
2307 	struct zip *intern;
2308 	zval *this = getThis();
2309 	long index;
2310 
2311 	if (!this) {
2312 		RETURN_FALSE;
2313 	}
2314 
2315 	ZIP_FROM_OBJECT(intern, this);
2316 
2317 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
2318 		return;
2319 	}
2320 
2321 	if (index < 0) {
2322 		RETURN_FALSE;
2323 	}
2324 
2325 	if (zip_unchange(intern, index) != 0) {
2326 		RETURN_FALSE;
2327 	} else {
2328 		RETURN_TRUE;
2329 	}
2330 }
2331 /* }}} */
2332 
2333 /* {{{ proto bool ZipArchive::unchangeName(string name)
2334 Changes to the file named 'name' are reverted */
ZIPARCHIVE_METHOD(unchangeName)2335 static ZIPARCHIVE_METHOD(unchangeName)
2336 {
2337 	struct zip *intern;
2338 	zval *this = getThis();
2339 	struct zip_stat sb;
2340 	char *name;
2341 	int name_len;
2342 
2343 	if (!this) {
2344 		RETURN_FALSE;
2345 	}
2346 
2347 	ZIP_FROM_OBJECT(intern, this);
2348 
2349 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
2350 		return;
2351 	}
2352 
2353 	if (name_len < 1) {
2354 		RETURN_FALSE;
2355 	}
2356 
2357 	PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2358 
2359 	if (zip_unchange(intern, sb.index) != 0) {
2360 		RETURN_FALSE;
2361 	} else {
2362 		RETURN_TRUE;
2363 	}
2364 }
2365 /* }}} */
2366 
2367 /* {{{ proto bool ZipArchive::unchangeAll()
2368 All changes to files and global information in archive are reverted */
ZIPARCHIVE_METHOD(unchangeAll)2369 static ZIPARCHIVE_METHOD(unchangeAll)
2370 {
2371 	struct zip *intern;
2372 	zval *this = getThis();
2373 
2374 	if (!this) {
2375 		RETURN_FALSE;
2376 	}
2377 
2378 	ZIP_FROM_OBJECT(intern, this);
2379 
2380 	if (zip_unchange_all(intern) != 0) {
2381 		RETURN_FALSE;
2382 	} else {
2383 		RETURN_TRUE;
2384 	}
2385 }
2386 /* }}} */
2387 
2388 /* {{{ proto bool ZipArchive::unchangeArchive()
2389 Revert all global changes to the archive archive.  For now, this only reverts archive comment changes. */
ZIPARCHIVE_METHOD(unchangeArchive)2390 static ZIPARCHIVE_METHOD(unchangeArchive)
2391 {
2392 	struct zip *intern;
2393 	zval *this = getThis();
2394 
2395 	if (!this) {
2396 		RETURN_FALSE;
2397 	}
2398 
2399 	ZIP_FROM_OBJECT(intern, this);
2400 
2401 	if (zip_unchange_archive(intern) != 0) {
2402 		RETURN_FALSE;
2403 	} else {
2404 		RETURN_TRUE;
2405 	}
2406 }
2407 /* }}} */
2408 
2409 /* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files])
2410 Extract one or more file from a zip archive */
2411 /* TODO:
2412  * - allow index or array of indeces
2413  * - replace path
2414  * - patterns
2415  */
ZIPARCHIVE_METHOD(extractTo)2416 static ZIPARCHIVE_METHOD(extractTo)
2417 {
2418 	struct zip *intern;
2419 
2420 	zval *this = getThis();
2421 	zval *zval_files = NULL;
2422 	zval **zval_file = NULL;
2423 	php_stream_statbuf ssb;
2424 	char *pathto;
2425 	int pathto_len;
2426 	int ret, i;
2427 
2428 	int nelems;
2429 
2430 	if (!this) {
2431 		RETURN_FALSE;
2432 	}
2433 
2434 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &pathto, &pathto_len, &zval_files) == FAILURE) {
2435 		return;
2436 	}
2437 
2438 	if (pathto_len < 1) {
2439 		RETURN_FALSE;
2440 	}
2441 
2442 	if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
2443 			ret = php_stream_mkdir(pathto, 0777,  PHP_STREAM_MKDIR_RECURSIVE, NULL);
2444 			if (!ret) {
2445 					RETURN_FALSE;
2446 			}
2447 	}
2448 
2449 	ZIP_FROM_OBJECT(intern, this);
2450 	if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) {
2451 		switch (Z_TYPE_P(zval_files)) {
2452 			case IS_STRING:
2453 				if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files) TSRMLS_CC)) {
2454 					RETURN_FALSE;
2455 				}
2456 				break;
2457 			case IS_ARRAY:
2458 				nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
2459 				if (nelems == 0 ) {
2460 					RETURN_FALSE;
2461 				}
2462 				for (i = 0; i < nelems; i++) {
2463 					if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
2464 						switch (Z_TYPE_PP(zval_file)) {
2465 							case IS_LONG:
2466 								break;
2467 							case IS_STRING:
2468 								if (!php_zip_extract_file(intern, pathto, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file) TSRMLS_CC)) {
2469 									RETURN_FALSE;
2470 								}
2471 								break;
2472 						}
2473 					}
2474 				}
2475 				break;
2476 			case IS_LONG:
2477 			default:
2478 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings");
2479 				break;
2480 		}
2481 	} else {
2482 		/* Extract all files */
2483 		int filecount = zip_get_num_files(intern);
2484 
2485 		if (filecount == -1) {
2486 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive");
2487 				RETURN_FALSE;
2488 		}
2489 
2490 		for (i = 0; i < filecount; i++) {
2491 			char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
2492 			if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) {
2493 					RETURN_FALSE;
2494 			}
2495 		}
2496 	}
2497 	RETURN_TRUE;
2498 }
2499 /* }}} */
2500 
php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS,int type)2501 static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
2502 {
2503 	struct zip *intern;
2504 	zval *this = getThis();
2505 
2506 	struct zip_stat sb;
2507 	struct zip_file *zf;
2508 
2509 	char *filename;
2510 	int	filename_len;
2511 	long index = -1;
2512 	long flags = 0;
2513 	long len = 0;
2514 
2515 	char *buffer;
2516 	int n = 0;
2517 
2518 	if (!this) {
2519 		RETURN_FALSE;
2520 	}
2521 
2522 	ZIP_FROM_OBJECT(intern, this);
2523 
2524 	if (type == 1) {
2525 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
2526 			return;
2527 		}
2528 		PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb);
2529 	} else {
2530 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &index, &len, &flags) == FAILURE) {
2531 			return;
2532 		}
2533 		PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2534 	}
2535 
2536 	if (sb.size < 1) {
2537 		RETURN_EMPTY_STRING();
2538 	}
2539 
2540 	if (len < 1) {
2541 		len = sb.size;
2542 	}
2543 	if (index >= 0) {
2544 		zf = zip_fopen_index(intern, index, flags);
2545 	} else {
2546 		zf = zip_fopen(intern, filename, flags);
2547 	}
2548 
2549 	if (zf == NULL) {
2550 		RETURN_FALSE;
2551 	}
2552 
2553 	buffer = safe_emalloc(len, 1, 2);
2554 	n = zip_fread(zf, buffer, len);
2555 	if (n < 1) {
2556 		efree(buffer);
2557 		RETURN_EMPTY_STRING();
2558 	}
2559 
2560 	zip_fclose(zf);
2561 	buffer[n] = 0;
2562 	RETURN_STRINGL(buffer, n, 0);
2563 }
2564 /* }}} */
2565 
2566 /* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]])
2567 get the contents of an entry using its name */
ZIPARCHIVE_METHOD(getFromName)2568 static ZIPARCHIVE_METHOD(getFromName)
2569 {
2570 	php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2571 }
2572 /* }}} */
2573 
2574 /* {{{ proto string ZipArchive::getFromIndex(int index[, int len [, int flags]])
2575 get the contents of an entry using its index */
ZIPARCHIVE_METHOD(getFromIndex)2576 static ZIPARCHIVE_METHOD(getFromIndex)
2577 {
2578 	php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2579 }
2580 /* }}} */
2581 
2582 /* {{{ proto resource ZipArchive::getStream(string entryname)
2583 get a stream for an entry using its name */
ZIPARCHIVE_METHOD(getStream)2584 static ZIPARCHIVE_METHOD(getStream)
2585 {
2586 	struct zip *intern;
2587 	zval *this = getThis();
2588 	struct zip_stat sb;
2589 	char *filename;
2590 	int	filename_len;
2591 	char *mode = "rb";
2592 	php_stream *stream;
2593 	ze_zip_object *obj;
2594 
2595 	if (!this) {
2596 		RETURN_FALSE;
2597 	}
2598 
2599 	ZIP_FROM_OBJECT(intern, this);
2600 
2601 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
2602 		return;
2603 	}
2604 
2605 	if (zip_stat(intern, filename, 0, &sb) != 0) {
2606 		RETURN_FALSE;
2607 	}
2608 
2609 	obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
2610 
2611 	stream = php_stream_zip_open(obj->filename, filename, mode STREAMS_CC TSRMLS_CC);
2612 	if (stream) {
2613 		php_stream_to_zval(stream, return_value);
2614 	}
2615 }
2616 /* }}} */
2617 
2618 /* {{{ arginfo */
2619 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1)
2620 	ZEND_ARG_INFO(0, filename)
2621 	ZEND_ARG_INFO(0, flags)
2622 ZEND_END_ARG_INFO()
2623 
2624 ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0)
2625 ZEND_END_ARG_INFO()
2626 
2627 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addemptydir, 0, 0, 1)
2628 	ZEND_ARG_INFO(0, dirname)
2629 ZEND_END_ARG_INFO()
2630 
2631 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addglob, 0, 0, 1)
2632 	ZEND_ARG_INFO(0, pattern)
2633 	ZEND_ARG_INFO(0, flags)
2634 	ZEND_ARG_INFO(0, options)
2635 ZEND_END_ARG_INFO()
2636 
2637 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addpattern, 0, 0, 1)
2638 	ZEND_ARG_INFO(0, pattern)
2639 	ZEND_ARG_INFO(0, path)
2640 	ZEND_ARG_INFO(0, options)
2641 ZEND_END_ARG_INFO()
2642 
2643 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfile, 0, 0, 1)
2644 	ZEND_ARG_INFO(0, filepath)
2645 	ZEND_ARG_INFO(0, entryname)
2646 	ZEND_ARG_INFO(0, start)
2647 	ZEND_ARG_INFO(0, length)
2648 ZEND_END_ARG_INFO()
2649 
2650 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfromstring, 0, 0, 2)
2651 	ZEND_ARG_INFO(0, name)
2652 	ZEND_ARG_INFO(0, content)
2653 ZEND_END_ARG_INFO()
2654 
2655 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statname, 0, 0, 1)
2656 	ZEND_ARG_INFO(0, filename)
2657 	ZEND_ARG_INFO(0, flags)
2658 ZEND_END_ARG_INFO()
2659 
2660 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statindex, 0, 0, 1)
2661 	ZEND_ARG_INFO(0, index)
2662 	ZEND_ARG_INFO(0, flags)
2663 ZEND_END_ARG_INFO()
2664 
2665 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setarchivecomment, 0, 0, 1)
2666 	ZEND_ARG_INFO(0, comment)
2667 ZEND_END_ARG_INFO()
2668 
2669 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentindex, 0, 0, 2)
2670 	ZEND_ARG_INFO(0, index)
2671 	ZEND_ARG_INFO(0, comment)
2672 ZEND_END_ARG_INFO()
2673 
2674 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentname, 0, 0, 1)
2675 	ZEND_ARG_INFO(0, name)
2676 	ZEND_ARG_INFO(0, flags)
2677 ZEND_END_ARG_INFO()
2678 
2679 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentindex, 0, 0, 1)
2680 	ZEND_ARG_INFO(0, index)
2681 	ZEND_ARG_INFO(0, flags)
2682 ZEND_END_ARG_INFO()
2683 
2684 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renameindex, 0, 0, 2)
2685 	ZEND_ARG_INFO(0, index)
2686 	ZEND_ARG_INFO(0, new_name)
2687 ZEND_END_ARG_INFO()
2688 
2689 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renamename, 0, 0, 2)
2690 	ZEND_ARG_INFO(0, name)
2691 	ZEND_ARG_INFO(0, new_name)
2692 ZEND_END_ARG_INFO()
2693 
2694 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangeindex, 0, 0, 1)
2695 	ZEND_ARG_INFO(0, index)
2696 ZEND_END_ARG_INFO()
2697 
2698 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangename, 0, 0, 1)
2699 	ZEND_ARG_INFO(0, name)
2700 ZEND_END_ARG_INFO()
2701 
2702 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_extractto, 0, 0, 1)
2703 	ZEND_ARG_INFO(0, pathto)
2704 	ZEND_ARG_INFO(0, files)
2705 ZEND_END_ARG_INFO()
2706 
2707 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromname, 0, 0, 1)
2708 	ZEND_ARG_INFO(0, entryname)
2709 	ZEND_ARG_INFO(0, len)
2710 	ZEND_ARG_INFO(0, flags)
2711 ZEND_END_ARG_INFO()
2712 
2713 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromindex, 0, 0, 1)
2714 	ZEND_ARG_INFO(0, index)
2715 	ZEND_ARG_INFO(0, len)
2716 	ZEND_ARG_INFO(0, flags)
2717 ZEND_END_ARG_INFO()
2718 
2719 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getarchivecomment, 0, 0, 0)
2720 	ZEND_ARG_INFO(0, flags)
2721 ZEND_END_ARG_INFO()
2722 
2723 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentname, 0, 0, 2)
2724 	ZEND_ARG_INFO(0, name)
2725 	ZEND_ARG_INFO(0, comment)
2726 ZEND_END_ARG_INFO()
2727 
2728 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getstream, 0, 0, 1)
2729 	ZEND_ARG_INFO(0, entryname)
2730 ZEND_END_ARG_INFO()
2731 /* }}} */
2732 
2733 /* {{{ ze_zip_object_class_functions */
2734 static const zend_function_entry zip_class_functions[] = {
2735 	ZIPARCHIVE_ME(open,					arginfo_ziparchive_open, ZEND_ACC_PUBLIC)
2736 	ZIPARCHIVE_ME(close,				arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2737 	ZIPARCHIVE_ME(getStatusString,		arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2738 	ZIPARCHIVE_ME(addEmptyDir,			arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC)
2739 	ZIPARCHIVE_ME(addFromString,		arginfo_ziparchive_addfromstring, ZEND_ACC_PUBLIC)
2740 	ZIPARCHIVE_ME(addFile,				arginfo_ziparchive_addfile, ZEND_ACC_PUBLIC)
2741 	ZIPARCHIVE_ME(addGlob,				arginfo_ziparchive_addglob, ZEND_ACC_PUBLIC)
2742 	ZIPARCHIVE_ME(addPattern,			arginfo_ziparchive_addpattern, ZEND_ACC_PUBLIC)
2743 	ZIPARCHIVE_ME(renameIndex,			arginfo_ziparchive_renameindex, ZEND_ACC_PUBLIC)
2744 	ZIPARCHIVE_ME(renameName,			arginfo_ziparchive_renamename, ZEND_ACC_PUBLIC)
2745 	ZIPARCHIVE_ME(setArchiveComment,	arginfo_ziparchive_setarchivecomment, ZEND_ACC_PUBLIC)
2746 	ZIPARCHIVE_ME(getArchiveComment,	arginfo_ziparchive_getarchivecomment, ZEND_ACC_PUBLIC)
2747 	ZIPARCHIVE_ME(setCommentIndex,		arginfo_ziparchive_setcommentindex, ZEND_ACC_PUBLIC)
2748 	ZIPARCHIVE_ME(setCommentName,		arginfo_ziparchive_setcommentname, ZEND_ACC_PUBLIC)
2749 	ZIPARCHIVE_ME(getCommentIndex,		arginfo_ziparchive_getcommentindex, ZEND_ACC_PUBLIC)
2750 	ZIPARCHIVE_ME(getCommentName,		arginfo_ziparchive_getcommentname, ZEND_ACC_PUBLIC)
2751 	ZIPARCHIVE_ME(deleteIndex,			arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
2752 	ZIPARCHIVE_ME(deleteName,			arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
2753 	ZIPARCHIVE_ME(statName,				arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
2754 	ZIPARCHIVE_ME(statIndex,			arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
2755 	ZIPARCHIVE_ME(locateName,			arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
2756 	ZIPARCHIVE_ME(getNameIndex,			arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
2757 	ZIPARCHIVE_ME(unchangeArchive,		arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2758 	ZIPARCHIVE_ME(unchangeAll,			arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2759 	ZIPARCHIVE_ME(unchangeIndex,		arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
2760 	ZIPARCHIVE_ME(unchangeName,			arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
2761 	ZIPARCHIVE_ME(extractTo,			arginfo_ziparchive_extractto, ZEND_ACC_PUBLIC)
2762 	ZIPARCHIVE_ME(getFromName,			arginfo_ziparchive_getfromname, ZEND_ACC_PUBLIC)
2763 	ZIPARCHIVE_ME(getFromIndex,			arginfo_ziparchive_getfromindex, ZEND_ACC_PUBLIC)
2764 	ZIPARCHIVE_ME(getStream,			arginfo_ziparchive_getstream, ZEND_ACC_PUBLIC)
2765 	{NULL, NULL, NULL}
2766 };
2767 /* }}} */
2768 #endif
2769 
2770 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(zip)2771 static PHP_MINIT_FUNCTION(zip)
2772 {
2773 #ifdef PHP_ZIP_USE_OO
2774 	zend_class_entry ce;
2775 
2776 	memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2777 	zip_object_handlers.clone_obj		= NULL;
2778 	zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
2779 
2780 	zip_object_handlers.get_properties = php_zip_get_properties;
2781 	zip_object_handlers.read_property	= php_zip_read_property;
2782 	zip_object_handlers.has_property	= php_zip_has_property;
2783 
2784 	INIT_CLASS_ENTRY(ce, "ZipArchive", zip_class_functions);
2785 	ce.create_object = php_zip_object_new;
2786 	zip_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
2787 
2788 	zend_hash_init(&zip_prop_handlers, 0, NULL, NULL, 1);
2789 	php_zip_register_prop_handler(&zip_prop_handlers, "status",    php_zip_status, NULL, NULL, IS_LONG TSRMLS_CC);
2790 	php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG TSRMLS_CC);
2791 	php_zip_register_prop_handler(&zip_prop_handlers, "numFiles",  php_zip_get_num_files, NULL, NULL, IS_LONG TSRMLS_CC);
2792 	php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC);
2793 	php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC);
2794 
2795 	REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
2796 	REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL);
2797 	REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS);
2798 	REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE);
2799 
2800 	REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE);
2801 	REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
2802 	REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
2803 	REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
2804 	REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
2805 	REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);
2806 	REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK);
2807 	REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1);
2808 	REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2);
2809 	REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3);
2810 	REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4);
2811 	REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE);
2812 	REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE);
2813 	REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64);
2814 	REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE);
2815 	REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2);
2816 	REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA);
2817 	REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE);
2818 	REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77);
2819 	REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK);
2820 	REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD);
2821 
2822 	/* Error code */
2823 	REGISTER_ZIP_CLASS_CONST_LONG("ER_OK",			ZIP_ER_OK);			/* N No error */
2824 	REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK",	ZIP_ER_MULTIDISK);	/* N Multi-disk zip archives not supported */
2825 	REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME",		ZIP_ER_RENAME);		/* S Renaming temporary file failed */
2826 	REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE",		ZIP_ER_CLOSE);		/* S Closing zip archive failed */
2827 	REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK",		ZIP_ER_SEEK);		/* S Seek error */
2828 	REGISTER_ZIP_CLASS_CONST_LONG("ER_READ",		ZIP_ER_READ);		/* S Read error */
2829 	REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE",		ZIP_ER_WRITE);		/* S Write error */
2830 	REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC",			ZIP_ER_CRC);		/* N CRC error */
2831 	REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED",	ZIP_ER_ZIPCLOSED);	/* N Containing zip archive was closed */
2832 	REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT",		ZIP_ER_NOENT);		/* N No such file */
2833 	REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS",		ZIP_ER_EXISTS);		/* N File already exists */
2834 	REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN",		ZIP_ER_OPEN);		/* S Can't open file */
2835 	REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN",		ZIP_ER_TMPOPEN);	/* S Failure to create temporary file */
2836 	REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB",		ZIP_ER_ZLIB);		/* Z Zlib error */
2837 	REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY",		ZIP_ER_MEMORY);		/* N Malloc failure */
2838 	REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED",		ZIP_ER_CHANGED);	/* N Entry has been changed */
2839 	REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP",	ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */
2840 	REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF",			ZIP_ER_EOF);		/* N Premature EOF */
2841 	REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL",		ZIP_ER_INVAL);		/* N Invalid argument */
2842 	REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP",		ZIP_ER_NOZIP);		/* N Not a zip archive */
2843 	REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL",	ZIP_ER_INTERNAL);	/* N Internal error */
2844 	REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS",		ZIP_ER_INCONS);		/* N Zip archive inconsistent */
2845 	REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE",		ZIP_ER_REMOVE);		/* S Can't remove file */
2846 	REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED",  	ZIP_ER_DELETED);	/* N Entry has been deleted */
2847 
2848 	php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC);
2849 #endif
2850 
2851 	le_zip_dir   = zend_register_list_destructors_ex(php_zip_free_dir,   NULL, le_zip_dir_name,   module_number);
2852 	le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
2853 
2854 	return SUCCESS;
2855 }
2856 /* }}} */
2857 
2858 /* {{{ PHP_MSHUTDOWN_FUNCTION
2859  */
PHP_MSHUTDOWN_FUNCTION(zip)2860 static PHP_MSHUTDOWN_FUNCTION(zip)
2861 {
2862 #ifdef PHP_ZIP_USE_OO
2863 	zend_hash_destroy(&zip_prop_handlers);
2864 	php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
2865 #endif
2866 	return SUCCESS;
2867 }
2868 /* }}} */
2869 
2870 /* {{{ PHP_MINFO_FUNCTION
2871  */
PHP_MINFO_FUNCTION(zip)2872 static PHP_MINFO_FUNCTION(zip)
2873 {
2874 	php_info_print_table_start();
2875 
2876 	php_info_print_table_row(2, "Zip", "enabled");
2877 	php_info_print_table_row(2, "Extension Version","$Id: 6c872ebfb022206b0cc2a183c7a388c7b6ad8685 $");
2878 	php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING);
2879 	php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
2880 
2881 	php_info_print_table_end();
2882 }
2883 /* }}} */
2884 
2885 /*
2886  * Local variables:
2887  * tab-width: 4
2888  * c-basic-offset: 4
2889  * End:
2890  * vim600: noet sw=4 ts=4 fdm=marker
2891  * vim<600: noet sw=4 ts=4
2892  */
2893