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. php_zip_get_from
  67. ZIPARCHIVE_METHOD
  68. ZIPARCHIVE_METHOD
  69. ZIPARCHIVE_METHOD
  70. PHP_MINIT_FUNCTION
  71. PHP_MSHUTDOWN_FUNCTION
  72. PHP_MINFO_FUNCTION

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

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