root/ext/zip/php_zip.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_zip_make_relative_path
  2. php_zip_extract_file
  3. php_zip_add_file
  4. php_zip_parse_options
  5. php_zip_status
  6. php_zip_status_sys
  7. php_zip_get_num_files
  8. php_zipobj_get_filename
  9. php_zipobj_get_zip_comment
  10. php_zip_glob
  11. php_zip_pcre
  12. php_zip_register_prop_handler
  13. php_zip_property_reader
  14. php_zip_get_property_ptr_ptr
  15. php_zip_read_property
  16. php_zip_has_property
  17. php_zip_get_properties
  18. php_zip_object_free_storage
  19. php_zip_object_new
  20. php_zip_free_dir
  21. php_zip_free_entry
  22. ZEND_GET_MODULE
  23. PHP_NAMED_FUNCTION
  24. PHP_NAMED_FUNCTION
  25. PHP_NAMED_FUNCTION
  26. PHP_NAMED_FUNCTION
  27. PHP_NAMED_FUNCTION
  28. php_zip_entry_get_info
  29. PHP_NAMED_FUNCTION
  30. PHP_NAMED_FUNCTION
  31. PHP_NAMED_FUNCTION
  32. PHP_NAMED_FUNCTION
  33. ZIPARCHIVE_METHOD
  34. ZIPARCHIVE_METHOD
  35. ZIPARCHIVE_METHOD
  36. ZIPARCHIVE_METHOD
  37. ZIPARCHIVE_METHOD
  38. php_zip_add_from_pattern
  39. ZIPARCHIVE_METHOD
  40. ZIPARCHIVE_METHOD
  41. ZIPARCHIVE_METHOD
  42. ZIPARCHIVE_METHOD
  43. ZIPARCHIVE_METHOD
  44. ZIPARCHIVE_METHOD
  45. ZIPARCHIVE_METHOD
  46. ZIPARCHIVE_METHOD
  47. ZIPARCHIVE_METHOD
  48. ZIPARCHIVE_METHOD
  49. ZIPARCHIVE_METHOD
  50. ZIPARCHIVE_METHOD
  51. ZIPARCHIVE_METHOD
  52. ZIPARCHIVE_METHOD
  53. ZIPARCHIVE_METHOD
  54. ZIPARCHIVE_METHOD
  55. ZIPARCHIVE_METHOD
  56. ZIPARCHIVE_METHOD
  57. ZIPARCHIVE_METHOD
  58. ZIPARCHIVE_METHOD
  59. ZIPARCHIVE_METHOD
  60. ZIPARCHIVE_METHOD
  61. ZIPARCHIVE_METHOD
  62. ZIPARCHIVE_METHOD
  63. ZIPARCHIVE_METHOD
  64. ZIPARCHIVE_METHOD
  65. ZIPARCHIVE_METHOD
  66. ZIPARCHIVE_METHOD
  67. ZIPARCHIVE_METHOD
  68. php_zip_get_from
  69. ZIPARCHIVE_METHOD
  70. ZIPARCHIVE_METHOD
  71. ZIPARCHIVE_METHOD
  72. php_zip_free_prop_handler
  73. PHP_MINIT_FUNCTION
  74. PHP_MSHUTDOWN_FUNCTION
  75. PHP_MINFO_FUNCTION

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

/* [<][>][^][v][top][bottom][index][help] */