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