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