Back to index

php5  5.3.10
php_zip.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt.                                 |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Author: Piere-Alain Joye <pierre@php.net>                            |
00016   +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id: php_zip.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 
00025 #include "php.h"
00026 #include "php_ini.h"
00027 #include "ext/standard/info.h"
00028 #include "ext/standard/file.h"
00029 #include "ext/standard/php_string.h"
00030 #include "ext/pcre/php_pcre.h"
00031 #include "php_zip.h"
00032 #include "lib/zip.h"
00033 #include "lib/zipint.h"
00034 
00035 /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */
00036 static PHP_NAMED_FUNCTION(zif_zip_open);
00037 static PHP_NAMED_FUNCTION(zif_zip_read);
00038 static PHP_NAMED_FUNCTION(zif_zip_close);
00039 static PHP_NAMED_FUNCTION(zif_zip_entry_read);
00040 static PHP_NAMED_FUNCTION(zif_zip_entry_filesize);
00041 static PHP_NAMED_FUNCTION(zif_zip_entry_name);
00042 static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize);
00043 static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod);
00044 static PHP_NAMED_FUNCTION(zif_zip_entry_open);
00045 static PHP_NAMED_FUNCTION(zif_zip_entry_close);
00046 
00047 #ifdef HAVE_GLOB
00048 #ifndef PHP_WIN32
00049 #include <glob.h>
00050 #else
00051 #include "win32/glob.h"
00052 #endif
00053 #endif
00054 
00055 /* {{{ Resource le */
00056 static int le_zip_dir;
00057 #define le_zip_dir_name "Zip Directory"
00058 static int le_zip_entry;
00059 #define le_zip_entry_name "Zip Entry"
00060 /* }}} */
00061 
00062 /* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
00063 #define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
00064        if (zip_stat_index(za, index, flags, &sb) != 0) { \
00065               RETURN_FALSE; \
00066        }
00067 /* }}} */
00068 
00069 /* {{{  PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */
00070 #define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
00071        if (path_len < 1) { \
00072               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); \
00073               RETURN_FALSE; \
00074        } \
00075        if (zip_stat(za, path, flags, &sb) != 0) { \
00076               RETURN_FALSE; \
00077        }
00078 /* }}} */
00079 
00080 /* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
00081 #define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
00082        if (comment_len == 0) { \
00083               /* Passing NULL remove the existing comment */ \
00084               if (zip_set_file_comment(intern, index, NULL, 0) < 0) { \
00085                      RETURN_FALSE; \
00086               } \
00087        } else if (zip_set_file_comment(intern, index, comment, comment_len) < 0) { \
00088               RETURN_FALSE; \
00089        } \
00090        RETURN_TRUE;
00091 /* }}} */
00092 
00093 #if (PHP_MAJOR_VERSION < 6)
00094 # define add_ascii_assoc_string add_assoc_string
00095 # define add_ascii_assoc_long add_assoc_long
00096 #endif
00097 
00098 /* Flatten a path by making a relative path (to .)*/
00099 static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
00100 {
00101        char *path_begin = path;
00102        size_t i;
00103 
00104        if (IS_SLASH(path[0])) {
00105               return path + 1;
00106        }
00107 
00108        if (path_len < 1 || path == NULL) {
00109               return NULL;
00110        }
00111 
00112        i = path_len;
00113 
00114        while (1) {
00115               while (i > 0 && !IS_SLASH(path[i])) {
00116                      i--;
00117               }
00118 
00119               if (!i) {
00120                      return path;
00121               }
00122 
00123               if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) {
00124                      /* i is the position of . or :, add 1 for / */
00125                      path_begin = path + i + 1;
00126                      break;
00127               }
00128               i--;
00129        }
00130 
00131        return path_begin;
00132 }
00133 /* }}} */
00134 
00135 #ifdef PHP_ZIP_USE_OO 
00136 /* {{{ php_zip_extract_file */
00137 static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC)
00138 {
00139        php_stream_statbuf ssb;
00140        struct zip_file *zf;
00141        struct zip_stat sb;
00142        char b[8192];
00143        int n, len, ret;
00144        php_stream *stream;
00145        char *fullpath;
00146        char *file_dirname_fullpath;
00147        char file_dirname[MAXPATHLEN];
00148        size_t dir_len;
00149        char *file_basename;
00150        size_t file_basename_len;
00151        int is_dir_only = 0;
00152        char *path_cleaned;
00153        size_t path_cleaned_len;
00154        cwd_state new_state;
00155 
00156        new_state.cwd = (char*)malloc(1);
00157        new_state.cwd[0] = '\0';
00158        new_state.cwd_length = 0;
00159 
00160        /* Clean/normlize the path and then transform any path (absolute or relative)
00161                to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
00162         */
00163        virtual_file_ex(&new_state, file, NULL, CWD_EXPAND);
00164        path_cleaned =  php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
00165        if(!path_cleaned) {
00166               return 0;
00167        }
00168        path_cleaned_len = strlen(path_cleaned);
00169 
00170        if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
00171               return 0;
00172        }
00173 
00174        /* it is a directory only, see #40228 */
00175        if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
00176               len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file);
00177               is_dir_only = 1;
00178        } else {
00179               memcpy(file_dirname, path_cleaned, path_cleaned_len);
00180               dir_len = php_dirname(file_dirname, path_cleaned_len);
00181 
00182               if (dir_len <= 0 || (dir_len == 1 && file_dirname[0] == '.')) {
00183                      len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
00184               } else {
00185                      len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
00186               }
00187 
00188               php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (size_t *)&file_basename_len TSRMLS_CC);
00189 
00190               if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
00191                      efree(file_dirname_fullpath);
00192                      efree(file_basename);
00193                      free(new_state.cwd);
00194                      return 0;
00195               }
00196        }
00197 
00198        /* let see if the path already exists */
00199        if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
00200 
00201 #if defined(PHP_WIN32) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1)
00202               char *e;
00203               e = file_dirname_fullpath;
00204               while (*e) {
00205                         if (*e == '/') {
00206                                       *e = DEFAULT_SLASH;
00207                         }
00208                         e++;
00209               }
00210 #endif
00211 
00212               ret = php_stream_mkdir(file_dirname_fullpath, 0777,  PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
00213               if (!ret) {
00214                      efree(file_dirname_fullpath);
00215                      if (!is_dir_only) {
00216                             efree(file_basename);
00217                             free(new_state.cwd);
00218                      }
00219                      return 0;
00220               }
00221        }
00222 
00223        /* it is a standalone directory, job done */
00224        if (is_dir_only) {
00225               efree(file_dirname_fullpath);
00226               free(new_state.cwd);
00227               return 1;
00228        }
00229 
00230        len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, file_basename);
00231        if (!len) {
00232               efree(file_dirname_fullpath);
00233               efree(file_basename);
00234               free(new_state.cwd);
00235               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot build full extract path");
00236               return 0;
00237        } else if (len > MAXPATHLEN) {
00238               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
00239               efree(file_dirname_fullpath);
00240               efree(file_basename);
00241               free(new_state.cwd);
00242               return 0;
00243        }
00244 
00245        /* check again the full path, not sure if it
00246         * is required, does a file can have a different
00247         * safemode status as its parent folder?
00248         */
00249        if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
00250               efree(fullpath);
00251               efree(file_dirname_fullpath);
00252               efree(file_basename);
00253               free(new_state.cwd);
00254               return 0;
00255        }
00256 
00257 #if PHP_API_VERSION < 20100412
00258        stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
00259 #else
00260        stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
00261 #endif
00262 
00263        if (stream == NULL) {
00264               n = -1;
00265               goto done;
00266        }
00267 
00268        zf = zip_fopen(za, file, 0);
00269        if (zf == NULL) {
00270               n = -1;
00271               php_stream_close(stream);
00272               goto done;
00273        }
00274 
00275        n = 0;
00276        if (stream == NULL) {
00277               int ret = zip_fclose(zf);
00278               efree(fullpath);
00279               efree(file_basename);
00280               efree(file_dirname_fullpath);
00281               free(new_state.cwd);
00282               return 0;
00283        }
00284 
00285        while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
00286               php_stream_write(stream, b, n);
00287        }
00288 
00289        php_stream_close(stream);
00290        n = zip_fclose(zf);
00291 
00292 done:
00293        efree(fullpath);
00294        efree(file_basename);
00295        efree(file_dirname_fullpath);
00296        free(new_state.cwd);
00297 
00298        if (n<0) {
00299               return 0;
00300        } else {
00301               return 1;
00302        }
00303 }
00304 /* }}} */
00305 
00306 static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len, 
00307        char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */
00308 {
00309        struct zip_source *zs;
00310        int cur_idx;
00311        char resolved_path[MAXPATHLEN];
00312 
00313 
00314        if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
00315               return -1;
00316        }
00317 
00318        if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
00319               return -1;
00320        }
00321 
00322        zs = zip_source_file(za, resolved_path, offset_start, offset_len);
00323        if (!zs) {
00324               return -1;
00325        }
00326 
00327        cur_idx = zip_name_locate(za, (const char *)entry_name, 0);
00328        /* TODO: fix  _zip_replace */
00329        if (cur_idx<0) {
00330               /* reset the error */
00331               if (za->error.str) {
00332                      _zip_error_fini(&za->error);
00333               }
00334               _zip_error_init(&za->error);
00335        } else {
00336               if (zip_delete(za, cur_idx) == -1) {
00337                      zip_source_free(zs);
00338                      return -1;
00339               }
00340        }
00341 
00342        if (zip_add(za, entry_name, zs) == -1) {
00343               return -1;
00344        } else {
00345               return 1;
00346        }
00347 }
00348 /* }}} */
00349 
00350 static int php_zip_parse_options(zval *options, long *remove_all_path, 
00351        char **remove_path, int *remove_path_len, char **add_path, int *add_path_len TSRMLS_DC) /* {{{ */
00352 {
00353        zval **option;
00354        if (zend_hash_find(HASH_OF(options), "remove_all_path", sizeof("remove_all_path"), (void **)&option) == SUCCESS) {
00355               long opt;
00356               if (Z_TYPE_PP(option) != IS_LONG) {
00357                      zval tmp = **option;
00358                      zval_copy_ctor(&tmp);
00359                      convert_to_long(&tmp);
00360                      opt = Z_LVAL(tmp);
00361               } else {
00362                      opt = Z_LVAL_PP(option);
00363               }
00364               *remove_all_path = opt;
00365        }
00366 
00367        /* If I add more options, it would make sense to create a nice static struct and loop over it. */
00368        if (zend_hash_find(HASH_OF(options), "remove_path", sizeof("remove_path"), (void **)&option) == SUCCESS) {
00369               if (Z_TYPE_PP(option) != IS_STRING) {
00370                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path option expected to be a string");
00371                      return -1;
00372               }
00373 
00374               if (Z_STRLEN_PP(option) < 1) {
00375                      php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as remove_path option");
00376                      return -1;
00377               }
00378 
00379               if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
00380                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)", 
00381                                           MAXPATHLEN - 1, Z_STRLEN_PP(option));
00382                      return -1;
00383               }
00384               *remove_path_len = Z_STRLEN_PP(option); 
00385               *remove_path = Z_STRVAL_PP(option);
00386        }
00387 
00388        if (zend_hash_find(HASH_OF(options), "add_path", sizeof("add_path"), (void **)&option) == SUCCESS) {
00389               if (Z_TYPE_PP(option) != IS_STRING) {
00390                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path option expected to be a string");
00391                      return -1;
00392               }
00393 
00394               if (Z_STRLEN_PP(option) < 1) {
00395                      php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as the add_path option");
00396                      return -1;
00397               }
00398 
00399               if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
00400                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)", 
00401                                           MAXPATHLEN - 1, Z_STRLEN_PP(option));
00402                      return -1;
00403               }
00404               *add_path_len = Z_STRLEN_PP(option); 
00405               *add_path = Z_STRVAL_PP(option);
00406        }
00407        return 1;
00408 }
00409 /* }}} */
00410 
00411 /* {{{ REGISTER_ZIP_CLASS_CONST_LONG */
00412 #define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \
00413            zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
00414 /* }}} */
00415 
00416 /* {{{ ZIP_FROM_OBJECT */
00417 #define ZIP_FROM_OBJECT(intern, object) \
00418        { \
00419               ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \
00420               intern = obj->za; \
00421               if (!intern) { \
00422                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized Zip object"); \
00423                      RETURN_FALSE; \
00424               } \
00425        }
00426 /* }}} */
00427 
00428 /* {{{ RETURN_SB(sb) */
00429 #define RETURN_SB(sb) \
00430        { \
00431               array_init(return_value); \
00432               add_ascii_assoc_string(return_value, "name", (char *)(sb)->name, 1); \
00433               add_ascii_assoc_long(return_value, "index", (long) (sb)->index); \
00434               add_ascii_assoc_long(return_value, "crc", (long) (sb)->crc); \
00435               add_ascii_assoc_long(return_value, "size", (long) (sb)->size); \
00436               add_ascii_assoc_long(return_value, "mtime", (long) (sb)->mtime); \
00437               add_ascii_assoc_long(return_value, "comp_size", (long) (sb)->comp_size); \
00438               add_ascii_assoc_long(return_value, "comp_method", (long) (sb)->comp_method); \
00439        }
00440 /* }}} */
00441 
00442 static int php_zip_status(struct zip *za TSRMLS_DC) /* {{{ */
00443 {
00444        int zep, syp;
00445 
00446        zip_error_get(za, &zep, &syp);
00447        return zep;
00448 }
00449 /* }}} */
00450 
00451 static int php_zip_status_sys(struct zip *za TSRMLS_DC) /* {{{ */
00452 {
00453        int zep, syp;
00454 
00455        zip_error_get(za, &zep, &syp);
00456        return syp;
00457 }
00458 /* }}} */
00459 
00460 static int php_zip_get_num_files(struct zip *za TSRMLS_DC) /* {{{ */
00461 {
00462        return zip_get_num_files(za);
00463 }
00464 /* }}} */
00465 
00466 static char * php_zipobj_get_filename(ze_zip_object *obj TSRMLS_DC) /* {{{ */
00467 {
00468 
00469        if (!obj) {
00470               return NULL;
00471        }
00472 
00473        if (obj->filename) {
00474               return obj->filename;
00475        }
00476        return NULL;
00477 }
00478 /* }}} */
00479 
00480 static char * php_zipobj_get_zip_comment(struct zip *za, int *len TSRMLS_DC) /* {{{ */
00481 {
00482        if (za) {
00483               return (char *)zip_get_archive_comment(za, len, 0);
00484        }
00485        return NULL;
00486 }
00487 /* }}} */
00488 
00489 #ifdef HAVE_GLOB /* {{{ */
00490 #ifndef GLOB_ONLYDIR
00491 #define GLOB_ONLYDIR (1<<30)
00492 #define GLOB_EMULATE_ONLYDIR
00493 #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
00494 #else
00495 #define GLOB_FLAGMASK (~0)
00496 #endif
00497 #ifndef GLOB_BRACE
00498 # define GLOB_BRACE 0
00499 #endif
00500 #ifndef GLOB_MARK
00501 # define GLOB_MARK 0
00502 #endif
00503 #ifndef GLOB_NOSORT
00504 # define GLOB_NOSORT 0
00505 #endif
00506 #ifndef GLOB_NOCHECK
00507 # define GLOB_NOCHECK 0
00508 #endif
00509 #ifndef GLOB_NOESCAPE
00510 # define GLOB_NOESCAPE 0
00511 #endif
00512 #ifndef GLOB_ERR
00513 # define GLOB_ERR 0
00514 #endif
00515 
00516 /* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
00517 #define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
00518 
00519 #endif /* }}} */
00520 
00521 int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value TSRMLS_DC) /* {{{ */
00522 {
00523 #ifdef HAVE_GLOB
00524        char cwd[MAXPATHLEN];
00525        int cwd_skip = 0;
00526 #ifdef ZTS
00527        char work_pattern[MAXPATHLEN];
00528        char *result;
00529 #endif
00530        glob_t globbuf;
00531        int n;
00532        int ret;
00533        
00534        if (pattern_len >= MAXPATHLEN) {
00535               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
00536               return -1;
00537        }
00538 
00539        if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
00540               php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
00541               return -1;
00542        }
00543 
00544 #ifdef ZTS 
00545        if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
00546               result = VCWD_GETCWD(cwd, MAXPATHLEN);    
00547               if (!result) {
00548                      cwd[0] = '\0';
00549               }
00550 #ifdef PHP_WIN32
00551               if (IS_SLASH(*pattern)) {
00552                      cwd[2] = '\0';
00553               }
00554 #endif
00555               cwd_skip = strlen(cwd)+1;
00556 
00557               snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
00558               pattern = work_pattern;
00559        } 
00560 #endif
00561 
00562        globbuf.gl_offs = 0;
00563        if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
00564 #ifdef GLOB_NOMATCH
00565               if (GLOB_NOMATCH == ret) {
00566                      /* Some glob implementation simply return no data if no matches
00567                         were found, others return the GLOB_NOMATCH error code.
00568                         We don't want to treat GLOB_NOMATCH as an error condition
00569                         so that PHP glob() behaves the same on both types of 
00570                         implementations and so that 'foreach (glob() as ...'
00571                         can be used for simple glob() calls without further error
00572                         checking.
00573                      */
00574                      array_init(return_value);
00575                      return 0;
00576               }
00577 #endif
00578               return 0;
00579        }
00580 
00581        /* now catch the FreeBSD style of "no matches" */
00582        if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
00583               array_init(return_value);
00584               return 0;
00585        }
00586 
00587        /* we assume that any glob pattern will match files from one directory only
00588           so checking the dirname of the first match should be sufficient */
00589        strncpy(cwd, globbuf.gl_pathv[0], MAXPATHLEN);
00590        if (ZIP_OPENBASEDIR_CHECKPATH(cwd)) {
00591               return -1;
00592        }
00593 
00594        array_init(return_value);
00595        for (n = 0; n < globbuf.gl_pathc; n++) {
00596               /* we need to do this everytime since GLOB_ONLYDIR does not guarantee that
00597                * all directories will be filtered. GNU libc documentation states the
00598                * following: 
00599                * If the information about the type of the file is easily available 
00600                * non-directories will be rejected but no extra work will be done to 
00601                * determine the information for each file. I.e., the caller must still be 
00602                * able to filter directories out. 
00603                */
00604               if (flags & GLOB_ONLYDIR) {
00605                      struct stat s;
00606 
00607                      if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
00608                             continue;
00609                      }
00610 
00611                      if (S_IFDIR != (s.st_mode & S_IFMT)) {
00612                             continue;
00613                      }
00614               }
00615               add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip, 1);
00616        }
00617 
00618        globfree(&globbuf);
00619        return globbuf.gl_pathc;
00620 #else
00621        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Glob support is not available");
00622        return 0;
00623 #endif  /* HAVE_GLOB */
00624 }
00625 /* }}} */
00626 
00627 int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *return_value TSRMLS_DC) /* {{{ */
00628 {
00629 #ifdef ZTS
00630        char cwd[MAXPATHLEN];
00631        int cwd_skip = 0;
00632        char work_path[MAXPATHLEN];
00633        char *result;
00634 #endif
00635        int files_cnt;
00636        char **namelist;
00637 
00638 #ifdef ZTS 
00639        if (!IS_ABSOLUTE_PATH(path, path_len)) {
00640               result = VCWD_GETCWD(cwd, MAXPATHLEN);    
00641               if (!result) {
00642                      cwd[0] = '\0';
00643               }
00644 #ifdef PHP_WIN32
00645               if (IS_SLASH(*path)) {
00646                      cwd[2] = '\0';
00647               }
00648 #endif
00649               cwd_skip = strlen(cwd)+1;
00650 
00651               snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
00652               path = work_path;
00653        } 
00654 #endif
00655 
00656        if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
00657               return -1;
00658        }
00659 
00660        files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
00661 
00662        if (files_cnt > 0) {
00663               pcre       *re = NULL;
00664               pcre_extra *pcre_extra = NULL;
00665               int preg_options = 0, i;
00666 
00667               re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
00668               if (!re) {
00669                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid expression");
00670                      return -1;    
00671               }
00672 
00673               array_init(return_value);
00674 
00675               /* only the files, directories are ignored */
00676               for (i = 0; i < files_cnt; i++) {
00677                      struct stat s;
00678                      char   fullpath[MAXPATHLEN];
00679                      int    ovector[3];
00680                      int    matches;
00681                      int    namelist_len = strlen(namelist[i]);
00682 
00683                      
00684                      if ((namelist_len == 1 && namelist[i][0] == '.') ||
00685                             (namelist_len == 2 && namelist[i][0] == '.' && namelist[i][1] == '.')) {
00686                             efree(namelist[i]);
00687                             continue;
00688                      }
00689 
00690                      if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
00691                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)", 
00692                                           MAXPATHLEN - 1, (path_len + namelist_len + 1));
00693                             efree(namelist[i]);
00694                             break;
00695                      }
00696 
00697                      snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, namelist[i]);
00698 
00699                      if (0 != VCWD_STAT(fullpath, &s)) {
00700                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot read <%s>", fullpath);
00701                             efree(namelist[i]);
00702                             continue;
00703                      }
00704 
00705                      if (S_IFDIR == (s.st_mode & S_IFMT)) {
00706                             efree(namelist[i]);
00707                             continue;
00708                      }
00709 
00710                      matches = pcre_exec(re, NULL, namelist[i], strlen(namelist[i]), 0, 0, ovector, 3);
00711                      /* 0 means that the vector is too small to hold all the captured substring offsets */
00712                      if (matches < 0) {
00713                             efree(namelist[i]);
00714                             continue;     
00715                      }
00716 
00717                      add_next_index_string(return_value, fullpath, 1);
00718                      efree(namelist[i]);
00719               }
00720               efree(namelist);
00721        }
00722        return files_cnt;
00723 }
00724 /* }}} */
00725 
00726 #endif
00727 
00728 /* {{{ arginfo */
00729 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1)
00730        ZEND_ARG_INFO(0, filename)
00731 ZEND_END_ARG_INFO()
00732 
00733 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_close, 0, 0, 1)
00734        ZEND_ARG_INFO(0, zip)
00735 ZEND_END_ARG_INFO()
00736 
00737 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_read, 0, 0, 1)
00738        ZEND_ARG_INFO(0, zip)
00739 ZEND_END_ARG_INFO()
00740 
00741 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_open, 0, 0, 2)
00742        ZEND_ARG_INFO(0, zip_dp)
00743        ZEND_ARG_INFO(0, zip_entry)
00744        ZEND_ARG_INFO(0, mode)
00745 ZEND_END_ARG_INFO()
00746 
00747 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_close, 0, 0, 1)
00748        ZEND_ARG_INFO(0, zip_ent)
00749 ZEND_END_ARG_INFO()
00750 
00751 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_read, 0, 0, 1)
00752        ZEND_ARG_INFO(0, zip_entry)
00753        ZEND_ARG_INFO(0, len)
00754 ZEND_END_ARG_INFO()
00755 
00756 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_name, 0, 0, 1)
00757        ZEND_ARG_INFO(0, zip_entry)
00758 ZEND_END_ARG_INFO()
00759 
00760 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressedsize, 0, 0, 1)
00761        ZEND_ARG_INFO(0, zip_entry)
00762 ZEND_END_ARG_INFO()
00763 
00764 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_filesize, 0, 0, 1)
00765        ZEND_ARG_INFO(0, zip_entry)
00766 ZEND_END_ARG_INFO()
00767 
00768 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressionmethod, 0, 0, 1)
00769        ZEND_ARG_INFO(0, zip_entry)
00770 ZEND_END_ARG_INFO()
00771 /* }}} */
00772 
00773 /* {{{ zend_function_entry */
00774 static const zend_function_entry zip_functions[] = {
00775        ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0)
00776        ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0)
00777        ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0)
00778        PHP_FE(zip_entry_open,             arginfo_zip_entry_open)
00779        PHP_FE(zip_entry_close,            arginfo_zip_entry_close)
00780        PHP_FE(zip_entry_read,             arginfo_zip_entry_read)
00781        PHP_FE(zip_entry_filesize,  arginfo_zip_entry_filesize)
00782        PHP_FE(zip_entry_name,             arginfo_zip_entry_name)
00783        PHP_FE(zip_entry_compressedsize,          arginfo_zip_entry_compressedsize)
00784        PHP_FE(zip_entry_compressionmethod,              arginfo_zip_entry_compressionmethod)
00785        PHP_FE_END
00786 };
00787 /* }}} */
00788 
00789 /* {{{ ZE2 OO definitions */
00790 #ifdef PHP_ZIP_USE_OO 
00791 static zend_class_entry *zip_class_entry;
00792 static zend_object_handlers zip_object_handlers;
00793 
00794 static HashTable zip_prop_handlers;
00795 
00796 typedef int (*zip_read_int_t)(struct zip *za TSRMLS_DC);
00797 typedef char *(*zip_read_const_char_t)(struct zip *za, int *len TSRMLS_DC);
00798 typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj TSRMLS_DC);
00799 
00800 typedef struct _zip_prop_handler {
00801        zip_read_int_t read_int_func;
00802        zip_read_const_char_t read_const_char_func;
00803        zip_read_const_char_from_ze_t read_const_char_from_obj_func;
00804 
00805        int type;
00806 } zip_prop_handler;
00807 #endif
00808 /* }}} */
00809 
00810 #ifdef PHP_ZIP_USE_OO 
00811 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) /* {{{ */
00812 {
00813        zip_prop_handler hnd;
00814 
00815        hnd.read_const_char_func = read_char_func;
00816        hnd.read_int_func = read_int_func;
00817        hnd.read_const_char_from_obj_func = read_char_from_obj_func;
00818        hnd.type = rettype;
00819        zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(zip_prop_handler), NULL);
00820 }
00821 /* }}} */
00822 
00823 static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval **retval, int newzval TSRMLS_DC) /* {{{ */
00824 {
00825        const char *retchar = NULL;
00826        int retint = 0;
00827        int len = 0;
00828 
00829        if (obj && obj->za != NULL) {
00830               if (hnd->read_const_char_func) {
00831                      retchar = hnd->read_const_char_func(obj->za, &len TSRMLS_CC);
00832               } else {
00833                      if (hnd->read_int_func) {
00834                             retint = hnd->read_int_func(obj->za TSRMLS_CC);
00835                             if (retint == -1) {
00836                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal zip error returned");
00837                                    return FAILURE;
00838                             }
00839                      } else {
00840                             if (hnd->read_const_char_from_obj_func) {
00841                                    retchar = hnd->read_const_char_from_obj_func(obj TSRMLS_CC);
00842                                    len = strlen(retchar);
00843                             }
00844                      }
00845               }
00846        }
00847 
00848        if (newzval) {
00849               ALLOC_ZVAL(*retval);
00850        }
00851 
00852        switch (hnd->type) {
00853               case IS_STRING:
00854                      if (retchar) {
00855                             ZVAL_STRINGL(*retval, (char *) retchar, len, 1);
00856                      } else {
00857                             ZVAL_EMPTY_STRING(*retval);
00858                      }
00859                      break;
00860               case IS_BOOL:
00861                      ZVAL_BOOL(*retval, (long)retint);
00862                      break;
00863               case IS_LONG:
00864                      ZVAL_LONG(*retval, (long)retint);
00865                      break;
00866               default:
00867                      ZVAL_NULL(*retval);
00868        }
00869 
00870        return SUCCESS;
00871 }
00872 /* }}} */
00873 
00874 static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
00875 {
00876        ze_zip_object *obj;
00877        zval tmp_member;
00878        zval **retval = NULL;
00879 
00880        zip_prop_handler *hnd;
00881        zend_object_handlers *std_hnd;
00882        int ret;
00883 
00884        if (member->type != IS_STRING) {
00885               tmp_member = *member;
00886               zval_copy_ctor(&tmp_member);
00887               convert_to_string(&tmp_member);
00888               member = &tmp_member;
00889        }
00890 
00891        ret = FAILURE;
00892        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
00893 
00894        if (obj->prop_handler != NULL) {
00895               ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
00896        }
00897 
00898 
00899        if (ret == FAILURE) {
00900               std_hnd = zend_get_std_object_handlers();
00901               retval = std_hnd->get_property_ptr_ptr(object, member TSRMLS_CC);
00902        }
00903 
00904        if (member == &tmp_member) {
00905               zval_dtor(member);
00906        }
00907        return retval;
00908 }
00909 /* }}} */
00910 
00911 static zval* php_zip_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
00912 {
00913        ze_zip_object *obj;
00914        zval tmp_member;
00915        zval *retval;
00916        zip_prop_handler *hnd;
00917        zend_object_handlers *std_hnd;
00918        int ret;
00919 
00920        if (member->type != IS_STRING) {
00921               tmp_member = *member;
00922               zval_copy_ctor(&tmp_member);
00923               convert_to_string(&tmp_member);
00924               member = &tmp_member;
00925        }
00926 
00927        ret = FAILURE;
00928        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
00929 
00930        if (obj->prop_handler != NULL) {
00931               ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
00932        }
00933 
00934        if (ret == SUCCESS) {
00935               ret = php_zip_property_reader(obj, hnd, &retval, 1 TSRMLS_CC);
00936               if (ret == SUCCESS) {
00937                      /* ensure we're creating a temporary variable */
00938                      Z_SET_REFCOUNT_P(retval, 0);
00939               } else {
00940                      retval = EG(uninitialized_zval_ptr);
00941               }
00942        } else {
00943               std_hnd = zend_get_std_object_handlers();
00944               retval = std_hnd->read_property(object, member, type TSRMLS_CC);
00945        }
00946 
00947        if (member == &tmp_member) {
00948               zval_dtor(member);
00949        }
00950        return retval;
00951 }
00952 /* }}} */
00953 
00954 static int php_zip_has_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
00955 {
00956        ze_zip_object *obj;
00957        zval tmp_member;
00958        zip_prop_handler *hnd;
00959        zend_object_handlers *std_hnd;
00960        int ret, retval = 0;
00961 
00962        if (member->type != IS_STRING) {
00963               tmp_member = *member;
00964               zval_copy_ctor(&tmp_member);
00965               convert_to_string(&tmp_member);
00966               member = &tmp_member;
00967        }
00968 
00969        ret = FAILURE;
00970        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
00971 
00972        if (obj->prop_handler != NULL) {
00973               ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
00974        }
00975 
00976        if (ret == SUCCESS) {
00977               zval *tmp;
00978               ALLOC_INIT_ZVAL(tmp);
00979 
00980               if (type == 2) {
00981                      retval = 1;
00982               } else if (php_zip_property_reader(obj, hnd, &tmp, 0 TSRMLS_CC) == SUCCESS) {
00983                      Z_SET_REFCOUNT_P(tmp, 1);
00984                      Z_UNSET_ISREF_P(tmp);
00985                      if (type == 1) {
00986                             retval = zend_is_true(tmp);
00987                      } else if (type == 0) {
00988                             retval = (Z_TYPE_P(tmp) != IS_NULL);
00989                      }
00990               }
00991 
00992               zval_ptr_dtor(&tmp);
00993        } else {
00994               std_hnd = zend_get_std_object_handlers();
00995               retval = std_hnd->has_property(object, member, type TSRMLS_CC);
00996        }
00997 
00998        if (member == &tmp_member) {
00999               zval_dtor(member);
01000        }
01001        return retval;
01002 }
01003 /* }}} */
01004 
01005 static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
01006 {
01007        ze_zip_object *obj;
01008        zip_prop_handler *hnd;
01009        HashTable *props;
01010        zval *val;
01011        int ret;
01012        char *key;
01013        uint key_len;
01014        HashPosition pos;
01015        ulong num_key;
01016 
01017        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
01018        props = obj->zo.properties;
01019 
01020        if (obj->prop_handler == NULL) {
01021               return NULL;
01022        }
01023        zend_hash_internal_pointer_reset_ex(obj->prop_handler, &pos);
01024 
01025        while (zend_hash_get_current_data_ex(obj->prop_handler, (void**)&hnd, &pos) == SUCCESS) {
01026               zend_hash_get_current_key_ex(obj->prop_handler, &key, &key_len, &num_key, 0, &pos);
01027               MAKE_STD_ZVAL(val);
01028               ret = php_zip_property_reader(obj, hnd, &val, 0 TSRMLS_CC);
01029               if (ret != SUCCESS) {
01030                      val = EG(uninitialized_zval_ptr);
01031               }
01032               zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
01033               zend_hash_move_forward_ex(obj->prop_handler, &pos);
01034        }
01035        return obj->zo.properties;
01036 }
01037 /* }}} */
01038 
01039 static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
01040 {
01041        ze_zip_object * intern = (ze_zip_object *) object;
01042        int i;
01043 
01044        if (!intern) {
01045               return;
01046        }
01047        if (intern->za) {
01048               if (zip_close(intern->za) != 0) {
01049                      _zip_free(intern->za);
01050               }
01051               intern->za = NULL;
01052        }
01053 
01054        if (intern->buffers_cnt>0) {
01055               for (i=0; i<intern->buffers_cnt; i++) {
01056                      efree(intern->buffers[i]);
01057               }
01058               efree(intern->buffers);
01059        }
01060 
01061        intern->za = NULL;
01062 
01063 #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)
01064        zend_object_std_dtor(&intern->zo TSRMLS_CC);
01065 #else
01066        if (intern->zo.guards) {
01067               zend_hash_destroy(intern->zo.guards);
01068               FREE_HASHTABLE(intern->zo.guards);
01069        }
01070 
01071        if (intern->zo.properties) {
01072               zend_hash_destroy(intern->zo.properties);
01073               FREE_HASHTABLE(intern->zo.properties);
01074        }
01075 #endif
01076 
01077        if (intern->filename) {
01078               efree(intern->filename);
01079        }
01080        efree(intern);
01081 }
01082 /* }}} */
01083 
01084 static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
01085 {
01086        ze_zip_object *intern;
01087        zval *tmp;
01088        zend_object_value retval;
01089 
01090        intern = emalloc(sizeof(ze_zip_object));
01091        memset(&intern->zo, 0, sizeof(zend_object));
01092 
01093        intern->za = NULL;
01094        intern->buffers = NULL;
01095        intern->filename = NULL;
01096        intern->buffers_cnt = 0;
01097        intern->prop_handler = &zip_prop_handlers;
01098 
01099 #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2))
01100        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
01101 #else
01102        ALLOC_HASHTABLE(intern->zo.properties);
01103        zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
01104        intern->zo.ce = class_type;
01105 #endif
01106 
01107        zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
01108                                    (void *) &tmp, sizeof(zval *));
01109 
01110        retval.handle = zend_objects_store_put(intern,
01111                                           NULL,
01112                                           (zend_objects_free_object_storage_t) php_zip_object_free_storage,
01113                                           NULL TSRMLS_CC);
01114 
01115        retval.handlers = (zend_object_handlers *) & zip_object_handlers;
01116 
01117        return retval;
01118 }
01119 /* }}} */
01120 #endif
01121 
01122 /* {{{ Resource dtors */
01123 
01124 /* {{{ php_zip_free_dir */
01125 static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC)
01126 {
01127        zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
01128 
01129        if (zip_int) {
01130               if (zip_int->za) {
01131                      if (zip_close(zip_int->za) != 0) {
01132                             _zip_free(zip_int->za);
01133                      }
01134                      zip_int->za = NULL;
01135               }
01136 
01137               efree(rsrc->ptr);
01138 
01139               rsrc->ptr = NULL;
01140        }
01141 }
01142 /* }}} */
01143 
01144 /* {{{ php_zip_free_entry */
01145 static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
01146 {
01147        zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
01148 
01149        if (zr_rsrc) {
01150               if (zr_rsrc->zf) {
01151                      zip_fclose(zr_rsrc->zf);
01152                      zr_rsrc->zf = NULL;
01153               }
01154               efree(zr_rsrc);
01155               rsrc->ptr = NULL;
01156        }
01157 }
01158 /* }}} */
01159 
01160 /* }}}*/
01161 
01162 /* reset macro */
01163 
01164 /* {{{ function prototypes */
01165 static PHP_MINIT_FUNCTION(zip);
01166 static PHP_MSHUTDOWN_FUNCTION(zip);
01167 static PHP_MINFO_FUNCTION(zip);
01168 /* }}} */
01169 
01170 /* {{{ zip_module_entry
01171  */
01172 zend_module_entry zip_module_entry = {
01173        STANDARD_MODULE_HEADER,
01174        "zip",
01175        zip_functions,
01176        PHP_MINIT(zip),
01177        PHP_MSHUTDOWN(zip),
01178        NULL,
01179        NULL,
01180        PHP_MINFO(zip),
01181        PHP_ZIP_VERSION_STRING,
01182        STANDARD_MODULE_PROPERTIES
01183 };
01184 /* }}} */
01185 
01186 #ifdef COMPILE_DL_ZIP
01187 ZEND_GET_MODULE(zip)
01188 #endif
01189 /* set macro */
01190 
01191 /* {{{ proto resource zip_open(string filename)
01192 Create new zip using source uri for output */
01193 static PHP_NAMED_FUNCTION(zif_zip_open)
01194 {
01195        char     *filename;
01196        int       filename_len;
01197        char resolved_path[MAXPATHLEN + 1];
01198        zip_rsrc *rsrc_int;
01199        int err = 0;
01200 
01201        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
01202               return;
01203        }
01204 
01205        if (filename_len == 0) {
01206               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
01207               RETURN_FALSE;
01208        }
01209 
01210        if (strlen(filename) != filename_len) {
01211               RETURN_FALSE;
01212        }
01213 
01214        if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
01215               RETURN_FALSE;
01216        }
01217 
01218        if(!expand_filepath(filename, resolved_path TSRMLS_CC)) {
01219               RETURN_FALSE;
01220        }
01221 
01222        rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
01223 
01224        rsrc_int->za = zip_open(resolved_path, 0, &err);
01225        if (rsrc_int->za == NULL) {
01226               efree(rsrc_int);
01227               RETURN_LONG((long)err);
01228        }
01229 
01230        rsrc_int->index_current = 0;
01231        rsrc_int->num_files = zip_get_num_files(rsrc_int->za);
01232 
01233        ZEND_REGISTER_RESOURCE(return_value, rsrc_int, le_zip_dir);
01234 }
01235 /* }}} */
01236 
01237 /* {{{ proto void zip_close(resource zip)
01238    Close a Zip archive */
01239 static PHP_NAMED_FUNCTION(zif_zip_close)
01240 {
01241        zval * zip;
01242        zip_rsrc *z_rsrc = NULL;
01243 
01244        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip) == FAILURE) {
01245               return;
01246        }
01247        ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
01248 
01249        /* really close the zip will break BC :-D */
01250        zend_list_delete(Z_LVAL_P(zip));
01251 }
01252 /* }}} */
01253 
01254 /* {{{ proto resource zip_read(resource zip)
01255    Returns the next file in the archive */
01256 static PHP_NAMED_FUNCTION(zif_zip_read)
01257 {
01258        zval *zip_dp;
01259        zip_read_rsrc *zr_rsrc;
01260        int ret;
01261        zip_rsrc *rsrc_int;
01262 
01263        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_dp) == FAILURE) {
01264               return;
01265        }
01266        ZEND_FETCH_RESOURCE(rsrc_int, zip_rsrc *, &zip_dp, -1, le_zip_dir_name, le_zip_dir);
01267 
01268        if (rsrc_int && rsrc_int->za) {
01269               if (rsrc_int->index_current >= rsrc_int->num_files) {
01270                      RETURN_FALSE;
01271               }
01272 
01273               zr_rsrc = emalloc(sizeof(zip_read_rsrc));
01274 
01275               ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
01276 
01277               if (ret != 0) {
01278                      efree(zr_rsrc);
01279                      RETURN_FALSE;
01280               }
01281 
01282               zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
01283               if (zr_rsrc->zf) {
01284                      rsrc_int->index_current++;
01285                      ZEND_REGISTER_RESOURCE(return_value, zr_rsrc, le_zip_entry);
01286               } else {
01287                      efree(zr_rsrc);
01288                      RETURN_FALSE;
01289               }
01290 
01291        } else {
01292               RETURN_FALSE;
01293        }
01294 }
01295 /* }}} */
01296 
01297 /* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode])
01298    Open a Zip File, pointed by the resource entry */
01299 /* Dummy function to follow the old API */
01300 static PHP_NAMED_FUNCTION(zif_zip_entry_open)
01301 {
01302        zval * zip;
01303        zval * zip_entry;
01304        char *mode = NULL;
01305        int mode_len = 0;
01306        zip_read_rsrc * zr_rsrc;
01307        zip_rsrc *z_rsrc;
01308 
01309        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
01310               return;
01311        }
01312 
01313        ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
01314        ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
01315 
01316        if (zr_rsrc->zf != NULL) {
01317               RETURN_TRUE;
01318        } else {
01319               RETURN_FALSE;
01320        }
01321 }
01322 /* }}} */
01323 
01324 /* {{{ proto void zip_entry_close(resource zip_ent)
01325    Close a zip entry */
01326 /* another dummy function to fit in the old api*/
01327 static PHP_NAMED_FUNCTION(zif_zip_entry_close)
01328 {
01329        zval * zip_entry;
01330        zip_read_rsrc * zr_rsrc;
01331 
01332        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
01333               return;
01334        }
01335 
01336        ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
01337        /*  we got a zip_entry resource, be happy */
01338        RETURN_TRUE;
01339 }
01340 /* }}} */
01341 
01342 /* {{{ proto mixed zip_entry_read(resource zip_entry [, int len])
01343    Read from an open directory entry */
01344 static PHP_NAMED_FUNCTION(zif_zip_entry_read)
01345 {
01346        zval * zip_entry;
01347        long len = 0;
01348        zip_read_rsrc * zr_rsrc;
01349        char *buffer;
01350        int n = 0;
01351 
01352        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zip_entry, &len) == FAILURE) {
01353               return;
01354        }
01355 
01356        ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
01357 
01358        if (len <= 0) {
01359               len = 1024;
01360        }
01361 
01362        if (zr_rsrc->zf) {
01363               buffer = safe_emalloc(len, 1, 1);
01364               n = zip_fread(zr_rsrc->zf, buffer, len);
01365               if (n > 0) {
01366                      buffer[n] = 0;
01367                      RETURN_STRINGL(buffer, n, 0);
01368               } else {
01369                      efree(buffer);
01370                      RETURN_EMPTY_STRING()
01371               }
01372        } else {
01373               RETURN_FALSE;
01374        }
01375 }
01376 /* }}} */
01377 
01378 static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
01379 {
01380        zval * zip_entry;
01381        zip_read_rsrc * zr_rsrc;
01382 
01383        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
01384               return;
01385        }
01386 
01387        ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
01388 
01389        if (!zr_rsrc->zf) {
01390               RETURN_FALSE;
01391        }
01392 
01393        switch (opt) {
01394               case 0:
01395                      RETURN_STRING((char *)zr_rsrc->sb.name, 1);
01396                      break;
01397               case 1:
01398                      RETURN_LONG((long) (zr_rsrc->sb.comp_size));
01399                      break;
01400               case 2:
01401                      RETURN_LONG((long) (zr_rsrc->sb.size));
01402                      break;
01403               case 3:
01404                      switch (zr_rsrc->sb.comp_method) {
01405                             case 0:
01406                                    RETURN_STRING("stored", 1);
01407                                    break;
01408                             case 1:
01409                                    RETURN_STRING("shrunk", 1);
01410                                    break;
01411                             case 2:
01412                             case 3:
01413                             case 4:
01414                             case 5:
01415                                    RETURN_STRING("reduced", 1);
01416                                    break;
01417                             case 6:
01418                                    RETURN_STRING("imploded", 1);
01419                                    break;
01420                             case 7:
01421                                    RETURN_STRING("tokenized", 1);
01422                                    break;
01423                             case 8:
01424                                    RETURN_STRING("deflated", 1);
01425                                    break;
01426                             case 9:
01427                                    RETURN_STRING("deflatedX", 1);
01428                                    break;
01429                             case 10:
01430                                    RETURN_STRING("implodedX", 1);
01431                                    break;
01432                             default:
01433                                    RETURN_FALSE;
01434                      }
01435                      RETURN_LONG((long) (zr_rsrc->sb.comp_method));
01436                      break;
01437        }
01438 
01439 }
01440 /* }}} */
01441 
01442 /* {{{ proto string zip_entry_name(resource zip_entry)
01443    Return the name given a ZZip entry */
01444 static PHP_NAMED_FUNCTION(zif_zip_entry_name)
01445 {
01446        php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
01447 }
01448 /* }}} */
01449 
01450 /* {{{ proto int zip_entry_compressedsize(resource zip_entry)
01451    Return the compressed size of a ZZip entry */
01452 static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)
01453 {
01454        php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
01455 }
01456 /* }}} */
01457 
01458 /* {{{ proto int zip_entry_filesize(resource zip_entry)
01459    Return the actual filesize of a ZZip entry */
01460 static PHP_NAMED_FUNCTION(zif_zip_entry_filesize)
01461 {
01462        php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
01463 }
01464 /* }}} */
01465 
01466 /* {{{ proto string zip_entry_compressionmethod(resource zip_entry)
01467    Return a string containing the compression method used on a particular entry */
01468 static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
01469 {
01470        php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
01471 }
01472 /* }}} */
01473 
01474 #ifdef PHP_ZIP_USE_OO 
01475 /* {{{ proto mixed ZipArchive::open(string source [, int flags])
01476 Create new zip using source uri for output, return TRUE on success or the error code */
01477 static ZIPARCHIVE_METHOD(open)
01478 {
01479        struct zip *intern;
01480        char *filename;
01481        int filename_len;
01482        int err = 0;
01483        long flags = 0;
01484        char resolved_path[MAXPATHLEN];
01485 
01486        zval *this = getThis();
01487        ze_zip_object *ze_obj = NULL;
01488 
01489        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
01490               return;
01491        }
01492 
01493        if (this) {
01494               /* We do not use ZIP_FROM_OBJECT, zip init function here */
01495               ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
01496        }
01497 
01498        if (filename_len == 0) {
01499               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
01500               RETURN_FALSE;
01501        }
01502 
01503        if (strlen(filename) != filename_len) {
01504               RETURN_FALSE;
01505        }
01506 
01507        if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
01508               RETURN_FALSE;
01509        }
01510 
01511        if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
01512               RETURN_FALSE;
01513        }
01514 
01515        if (ze_obj->za) {
01516               /* we already have an opened zip, free it */
01517               if (zip_close(ze_obj->za) != 0) {
01518                      _zip_free(ze_obj->za);
01519               }
01520               ze_obj->za = NULL;
01521        }
01522        if (ze_obj->filename) {
01523               efree(ze_obj->filename);
01524               ze_obj->filename = NULL;
01525        }
01526 
01527        intern = zip_open(resolved_path, flags, &err);
01528        if (!intern || err) {
01529               RETURN_LONG((long)err);
01530        }
01531        ze_obj->filename = estrdup(resolved_path);
01532        ze_obj->filename_len = filename_len;
01533        ze_obj->za = intern;
01534        RETURN_TRUE;
01535 }
01536 /* }}} */
01537 
01538 /* {{{ proto bool ZipArchive::close()
01539 close the zip archive */
01540 static ZIPARCHIVE_METHOD(close)
01541 {
01542        struct zip *intern;
01543        zval *this = getThis();
01544        ze_zip_object *ze_obj;
01545 
01546        if (!this) {
01547                      RETURN_FALSE;
01548        }
01549 
01550        ZIP_FROM_OBJECT(intern, this);
01551 
01552        ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
01553 
01554        if (zip_close(intern)) {
01555               RETURN_FALSE;
01556        }
01557 
01558        efree(ze_obj->filename);
01559        ze_obj->filename = NULL;
01560        ze_obj->filename_len = 0;
01561        ze_obj->za = NULL;
01562 
01563        RETURN_TRUE;
01564 }
01565 /* }}} */
01566 
01567 /* {{{ proto string ZipArchive::getStatusString()
01568  * Returns the status error message, system and/or zip messages */
01569 static ZIPARCHIVE_METHOD(getStatusString)
01570 {
01571        struct zip *intern;
01572        zval *this = getThis();
01573        int zep, syp, len;
01574        char error_string[128];
01575 
01576        if (!this) {
01577               RETURN_FALSE;
01578        }
01579 
01580        ZIP_FROM_OBJECT(intern, this);
01581 
01582        zip_error_get(intern, &zep, &syp);
01583 
01584        len = zip_error_to_str(error_string, 128, zep, syp);
01585        RETVAL_STRINGL(error_string, len, 1); 
01586 }
01587 /* }}} */
01588 
01589 /* {{{ proto bool ZipArchive::createEmptyDir(string dirname)
01590 Returns the index of the entry named filename in the archive */
01591 static ZIPARCHIVE_METHOD(addEmptyDir)
01592 {
01593        struct zip *intern;
01594        zval *this = getThis();
01595        char *dirname;
01596        int   dirname_len;
01597        int idx;
01598        struct zip_stat sb;
01599        char *s;
01600 
01601        if (!this) {
01602               RETURN_FALSE;
01603        }
01604 
01605        ZIP_FROM_OBJECT(intern, this);
01606 
01607        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
01608                             &dirname, &dirname_len) == FAILURE) {
01609               return;
01610        }
01611 
01612        if (dirname_len<1) {
01613               RETURN_FALSE;
01614        }
01615 
01616        if (dirname[dirname_len-1] != '/') {
01617               s=(char *)emalloc(dirname_len+2);
01618               strcpy(s, dirname);
01619               s[dirname_len] = '/';
01620               s[dirname_len+1] = '\0';
01621        } else {
01622               s = dirname;
01623        }
01624 
01625        idx = zip_stat(intern, s, 0, &sb);
01626        if (idx >= 0) {
01627               RETVAL_FALSE;
01628        } else {
01629               if (zip_add_dir(intern, (const char *)s) == -1) {
01630                      RETVAL_FALSE;
01631               }
01632               RETVAL_TRUE;
01633        }
01634 
01635        if (s != dirname) {
01636               efree(s);
01637        }
01638 }
01639 /* }}} */
01640 
01641 static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
01642 {
01643        struct zip *intern;
01644        zval *this = getThis();
01645        char *pattern;
01646        char *path = NULL;
01647        char *remove_path = NULL;
01648        char *add_path = NULL;
01649        int pattern_len, add_path_len, remove_path_len, path_len = 0;
01650        long remove_all_path = 0;
01651        long flags = 0;
01652        zval *options = NULL;
01653        int found;
01654 
01655        if (!this) {
01656               RETURN_FALSE;
01657        }
01658 
01659        ZIP_FROM_OBJECT(intern, this);
01660        /* 1 == glob, 2==pcre */
01661        if (type == 1) {
01662               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la", 
01663                                    &pattern, &pattern_len, &flags, &options) == FAILURE) {
01664                      return;
01665               }
01666        } else {
01667               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sa", 
01668                                    &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
01669                      return;
01670               }
01671        }
01672 
01673        if (pattern_len == 0) {
01674               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as pattern");
01675               RETURN_FALSE;
01676        }
01677        if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len,
01678                      &add_path, &add_path_len TSRMLS_CC) < 0)) {
01679               RETURN_FALSE;
01680        }
01681 
01682        if (remove_path && remove_path_len > 1 && (remove_path[strlen(remove_path) - 1] == '/' ||
01683               remove_path[strlen(remove_path) - 1] == '\\')) {
01684               remove_path[strlen(remove_path) - 1] = '\0';
01685        }
01686 
01687        if (type == 1) {
01688               found = php_zip_glob(pattern, pattern_len, flags, return_value TSRMLS_CC);
01689        } else {
01690               found = php_zip_pcre(pattern, pattern_len, path, path_len, return_value TSRMLS_CC);
01691        }
01692 
01693        if (found > 0) {
01694               int i;
01695               zval **zval_file = NULL;
01696 
01697               for (i = 0; i < found; i++) {
01698                      char *file, *file_stripped, *entry_name;
01699                      size_t entry_name_len, file_stripped_len;
01700                      char entry_name_buf[MAXPATHLEN];
01701                      char *basename = NULL;
01702 
01703                      if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) {
01704                             file = Z_STRVAL_PP(zval_file);
01705                             if (remove_all_path) {
01706                                    php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0,
01707                                                                &basename, (size_t *)&file_stripped_len TSRMLS_CC);
01708                                    file_stripped = basename;
01709                             } else if (remove_path && strstr(Z_STRVAL_PP(zval_file), remove_path) != NULL) {
01710                                    file_stripped = Z_STRVAL_PP(zval_file) + remove_path_len + 1;
01711                                    file_stripped_len = Z_STRLEN_PP(zval_file) - remove_path_len - 1;
01712                             } else {
01713                                    file_stripped = Z_STRVAL_PP(zval_file);
01714                                    file_stripped_len = Z_STRLEN_PP(zval_file);
01715                             }
01716 
01717                             if (add_path) {
01718                                    if ((add_path_len + file_stripped_len) > MAXPATHLEN) {
01719                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)", 
01720                                           MAXPATHLEN - 1, (add_path_len + file_stripped_len));
01721                                           zval_dtor(return_value);
01722                                           RETURN_FALSE;
01723                                    }
01724 
01725                                    snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped);
01726                                    entry_name = entry_name_buf; 
01727                                    entry_name_len = strlen(entry_name);
01728                             } else {
01729                                    entry_name = Z_STRVAL_PP(zval_file);
01730                                    entry_name_len = Z_STRLEN_PP(zval_file);
01731                             }
01732                             if (basename) {
01733                                    efree(basename);
01734                                    basename = NULL;
01735                             }
01736                             if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), 
01737                                    entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
01738                                    zval_dtor(return_value);
01739                                    RETURN_FALSE;
01740                             }
01741                      }
01742               }
01743        }
01744 }
01745 /* }}} */
01746 
01747 /* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]])
01748 Add files matching the glob pattern. See php's glob for the pattern syntax. */
01749 static ZIPARCHIVE_METHOD(addGlob)
01750 {
01751        php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
01752 }
01753 /* }}} */
01754 
01755 /* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]])
01756 Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
01757 static ZIPARCHIVE_METHOD(addPattern)
01758 {
01759        php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
01760 }
01761 /* }}} */
01762 
01763 /* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]])
01764 Add a file in a Zip archive using its path and the name to use. */
01765 static ZIPARCHIVE_METHOD(addFile)
01766 {
01767        struct zip *intern;
01768        zval *this = getThis();
01769        char *filename;
01770        int filename_len;
01771        char *entry_name = NULL;
01772        int entry_name_len = 0;
01773        long offset_start = 0, offset_len = 0;
01774 
01775        if (!this) {
01776               RETURN_FALSE;
01777        }
01778 
01779        ZIP_FROM_OBJECT(intern, this);
01780 
01781        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sll",
01782                      &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
01783               return;
01784        }
01785 
01786        if (filename_len == 0) {
01787               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as filename");
01788               RETURN_FALSE;
01789        }
01790 
01791        if (entry_name_len == 0) {
01792               entry_name = filename;
01793               entry_name_len = filename_len;
01794        }
01795 
01796        if (php_zip_add_file(intern, filename, filename_len, 
01797               entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
01798               RETURN_FALSE;
01799        } else {
01800               RETURN_TRUE;
01801        }
01802 }
01803 /* }}} */
01804 
01805 /* {{{ proto bool ZipArchive::addFromString(string name, string content)
01806 Add a file using content and the entry name */
01807 static ZIPARCHIVE_METHOD(addFromString)
01808 {
01809        struct zip *intern;
01810        zval *this = getThis();
01811        char *buffer, *name;
01812        int buffer_len, name_len;
01813        ze_zip_object *ze_obj;
01814        struct zip_source *zs;
01815        int pos = 0;
01816        int cur_idx;
01817 
01818        if (!this) {
01819               RETURN_FALSE;
01820        }
01821 
01822        ZIP_FROM_OBJECT(intern, this);
01823 
01824        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
01825                      &name, &name_len, &buffer, &buffer_len) == FAILURE) {
01826               return;
01827        }
01828 
01829        ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
01830        if (ze_obj->buffers_cnt) {
01831               ze_obj->buffers = (char **)erealloc(ze_obj->buffers, sizeof(char *) * (ze_obj->buffers_cnt+1));
01832               pos = ze_obj->buffers_cnt++;
01833        } else {
01834               ze_obj->buffers = (char **)emalloc(sizeof(char *));
01835               ze_obj->buffers_cnt++;
01836               pos = 0;
01837        }
01838        ze_obj->buffers[pos] = (char *)emalloc(buffer_len + 1);
01839        memcpy(ze_obj->buffers[pos], buffer, buffer_len + 1);
01840 
01841        zs = zip_source_buffer(intern, ze_obj->buffers[pos], buffer_len, 0);
01842 
01843        if (zs == NULL) {
01844               RETURN_FALSE;
01845        }
01846 
01847        cur_idx = zip_name_locate(intern, (const char *)name, 0);
01848        /* TODO: fix  _zip_replace */
01849        if (cur_idx >= 0) {
01850               if (zip_delete(intern, cur_idx) == -1) {
01851                      RETURN_FALSE;
01852               }
01853        }
01854 
01855        if (zip_add(intern, name, zs) == -1) {
01856               RETURN_FALSE;
01857        } else {
01858               RETURN_TRUE;
01859        }
01860 }
01861 /* }}} */
01862 
01863 /* {{{ proto array ZipArchive::statName(string filename[, int flags])
01864 Returns the information about a the zip entry filename */
01865 static ZIPARCHIVE_METHOD(statName)
01866 {
01867        struct zip *intern;
01868        zval *this = getThis();
01869        char *name;
01870        int name_len;
01871        long flags = 0;
01872        struct zip_stat sb;
01873 
01874        if (!this) {
01875               RETURN_FALSE;
01876        }
01877 
01878        ZIP_FROM_OBJECT(intern, this);
01879 
01880        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
01881                      &name, &name_len, &flags) == FAILURE) {
01882               return;
01883        }
01884 
01885        PHP_ZIP_STAT_PATH(intern, name, name_len, flags, sb);
01886 
01887        RETURN_SB(&sb);
01888 }
01889 /* }}} */
01890 
01891 /* {{{ proto resource ZipArchive::statIndex(int index[, int flags])
01892 Returns the zip entry informations using its index */
01893 static ZIPARCHIVE_METHOD(statIndex)
01894 {
01895        struct zip *intern;
01896        zval *this = getThis();
01897        long index, flags = 0;
01898 
01899        struct zip_stat sb;
01900 
01901        if (!this) {
01902               RETURN_FALSE;
01903        }
01904 
01905        ZIP_FROM_OBJECT(intern, this);
01906 
01907        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
01908                      &index, &flags) == FAILURE) {
01909               return;
01910        }
01911 
01912        if (zip_stat_index(intern, index, flags, &sb) != 0) {
01913               RETURN_FALSE;
01914        }
01915        RETURN_SB(&sb);
01916 }
01917 /* }}} */
01918 
01919 /* {{{ proto int ZipArchive::locateName(string filename[, int flags])
01920 Returns the index of the entry named filename in the archive */
01921 static ZIPARCHIVE_METHOD(locateName)
01922 {
01923        struct zip *intern;
01924        zval *this = getThis();
01925        char *name;
01926        int name_len;
01927        long flags = 0;
01928        long idx = -1;
01929 
01930        if (!this) {
01931               RETURN_FALSE;
01932        }
01933 
01934        ZIP_FROM_OBJECT(intern, this);
01935 
01936        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
01937                      &name, &name_len, &flags) == FAILURE) {
01938               return;
01939        }
01940        if (name_len<1) {
01941               RETURN_FALSE;
01942        }
01943 
01944        idx = (long)zip_name_locate(intern, (const char *)name, flags);
01945 
01946        if (idx >= 0) {
01947               RETURN_LONG(idx);
01948        } else {
01949               RETURN_FALSE;
01950        }
01951 }
01952 /* }}} */
01953 
01954 /* {{{ proto string ZipArchive::getNameIndex(int index [, int flags])
01955 Returns the name of the file at position index */
01956 static ZIPARCHIVE_METHOD(getNameIndex)
01957 {
01958        struct zip *intern;
01959        zval *this = getThis();
01960        const char *name;
01961        long flags = 0, index = 0;
01962 
01963        if (!this) {
01964               RETURN_FALSE;
01965        }
01966 
01967        ZIP_FROM_OBJECT(intern, this);
01968 
01969        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
01970                      &index, &flags) == FAILURE) {
01971               return;
01972        }
01973 
01974        name = zip_get_name(intern, (int) index, flags);
01975 
01976        if (name) {
01977               RETVAL_STRING((char *)name, 1);
01978        } else {
01979               RETURN_FALSE;
01980        }
01981 }
01982 /* }}} */
01983 
01984 /* {{{ proto bool ZipArchive::setArchiveComment(string comment)
01985 Set or remove (NULL/'') the comment of the archive */
01986 static ZIPARCHIVE_METHOD(setArchiveComment)
01987 {
01988        struct zip *intern;
01989        zval *this = getThis();
01990        int comment_len;
01991        char * comment;
01992 
01993        if (!this) {
01994               RETURN_FALSE;
01995        }
01996 
01997        ZIP_FROM_OBJECT(intern, this);
01998 
01999        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &comment, &comment_len) == FAILURE) {
02000               return;
02001        }
02002        if (zip_set_archive_comment(intern, (const char *)comment, (int)comment_len)) {
02003               RETURN_FALSE;
02004        } else {
02005               RETURN_TRUE;
02006        }
02007 }
02008 /* }}} */
02009 
02010 /* {{{ proto string ZipArchive::getArchiveComment([int flags])
02011 Returns the comment of an entry using its index */
02012 static ZIPARCHIVE_METHOD(getArchiveComment)
02013 {
02014        struct zip *intern;
02015        zval *this = getThis();
02016        long flags = 0;
02017        const char * comment;
02018        int comment_len = 0;
02019 
02020        if (!this) {
02021               RETURN_FALSE;
02022        }
02023 
02024        ZIP_FROM_OBJECT(intern, this);
02025 
02026        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
02027               return;
02028        }
02029 
02030        comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
02031        if(comment==NULL) {
02032               RETURN_FALSE;
02033        }
02034        RETURN_STRINGL((char *)comment, (long)comment_len, 1);
02035 }
02036 /* }}} */
02037 
02038 /* {{{ proto bool ZipArchive::setCommentName(string name, string comment)
02039 Set or remove (NULL/'') the comment of an entry using its Name */
02040 static ZIPARCHIVE_METHOD(setCommentName)
02041 {
02042        struct zip *intern;
02043        zval *this = getThis();
02044        int comment_len, name_len;
02045        char * comment, *name;
02046        int idx;
02047 
02048        if (!this) {
02049               RETURN_FALSE;
02050        }
02051 
02052        ZIP_FROM_OBJECT(intern, this);
02053 
02054        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
02055                      &name, &name_len, &comment, &comment_len) == FAILURE) {
02056               return;
02057        }
02058 
02059        if (name_len < 1) {
02060               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
02061        }
02062 
02063        idx = zip_name_locate(intern, name, 0);
02064        if (idx < 0) {
02065               RETURN_FALSE;
02066        }
02067        PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
02068 }
02069 /* }}} */
02070 
02071 /* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment)
02072 Set or remove (NULL/'') the comment of an entry using its index */
02073 static ZIPARCHIVE_METHOD(setCommentIndex)
02074 {
02075        struct zip *intern;
02076        zval *this = getThis();
02077        long index;
02078        int comment_len;
02079        char * comment;
02080        struct zip_stat sb;
02081 
02082        if (!this) {
02083               RETURN_FALSE;
02084        }
02085 
02086        ZIP_FROM_OBJECT(intern, this);
02087 
02088        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls",
02089                      &index, &comment, &comment_len) == FAILURE) {
02090               return;
02091        }
02092 
02093        PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
02094        PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
02095 }
02096 /* }}} */
02097 
02098 /* {{{ proto string ZipArchive::getCommentName(string name[, int flags])
02099 Returns the comment of an entry using its name */
02100 static ZIPARCHIVE_METHOD(getCommentName)
02101 {
02102        struct zip *intern;
02103        zval *this = getThis();
02104        int name_len, idx;
02105        long flags = 0;
02106        int comment_len = 0;
02107        const char * comment;
02108        char *name;
02109 
02110        if (!this) {
02111               RETURN_FALSE;
02112        }
02113 
02114        ZIP_FROM_OBJECT(intern, this);
02115 
02116        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
02117                      &name, &name_len, &flags) == FAILURE) {
02118               return;
02119        }
02120        if (name_len < 1) {
02121               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
02122               RETURN_FALSE;
02123        }
02124 
02125        idx = zip_name_locate(intern, name, 0);
02126        if (idx < 0) {
02127               RETURN_FALSE;
02128        }
02129 
02130        comment = zip_get_file_comment(intern, idx, &comment_len, (int)flags);
02131        RETURN_STRINGL((char *)comment, (long)comment_len, 1);
02132 }
02133 /* }}} */
02134 
02135 /* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags])
02136 Returns the comment of an entry using its index */
02137 static ZIPARCHIVE_METHOD(getCommentIndex)
02138 {
02139        struct zip *intern;
02140        zval *this = getThis();
02141        long index, flags = 0;
02142        const char * comment;
02143        int comment_len = 0;
02144        struct zip_stat sb;
02145 
02146        if (!this) {
02147               RETURN_FALSE;
02148        }
02149 
02150        ZIP_FROM_OBJECT(intern, this);
02151 
02152        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
02153                             &index, &flags) == FAILURE) {
02154               return;
02155        }
02156 
02157        PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
02158        comment = zip_get_file_comment(intern, index, &comment_len, (int)flags);
02159        RETURN_STRINGL((char *)comment, (long)comment_len, 1);
02160 }
02161 /* }}} */
02162 
02163 /* {{{ proto bool ZipArchive::deleteIndex(int index)
02164 Delete a file using its index */
02165 static ZIPARCHIVE_METHOD(deleteIndex)
02166 {
02167        struct zip *intern;
02168        zval *this = getThis();
02169        long index;
02170 
02171        if (!this) {
02172               RETURN_FALSE;
02173        }
02174 
02175        ZIP_FROM_OBJECT(intern, this);
02176 
02177        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
02178               return;
02179        }
02180 
02181        if (index < 0) {
02182               RETURN_FALSE;
02183        }
02184 
02185        if (zip_delete(intern, index) < 0) {
02186               RETURN_FALSE;
02187        }
02188 
02189        RETURN_TRUE;
02190 }
02191 /* }}} */
02192 
02193 /* {{{ proto bool ZipArchive::deleteName(string name)
02194 Delete a file using its index */
02195 static ZIPARCHIVE_METHOD(deleteName)
02196 {
02197        struct zip *intern;
02198        zval *this = getThis();
02199        int name_len;
02200        char *name;
02201        struct zip_stat sb;
02202 
02203        if (!this) {
02204               RETURN_FALSE;
02205        }
02206 
02207        ZIP_FROM_OBJECT(intern, this);
02208 
02209        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
02210               return;
02211        }
02212        if (name_len < 1) {
02213               RETURN_FALSE;
02214        }
02215 
02216        PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
02217        if (zip_delete(intern, sb.index)) {
02218               RETURN_FALSE;
02219        }
02220        RETURN_TRUE;
02221 }
02222 /* }}} */
02223 
02224 /* {{{ proto bool ZipArchive::renameIndex(int index, string new_name)
02225 Rename an entry selected by its index to new_name */
02226 static ZIPARCHIVE_METHOD(renameIndex)
02227 {
02228        struct zip *intern;
02229        zval *this = getThis();
02230 
02231        char *new_name;
02232        int new_name_len;
02233        long index;
02234 
02235        if (!this) {
02236               RETURN_FALSE;
02237        }
02238 
02239        ZIP_FROM_OBJECT(intern, this);
02240 
02241        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &index, &new_name, &new_name_len) == FAILURE) {
02242               return;
02243        }
02244 
02245        if (index < 0) {
02246               RETURN_FALSE;
02247        }
02248 
02249        if (new_name_len < 1) {
02250               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
02251               RETURN_FALSE;
02252        }
02253        if (zip_rename(intern, index, (const char *)new_name) != 0) {
02254               RETURN_FALSE;
02255        }
02256        RETURN_TRUE;
02257 }
02258 /* }}} */
02259 
02260 /* {{{ proto bool ZipArchive::renameName(string name, string new_name)
02261 Rename an entry selected by its name to new_name */
02262 static ZIPARCHIVE_METHOD(renameName)
02263 {
02264        struct zip *intern;
02265        zval *this = getThis();
02266        struct zip_stat sb;
02267        char *name, *new_name;
02268        int name_len, new_name_len;
02269 
02270        if (!this) {
02271               RETURN_FALSE;
02272        }
02273 
02274        ZIP_FROM_OBJECT(intern, this);
02275 
02276        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
02277               return;
02278        }
02279 
02280        if (new_name_len < 1) {
02281               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
02282               RETURN_FALSE;
02283        }
02284 
02285        PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
02286 
02287        if (zip_rename(intern, sb.index, (const char *)new_name)) {
02288               RETURN_FALSE;
02289        }
02290        RETURN_TRUE;
02291 }
02292 /* }}} */
02293 
02294 /* {{{ proto bool ZipArchive::unchangeIndex(int index)
02295 Changes to the file at position index are reverted */
02296 static ZIPARCHIVE_METHOD(unchangeIndex)
02297 {
02298        struct zip *intern;
02299        zval *this = getThis();
02300        long index;
02301 
02302        if (!this) {
02303               RETURN_FALSE;
02304        }
02305 
02306        ZIP_FROM_OBJECT(intern, this);
02307 
02308        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
02309               return;
02310        }
02311 
02312        if (index < 0) {
02313               RETURN_FALSE;
02314        }
02315 
02316        if (zip_unchange(intern, index) != 0) {
02317               RETURN_FALSE;
02318        } else {
02319               RETURN_TRUE;
02320        }
02321 }
02322 /* }}} */
02323 
02324 /* {{{ proto bool ZipArchive::unchangeName(string name)
02325 Changes to the file named 'name' are reverted */
02326 static ZIPARCHIVE_METHOD(unchangeName)
02327 {
02328        struct zip *intern;
02329        zval *this = getThis();
02330        struct zip_stat sb;
02331        char *name;
02332        int name_len;
02333 
02334        if (!this) {
02335               RETURN_FALSE;
02336        }
02337 
02338        ZIP_FROM_OBJECT(intern, this);
02339 
02340        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
02341               return;
02342        }
02343 
02344        if (name_len < 1) {
02345               RETURN_FALSE;
02346        }
02347 
02348        PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
02349 
02350        if (zip_unchange(intern, sb.index) != 0) {
02351               RETURN_FALSE;
02352        } else {
02353               RETURN_TRUE;
02354        }
02355 }
02356 /* }}} */
02357 
02358 /* {{{ proto bool ZipArchive::unchangeAll()
02359 All changes to files and global information in archive are reverted */
02360 static ZIPARCHIVE_METHOD(unchangeAll)
02361 {
02362        struct zip *intern;
02363        zval *this = getThis();
02364 
02365        if (!this) {
02366               RETURN_FALSE;
02367        }
02368 
02369        ZIP_FROM_OBJECT(intern, this);
02370 
02371        if (zip_unchange_all(intern) != 0) {
02372               RETURN_FALSE;
02373        } else {
02374               RETURN_TRUE;
02375        }
02376 }
02377 /* }}} */
02378 
02379 /* {{{ proto bool ZipArchive::unchangeArchive()
02380 Revert all global changes to the archive archive.  For now, this only reverts archive comment changes. */
02381 static ZIPARCHIVE_METHOD(unchangeArchive)
02382 {
02383        struct zip *intern;
02384        zval *this = getThis();
02385 
02386        if (!this) {
02387               RETURN_FALSE;
02388        }
02389 
02390        ZIP_FROM_OBJECT(intern, this);
02391 
02392        if (zip_unchange_archive(intern) != 0) {
02393               RETURN_FALSE;
02394        } else {
02395               RETURN_TRUE;
02396        }
02397 }
02398 /* }}} */
02399 
02400 /* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files])
02401 Extract one or more file from a zip archive */
02402 /* TODO:
02403  * - allow index or array of indeces
02404  * - replace path
02405  * - patterns
02406  */
02407 static ZIPARCHIVE_METHOD(extractTo)
02408 {
02409        struct zip *intern;
02410 
02411        zval *this = getThis();
02412        zval *zval_files = NULL;
02413        zval **zval_file = NULL;
02414        php_stream_statbuf ssb;
02415        char *pathto;
02416        int pathto_len;
02417        int ret, i;
02418 
02419        int nelems;
02420 
02421        if (!this) {
02422               RETURN_FALSE;
02423        }
02424 
02425        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &pathto, &pathto_len, &zval_files) == FAILURE) {
02426               return;
02427        }
02428 
02429        if (pathto_len < 1) {
02430               RETURN_FALSE;
02431        }
02432 
02433        if (strlen(pathto) != pathto_len) {
02434               RETURN_FALSE;
02435        }
02436 
02437        if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
02438               ret = php_stream_mkdir(pathto, 0777,  PHP_STREAM_MKDIR_RECURSIVE, NULL);
02439               if (!ret) {
02440                      RETURN_FALSE;
02441               }
02442        }
02443 
02444        ZIP_FROM_OBJECT(intern, this);
02445        if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) {
02446               switch (Z_TYPE_P(zval_files)) {
02447                      case IS_STRING:
02448                             if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files) TSRMLS_CC)) {
02449                                    RETURN_FALSE;
02450                             }
02451                             break;
02452                      case IS_ARRAY:
02453                             nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
02454                             if (nelems == 0 ) {
02455                                    RETURN_FALSE;
02456                             }
02457                             for (i = 0; i < nelems; i++) {
02458                                    if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
02459                                           switch (Z_TYPE_PP(zval_file)) {
02460                                                  case IS_LONG:
02461                                                         break;
02462                                                  case IS_STRING:
02463                                                         if (!php_zip_extract_file(intern, pathto, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file) TSRMLS_CC)) {
02464                                                                RETURN_FALSE;
02465                                                         }
02466                                                         break;
02467                                           }
02468                                    }
02469                             }
02470                             break;
02471                      case IS_LONG:
02472                      default:
02473                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings");
02474                             break;
02475               }
02476        } else {
02477                             /* Extract all files */
02478                             int filecount = zip_get_num_files(intern);
02479 
02480                             if (filecount == -1) {
02481                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive");
02482                                           RETURN_FALSE;
02483                             }
02484 
02485                             for (i = 0; i < filecount; i++) {
02486                                           char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
02487                                           if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) {
02488                                                  RETURN_FALSE;
02489                                           }
02490                             }
02491               }
02492        RETURN_TRUE;
02493 }
02494 /* }}} */
02495 
02496 static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
02497 {
02498        struct zip *intern;
02499        zval *this = getThis();
02500 
02501        struct zip_stat sb;
02502        struct zip_file *zf;
02503 
02504        char *filename;
02505        int    filename_len;
02506        long index = -1;
02507        long flags = 0;
02508        long len = 0;
02509 
02510        char *buffer;
02511        int n = 0;
02512 
02513        if (!this) {
02514               RETURN_FALSE;
02515        }
02516 
02517        ZIP_FROM_OBJECT(intern, this);
02518 
02519        if (type == 1) {
02520               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
02521                      return;
02522               }
02523               if (strlen(filename) != filename_len) {
02524                      return;
02525               }
02526               PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb);
02527        } else {
02528               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &index, &len, &flags) == FAILURE) {
02529                      return;
02530               }
02531               PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
02532        }
02533 
02534        if (sb.size < 1) {
02535               RETURN_EMPTY_STRING();
02536        }
02537 
02538        if (len < 1) {
02539               len = sb.size;
02540        }
02541        if (index >= 0) {
02542               zf = zip_fopen_index(intern, index, flags);
02543        } else {
02544               zf = zip_fopen(intern, filename, flags);
02545        }
02546 
02547        if (zf == NULL) {
02548               RETURN_FALSE;
02549        }
02550 
02551        buffer = safe_emalloc(len, 1, 2);
02552        n = zip_fread(zf, buffer, len);
02553        if (n < 1) {
02554               efree(buffer);
02555               RETURN_EMPTY_STRING();
02556        }
02557 
02558        zip_fclose(zf);
02559        buffer[n] = 0;
02560        RETURN_STRINGL(buffer, n, 0);
02561 }
02562 /* }}} */
02563 
02564 /* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]])
02565 get the contents of an entry using its name */
02566 static ZIPARCHIVE_METHOD(getFromName)
02567 {
02568        php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
02569 }
02570 /* }}} */
02571 
02572 /* {{{ proto string ZipArchive::getFromIndex(int index[, int len [, int flags]])
02573 get the contents of an entry using its index */
02574 static ZIPARCHIVE_METHOD(getFromIndex)
02575 {
02576        php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
02577 }
02578 /* }}} */
02579 
02580 /* {{{ proto resource ZipArchive::getStream(string entryname)
02581 get a stream for an entry using its name */
02582 static ZIPARCHIVE_METHOD(getStream)
02583 {
02584        struct zip *intern;
02585        zval *this = getThis();
02586        struct zip_stat sb;
02587        char *filename;
02588        int    filename_len;
02589        char *mode = "rb";
02590        php_stream *stream;
02591        ze_zip_object *obj;
02592 
02593        if (!this) {
02594               RETURN_FALSE;
02595        }
02596 
02597        ZIP_FROM_OBJECT(intern, this);
02598 
02599        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
02600               return;
02601        }
02602 
02603        if (zip_stat(intern, filename, 0, &sb) != 0) {
02604               RETURN_FALSE;
02605        }
02606 
02607        obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
02608 
02609        stream = php_stream_zip_open(obj->filename, filename, mode STREAMS_CC TSRMLS_CC);
02610        if (stream) {
02611               php_stream_to_zval(stream, return_value);
02612        }
02613 }
02614 /* }}} */
02615 
02616 /* {{{ arginfo */
02617 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1)
02618        ZEND_ARG_INFO(0, filename)
02619        ZEND_ARG_INFO(0, flags)
02620 ZEND_END_ARG_INFO()
02621 
02622 ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0)
02623 ZEND_END_ARG_INFO()
02624 
02625 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addemptydir, 0, 0, 1)
02626        ZEND_ARG_INFO(0, dirname)
02627 ZEND_END_ARG_INFO()
02628 
02629 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addglob, 0, 0, 1)
02630        ZEND_ARG_INFO(0, pattern)
02631        ZEND_ARG_INFO(0, flags)
02632        ZEND_ARG_INFO(0, options)
02633 ZEND_END_ARG_INFO()
02634 
02635 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addpattern, 0, 0, 1)
02636        ZEND_ARG_INFO(0, pattern)
02637        ZEND_ARG_INFO(0, path)
02638        ZEND_ARG_INFO(0, options)
02639 ZEND_END_ARG_INFO()
02640 
02641 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfile, 0, 0, 1)
02642        ZEND_ARG_INFO(0, filepath)
02643        ZEND_ARG_INFO(0, entryname)
02644        ZEND_ARG_INFO(0, start)
02645        ZEND_ARG_INFO(0, length)
02646 ZEND_END_ARG_INFO()
02647 
02648 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfromstring, 0, 0, 2)
02649        ZEND_ARG_INFO(0, name)
02650        ZEND_ARG_INFO(0, content)
02651 ZEND_END_ARG_INFO()
02652 
02653 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statname, 0, 0, 1)
02654        ZEND_ARG_INFO(0, filename)
02655        ZEND_ARG_INFO(0, flags)
02656 ZEND_END_ARG_INFO()
02657 
02658 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statindex, 0, 0, 1)
02659        ZEND_ARG_INFO(0, index)
02660        ZEND_ARG_INFO(0, flags)
02661 ZEND_END_ARG_INFO()
02662 
02663 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setarchivecomment, 0, 0, 1)
02664        ZEND_ARG_INFO(0, comment)
02665 ZEND_END_ARG_INFO()
02666 
02667 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentindex, 0, 0, 2)
02668        ZEND_ARG_INFO(0, index)
02669        ZEND_ARG_INFO(0, comment)
02670 ZEND_END_ARG_INFO()
02671 
02672 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentname, 0, 0, 1)
02673        ZEND_ARG_INFO(0, name)
02674        ZEND_ARG_INFO(0, flags)
02675 ZEND_END_ARG_INFO()
02676 
02677 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentindex, 0, 0, 1)
02678        ZEND_ARG_INFO(0, index)
02679        ZEND_ARG_INFO(0, flags)
02680 ZEND_END_ARG_INFO()
02681 
02682 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renameindex, 0, 0, 2)
02683        ZEND_ARG_INFO(0, index)
02684        ZEND_ARG_INFO(0, new_name)
02685 ZEND_END_ARG_INFO()
02686 
02687 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renamename, 0, 0, 2)
02688        ZEND_ARG_INFO(0, name)
02689        ZEND_ARG_INFO(0, new_name)
02690 ZEND_END_ARG_INFO()
02691 
02692 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangeindex, 0, 0, 1)
02693        ZEND_ARG_INFO(0, index)
02694 ZEND_END_ARG_INFO()
02695 
02696 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangename, 0, 0, 1)
02697        ZEND_ARG_INFO(0, name)
02698 ZEND_END_ARG_INFO()
02699 
02700 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_extractto, 0, 0, 1)
02701        ZEND_ARG_INFO(0, pathto)
02702        ZEND_ARG_INFO(0, files)
02703 ZEND_END_ARG_INFO()
02704 
02705 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromname, 0, 0, 1)
02706        ZEND_ARG_INFO(0, entryname)
02707        ZEND_ARG_INFO(0, len)
02708        ZEND_ARG_INFO(0, flags)
02709 ZEND_END_ARG_INFO()
02710 
02711 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromindex, 0, 0, 1)
02712        ZEND_ARG_INFO(0, index)
02713        ZEND_ARG_INFO(0, len)
02714        ZEND_ARG_INFO(0, flags)
02715 ZEND_END_ARG_INFO()
02716 
02717 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getarchivecomment, 0, 0, 0)
02718        ZEND_ARG_INFO(0, flags)
02719 ZEND_END_ARG_INFO()
02720 
02721 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentname, 0, 0, 2)
02722        ZEND_ARG_INFO(0, name)
02723        ZEND_ARG_INFO(0, comment)
02724 ZEND_END_ARG_INFO()
02725 
02726 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getstream, 0, 0, 1)
02727        ZEND_ARG_INFO(0, entryname)
02728 ZEND_END_ARG_INFO()
02729 /* }}} */
02730 
02731 /* {{{ ze_zip_object_class_functions */
02732 static const zend_function_entry zip_class_functions[] = {
02733        ZIPARCHIVE_ME(open,                              arginfo_ziparchive_open, ZEND_ACC_PUBLIC)
02734        ZIPARCHIVE_ME(close,                      arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
02735        ZIPARCHIVE_ME(getStatusString,            arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
02736        ZIPARCHIVE_ME(addEmptyDir,                arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC)
02737        ZIPARCHIVE_ME(addFromString,              arginfo_ziparchive_addfromstring, ZEND_ACC_PUBLIC)
02738        ZIPARCHIVE_ME(addFile,                           arginfo_ziparchive_addfile, ZEND_ACC_PUBLIC)
02739        ZIPARCHIVE_ME(addGlob,                           arginfo_ziparchive_addglob, ZEND_ACC_PUBLIC)
02740        ZIPARCHIVE_ME(addPattern,                 arginfo_ziparchive_addpattern, ZEND_ACC_PUBLIC)
02741        ZIPARCHIVE_ME(renameIndex,                arginfo_ziparchive_renameindex, ZEND_ACC_PUBLIC)
02742        ZIPARCHIVE_ME(renameName,                 arginfo_ziparchive_renamename, ZEND_ACC_PUBLIC)
02743        ZIPARCHIVE_ME(setArchiveComment,   arginfo_ziparchive_setarchivecomment, ZEND_ACC_PUBLIC)
02744        ZIPARCHIVE_ME(getArchiveComment,   arginfo_ziparchive_getarchivecomment, ZEND_ACC_PUBLIC)
02745        ZIPARCHIVE_ME(setCommentIndex,            arginfo_ziparchive_setcommentindex, ZEND_ACC_PUBLIC)
02746        ZIPARCHIVE_ME(setCommentName,             arginfo_ziparchive_setcommentname, ZEND_ACC_PUBLIC)
02747        ZIPARCHIVE_ME(getCommentIndex,            arginfo_ziparchive_getcommentindex, ZEND_ACC_PUBLIC)
02748        ZIPARCHIVE_ME(getCommentName,             arginfo_ziparchive_getcommentname, ZEND_ACC_PUBLIC)
02749        ZIPARCHIVE_ME(deleteIndex,                arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
02750        ZIPARCHIVE_ME(deleteName,                 arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
02751        ZIPARCHIVE_ME(statName,                          arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
02752        ZIPARCHIVE_ME(statIndex,                  arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
02753        ZIPARCHIVE_ME(locateName,                 arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
02754        ZIPARCHIVE_ME(getNameIndex,               arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
02755        ZIPARCHIVE_ME(unchangeArchive,            arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
02756        ZIPARCHIVE_ME(unchangeAll,                arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
02757        ZIPARCHIVE_ME(unchangeIndex,              arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
02758        ZIPARCHIVE_ME(unchangeName,               arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
02759        ZIPARCHIVE_ME(extractTo,                  arginfo_ziparchive_extractto, ZEND_ACC_PUBLIC)
02760        ZIPARCHIVE_ME(getFromName,                arginfo_ziparchive_getfromname, ZEND_ACC_PUBLIC)
02761        ZIPARCHIVE_ME(getFromIndex,               arginfo_ziparchive_getfromindex, ZEND_ACC_PUBLIC)
02762        ZIPARCHIVE_ME(getStream,                  arginfo_ziparchive_getstream, ZEND_ACC_PUBLIC)
02763        {NULL, NULL, NULL}
02764 };
02765 /* }}} */
02766 #endif
02767 
02768 /* {{{ PHP_MINIT_FUNCTION */
02769 static PHP_MINIT_FUNCTION(zip)
02770 {
02771 #ifdef PHP_ZIP_USE_OO 
02772        zend_class_entry ce;
02773 
02774        memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
02775        zip_object_handlers.clone_obj             = NULL;
02776        zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
02777 
02778        zip_object_handlers.get_properties = php_zip_get_properties;
02779        zip_object_handlers.read_property  = php_zip_read_property;
02780        zip_object_handlers.has_property   = php_zip_has_property;
02781 
02782        INIT_CLASS_ENTRY(ce, "ZipArchive", zip_class_functions);
02783        ce.create_object = php_zip_object_new;
02784        zip_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
02785 
02786        zend_hash_init(&zip_prop_handlers, 0, NULL, NULL, 1);
02787        php_zip_register_prop_handler(&zip_prop_handlers, "status",    php_zip_status, NULL, NULL, IS_LONG TSRMLS_CC);
02788        php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG TSRMLS_CC);
02789        php_zip_register_prop_handler(&zip_prop_handlers, "numFiles",  php_zip_get_num_files, NULL, NULL, IS_LONG TSRMLS_CC);
02790        php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC);
02791        php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC);
02792 
02793        REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
02794        REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL);
02795        REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS);
02796        REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE);
02797 
02798        REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE);
02799        REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
02800        REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
02801        REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
02802        REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
02803        REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);
02804        REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK);
02805        REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1);
02806        REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2);
02807        REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3);
02808        REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4);
02809        REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE);
02810        REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE);
02811        REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64);
02812        REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE);
02813        REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2);
02814        REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA);
02815        REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE);
02816        REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77);
02817        REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK);
02818        REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD);
02819 
02820        /* Error code */
02821        REGISTER_ZIP_CLASS_CONST_LONG("ER_OK",                  ZIP_ER_OK);                 /* N No error */
02822        REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK",    ZIP_ER_MULTIDISK);   /* N Multi-disk zip archives not supported */
02823        REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME",              ZIP_ER_RENAME);             /* S Renaming temporary file failed */
02824        REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE",        ZIP_ER_CLOSE);              /* S Closing zip archive failed */
02825        REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK",         ZIP_ER_SEEK);        /* S Seek error */
02826        REGISTER_ZIP_CLASS_CONST_LONG("ER_READ",         ZIP_ER_READ);        /* S Read error */
02827        REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE",        ZIP_ER_WRITE);              /* S Write error */
02828        REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC",                 ZIP_ER_CRC);         /* N CRC error */
02829        REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED",    ZIP_ER_ZIPCLOSED);   /* N Containing zip archive was closed */
02830        REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT",        ZIP_ER_NOENT);              /* N No such file */
02831        REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS",              ZIP_ER_EXISTS);             /* N File already exists */
02832        REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN",         ZIP_ER_OPEN);        /* S Can't open file */
02833        REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN",             ZIP_ER_TMPOPEN);     /* S Failure to create temporary file */
02834        REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB",         ZIP_ER_ZLIB);        /* Z Zlib error */
02835        REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY",              ZIP_ER_MEMORY);             /* N Malloc failure */
02836        REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED",             ZIP_ER_CHANGED);     /* N Entry has been changed */
02837        REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP",  ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */
02838        REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF",                 ZIP_ER_EOF);         /* N Premature EOF */
02839        REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL",        ZIP_ER_INVAL);              /* N Invalid argument */
02840        REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP",        ZIP_ER_NOZIP);              /* N Not a zip archive */
02841        REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL",     ZIP_ER_INTERNAL);    /* N Internal error */
02842        REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS",              ZIP_ER_INCONS);             /* N Zip archive inconsistent */
02843        REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE",              ZIP_ER_REMOVE);             /* S Can't remove file */
02844        REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED",      ZIP_ER_DELETED);     /* N Entry has been deleted */
02845 
02846        php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC);
02847 #endif
02848 
02849        le_zip_dir   = zend_register_list_destructors_ex(php_zip_free_dir,   NULL, le_zip_dir_name,   module_number);
02850        le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
02851 
02852        return SUCCESS;
02853 }
02854 /* }}} */
02855 
02856 /* {{{ PHP_MSHUTDOWN_FUNCTION
02857  */
02858 static PHP_MSHUTDOWN_FUNCTION(zip)
02859 {
02860 #ifdef PHP_ZIP_USE_OO 
02861        zend_hash_destroy(&zip_prop_handlers);
02862        php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
02863 #endif
02864        return SUCCESS;
02865 }
02866 /* }}} */
02867 
02868 /* {{{ PHP_MINFO_FUNCTION
02869  */
02870 static PHP_MINFO_FUNCTION(zip)
02871 {
02872        php_info_print_table_start();
02873 
02874        php_info_print_table_row(2, "Zip", "enabled");
02875        php_info_print_table_row(2, "Extension Version","$Id: php_zip.c 321634 2012-01-01 13:15:04Z felipe $");
02876        php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING);
02877        php_info_print_table_row(2, "Libzip version", "0.9.0");
02878 
02879        php_info_print_table_end();
02880 }
02881 /* }}} */
02882 
02883 /*
02884  * Local variables:
02885  * tab-width: 4
02886  * c-basic-offset: 4
02887  * End:
02888  * vim600: noet sw=4 ts=4 fdm=marker
02889  * vim<600: noet sw=4 ts=4
02890  */