diff options
Diffstat (limited to 'ext/zip')
154 files changed, 13498 insertions, 0 deletions
diff --git a/ext/zip/CREDITS b/ext/zip/CREDITS new file mode 100644 index 0000000..6c7e42d --- /dev/null +++ b/ext/zip/CREDITS @@ -0,0 +1,2 @@ +Zip +Pierre-Alain Joye diff --git a/ext/zip/TODO b/ext/zip/TODO new file mode 100644 index 0000000..c1baba9 --- /dev/null +++ b/ext/zip/TODO @@ -0,0 +1,4 @@ +- add pattern support to extract or add files +- stream to add or modify entries +- crypt support for zip (read and write) +- Iterators diff --git a/ext/zip/config.m4 b/ext/zip/config.m4 new file mode 100644 index 0000000..85f9119 --- /dev/null +++ b/ext/zip/config.m4 @@ -0,0 +1,108 @@ +dnl +dnl $Id$ +dnl + +PHP_ARG_ENABLE(zip, for zip archive read/writesupport, +[ --enable-zip Include Zip read/write support]) + +if test -z "$PHP_ZLIB_DIR"; then + PHP_ARG_WITH(zlib-dir, for the location of libz, + [ --with-zlib-dir[=DIR] ZIP: Set the path to libz install prefix], no, no) +fi + +PHP_ARG_WITH(pcre-dir, pcre install prefix, +[ --with-pcre-dir ZIP: pcre install prefix], no, no) + +if test "$PHP_ZIP" != "no"; then + + if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then + if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then + PHP_ZLIB_DIR="$PHP_ZLIB_DIR" + PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include/zlib" + elif test -f "$PHP_ZLIB_DIR/include/zlib.h"; then + PHP_ZLIB_DIR="$PHP_ZLIB_DIR" + PHP_ZLIB_INCDIR="$PHP_ZLIB_DIR/include" + else + AC_MSG_ERROR([Can not find zlib headers under "$PHP_ZLIB_DIR"]) + fi + else + for i in /usr/local /usr; do + if test -f "$i/include/zlib/zlib.h"; then + PHP_ZLIB_DIR="$i" + PHP_ZLIB_INCDIR="$i/include/zlib" + elif test -f "$i/include/zlib.h"; then + PHP_ZLIB_DIR="$i" + PHP_ZLIB_INCDIR="$i/include" + fi + done + fi + + dnl # zlib + AC_MSG_CHECKING([for the location of zlib]) + if test "$PHP_ZLIB_DIR" = "no"; then + AC_MSG_ERROR([zip support requires ZLIB. Use --with-zlib-dir=<DIR> to specify prefix where ZLIB include and library are located]) + else + AC_MSG_RESULT([$PHP_ZLIB_DIR]) + PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR/$PHP_LIBDIR, ZIP_SHARED_LIBADD) + PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR) + fi + + dnl This is PECL build, check if bundled PCRE library is used + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=$INCLUDES + AC_EGREP_CPP(yes,[ +#include <main/php_config.h> +#if defined(HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) +yes +#endif + ],[ + PHP_PCRE_REGEX=yes + ],[ + AC_EGREP_CPP(yes,[ +#include <main/php_config.h> +#if defined(HAVE_PCRE) && !defined(COMPILE_DL_PCRE) +yes +#endif + ],[ + PHP_PCRE_REGEX=pecl + ],[ + PHP_PCRE_REGEX=no + ]) + ]) + CPPFLAGS=$old_CPPFLAGS + + PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_error.c lib/zip_fclose.c \ + lib/zip_fread.c lib/zip_open.c lib/zip_source_filep.c \ + lib/zip_strerror.c lib/zip_close.c lib/zip_error_get.c \ + lib/zip_file_error_get.c lib/zip_free.c lib/zip_rename.c \ + lib/zip_source_free.c lib/zip_unchange_all.c lib/zip_delete.c \ + lib/zip_error_get_sys_type.c lib/zip_file_get_offset.c \ + lib/zip_get_name.c lib/zip_replace.c lib/zip_source_function.c \ + lib/zip_unchange.c lib/zip_dirent.c lib/zip_error_strerror.c \ + lib/zip_filerange_crc.c lib/zip_file_strerror.c lib/zip_get_num_files.c \ + lib/zip_get_archive_flag.c lib/zip_set_archive_flag.c \ + lib/zip_set_name.c lib/zip_source_zip.c lib/zip_unchange_data.c \ + lib/zip_entry_free.c lib/zip_error_to_str.c lib/zip_fopen.c \ + lib/zip_name_locate.c lib/zip_source_buffer.c lib/zip_stat.c \ + lib/zip_entry_new.c lib/zip_err_str.c lib/zip_fopen_index.c \ + lib/zip_get_archive_comment.c lib/zip_get_file_comment.c \ + lib/zip_new.c lib/zip_source_file.c lib/zip_stat_index.c \ + lib/zip_set_archive_comment.c lib/zip_set_file_comment.c \ + lib/zip_unchange_archive.c lib/zip_memdup.c lib/zip_stat_init.c lib/zip_add_dir.c \ + lib/zip_error_clear.c lib/zip_file_error_clear.c \ + lib/zip_fdopen.c lib/zip_fopen_encrypted.c lib/zip_fopen_index_encrypted.c \ + lib/zip_get_compression_implementation.c lib/zip_get_encryption_implementation.c \ + lib/zip_get_file_extra.c lib/zip_get_num_entries.c lib/zip_set_default_password.c \ + lib/zip_set_file_extra.c lib/zip_source_close.c lib/zip_source_crc.c \ + lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_layered.c \ + lib/zip_source_open.c lib/zip_source_pkware.c lib/zip_source_pop.c \ + lib/zip_source_read.c lib/zip_source_stat.c" + + AC_DEFINE(HAVE_ZIP,1,[ ]) + PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c $PHP_ZIP_SOURCES, $ext_shared) + PHP_ADD_BUILD_DIR($ext_builddir/lib, 1) + PHP_SUBST(ZIP_SHARED_LIBADD) + + dnl so we always include the known-good working hack. + PHP_ADD_MAKEFILE_FRAGMENT +fi diff --git a/ext/zip/config.w32 b/ext/zip/config.w32 new file mode 100644 index 0000000..fa0a518 --- /dev/null +++ b/ext/zip/config.w32 @@ -0,0 +1,44 @@ +// $Id$ +// vim:ft=javascript + +ARG_ENABLE("zip", "ZIP support", "yes"); + +if (PHP_ZIP != "no") { + if (CHECK_HEADER_ADD_INCLUDE("zlib.h", "CFLAGS_ZIP", "..\\zlib;" + PHP_ZIP) && + (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib", "zip", PHP_ZIP) || CHECK_LIB("zlib.lib", "zip", PHP_ZIP))) || + (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "zip", PHP_ZIP)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED))) + ) { + EXTENSION('zip', 'php_zip.c zip_stream.c'); + ADD_SOURCES(configure_module_dirname + "/lib", "zip_add.c zip_error.c zip_fclose.c \ + zip_fread.c zip_open.c zip_source_filep.c \ + zip_strerror.c zip_close.c zip_error_get.c \ + zip_file_error_get.c zip_free.c zip_rename.c \ + zip_source_free.c zip_unchange_all.c zip_delete.c \ + zip_error_get_sys_type.c zip_file_get_offset.c \ + zip_get_name.c zip_replace.c zip_source_function.c \ + zip_unchange.c zip_dirent.c zip_error_strerror.c \ + zip_filerange_crc.c zip_file_strerror.c zip_get_num_files.c \ + zip_get_archive_flag.c zip_set_archive_flag.c \ + zip_set_name.c zip_source_zip.c zip_unchange_data.c \ + zip_entry_free.c zip_error_to_str.c zip_fopen.c \ + zip_name_locate.c zip_source_buffer.c zip_stat.c \ + zip_entry_new.c zip_err_str.c zip_fopen_index.c \ + zip_new.c zip_source_file.c zip_stat_index.c \ + zip_get_archive_comment.c zip_get_file_comment.c \ + zip_set_archive_comment.c zip_set_file_comment.c \ + zip_unchange_archive.c zip_memdup.c zip_stat_init.c \ + zip_add_dir.c zip_file_error_clear.c zip_error_clear.c \ + zip_fdopen.c zip_fopen_encrypted.c zip_fopen_index_encrypted.c \ + zip_get_compression_implementation.c zip_get_encryption_implementation.c \ + zip_get_file_extra.c zip_get_num_entries.c zip_set_default_password.c \ + zip_set_file_extra.c zip_source_close.c zip_source_crc.c \ + zip_source_deflate.c zip_source_error.c zip_source_layered.c \ + zip_source_open.c zip_source_pkware.c zip_source_pop.c \ + zip_source_read.c zip_source_stat.c", "zip"); + + AC_DEFINE('HAVE_ZIP', 1); + } else { + WARNING("zip not enabled; libraries and headers not found"); + } +} + diff --git a/ext/zip/examples/comment.php b/ext/zip/examples/comment.php new file mode 100644 index 0000000..90b37d3 --- /dev/null +++ b/ext/zip/examples/comment.php @@ -0,0 +1,6 @@ +<?php +$z = new ZipArchive; +$z->open('test_with_comment.zip'); +// Add "Foo Comment" as comment for the foo entry +$z->setCommentName('foo', 'Too Comment ' . time()); +$z->close(); diff --git a/ext/zip/examples/create.php b/ext/zip/examples/create.php new file mode 100644 index 0000000..a41c8e6 --- /dev/null +++ b/ext/zip/examples/create.php @@ -0,0 +1,23 @@ +<?php +error_reporting(E_ALL); +if (!extension_loaded('zip')) { + dl('zip.so'); +} +$thisdir = dirname(__FILE__); +unlink("./test112.zip"); +$zip = new ZipArchive(); +$filename = "./test112.zip"; + +if (!$zip->open($filename, ZIPARCHIVE::CREATE)) { + exit("cannot open <$filename>\n"); +} else { + echo "file <$filename> OK\n"; +} + +$zip->addFromString("testfilephp.txt" . time(), "#1 This is a test string added as testfilephp.txt.\n"); +$zip->addFromString("testfilephp2.txt" . time(), "#2 This is a test string added as testfilephp2.txt.\n"); +$zip->addFile($thisdir . "/too.php","/testfromfile.php"); +echo "numfiles: " . $zip->numFiles . "\n"; +echo "status:" . $zip->status . "\n"; +$zip->close(); +unset($zip); diff --git a/ext/zip/examples/dir.php b/ext/zip/examples/dir.php new file mode 100644 index 0000000..c362a72 --- /dev/null +++ b/ext/zip/examples/dir.php @@ -0,0 +1,21 @@ +<?php +if (!extension_loaded('zip')) { + dl('zip.so'); +} + +$za = new ZipArchive(); + +$za->open('test_with_comment.zip'); +print_r($za); +var_dump($za); +echo "numFiles: " . $za->numFiles . "\n"; +echo "status: " . $za->status . "\n"; +echo "statusSys: " . $za->statusSys . "\n"; +echo "filename: " . $za->filename . "\n"; +echo "comment: " . $za->comment . "\n"; + +for ($i=0; $i<$za->numFiles;$i++) { + echo "index: $i\n"; + print_r($za->statIndex($i)); +} +echo "numFile:" . $za->numFiles . "\n"; diff --git a/ext/zip/examples/extract.php b/ext/zip/examples/extract.php new file mode 100644 index 0000000..5276b0d --- /dev/null +++ b/ext/zip/examples/extract.php @@ -0,0 +1,28 @@ +<?php +if (!extension_loaded('zip')) { + dl('zip.so'); +} + +$zip = new ZipArchive(); + +echo $zip->filename . "\n"; +$zip->open("test.zip"); +/* +$zip->addFile("./modules/"); +$zip->addFile("./testempty"); +*/ +echo $zip->status . "\n"; +echo $zip->statusSys . "\n"; + +echo $zip->numFiles . "\n"; +echo $zip->filename . "\n"; +var_dump($zip); +$files = array('test', 'testdir/test2'); +if (!$zip->extractTo("./testext/path/to", $files)) { + echo "error!\n"; + echo $zip->status . "\n"; + echo $zip->statusSys . "\n"; + +} + +$zip->close(); diff --git a/ext/zip/examples/extractAll.php b/ext/zip/examples/extractAll.php new file mode 100644 index 0000000..d318a45 --- /dev/null +++ b/ext/zip/examples/extractAll.php @@ -0,0 +1,24 @@ +<?php +$zip = new ZipArchive(); + +echo $zip->filename . "\n"; +$zip->open("test.zip"); +/* +$zip->addFile("./modules/"); +$zip->addFile("./testempty"); +*/ +echo $zip->status . "\n"; +echo $zip->statusSys . "\n"; + +echo $zip->numFiles . "\n"; +echo $zip->filename . "\n"; +var_dump($zip); +$files = array('test', 'testdir/test2'); +if (!$zip->extractTo("./testext/path/to")) { + echo "error!\n"; + echo $zip->status . "\n"; + echo $zip->statusSys . "\n"; + +} + +$zip->close(); diff --git a/ext/zip/examples/fopen.php b/ext/zip/examples/fopen.php new file mode 100644 index 0000000..32357f3 --- /dev/null +++ b/ext/zip/examples/fopen.php @@ -0,0 +1,35 @@ +<?php +if (!extension_loaded('zip')) { + dl('zip.so'); +} + + +$fp = fopen('zip://' . dirname(__FILE__) . '/test.zip#test', 'r'); +if (!$fp) { + exit("cannot open\n"); +} +while (!feof($fp)) { + $contents .= fread($fp, 2); + echo "$contents\n"; +} + +fclose($fp); +echo "done.\n"; + + +$content = ''; +$z = new ZipArchive(); +$z->open(dirname(__FILE__) . '/test.zip'); +$fp = $z->getStream('test'); + +var_dump($fp); +if(!$fp) exit("\n"); +while (!feof($fp)) { + $contents .= fread($fp, 2); +} + +fclose($fp); +file_put_contents('t',$contents); +echo "done.\n"; + + diff --git a/ext/zip/examples/get_set_comments.php b/ext/zip/examples/get_set_comments.php new file mode 100644 index 0000000..5bd302e --- /dev/null +++ b/ext/zip/examples/get_set_comments.php @@ -0,0 +1,38 @@ +<?php +error_reporting(E_ALL|E_STRICT); + +copy('test_with_comment.zip', 't.zip'); +$z = new ZipArchive; +$z->open('t.zip'); + +print_r($z); + +for ($i=0; $i<$z->numFiles; $i++) { + echo "index: $i\n"; + print_r($z->getCommentIndex($i)); + echo "\n\n"; +} +echo "foobar/ " . $z->getCommentName('foobar/') . "\n"; + +echo "Archive comment: " . $z->getArchiveComment() . "\n"; + + +$z->setCommentIndex(1, 'new comment idx 1'); +$z->setCommentName('foobar/', 'new comment foobar/'); + +$z->setArchiveComment( 'new archive comment'); + +for ($i=0; $i<$z->numFiles; $i++) { + echo "index: $i\n"; + print_r($z->getCommentIndex($i)); + echo "\n\n"; +} + +echo $z->getCommentName('foobar/') . "\n"; + +// Get the original comment +echo $z->getCommentName('foobar/', ZIPARCHIVE::FL_UNCHANGED) . "\n"; + +echo "Archive comment: " . $z->getArchiveComment() . "\n"; +echo "Archive comment (original): " . $z->getArchiveComment(ZIPARCHIVE::FL_UNCHANGED) . "\n"; + diff --git a/ext/zip/examples/im.php b/ext/zip/examples/im.php new file mode 100644 index 0000000..3721434 --- /dev/null +++ b/ext/zip/examples/im.php @@ -0,0 +1,11 @@ +<?php +/* $Id$ */ +$im = imagecreatefromgif('zip://' . dirname(__FILE__) . '/test_im.zip#pear_item.gif'); +imagepng($im, 'a.png'); + +$z = new ZipArchive(); +$z->open(dirname(__FILE__) . '/test_im.zip'); +$im_string = $z->getFromName("pear_item.gif"); +$im = imagecreatefromstring($im_string); +imagepng($im, 'b.png'); + diff --git a/ext/zip/examples/odt.php b/ext/zip/examples/odt.php new file mode 100644 index 0000000..c829f12 --- /dev/null +++ b/ext/zip/examples/odt.php @@ -0,0 +1,20 @@ +<?php +/* $Id$ */ +$reader = new XMLReader(); + +$reader->open('zip://' . dirname(__FILE__) . '/test.odt#meta.xml'); +$odt_meta = array(); +while ($reader->read()) { + if ($reader->nodeType == XMLREADER::ELEMENT) { + $elm = $reader->name; + } else { + if ($reader->nodeType == XMLREADER::END_ELEMENT && $reader->name == 'office:meta') { + break; + } + if (!trim($reader->value)) { + continue; + } + $odt_meta[$elm] = $reader->value; + } +} +print_r($odt_meta); diff --git a/ext/zip/examples/oldapi.php b/ext/zip/examples/oldapi.php new file mode 100644 index 0000000..2f17f43 --- /dev/null +++ b/ext/zip/examples/oldapi.php @@ -0,0 +1,17 @@ +<?php + +$zip = zip_open('examples/test1.zip'); +var_dump($zip); + +if ($zip) { + $i = 0; + while ($zip_entry = zip_read($zip)) { + var_dump($zip_entry); + $txt = zip_entry_read($zip_entry, 10); + echo $i . ": " . $txt . "size: " . zip_entry_filesize($zip_entry) . + "comp_method: " . zip_entry_compressionmethod($zip_entry) . + "\n"; + $i++; + } + var_dump($zip_entry); +} diff --git a/ext/zip/examples/test.odt b/ext/zip/examples/test.odt Binary files differnew file mode 100644 index 0000000..6a816ad --- /dev/null +++ b/ext/zip/examples/test.odt diff --git a/ext/zip/examples/test.zip b/ext/zip/examples/test.zip Binary files differnew file mode 100644 index 0000000..a6a2e62 --- /dev/null +++ b/ext/zip/examples/test.zip diff --git a/ext/zip/examples/test1.zip b/ext/zip/examples/test1.zip Binary files differnew file mode 100644 index 0000000..a4deb13 --- /dev/null +++ b/ext/zip/examples/test1.zip diff --git a/ext/zip/examples/test_im.zip b/ext/zip/examples/test_im.zip Binary files differnew file mode 100644 index 0000000..6385ee9 --- /dev/null +++ b/ext/zip/examples/test_im.zip diff --git a/ext/zip/examples/test_with_comment.zip b/ext/zip/examples/test_with_comment.zip Binary files differnew file mode 100644 index 0000000..cc65375 --- /dev/null +++ b/ext/zip/examples/test_with_comment.zip diff --git a/ext/zip/examples/too.php b/ext/zip/examples/too.php new file mode 100644 index 0000000..6d21008 --- /dev/null +++ b/ext/zip/examples/too.php @@ -0,0 +1,2 @@ +<?php +echo "too"; diff --git a/ext/zip/lib/zip.h b/ext/zip/lib/zip.h new file mode 100644 index 0000000..f11c9ab --- /dev/null +++ b/ext/zip/lib/zip.h @@ -0,0 +1,276 @@ +#ifndef _HAD_ZIP_H +#define _HAD_ZIP_H + +/* + zip.h -- exported declarations. + Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "main/php.h" + +#ifdef PHP_WIN32 +# include "zip_win32.h" +# ifdef PHP_ZIP_EXPORTS +# define ZIP_EXTERN(rt) __declspec(dllexport)rt _stdcall +# else +# define ZIP_EXTERN(rt) rt +# endif +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define ZIP_EXTERN(rt) __attribute__ ((visibility("default"))) rt +#else +# define ZIP_EXTERN(rt) rt +#endif + +BEGIN_EXTERN_C() + +#include "zipconf.h" + +#include <sys/types.h> +#include <stdio.h> +#include <time.h> + +/* flags for zip_open */ + +#define ZIP_CREATE 1 +#define ZIP_EXCL 2 +#define ZIP_CHECKCONS 4 +#define ZIP_OVERWRITE 8 + + +/* flags for zip_name_locate, zip_fopen, zip_stat, ... */ + +#define ZIP_FL_NOCASE 1 /* ignore case on name lookup */ +#define ZIP_FL_NODIR 2 /* ignore directory component */ +#define ZIP_FL_COMPRESSED 4 /* read compressed data */ +#define ZIP_FL_UNCHANGED 8 /* use original data, ignoring changes */ +#define ZIP_FL_RECOMPRESS 16 /* force recompression of data */ +#define ZIP_FL_ENCRYPTED 32 /* read encrypted data + (implies ZIP_FL_COMPRESSED) */ + +/* archive global flags flags */ + +#define ZIP_AFL_TORRENT 1 /* torrent zipped */ +#define ZIP_AFL_RDONLY 2 /* read only -- cannot be cleared */ + + +/* flags for compression and encryption sources */ + +#define ZIP_CODEC_ENCODE 1 /* compress/encrypt */ + + +/* libzip error codes */ + +#define ZIP_ER_OK 0 /* N No error */ +#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */ +#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */ +#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */ +#define ZIP_ER_SEEK 4 /* S Seek error */ +#define ZIP_ER_READ 5 /* S Read error */ +#define ZIP_ER_WRITE 6 /* S Write error */ +#define ZIP_ER_CRC 7 /* N CRC error */ +#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */ +#define ZIP_ER_NOENT 9 /* N No such file */ +#define ZIP_ER_EXISTS 10 /* N File already exists */ +#define ZIP_ER_OPEN 11 /* S Can't open file */ +#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */ +#define ZIP_ER_ZLIB 13 /* Z Zlib error */ +#define ZIP_ER_MEMORY 14 /* N Malloc failure */ +#define ZIP_ER_CHANGED 15 /* N Entry has been changed */ +#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */ +#define ZIP_ER_EOF 17 /* N Premature EOF */ +#define ZIP_ER_INVAL 18 /* N Invalid argument */ +#define ZIP_ER_NOZIP 19 /* N Not a zip archive */ +#define ZIP_ER_INTERNAL 20 /* N Internal error */ +#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */ +#define ZIP_ER_REMOVE 22 /* S Can't remove file */ +#define ZIP_ER_DELETED 23 /* N Entry has been deleted */ +#define ZIP_ER_ENCRNOTSUPP 24 /* N Encryption method not supported */ +#define ZIP_ER_RDONLY 25 /* N Read-only archive */ +#define ZIP_ER_NOPASSWD 26 /* N No password provided */ +#define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */ + +/* type of system error value */ + +#define ZIP_ET_NONE 0 /* sys_err unused */ +#define ZIP_ET_SYS 1 /* sys_err is errno */ +#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */ + +/* compression methods */ + +#define ZIP_CM_DEFAULT -1 /* better of deflate or store */ +#define ZIP_CM_STORE 0 /* stored (uncompressed) */ +#define ZIP_CM_SHRINK 1 /* shrunk */ +#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */ +#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */ +#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */ +#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */ +#define ZIP_CM_IMPLODE 6 /* imploded */ +/* 7 - Reserved for Tokenizing compression algorithm */ +#define ZIP_CM_DEFLATE 8 /* deflated */ +#define ZIP_CM_DEFLATE64 9 /* deflate64 */ +#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */ +/* 11 - Reserved by PKWARE */ +#define ZIP_CM_BZIP2 12 /* compressed using BZIP2 algorithm */ +/* 13 - Reserved by PKWARE */ +#define ZIP_CM_LZMA 14 /* LZMA (EFS) */ +/* 15-17 - Reserved by PKWARE */ +#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */ +#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */ +#define ZIP_CM_WAVPACK 97 /* WavPack compressed data */ +#define ZIP_CM_PPMD 98 /* PPMd version I, Rev 1 */ + +/* encryption methods */ + +#define ZIP_EM_NONE 0 /* not encrypted */ +#define ZIP_EM_TRAD_PKWARE 1 /* traditional PKWARE encryption */ +#if 0 /* Strong Encryption Header not parsed yet */ +#define ZIP_EM_DES 0x6601 /* strong encryption: DES */ +#define ZIP_EM_RC2_OLD 0x6602 /* strong encryption: RC2, version < 5.2 */ +#define ZIP_EM_3DES_168 0x6603 +#define ZIP_EM_3DES_112 0x6609 +#define ZIP_EM_AES_128 0x660e +#define ZIP_EM_AES_192 0x660f +#define ZIP_EM_AES_256 0x6610 +#define ZIP_EM_RC2 0x6702 /* strong encryption: RC2, version >= 5.2 */ +#define ZIP_EM_RC4 0x6801 +#endif +#define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */ + + + +enum zip_source_cmd { + ZIP_SOURCE_OPEN, /* prepare for reading */ + ZIP_SOURCE_READ, /* read data */ + ZIP_SOURCE_CLOSE, /* reading is done */ + ZIP_SOURCE_STAT, /* get meta information */ + ZIP_SOURCE_ERROR, /* get error information */ + ZIP_SOURCE_FREE /* cleanup and free resources */ +}; + +#define ZIP_SOURCE_ERR_LOWER -2 + +#define ZIP_STAT_NAME 0x0001 +#define ZIP_STAT_INDEX 0x0002 +#define ZIP_STAT_SIZE 0x0004 +#define ZIP_STAT_COMP_SIZE 0x0008 +#define ZIP_STAT_MTIME 0x0010 +#define ZIP_STAT_CRC 0x0020 +#define ZIP_STAT_COMP_METHOD 0x0040 +#define ZIP_STAT_ENCRYPTION_METHOD 0x0080 +#define ZIP_STAT_FLAGS 0x0100 + +struct zip_stat { + zip_uint64_t valid; /* which fields have valid values */ + const char *name; /* name of the file */ + zip_uint64_t index; /* index within archive */ + zip_uint64_t size; /* size of file (uncompressed) */ + zip_uint64_t comp_size; /* size of file (compressed) */ + time_t mtime; /* modification time */ + zip_uint32_t crc; /* crc of file data */ + zip_uint16_t comp_method; /* compression method used */ + zip_uint16_t encryption_method; /* encryption method used */ + zip_uint32_t flags; /* reserved for future use */ +}; + +struct zip; +struct zip_file; +struct zip_source; + +typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, + enum zip_source_cmd); + + + +ZIP_EXTERN(zip_int64_t) zip_add(struct zip *, const char *, struct zip_source *); +ZIP_EXTERN(zip_int64_t) zip_add_dir(struct zip *, const char *); +ZIP_EXTERN(int) zip_close(struct zip *); +ZIP_EXTERN(int) zip_delete(struct zip *, zip_uint64_t); +ZIP_EXTERN(void) zip_error_clear(struct zip *); +ZIP_EXTERN(void) zip_error_get(struct zip *, int *, int *); +ZIP_EXTERN(int) zip_error_get_sys_type(int); +ZIP_EXTERN(int) zip_error_to_str(char *, zip_uint64_t, int, int); +ZIP_EXTERN(int) zip_fclose(struct zip_file *); +ZIP_EXTERN(struct zip *)zip_fdopen(int, int, int *); +ZIP_EXTERN(void) zip_file_error_clear(struct zip_file *); +ZIP_EXTERN(void) zip_file_error_get(struct zip_file *, int *, int *); +ZIP_EXTERN(const char *)zip_file_strerror(struct zip_file *); +ZIP_EXTERN(struct) zip_file *zip_fopen(struct zip *, const char *, int); +ZIP_EXTERN(struct) zip_file *zip_fopen_encrypted(struct zip *, const char *, + int, const char *); +ZIP_EXTERN(struct zip_file *)zip_fopen_index(struct zip *, zip_uint64_t, int); +ZIP_EXTERN(struct zip_file *)zip_fopen_index_encrypted(struct zip *, + zip_uint64_t, int, + const char *); +ZIP_EXTERN(zip_int64_t) zip_fread(struct zip_file *, void *, zip_uint64_t); +ZIP_EXTERN(const char *)zip_get_archive_comment(struct zip *, int *, int); +ZIP_EXTERN(int) zip_get_archive_flag(struct zip *, int, int); +ZIP_EXTERN(const char *)zip_get_file_comment(struct zip *, zip_uint64_t, + int *, int); +ZIP_EXTERN(const char *)zip_get_file_extra(struct zip *, zip_uint64_t, + int *, int); +ZIP_EXTERN(const char *)zip_get_name(struct zip *, zip_uint64_t, int); +ZIP_EXTERN(zip_uint64_t) zip_get_num_entries(struct zip *, int); +ZIP_EXTERN(int) zip_get_num_files(struct zip *); /* deprecated, use zip_get_num_entries instead */ +ZIP_EXTERN(int) zip_name_locate(struct zip *, const char *, int); +ZIP_EXTERN(struct zip *)zip_open(const char *, int, int *); +ZIP_EXTERN(int) zip_rename(struct zip *, zip_uint64_t, const char *); +ZIP_EXTERN(int) zip_replace(struct zip *, zip_uint64_t, struct zip_source *); +ZIP_EXTERN(int) zip_set_archive_comment(struct zip *, const char *, int); +ZIP_EXTERN(int) zip_set_archive_flag(struct zip *, int, int); +ZIP_EXTERN(int) zip_set_default_password(struct zip *, const char *); +ZIP_EXTERN(int) zip_set_file_comment(struct zip *, zip_uint64_t, + const char *, int); +ZIP_EXTERN(int) zip_set_file_extra(struct zip *, zip_uint64_t, + const char *, int); +ZIP_EXTERN(struct) zip_source *zip_source_buffer(struct zip *, const void *, + zip_uint64_t, int); +ZIP_EXTERN(struct) zip_source *zip_source_file(struct zip *, const char *, + zip_uint64_t, zip_int64_t); +ZIP_EXTERN(struct) zip_source *zip_source_filep(struct zip *, FILE *, + zip_uint64_t, zip_int64_t); +ZIP_EXTERN(void) zip_source_free(struct zip_source *); +ZIP_EXTERN(struct zip_source *)zip_source_function(struct zip *, + zip_source_callback, void *); +ZIP_EXTERN(struct zip_source *)zip_source_zip(struct zip *, struct zip *, + zip_uint64_t, int, + zip_uint64_t, zip_int64_t); +ZIP_EXTERN(int) zip_stat(struct zip *, const char *, int, struct zip_stat *); +ZIP_EXTERN(int) zip_stat_index(struct zip *, zip_uint64_t, int, + struct zip_stat *); +ZIP_EXTERN(void) zip_stat_init(struct zip_stat *); +ZIP_EXTERN(const char *)zip_strerror(struct zip *); +ZIP_EXTERN(int) zip_unchange(struct zip *, zip_uint64_t); +ZIP_EXTERN(int) zip_unchange_all(struct zip *); +ZIP_EXTERN(int) zip_unchange_archive(struct zip *); + +END_EXTERN_C(); +#endif /* _HAD_ZIP_H */ diff --git a/ext/zip/lib/zip_add.c b/ext/zip/lib/zip_add.c new file mode 100644 index 0000000..6067abb --- /dev/null +++ b/ext/zip/lib/zip_add.c @@ -0,0 +1,56 @@ +/* + zip_add.c -- add file via callback function + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +/* + NOTE: Return type is signed so we can return -1 on error. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. +*/ + +ZIP_EXTERN(zip_int64_t) +zip_add(struct zip *za, const char *name, struct zip_source *source) +{ + if (name == NULL || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_replace(za, ZIP_UINT64_MAX, name, source); +} diff --git a/ext/zip/lib/zip_add_dir.c b/ext/zip/lib/zip_add_dir.c new file mode 100644 index 0000000..0a9d7f4 --- /dev/null +++ b/ext/zip/lib/zip_add_dir.c @@ -0,0 +1,88 @@ +/* + zip_add_dir.c -- add directory + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +ZIP_EXTERN(zip_int64_t) +zip_add_dir(struct zip *za, const char *name) +{ + int len; + zip_int64_t ret; + char *s; + struct zip_source *source; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + s = NULL; + len = strlen(name); + + if (name[len-1] != '/') { + if ((s=(char *)malloc(len+2)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + strcpy(s, name); + s[len] = '/'; + s[len+1] = '\0'; + } + + if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) { + free(s); + return -1; + } + + ret = _zip_replace(za, -1, s ? s : name, source); + + free(s); + if (ret < 0) + zip_source_free(source); + + return ret; +} diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c new file mode 100644 index 0000000..362f92d --- /dev/null +++ b/ext/zip/lib/zip_close.c @@ -0,0 +1,646 @@ +/* + zip_close.c -- close zip archive and update changes + Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#ifdef PHP_WIN32 +#include <io.h> +#include <fcntl.h> +#endif + +static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, + FILE *); +static int copy_data(FILE *, off_t, FILE *, struct zip_error *); +static int copy_source(struct zip *, struct zip_source *, FILE *); +static int write_cdir(struct zip *, struct zip_cdir *, FILE *); +static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *); +static char *_zip_create_temp_output(struct zip *, FILE **); +static int _zip_torrentzip_cmp(const void *, const void *); + + + +struct filelist { + int idx; + const char *name; +}; + + + +ZIP_EXTERN(int) +zip_close(struct zip *za) +{ + int survivors; + int i, j, error; + char *temp; + FILE *out; +#ifndef PHP_WIN32 + mode_t mask; +#endif + struct zip_cdir *cd; + struct zip_dirent de; + struct filelist *filelist; + int reopen_on_error; + int new_torrentzip; + + reopen_on_error = 0; + + if (za == NULL) + return -1; + + if (!_zip_changed(za, &survivors)) { + _zip_free(za); + return 0; + } + + /* don't create zip files with no entries */ + if (survivors == 0) { + if (za->zn && za->zp) { + if (remove(za->zn) != 0) { + _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); + return -1; + } + } + _zip_free(za); + return 0; + } + + if ((filelist=(struct filelist *)malloc(sizeof(filelist[0])*survivors)) + == NULL) + return -1; + + if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL) { + free(filelist); + return -1; + } + + for (i=0; i<survivors; i++) + _zip_dirent_init(&cd->entry[i]); + + /* archive comment is special for torrentzip */ + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) { + cd->comment = _zip_memdup(TORRENT_SIG "XXXXXXXX", + TORRENT_SIG_LEN + TORRENT_CRC_LEN, + &za->error); + if (cd->comment == NULL) { + _zip_cdir_free(cd); + free(filelist); + return -1; + } + cd->comment_len = TORRENT_SIG_LEN + TORRENT_CRC_LEN; + } + else if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, ZIP_FL_UNCHANGED) == 0) { + if (_zip_cdir_set_comment(cd, za) == -1) { + _zip_cdir_free(cd); + free(filelist); + return -1; + } + } + + if ((temp=_zip_create_temp_output(za, &out)) == NULL) { + _zip_cdir_free(cd); + free(filelist); + return -1; + } + + + /* create list of files with index into original archive */ + for (i=j=0; i<za->nentry; i++) { + if (za->entry[i].state == ZIP_ST_DELETED) + continue; + + filelist[j].idx = i; + filelist[j].name = zip_get_name(za, i, 0); + j++; + } + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + qsort(filelist, survivors, sizeof(filelist[0]), + _zip_torrentzip_cmp); + + new_torrentzip = (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 1 + && zip_get_archive_flag(za, ZIP_AFL_TORRENT, + ZIP_FL_UNCHANGED) == 0); + error = 0; + for (j=0; j<survivors; j++) { + i = filelist[j].idx; + + /* create new local directory entry */ + if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) { + _zip_dirent_init(&de); + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + _zip_dirent_torrent_normalize(&de); + + /* use it as central directory entry */ + memcpy(cd->entry+j, &de, sizeof(cd->entry[j])); + + /* set/update file name */ + if (za->entry[i].ch_filename == NULL) { + if (za->entry[i].state == ZIP_ST_ADDED) { + de.filename = strdup("-"); + de.filename_len = 1; + cd->entry[j].filename = "-"; + cd->entry[j].filename_len = 1; + } + else { + de.filename = strdup(za->cdir->entry[i].filename); + de.filename_len = strlen(de.filename); + cd->entry[j].filename = za->cdir->entry[i].filename; + cd->entry[j].filename_len = de.filename_len; + } + } + } + else { + /* copy existing directory entries */ + if (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + error = 1; + break; + } + if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, + &za->error) != 0) { + error = 1; + break; + } + memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j])); + if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + de.crc = za->cdir->entry[i].crc; + de.comp_size = za->cdir->entry[i].comp_size; + de.uncomp_size = za->cdir->entry[i].uncomp_size; + de.bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; + cd->entry[j].bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; + } + } + + if (za->entry[i].ch_filename) { + free(de.filename); + if ((de.filename=strdup(za->entry[i].ch_filename)) == NULL) { + error = 1; + break; + } + de.filename_len = strlen(de.filename); + cd->entry[j].filename = za->entry[i].ch_filename; + cd->entry[j].filename_len = de.filename_len; + } + + if (za->entry[i].ch_extra_len != -1) { + free(de.extrafield); + if ((de.extrafield=malloc(za->entry[i].ch_extra_len)) == NULL) { + error = 1; + break; + } + memcpy(de.extrafield, za->entry[i].ch_extra, za->entry[i].ch_extra_len); + de.extrafield_len = za->entry[i].ch_extra_len; + /* as the rest of cd entries, its malloc/free is done by za */ + /* TODO unsure if this should also be set in the CD -- + * not done for now + cd->entry[j].extrafield = za->entry[i].ch_extra; + cd->entry[j].extrafield_len = za->entry[i].ch_extra_len; + */ + } + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0 + && za->entry[i].ch_comment_len != -1) { + /* as the rest of cd entries, its malloc/free is done by za */ + cd->entry[j].comment = za->entry[i].ch_comment; + cd->entry[j].comment_len = za->entry[i].ch_comment_len; + } + + cd->entry[j].offset = ftello(out); + + if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) { + struct zip_source *zs; + + zs = NULL; + if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) { + if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1)) + == NULL) { + error = 1; + break; + } + } + + if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) { + error = 1; + if (zs) + zip_source_free(zs); + break; + } + if (zs) + zip_source_free(zs); + + cd->entry[j].last_mod = de.last_mod; + cd->entry[j].comp_method = de.comp_method; + cd->entry[j].comp_size = de.comp_size; + cd->entry[j].uncomp_size = de.uncomp_size; + cd->entry[j].crc = de.crc; + } + else { + if (_zip_dirent_write(&de, out, 1, &za->error) < 0) { + error = 1; + break; + } + /* we just read the local dirent, file is at correct position */ + if (copy_data(za->zp, cd->entry[j].comp_size, out, + &za->error) < 0) { + error = 1; + break; + } + } + + _zip_dirent_finalize(&de); + } + + free(filelist); + + if (!error) { + if (write_cdir(za, cd, out) < 0) + error = 1; + } + + /* pointers in cd entries are owned by za */ + cd->nentry = 0; + _zip_cdir_free(cd); + + if (error) { + _zip_dirent_finalize(&de); + fclose(out); + remove(temp); + free(temp); + return -1; + } + + if (fclose(out) != 0) { + _zip_error_set(&za->error, ZIP_ER_CLOSE, errno); + remove(temp); + free(temp); + return -1; + } + + if (za->zp) { + fclose(za->zp); + za->zp = NULL; + reopen_on_error = 1; + } + if (_zip_rename(temp, za->zn) != 0) { + _zip_error_set(&za->error, ZIP_ER_RENAME, errno); + remove(temp); + free(temp); + if (reopen_on_error) { + /* ignore errors, since we're already in an error case */ + za->zp = fopen(za->zn, "rb"); + } + return -1; + } +#ifndef PHP_WIN32 + mask = umask(0); + umask(mask); + chmod(za->zn, 0666&~mask); +#endif + + _zip_free(za); + free(temp); + + return 0; +} + + + +static int +add_data(struct zip *za, struct zip_source *src, struct zip_dirent *de, + FILE *ft) +{ + off_t offstart, offdata, offend; + struct zip_stat st; + struct zip_source *s2; + zip_compression_implementation comp_impl; + int ret; + + if (zip_source_stat(src, &st) < 0) { + _zip_error_set_from_source(&za->error, src); + return -1; + } + + offstart = ftello(ft); + + if (_zip_dirent_write(de, ft, 1, &za->error) < 0) + return -1; + + if ((s2=zip_source_crc(za, src, 0)) == NULL) { + zip_source_pop(s2); + return -1; + } + + /* XXX: deflate 0-byte files for torrentzip? */ + if (((st.valid & ZIP_STAT_COMP_METHOD) == 0 + || st.comp_method == ZIP_CM_STORE) + && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) { + comp_impl = NULL; + if ((comp_impl=zip_get_compression_implementation(ZIP_CM_DEFLATE)) + == NULL) { + _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_source_pop(s2); + return -1; + } + if ((s2=comp_impl(za, s2, ZIP_CM_DEFLATE, ZIP_CODEC_ENCODE)) + == NULL) { + /* XXX: set error? */ + zip_source_pop(s2); + return -1; + } + } + else + s2 = src; + + offdata = ftello(ft); + + ret = copy_source(za, s2, ft); + + if (zip_source_stat(s2, &st) < 0) + ret = -1; + + while (s2 != src) { + if ((s2=zip_source_pop(s2)) == NULL) { + /* XXX: set erorr */ + ret = -1; + break; + } + } + + if (ret < 0) + return -1; + + offend = ftello(ft); + + if (fseeko(ft, offstart, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + de->last_mod = st.mtime; + de->comp_method = st.comp_method; + de->crc = st.crc; + de->uncomp_size = st.size; + de->comp_size = offend - offdata; + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + _zip_dirent_torrent_normalize(de); + + if (_zip_dirent_write(de, ft, 1, &za->error) < 0) + return -1; + + if (fseeko(ft, offend, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + return 0; +} + + + +static int +copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error) +{ + char buf[BUFSIZE]; + int n, nn; + + if (len == 0) + return 0; + + while (len > 0) { + nn = len > sizeof(buf) ? sizeof(buf) : len; + if ((n=fread(buf, 1, nn, fs)) < 0) { + _zip_error_set(error, ZIP_ER_READ, errno); + return -1; + } + else if (n == 0) { + _zip_error_set(error, ZIP_ER_EOF, 0); + return -1; + } + + if (fwrite(buf, 1, n, ft) != (size_t)n) { + _zip_error_set(error, ZIP_ER_WRITE, errno); + return -1; + } + + len -= n; + } + + return 0; +} + + + +static int +copy_source(struct zip *za, struct zip_source *src, FILE *ft) +{ + char buf[BUFSIZE]; + zip_int64_t n; + int ret; + + if (zip_source_open(src) < 0) { + _zip_error_set_from_source(&za->error, src); + return -1; + } + + ret = 0; + while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) { + if (fwrite(buf, 1, n, ft) != (size_t)n) { + _zip_error_set(&za->error, ZIP_ER_WRITE, errno); + ret = -1; + break; + } + } + + if (n < 0) { + if (ret == 0) + _zip_error_set_from_source(&za->error, src); + ret = -1; + } + + zip_source_close(src); + + return ret; +} + + + +static int +write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out) +{ + off_t offset; + uLong crc; + char buf[TORRENT_CRC_LEN+1]; + + if (_zip_cdir_write(cd, out, &za->error) < 0) + return -1; + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0) + return 0; + + + /* fix up torrentzip comment */ + + offset = ftello(out); + + if (_zip_filerange_crc(out, cd->offset, cd->size, &crc, &za->error) < 0) + return -1; + + snprintf(buf, sizeof(buf), "%08lX", (long)crc); + + if (fseeko(out, offset-TORRENT_CRC_LEN, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) { + _zip_error_set(&za->error, ZIP_ER_WRITE, errno); + return -1; + } + + return 0; +} + + + +static int +_zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src) +{ + if (src->ch_comment_len != -1) { + dest->comment = _zip_memdup(src->ch_comment, + src->ch_comment_len, &src->error); + if (dest->comment == NULL) + return -1; + dest->comment_len = src->ch_comment_len; + } else { + if (src->cdir && src->cdir->comment) { + dest->comment = _zip_memdup(src->cdir->comment, + src->cdir->comment_len, &src->error); + if (dest->comment == NULL) + return -1; + dest->comment_len = src->cdir->comment_len; + } + } + + return 0; +} + + + +int +_zip_changed(struct zip *za, int *survivorsp) +{ + int changed, i, survivors; + + changed = survivors = 0; + + if (za->ch_comment_len != -1 + || za->ch_flags != za->flags) + changed = 1; + + for (i=0; i<za->nentry; i++) { + if ((za->entry[i].state != ZIP_ST_UNCHANGED) + || (za->entry[i].ch_extra_len != -1) + || (za->entry[i].ch_comment_len != -1)) + changed = 1; + if (za->entry[i].state != ZIP_ST_DELETED) + survivors++; + } + + if (survivorsp) + *survivorsp = survivors; + + return changed; +} + + + +static char * +_zip_create_temp_output(struct zip *za, FILE **outp) +{ + char *temp; + int tfd; + FILE *tfp; + int len = strlen(za->zn) + 8; + + if ((temp=(char *)malloc(len)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + snprintf(temp, len, "%s.XXXXXX", za->zn); + + if ((tfd=mkstemp(temp)) == -1) { + _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return NULL; + } + + if ((tfp=fdopen(tfd, "r+b")) == NULL) { + _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); + close(tfd); + remove(temp); + free(temp); + return NULL; + } +#ifdef PHP_WIN32 + /* + According to Pierre Joye, Windows in some environments per + default creates text files, so force binary mode. + */ + _setmode(_fileno(tfp), _O_BINARY ); +#endif + + *outp = tfp; + return temp; +} + + + +static int +_zip_torrentzip_cmp(const void *a, const void *b) +{ + return strcasecmp(((const struct filelist *)a)->name, + ((const struct filelist *)b)->name); +} diff --git a/ext/zip/lib/zip_delete.c b/ext/zip/lib/zip_delete.c new file mode 100644 index 0000000..131d444 --- /dev/null +++ b/ext/zip/lib/zip_delete.c @@ -0,0 +1,63 @@ +/* + zip_delete.c -- delete file from zip archive + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_delete(struct zip *za, zip_uint64_t idx) +{ + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + /* allow duplicate file names, because the file will + * be removed directly afterwards */ + if (_zip_unchange(za, idx, 1) != 0) + return -1; + + za->entry[idx].state = ZIP_ST_DELETED; + + return 0; +} + + diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c new file mode 100644 index 0000000..b5b9d27 --- /dev/null +++ b/ext/zip/lib/zip_dirent.c @@ -0,0 +1,614 @@ +/* + zip_dirent.c -- read directory entry (local or central), clean dirent + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "zipint.h" + +static time_t _zip_d2u_time(int, int); +static char *_zip_readfpstr(FILE *, unsigned int, int, struct zip_error *); +static char *_zip_readstr(unsigned char **, int, int, struct zip_error *); +static void _zip_write2(unsigned short, FILE *); +static void _zip_write4(unsigned int, FILE *); + + + +void +_zip_cdir_free(struct zip_cdir *cd) +{ + int i; + + if (!cd) + return; + + for (i=0; i<cd->nentry; i++) + _zip_dirent_finalize(cd->entry+i); + free(cd->comment); + free(cd->entry); + free(cd); +} + + + +int +_zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error) +{ + struct zip_dirent *entry; + + if (nentry < cd->nentry) { + _zip_error_set(error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((entry=((struct zip_dirent *) + realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + + cd->nentry = nentry; + cd->entry = entry; + + return 0; +} + + + +struct zip_cdir * +_zip_cdir_new(int nentry, struct zip_error *error) +{ + struct zip_cdir *cd; + + if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*nentry)) + == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + free(cd); + return NULL; + } + + /* entries must be initialized by caller */ + + cd->nentry = nentry; + cd->size = cd->offset = 0; + cd->comment = NULL; + cd->comment_len = 0; + + return cd; +} + + + +int +_zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error) +{ + int i; + + cd->offset = ftello(fp); + + for (i=0; i<cd->nentry; i++) { + if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0) + return -1; + } + + cd->size = ftello(fp) - cd->offset; + + /* clearerr(fp); */ + fwrite(EOCD_MAGIC, 1, 4, fp); + _zip_write4(0, fp); + _zip_write2((unsigned short)cd->nentry, fp); + _zip_write2((unsigned short)cd->nentry, fp); + _zip_write4(cd->size, fp); + _zip_write4(cd->offset, fp); + _zip_write2(cd->comment_len, fp); + fwrite(cd->comment, 1, cd->comment_len, fp); + + if (ferror(fp)) { + _zip_error_set(error, ZIP_ER_WRITE, errno); + return -1; + } + + return 0; +} + + + +void +_zip_dirent_finalize(struct zip_dirent *zde) +{ + free(zde->filename); + zde->filename = NULL; + free(zde->extrafield); + zde->extrafield = NULL; + free(zde->comment); + zde->comment = NULL; +} + + + +void +_zip_dirent_init(struct zip_dirent *de) +{ + de->version_madeby = 0; + de->version_needed = 20; /* 2.0 */ + de->bitflags = 0; + de->comp_method = 0; + de->last_mod = 0; + de->crc = 0; + de->comp_size = 0; + de->uncomp_size = 0; + de->filename = NULL; + de->filename_len = 0; + de->extrafield = NULL; + de->extrafield_len = 0; + de->comment = NULL; + de->comment_len = 0; + de->disk_number = 0; + de->int_attrib = 0; + de->ext_attrib = 0; + de->offset = 0; +} + + + +/* _zip_dirent_read(zde, fp, bufp, left, localp, error): + Fills the zip directory entry zde. + + If bufp is non-NULL, data is taken from there and bufp is advanced + by the amount of data used; otherwise data is read from fp as needed. + + if leftp is non-NULL, no more bytes than specified by it are used, + and *leftp is reduced by the number of bytes used. + + If local != 0, it reads a local header instead of a central + directory entry. + + Returns 0 if successful. On error, error is filled in and -1 is + returned. + + XXX: leftp and file position undefined on error. +*/ + +int +_zip_dirent_read(struct zip_dirent *zde, FILE *fp, + unsigned char **bufp, zip_uint32_t *leftp, int local, + struct zip_error *error) +{ + unsigned char buf[CDENTRYSIZE]; + unsigned char *cur; + unsigned short dostime, dosdate; + zip_uint32_t size; + + if (local) + size = LENTRYSIZE; + else + size = CDENTRYSIZE; + + if (leftp && (*leftp < size)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (bufp) { + /* use data from buffer */ + cur = *bufp; + } + else { + /* read entry from disk */ + if ((fread(buf, 1, size, fp)<size)) { + _zip_error_set(error, ZIP_ER_READ, errno); + return -1; + } + cur = buf; + } + + if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + cur += 4; + + + /* convert buffercontents to zip_dirent */ + + if (!local) + zde->version_madeby = _zip_read2(&cur); + else + zde->version_madeby = 0; + zde->version_needed = _zip_read2(&cur); + zde->bitflags = _zip_read2(&cur); + zde->comp_method = _zip_read2(&cur); + + /* convert to time_t */ + dostime = _zip_read2(&cur); + dosdate = _zip_read2(&cur); + zde->last_mod = _zip_d2u_time(dostime, dosdate); + + zde->crc = _zip_read4(&cur); + zde->comp_size = _zip_read4(&cur); + zde->uncomp_size = _zip_read4(&cur); + + zde->filename_len = _zip_read2(&cur); + zde->extrafield_len = _zip_read2(&cur); + + if (local) { + zde->comment_len = 0; + zde->disk_number = 0; + zde->int_attrib = 0; + zde->ext_attrib = 0; + zde->offset = 0; + } else { + zde->comment_len = _zip_read2(&cur); + zde->disk_number = _zip_read2(&cur); + zde->int_attrib = _zip_read2(&cur); + zde->ext_attrib = _zip_read4(&cur); + zde->offset = _zip_read4(&cur); + } + + zde->filename = NULL; + zde->extrafield = NULL; + zde->comment = NULL; + + size += zde->filename_len+zde->extrafield_len+zde->comment_len; + + if (leftp && (*leftp < size)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (bufp) { + if (zde->filename_len) { + zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error); + if (!zde->filename) + return -1; + } + + if (zde->extrafield_len) { + zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0, + error); + if (!zde->extrafield) + return -1; + } + + if (zde->comment_len) { + zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error); + if (!zde->comment) + return -1; + } + } + else { + if (zde->filename_len) { + zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error); + if (!zde->filename) + return -1; + } + + if (zde->extrafield_len) { + zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0, + error); + if (!zde->extrafield) + return -1; + } + + if (zde->comment_len) { + zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error); + if (!zde->comment) + return -1; + } + } + + if (bufp) + *bufp = cur; + if (leftp) + *leftp -= size; + + return 0; +} + + + +/* _zip_dirent_torrent_normalize(de); + Set values suitable for torrentzip. +*/ + +void +_zip_dirent_torrent_normalize(struct zip_dirent *de) +{ + static struct tm torrenttime; + static time_t last_mod = 0; + + if (last_mod == 0) { +#ifdef HAVE_STRUCT_TM_TM_ZONE + time_t now; + struct tm *l; +#endif + + torrenttime.tm_sec = 0; + torrenttime.tm_min = 32; + torrenttime.tm_hour = 23; + torrenttime.tm_mday = 24; + torrenttime.tm_mon = 11; + torrenttime.tm_year = 96; + torrenttime.tm_wday = 0; + torrenttime.tm_yday = 0; + torrenttime.tm_isdst = 0; + +#ifdef HAVE_STRUCT_TM_TM_ZONE + time(&now); + l = localtime(&now); + torrenttime.tm_gmtoff = l->tm_gmtoff; + torrenttime.tm_zone = l->tm_zone; +#endif + + last_mod = mktime(&torrenttime); + } + + de->version_madeby = 0; + de->version_needed = 20; /* 2.0 */ + de->bitflags = 2; /* maximum compression */ + de->comp_method = ZIP_CM_DEFLATE; + de->last_mod = last_mod; + + de->disk_number = 0; + de->int_attrib = 0; + de->ext_attrib = 0; + de->offset = 0; + + free(de->extrafield); + de->extrafield = NULL; + de->extrafield_len = 0; + free(de->comment); + de->comment = NULL; + de->comment_len = 0; +} + + + +/* _zip_dirent_write(zde, fp, localp, error): + Writes zip directory entry zde to file fp. + + If localp != 0, it writes a local header instead of a central + directory entry. + + Returns 0 if successful. On error, error is filled in and -1 is + returned. +*/ + +int +_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp, + struct zip_error *error) +{ + unsigned short dostime, dosdate; + + fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp); + + if (!localp) + _zip_write2(zde->version_madeby, fp); + _zip_write2(zde->version_needed, fp); + _zip_write2(zde->bitflags, fp); + _zip_write2(zde->comp_method, fp); + + _zip_u2d_time(zde->last_mod, &dostime, &dosdate); + _zip_write2(dostime, fp); + _zip_write2(dosdate, fp); + + _zip_write4(zde->crc, fp); + _zip_write4(zde->comp_size, fp); + _zip_write4(zde->uncomp_size, fp); + + _zip_write2(zde->filename_len, fp); + _zip_write2(zde->extrafield_len, fp); + + if (!localp) { + _zip_write2(zde->comment_len, fp); + _zip_write2(zde->disk_number, fp); + _zip_write2(zde->int_attrib, fp); + _zip_write4(zde->ext_attrib, fp); + _zip_write4(zde->offset, fp); + } + + if (zde->filename_len) + fwrite(zde->filename, 1, zde->filename_len, fp); + + if (zde->extrafield_len) + fwrite(zde->extrafield, 1, zde->extrafield_len, fp); + + if (!localp) { + if (zde->comment_len) + fwrite(zde->comment, 1, zde->comment_len, fp); + } + + if (ferror(fp)) { + _zip_error_set(error, ZIP_ER_WRITE, errno); + return -1; + } + + return 0; +} + + + +static time_t +_zip_d2u_time(int dtime, int ddate) +{ + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + + /* let mktime decide if DST is in effect */ + tm.tm_isdst = -1; + + tm.tm_year = ((ddate>>9)&127) + 1980 - 1900; + tm.tm_mon = ((ddate>>5)&15) - 1; + tm.tm_mday = ddate&31; + + tm.tm_hour = (dtime>>11)&31; + tm.tm_min = (dtime>>5)&63; + tm.tm_sec = (dtime<<1)&62; + + return mktime(&tm); +} + + + +unsigned short +_zip_read2(unsigned char **a) +{ + unsigned short ret; + + ret = (*a)[0]+((*a)[1]<<8); + *a += 2; + + return ret; +} + + + +unsigned int +_zip_read4(unsigned char **a) +{ + unsigned int ret; + + ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + + return ret; +} + + + +static char * +_zip_readfpstr(FILE *fp, unsigned int len, int nulp, struct zip_error *error) +{ + char *r, *o; + + r = (char *)malloc(nulp ? len+1 : len); + if (!r) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (fread(r, 1, len, fp)<len) { + free(r); + _zip_error_set(error, ZIP_ER_READ, errno); + return NULL; + } + + if (nulp) { + /* replace any in-string NUL characters with spaces */ + r[len] = 0; + for (o=r; o<r+len; o++) + if (*o == '\0') + *o = ' '; + } + + return r; +} + + + +static char * +_zip_readstr(unsigned char **buf, int len, int nulp, struct zip_error *error) +{ + char *r, *o; + + r = (char *)malloc(nulp ? len+1 : len); + if (!r) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + memcpy(r, *buf, len); + *buf += len; + + if (nulp) { + /* replace any in-string NUL characters with spaces */ + r[len] = 0; + for (o=r; o<r+len; o++) + if (*o == '\0') + *o = ' '; + } + + return r; +} + + + +static void +_zip_write2(unsigned short i, FILE *fp) +{ + putc(i&0xff, fp); + putc((i>>8)&0xff, fp); + + return; +} + + + +static void +_zip_write4(unsigned int i, FILE *fp) +{ + putc(i&0xff, fp); + putc((i>>8)&0xff, fp); + putc((i>>16)&0xff, fp); + putc((i>>24)&0xff, fp); + + return; +} + + + +void +_zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate) +{ + struct tm *tm; + + tm = localtime(&time); + *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + + tm->tm_mday; + *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + + ((tm->tm_sec)>>1); + + return; +} diff --git a/ext/zip/lib/zip_entry_free.c b/ext/zip/lib/zip_entry_free.c new file mode 100644 index 0000000..e8a7770 --- /dev/null +++ b/ext/zip/lib/zip_entry_free.c @@ -0,0 +1,55 @@ +/* + zip_entry_free.c -- free struct zip_entry + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +void +_zip_entry_free(struct zip_entry *ze) +{ + free(ze->ch_filename); + ze->ch_filename = NULL; + free(ze->ch_extra); + ze->ch_extra = NULL; + ze->ch_extra_len = -1; + free(ze->ch_comment); + ze->ch_comment = NULL; + ze->ch_comment_len = -1; + + _zip_unchange_data(ze); +} diff --git a/ext/zip/lib/zip_entry_new.c b/ext/zip/lib/zip_entry_new.c new file mode 100644 index 0000000..ad5d599 --- /dev/null +++ b/ext/zip/lib/zip_entry_new.c @@ -0,0 +1,81 @@ +/* + zip_entry_new.c -- create and init struct zip_entry + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +struct zip_entry * +_zip_entry_new(struct zip *za) +{ + struct zip_entry *ze; + if (!za) { + ze = (struct zip_entry *)malloc(sizeof(struct zip_entry)); + if (!ze) { + return NULL; + } + } + else { + if (za->nentry+1 >= za->nentry_alloc) { + struct zip_entry *rentries; + za->nentry_alloc += 16; + rentries = (struct zip_entry *)realloc(za->entry, + sizeof(struct zip_entry) + * za->nentry_alloc); + if (!rentries) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + za->entry = rentries; + } + ze = za->entry+za->nentry; + } + + ze->state = ZIP_ST_UNCHANGED; + + ze->ch_filename = NULL; + ze->ch_extra = NULL; + ze->ch_extra_len = -1; + ze->ch_comment = NULL; + ze->ch_comment_len = -1; + ze->source = NULL; + + if (za) + za->nentry++; + + return ze; +} diff --git a/ext/zip/lib/zip_err_str.c b/ext/zip/lib/zip_err_str.c new file mode 100644 index 0000000..8fb6003 --- /dev/null +++ b/ext/zip/lib/zip_err_str.c @@ -0,0 +1,76 @@ +/* + This file was generated automatically by ./make_zip_err_str.sh + from ./zip.h; make changes there. + */ + +#include "zipint.h" + + + +const char * const _zip_err_str[] = { + "No error", + "Multi-disk zip archives not supported", + "Renaming temporary file failed", + "Closing zip archive failed", + "Seek error", + "Read error", + "Write error", + "CRC error", + "Containing zip archive was closed", + "No such file", + "File already exists", + "Can't open file", + "Failure to create temporary file", + "Zlib error", + "Malloc failure", + "Entry has been changed", + "Compression method not supported", + "Premature EOF", + "Invalid argument", + "Not a zip archive", + "Internal error", + "Zip archive inconsistent", + "Can't remove file", + "Entry has been deleted", + "Encryption method not supported", + "Read-only archive", + "No password provided", + "Wrong password provided", +}; + +const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); + +#define N ZIP_ET_NONE +#define S ZIP_ET_SYS +#define Z ZIP_ET_ZLIB + +const int _zip_err_type[] = { + N, + N, + S, + S, + S, + S, + S, + N, + N, + N, + N, + S, + S, + Z, + N, + N, + N, + N, + N, + N, + N, + N, + S, + N, + N, + N, + N, + N, +}; diff --git a/ext/zip/lib/zip_error.c b/ext/zip/lib/zip_error.c new file mode 100644 index 0000000..b8d907a --- /dev/null +++ b/ext/zip/lib/zip_error.c @@ -0,0 +1,112 @@ +/* + zip_error.c -- struct zip_error helper functions + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +void +_zip_error_clear(struct zip_error *err) +{ + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; +} + + + +void +_zip_error_copy(struct zip_error *dst, struct zip_error *src) +{ + dst->zip_err = src->zip_err; + dst->sys_err = src->sys_err; +} + + + +void +_zip_error_fini(struct zip_error *err) +{ + free(err->str); + err->str = NULL; +} + + + +void +_zip_error_get(struct zip_error *err, int *zep, int *sep) +{ + if (zep) + *zep = err->zip_err; + if (sep) { + if (zip_error_get_sys_type(err->zip_err) != ZIP_ET_NONE) + *sep = err->sys_err; + else + *sep = 0; + } +} + + + +void +_zip_error_init(struct zip_error *err) +{ + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; + err->str = NULL; +} + + + +void +_zip_error_set(struct zip_error *err, int ze, int se) +{ + if (err) { + err->zip_err = ze; + err->sys_err = se; + } +} + + + +void +_zip_error_set_from_source(struct zip_error *err, struct zip_source *src) +{ + int ze, se; + + zip_source_error(src, &ze, &se); + _zip_error_set(err, ze, se); +} diff --git a/ext/zip/lib/zip_error_clear.c b/ext/zip/lib/zip_error_clear.c new file mode 100644 index 0000000..34e7dea --- /dev/null +++ b/ext/zip/lib/zip_error_clear.c @@ -0,0 +1,44 @@ +/* + zip_error_clear.c -- clear zip error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_error_clear(struct zip *za) +{ + _zip_error_clear(&za->error); +} diff --git a/ext/zip/lib/zip_error_get.c b/ext/zip/lib/zip_error_get.c new file mode 100644 index 0000000..c15705e --- /dev/null +++ b/ext/zip/lib/zip_error_get.c @@ -0,0 +1,44 @@ +/* + zip_error_get.c -- get zip error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_error_get(struct zip *za, int *zep, int *sep) +{ + _zip_error_get(&za->error, zep, sep); +} diff --git a/ext/zip/lib/zip_error_get_sys_type.c b/ext/zip/lib/zip_error_get_sys_type.c new file mode 100644 index 0000000..47aa93e --- /dev/null +++ b/ext/zip/lib/zip_error_get_sys_type.c @@ -0,0 +1,47 @@ +/* + zip_error_get_sys_type.c -- return type of system error code + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_error_get_sys_type(int ze) +{ + if (ze < 0 || ze >= _zip_nerr_str) + return 0; + + return _zip_err_type[ze]; +} diff --git a/ext/zip/lib/zip_error_strerror.c b/ext/zip/lib/zip_error_strerror.c new file mode 100644 index 0000000..3d0951c --- /dev/null +++ b/ext/zip/lib/zip_error_strerror.c @@ -0,0 +1,90 @@ +/* + zip_error_sterror.c -- get string representation of struct zip_error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +const char * +_zip_error_strerror(struct zip_error *err) +{ + const char *zs, *ss; + char buf[128], *s; + + _zip_error_fini(err); + + if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) { + sprintf(buf, "Unknown error %d", err->zip_err); + zs = NULL; + ss = buf; + } + else { + zs = _zip_err_str[err->zip_err]; + + switch (_zip_err_type[err->zip_err]) { + case ZIP_ET_SYS: + ss = strerror(err->sys_err); + break; + + case ZIP_ET_ZLIB: + ss = zError(err->sys_err); + break; + + default: + ss = NULL; + } + } + + if (ss == NULL) + return zs; + else { + if ((s=(char *)malloc(strlen(ss) + + (zs ? strlen(zs)+2 : 0) + 1)) == NULL) + return _zip_err_str[ZIP_ER_MEMORY]; + + sprintf(s, "%s%s%s", + (zs ? zs : ""), + (zs ? ": " : ""), + ss); + err->str = s; + + return s; + } +} diff --git a/ext/zip/lib/zip_error_to_str.c b/ext/zip/lib/zip_error_to_str.c new file mode 100644 index 0000000..bafe743 --- /dev/null +++ b/ext/zip/lib/zip_error_to_str.c @@ -0,0 +1,70 @@ +/* + zip_error_to_str.c -- get string representation of zip error code + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) +{ + const char *zs, *ss; + + if (ze < 0 || ze >= _zip_nerr_str) + return snprintf(buf, len, "Unknown error %d", ze); + + zs = _zip_err_str[ze]; + + switch (_zip_err_type[ze]) { + case ZIP_ET_SYS: + ss = strerror(se); + break; + + case ZIP_ET_ZLIB: + ss = zError(se); + break; + + default: + ss = NULL; + } + + return snprintf(buf, len, "%s%s%s", + zs, (ss ? ": " : ""), (ss ? ss : "")); +} diff --git a/ext/zip/lib/zip_fclose.c b/ext/zip/lib/zip_fclose.c new file mode 100644 index 0000000..eb55ddb --- /dev/null +++ b/ext/zip/lib/zip_fclose.c @@ -0,0 +1,64 @@ +/* + zip_fclose.c -- close file in zip archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_fclose(struct zip_file *zf) +{ + int i, ret; + + if (zf->src) + zip_source_free(zf->src); + + for (i=0; i<zf->za->nfile; i++) { + if (zf->za->file[i] == zf) { + zf->za->file[i] = zf->za->file[zf->za->nfile-1]; + zf->za->nfile--; + break; + } + } + + ret = 0; + if (zf->error.zip_err) + ret = zf->error.zip_err; + + free(zf); + return ret; +} diff --git a/ext/zip/lib/zip_fdopen.c b/ext/zip/lib/zip_fdopen.c new file mode 100644 index 0000000..df70f27 --- /dev/null +++ b/ext/zip/lib/zip_fdopen.c @@ -0,0 +1,62 @@ +/* + zip_fdopen.c -- open read-only archive from file descriptor + Copyright (C) 2009-2010 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip *) +zip_fdopen(int fd_orig, int flags, int *zep) +{ + int fd; + FILE *fp; + + /* We dup() here to avoid messing with the passed in fd. + We could not restore it to the original state in case of error. */ + + if ((fd=dup(fd_orig)) < 0) { + *zep = ZIP_ER_OPEN; + return NULL; + } + + if ((fp=fdopen(fd, "rb")) == NULL) { + close(fd); + *zep = ZIP_ER_OPEN; + return NULL; + } + + close(fd_orig); + return _zip_open(NULL, fp, flags, ZIP_AFL_RDONLY, zep); +} diff --git a/ext/zip/lib/zip_file_error_clear.c b/ext/zip/lib/zip_file_error_clear.c new file mode 100644 index 0000000..6c9c2a0 --- /dev/null +++ b/ext/zip/lib/zip_file_error_clear.c @@ -0,0 +1,44 @@ +/* + zip_file_error_clear.c -- clear zip file error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_file_error_clear(struct zip_file *zf) +{ + _zip_error_clear(&zf->error); +} diff --git a/ext/zip/lib/zip_file_error_get.c b/ext/zip/lib/zip_file_error_get.c new file mode 100644 index 0000000..a53fa7e --- /dev/null +++ b/ext/zip/lib/zip_file_error_get.c @@ -0,0 +1,44 @@ +/* + zip_file_error_get.c -- get zip file error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_file_error_get(struct zip_file *zf, int *zep, int *sep) +{ + _zip_error_get(&zf->error, zep, sep); +} diff --git a/ext/zip/lib/zip_file_get_offset.c b/ext/zip/lib/zip_file_get_offset.c new file mode 100644 index 0000000..b96fd5e --- /dev/null +++ b/ext/zip/lib/zip_file_get_offset.c @@ -0,0 +1,74 @@ +/* + zip_file_get_offset.c -- get offset of file data in archive. + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "zipint.h" + + + +/* _zip_file_get_offset(za, ze): + Returns the offset of the file data for entry ze. + + On error, fills in za->error and returns 0. +*/ + +unsigned int +_zip_file_get_offset(struct zip *za, int idx) +{ + struct zip_dirent de; + unsigned int offset; + + offset = za->cdir->entry[idx].offset; + + if (fseeko(za->zp, offset, SEEK_SET) != 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return 0; + } + + if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, &za->error) != 0) + return 0; + + offset += LENTRYSIZE + de.filename_len + de.extrafield_len; + + _zip_dirent_finalize(&de); + + return offset; +} diff --git a/ext/zip/lib/zip_file_strerror.c b/ext/zip/lib/zip_file_strerror.c new file mode 100644 index 0000000..c2864f2 --- /dev/null +++ b/ext/zip/lib/zip_file_strerror.c @@ -0,0 +1,44 @@ +/* + zip_file_sterror.c -- get string representation of zip file error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(const char *) +zip_file_strerror(struct zip_file *zf) +{ + return _zip_error_strerror(&zf->error); +} diff --git a/ext/zip/lib/zip_filerange_crc.c b/ext/zip/lib/zip_filerange_crc.c new file mode 100644 index 0000000..4d1ad56 --- /dev/null +++ b/ext/zip/lib/zip_filerange_crc.c @@ -0,0 +1,71 @@ +/* + zip_filerange_crc.c -- compute CRC32 for a range of a file + Copyright (C) 2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdio.h> +#include <errno.h> + +#include "zipint.h" + + + + +int +_zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp, + struct zip_error *errp) +{ + Bytef buf[BUFSIZE]; + size_t n; + + *crcp = crc32(0L, Z_NULL, 0); + + if (fseeko(fp, start, SEEK_SET) != 0) { + _zip_error_set(errp, ZIP_ER_SEEK, errno); + return -1; + } + + while (len > 0) { + n = len > BUFSIZE ? BUFSIZE : len; + if ((n=fread(buf, 1, n, fp)) <= 0) { + _zip_error_set(errp, ZIP_ER_READ, errno); + return -1; + } + + *crcp = crc32(*crcp, buf, n); + + len-= n; + } + + return 0; +} diff --git a/ext/zip/lib/zip_fopen.c b/ext/zip/lib/zip_fopen.c new file mode 100644 index 0000000..f62adbb --- /dev/null +++ b/ext/zip/lib/zip_fopen.c @@ -0,0 +1,49 @@ +/* + zip_fopen.c -- open file in zip archive for reading + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip_file *) +zip_fopen(struct zip *za, const char *fname, int flags) +{ + int idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return NULL; + + return zip_fopen_index_encrypted(za, idx, flags, za->default_password); +} diff --git a/ext/zip/lib/zip_fopen_encrypted.c b/ext/zip/lib/zip_fopen_encrypted.c new file mode 100644 index 0000000..8aba062 --- /dev/null +++ b/ext/zip/lib/zip_fopen_encrypted.c @@ -0,0 +1,50 @@ +/* + zip_fopen_encrypted.c -- open file for reading with password + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip_file *) +zip_fopen_encrypted(struct zip *za, const char *fname, int flags, + const char *password) +{ + int idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return NULL; + + return zip_fopen_index_encrypted(za, idx, flags, password); +} diff --git a/ext/zip/lib/zip_fopen_index.c b/ext/zip/lib/zip_fopen_index.c new file mode 100644 index 0000000..b60fd33 --- /dev/null +++ b/ext/zip/lib/zip_fopen_index.c @@ -0,0 +1,48 @@ +/* + zip_fopen_index.c -- open file in zip archive for reading by index + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip_file *) +zip_fopen_index(struct zip *za, zip_uint64_t fileno, int flags) +{ + return zip_fopen_index_encrypted(za, fileno, flags, za->default_password); +} diff --git a/ext/zip/lib/zip_fopen_index_encrypted.c b/ext/zip/lib/zip_fopen_index_encrypted.c new file mode 100644 index 0000000..988a78f --- /dev/null +++ b/ext/zip/lib/zip_fopen_index_encrypted.c @@ -0,0 +1,191 @@ +/* + zip_fopen_index_encrypted.c -- open file for reading by index w/ password + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include "zipint.h" + +static struct zip_file *_zip_file_new(struct zip *za); + + + +ZIP_EXTERN(struct zip_file *) +zip_fopen_index_encrypted(struct zip *za, zip_uint64_t fileno, int flags, + const char *password) +{ + struct zip_file *zf; + zip_compression_implementation comp_impl; + zip_encryption_implementation enc_impl; + struct zip_source *src, *s2; + zip_uint64_t start; + struct zip_stat st; + + if (fileno >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(za->entry+fileno)) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return NULL; + } + + if (fileno >= za->cdir->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (flags & ZIP_FL_ENCRYPTED) + flags |= ZIP_FL_COMPRESSED; + + zip_stat_index(za, fileno, flags, &st); + + enc_impl = NULL; + if ((flags & ZIP_FL_ENCRYPTED) == 0) { + if (st.encryption_method != ZIP_EM_NONE) { + if (password == NULL) { + _zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); + return NULL; + } + if ((enc_impl=zip_get_encryption_implementation( + st.encryption_method)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + } + } + + comp_impl = NULL; + if ((flags & ZIP_FL_COMPRESSED) == 0) { + if (st.comp_method != ZIP_CM_STORE) { + if ((comp_impl=zip_get_compression_implementation( + st.comp_method)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return NULL; + } + } + } + + if ((start=_zip_file_get_offset(za, fileno)) == 0) + return NULL; + + if (st.comp_size == 0) { + if ((src=zip_source_buffer(za, NULL, 0, 0)) == NULL) + return NULL; + } + else { + if ((src=_zip_source_file_or_p(za, NULL, za->zp, start, st.comp_size, + 0, &st)) == NULL) + return NULL; + if (enc_impl) { + if ((s2=enc_impl(za, src, ZIP_EM_TRAD_PKWARE, 0, + password)) == NULL) { + zip_source_free(src); + /* XXX: set error (how?) */ + return NULL; + } + src = s2; + } + if (comp_impl) { + if ((s2=comp_impl(za, src, za->cdir->entry[fileno].comp_method, + 0)) == NULL) { + zip_source_free(src); + /* XXX: set error (how?) */ + return NULL; + } + src = s2; + } + if ((flags & ZIP_FL_COMPRESSED) == 0 + || st.comp_method == ZIP_CM_STORE ) { + if ((s2=zip_source_crc(za, src, 1)) == NULL) { + zip_source_free(src); + /* XXX: set error (how?) */ + return NULL; + } + src = s2; + } + } + + if (zip_source_open(src) < 0) { + _zip_error_set_from_source(&za->error, src); + zip_source_free(src); + return NULL; + } + + zf = _zip_file_new(za); + + zf->src = src; + + return zf; +} + + + +static struct zip_file * +_zip_file_new(struct zip *za) +{ + struct zip_file *zf, **file; + int n; + + if ((zf=(struct zip_file *)malloc(sizeof(struct zip_file))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (za->nfile >= za->nfile_alloc-1) { + n = za->nfile_alloc + 10; + file = (struct zip_file **)realloc(za->file, + n*sizeof(struct zip_file *)); + if (file == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + free(zf); + return NULL; + } + za->nfile_alloc = n; + za->file = file; + } + + za->file[za->nfile++] = zf; + + zf->za = za; + _zip_error_init(&zf->error); + zf->eof = 0; + zf->src = NULL; + + return zf; +} diff --git a/ext/zip/lib/zip_fread.c b/ext/zip/lib/zip_fread.c new file mode 100644 index 0000000..a6c0851 --- /dev/null +++ b/ext/zip/lib/zip_fread.c @@ -0,0 +1,65 @@ +/* + zip_fread.c -- read from file + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(zip_int64_t) +zip_fread(struct zip_file *zf, void *outbuf, zip_uint64_t toread) +{ + zip_int64_t n; + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if (toread > ZIP_INT64_MAX) { + _zip_error_set(&zf->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((zf->eof) || (toread == 0)) + return 0; + + if ((n=zip_source_read(zf->src, outbuf, toread)) < 0) { + _zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return n; +} diff --git a/ext/zip/lib/zip_free.c b/ext/zip/lib/zip_free.c new file mode 100644 index 0000000..9932c14 --- /dev/null +++ b/ext/zip/lib/zip_free.c @@ -0,0 +1,83 @@ +/* + zip_free.c -- free struct zip + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +/* _zip_free: + frees the space allocated to a zipfile struct, and closes the + corresponding file. */ + +void +_zip_free(struct zip *za) +{ + int i; + + if (za == NULL) + return; + + if (za->zn) + free(za->zn); + + if (za->zp) + fclose(za->zp); + + free(za->default_password); + _zip_cdir_free(za->cdir); + free(za->ch_comment); + + if (za->entry) { + for (i=0; i<za->nentry; i++) { + _zip_entry_free(za->entry+i); + } + free(za->entry); + } + + for (i=0; i<za->nfile; i++) { + if (za->file[i]->error.zip_err == ZIP_ER_OK) { + _zip_error_set(&za->file[i]->error, ZIP_ER_ZIPCLOSED, 0); + za->file[i]->za = NULL; + } + } + + free(za->file); + + free(za); + + return; +} diff --git a/ext/zip/lib/zip_get_archive_comment.c b/ext/zip/lib/zip_get_archive_comment.c new file mode 100644 index 0000000..fe97e6e --- /dev/null +++ b/ext/zip/lib/zip_get_archive_comment.c @@ -0,0 +1,60 @@ +/* + zip_get_archive_comment.c -- get archive comment + Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(const char *) +zip_get_archive_comment(struct zip *za, int *lenp, int flags) +{ + if ((flags & ZIP_FL_UNCHANGED) + || (za->ch_comment_len == -1)) { + if (za->cdir) { + if (lenp != NULL) + *lenp = za->cdir->comment_len; + return za->cdir->comment; + } + else { + if (lenp != NULL) + *lenp = -1; + return NULL; + } + } + + if (lenp != NULL) + *lenp = za->ch_comment_len; + return za->ch_comment; +} diff --git a/ext/zip/lib/zip_get_archive_flag.c b/ext/zip/lib/zip_get_archive_flag.c new file mode 100644 index 0000000..2d46aa3 --- /dev/null +++ b/ext/zip/lib/zip_get_archive_flag.c @@ -0,0 +1,48 @@ +/* + zip_get_archive_flag.c -- get archive global flag + Copyright (C) 2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_get_archive_flag(struct zip *za, int flag, int flags) +{ + int fl; + + fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags; + + return (fl & flag) ? 1 : 0; +} diff --git a/ext/zip/lib/zip_get_compression_implementation.c b/ext/zip/lib/zip_get_compression_implementation.c new file mode 100644 index 0000000..197cd49 --- /dev/null +++ b/ext/zip/lib/zip_get_compression_implementation.c @@ -0,0 +1,46 @@ +/* + zip_get_compression_implementation.c -- get compression implementation + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(zip_compression_implementation) +zip_get_compression_implementation(zip_uint16_t cm) +{ + if (cm == ZIP_CM_DEFLATE) + return zip_source_deflate; + return NULL; +} diff --git a/ext/zip/lib/zip_get_encryption_implementation.c b/ext/zip/lib/zip_get_encryption_implementation.c new file mode 100644 index 0000000..783d538 --- /dev/null +++ b/ext/zip/lib/zip_get_encryption_implementation.c @@ -0,0 +1,46 @@ +/* + zip_get_encryption_implementation.c -- get encryption implementation + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(zip_encryption_implementation) +zip_get_encryption_implementation(zip_uint16_t em) +{ + if (em == ZIP_EM_TRAD_PKWARE) + return zip_source_pkware; + return NULL; +} diff --git a/ext/zip/lib/zip_get_file_comment.c b/ext/zip/lib/zip_get_file_comment.c new file mode 100644 index 0000000..43c1520 --- /dev/null +++ b/ext/zip/lib/zip_get_file_comment.c @@ -0,0 +1,58 @@ +/* + zip_get_file_comment.c -- get file comment + Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(const char *) +zip_get_file_comment(struct zip *za, zip_uint64_t idx, int *lenp, int flags) +{ + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) + || (za->entry[idx].ch_comment_len == -1)) { + if (lenp != NULL) + *lenp = za->cdir->entry[idx].comment_len; + return za->cdir->entry[idx].comment; + } + + if (lenp != NULL) + *lenp = za->entry[idx].ch_comment_len; + return za->entry[idx].ch_comment; +} diff --git a/ext/zip/lib/zip_get_file_extra.c b/ext/zip/lib/zip_get_file_extra.c new file mode 100644 index 0000000..a27edd8 --- /dev/null +++ b/ext/zip/lib/zip_get_file_extra.c @@ -0,0 +1,58 @@ +/* + zip_get_file_extra.c -- get file extra field + Copyright (C) 2006-2010 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(const char *) +zip_get_file_extra(struct zip *za, zip_uint64_t idx, int *lenp, int flags) +{ + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) + || (za->entry[idx].ch_extra_len == -1)) { + if (lenp != NULL) + *lenp = za->cdir->entry[idx].extrafield_len; + return za->cdir->entry[idx].extrafield; + } + + if (lenp != NULL) + *lenp = za->entry[idx].ch_extra_len; + return za->entry[idx].ch_extra; +} diff --git a/ext/zip/lib/zip_get_name.c b/ext/zip/lib/zip_get_name.c new file mode 100644 index 0000000..945e24e --- /dev/null +++ b/ext/zip/lib/zip_get_name.c @@ -0,0 +1,72 @@ +/* + zip_get_name.c -- get filename for a file in zip file + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(const char *) +zip_get_name(struct zip *za, zip_uint64_t idx, int flags) +{ + return _zip_get_name(za, idx, flags, &za->error); +} + + + +const char * +_zip_get_name(struct zip *za, zip_uint64_t idx, int flags, + struct zip_error *error) +{ + if (idx >= za->nentry) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0) { + if (za->entry[idx].state == ZIP_ST_DELETED) { + _zip_error_set(error, ZIP_ER_DELETED, 0); + return NULL; + } + if (za->entry[idx].ch_filename) + return za->entry[idx].ch_filename; + } + + if (za->cdir == NULL || idx >= za->cdir->nentry) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return za->cdir->entry[idx].filename; +} diff --git a/ext/zip/lib/zip_get_num_entries.c b/ext/zip/lib/zip_get_num_entries.c new file mode 100644 index 0000000..dd392e9 --- /dev/null +++ b/ext/zip/lib/zip_get_num_entries.c @@ -0,0 +1,52 @@ +/* + zip_get_num_entries.c -- get number of entries in archive + Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(zip_uint64_t) +zip_get_num_entries(struct zip *za, int flags) +{ + if (za == NULL) + return -1; + + if (flags & ZIP_FL_UNCHANGED) { + if (za->cdir == NULL) + return 0; + return za->cdir->nentry; + } + return za->nentry; +} diff --git a/ext/zip/lib/zip_get_num_files.c b/ext/zip/lib/zip_get_num_files.c new file mode 100644 index 0000000..a442f29 --- /dev/null +++ b/ext/zip/lib/zip_get_num_files.c @@ -0,0 +1,47 @@ +/* + zip_get_num_files.c -- get number of files in archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_get_num_files(struct zip *za) +{ + if (za == NULL) + return -1; + + return za->nentry; +} diff --git a/ext/zip/lib/zip_memdup.c b/ext/zip/lib/zip_memdup.c new file mode 100644 index 0000000..641125e --- /dev/null +++ b/ext/zip/lib/zip_memdup.c @@ -0,0 +1,55 @@ +/* + zip_memdup.c -- internal zip function, "strdup" with len + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +void * +_zip_memdup(const void *mem, size_t len, struct zip_error *error) +{ + void *ret; + + ret = malloc(len); + if (!ret) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + memcpy(ret, mem, len); + + return ret; +} diff --git a/ext/zip/lib/zip_name_locate.c b/ext/zip/lib/zip_name_locate.c new file mode 100644 index 0000000..8cdd2c4 --- /dev/null +++ b/ext/zip/lib/zip_name_locate.c @@ -0,0 +1,97 @@ +/* + zip_name_locate.c -- get index by name + Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <string.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_name_locate(struct zip *za, const char *fname, int flags) +{ + return _zip_name_locate(za, fname, flags, &za->error); +} + + + +int +_zip_name_locate(struct zip *za, const char *fname, int flags, + struct zip_error *error) +{ + int (*cmp)(const char *, const char *); + const char *fn, *p; + int i, n; + + if (za == NULL) + return -1; + + if (fname == NULL) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((flags & ZIP_FL_UNCHANGED) && za->cdir == NULL) { + _zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; + } + + cmp = (flags & ZIP_FL_NOCASE) ? strcmpi : strcmp; + + n = (flags & ZIP_FL_UNCHANGED) ? za->cdir->nentry : za->nentry; + for (i=0; i<n; i++) { + if (flags & ZIP_FL_UNCHANGED) + fn = za->cdir->entry[i].filename; + else + fn = _zip_get_name(za, i, flags, error); + + /* newly added (partially filled) entry */ + if (fn == NULL) + continue; + + if (flags & ZIP_FL_NODIR) { + p = strrchr(fn, '/'); + if (p) + fn = p+1; + } + + if (cmp(fname, fn) == 0) + return i; + } + +/* Look for an entry should not raise an error */ +/* _zip_error_set(error, ZIP_ER_NOENT, 0);*/ + return -1; +} diff --git a/ext/zip/lib/zip_new.c b/ext/zip/lib/zip_new.c new file mode 100644 index 0000000..7ce1237 --- /dev/null +++ b/ext/zip/lib/zip_new.c @@ -0,0 +1,71 @@ +/* + zip_new.c -- create and init struct zip + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +/* _zip_new: + creates a new zipfile struct, and sets the contents to zero; returns + the new struct. */ + +struct zip * +_zip_new(struct zip_error *error) +{ + struct zip *za; + + za = (struct zip *)malloc(sizeof(struct zip)); + if (!za) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + za->zn = NULL; + za->zp = NULL; + _zip_error_init(&za->error); + za->cdir = NULL; + za->ch_comment = NULL; + za->ch_comment_len = -1; + za->nentry = za->nentry_alloc = 0; + za->entry = NULL; + za->nfile = za->nfile_alloc = 0; + za->file = NULL; + za->flags = za->ch_flags = 0; + za->default_password = NULL; + + return za; +} diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c new file mode 100644 index 0000000..2f56881 --- /dev/null +++ b/ext/zip/lib/zip_open.c @@ -0,0 +1,608 @@ +/* + zip_open.c -- open zip archive by name + Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <sys/stat.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +static void set_error(int *, struct zip_error *, int); +static struct zip *_zip_allocate_new(const char *, int *); +static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); +static void _zip_check_torrentzip(struct zip *); +static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t); +static int _zip_file_exists(const char *, int, int *); +static int _zip_headercomp(struct zip_dirent *, int, + struct zip_dirent *, int); +static unsigned char *_zip_memmem(const unsigned char *, int, + const unsigned char *, int); +static struct zip_cdir *_zip_readcdir(FILE *, off_t, unsigned char *, unsigned char *, + int, int, struct zip_error *); + + + +ZIP_EXTERN(struct zip *) +zip_open(const char *fn, int flags, int *zep) +{ + FILE *fp; + + if (flags & ZIP_OVERWRITE) { + return _zip_allocate_new(fn, zep); + } + + switch (_zip_file_exists(fn, flags, zep)) { + case -1: + if (!(flags & ZIP_OVERWRITE)) { + return NULL; + } + case 0: + return _zip_allocate_new(fn, zep); + default: + break; + } + + if ((fp=fopen(fn, "rb")) == NULL) { + set_error(zep, NULL, ZIP_ER_OPEN); + return NULL; + } + + return _zip_open(fn, fp, flags, 0, zep); +} + + + +struct zip * +_zip_open(const char *fn, FILE *fp, int flags, int aflags, int *zep) +{ + struct zip *za; + struct zip_cdir *cdir; + int i; + off_t len; + + if (fseeko(fp, 0, SEEK_END) < 0) { + *zep = ZIP_ER_SEEK; + return NULL; + } + len = ftello(fp); + + /* treat empty files as empty archives */ + if (len == 0) { + if ((za=_zip_allocate_new(fn, zep)) == NULL) + fclose(fp); + else + za->zp = fp; + return za; + } + + cdir = _zip_find_central_dir(fp, flags, zep, len); + if (cdir == NULL) { + fclose(fp); + return NULL; + } + + if ((za=_zip_allocate_new(fn, zep)) == NULL) { + _zip_cdir_free(cdir); + fclose(fp); + return NULL; + } + + za->cdir = cdir; + za->zp = fp; + + if ((za->entry=(struct zip_entry *)malloc(sizeof(*(za->entry)) + * cdir->nentry)) == NULL) { + set_error(zep, NULL, ZIP_ER_MEMORY); + _zip_free(za); + return NULL; + } + for (i=0; i<cdir->nentry; i++) + _zip_entry_new(za); + + _zip_check_torrentzip(za); + za->ch_flags = za->flags; + + return za; +} + + + +static void +set_error(int *zep, struct zip_error *err, int ze) +{ + int se; + + if (err) { + _zip_error_get(err, &ze, &se); + if (zip_error_get_sys_type(ze) == ZIP_ET_SYS) + errno = se; + } + + if (zep) + *zep = ze; +} + + + +/* _zip_readcdir: + tries to find a valid end-of-central-directory at the beginning of + buf, and then the corresponding central directory entries. + Returns a struct zip_cdir which contains the central directory + entries, or NULL if unsuccessful. */ + +static struct zip_cdir * +_zip_readcdir(FILE *fp, off_t buf_offset, unsigned char *buf, unsigned char *eocd, int buflen, + int flags, struct zip_error *error) +{ + struct zip_cdir *cd; + unsigned char *cdp, **bufp; + int i, comlen, nentry; + zip_uint32_t left; + + comlen = buf + buflen - eocd - EOCDLEN; + if (comlen < 0) { + /* not enough bytes left for comment */ + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + /* check for end-of-central-dir magic */ + if (memcmp(eocd, EOCD_MAGIC, 4) != 0) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + if (memcmp(eocd+4, "\0\0\0\0", 4) != 0) { + _zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; + } + + cdp = eocd + 8; + /* number of cdir-entries on this disk */ + i = _zip_read2(&cdp); + /* number of cdir-entries */ + nentry = _zip_read2(&cdp); + + if ((cd=_zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->size = _zip_read4(&cdp); + cd->offset = _zip_read4(&cdp); + cd->comment = NULL; + cd->comment_len = _zip_read2(&cdp); + + if (((zip_uint64_t)cd->offset)+cd->size > buf_offset + (eocd-buf)) { + /* cdir spans past EOCD record */ + _zip_error_set(error, ZIP_ER_INCONS, 0); + cd->nentry = 0; + _zip_cdir_free(cd); + return NULL; + } + + if ((comlen < cd->comment_len) || (cd->nentry != i)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + cd->nentry = 0; + _zip_cdir_free(cd); + return NULL; + } + if ((flags & ZIP_CHECKCONS) && comlen != cd->comment_len) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + cd->nentry = 0; + _zip_cdir_free(cd); + return NULL; + } + + if (cd->comment_len) { + if ((cd->comment=(char *)_zip_memdup(eocd+EOCDLEN, + cd->comment_len, error)) + == NULL) { + cd->nentry = 0; + _zip_cdir_free(cd); + return NULL; + } + } + + if (cd->offset >= buf_offset) { + /* if buffer already read in, use it */ + cdp = buf + (cd->offset - buf_offset); + bufp = &cdp; + } + else { + /* go to start of cdir and read it entry by entry */ + bufp = NULL; + clearerr(fp); + fseeko(fp, cd->offset, SEEK_SET); + /* possible consistency check: cd->offset = + len-(cd->size+cd->comment_len+EOCDLEN) ? */ + if (ferror(fp) || ((unsigned long)ftello(fp) != cd->offset)) { + /* seek error or offset of cdir wrong */ + if (ferror(fp)) + _zip_error_set(error, ZIP_ER_SEEK, errno); + else + _zip_error_set(error, ZIP_ER_NOZIP, 0); + cd->nentry = 0; + _zip_cdir_free(cd); + return NULL; + } + } + + left = cd->size; + i=0; + while (i<cd->nentry && left > 0) { + if ((_zip_dirent_read(cd->entry+i, fp, bufp, &left, 0, error)) < 0) { + cd->nentry = i; + _zip_cdir_free(cd); + return NULL; + } + i++; + + if (i == cd->nentry && left > 0) { + /* Infozip extension for more than 64k entries: + nentries wraps around, size indicates correct EOCD */ + if (_zip_cdir_grow(cd, cd->nentry+ZIP_UINT16_MAX, error) < 0) { + cd->nentry = i; + _zip_cdir_free(cd); + return NULL; + } + } + } + + cd->nentry = i; + + return cd; +} + + + +/* _zip_checkcons: + Checks the consistency of the central directory by comparing central + directory entries with local headers and checking for plausible + file and header offsets. Returns -1 if not plausible, else the + difference between the lowest and the highest fileposition reached */ + +static int +_zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error) +{ + int i; + unsigned int min, max, j; + struct zip_dirent temp; + + if (cd->nentry) { + max = cd->entry[0].offset; + min = cd->entry[0].offset; + } + else + min = max = 0; + + for (i=0; i<cd->nentry; i++) { + if (cd->entry[i].offset < min) + min = cd->entry[i].offset; + if (min > cd->offset) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + j = cd->entry[i].offset + cd->entry[i].comp_size + + cd->entry[i].filename_len + LENTRYSIZE; + if (j > max) + max = j; + if (max > cd->offset) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (fseeko(fp, cd->entry[i].offset, SEEK_SET) != 0) { + _zip_error_set(error, ZIP_ER_SEEK, 0); + return -1; + } + + if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1) + return -1; + + if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_dirent_finalize(&temp); + return -1; + } + _zip_dirent_finalize(&temp); + } + + return max - min; +} + + + +/* _zip_check_torrentzip: + check wether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */ + +static void +_zip_check_torrentzip(struct zip *za) +{ + uLong crc_got, crc_should; + char buf[8+1]; + char *end; + + if (za->zp == NULL || za->cdir == NULL) + return; + + if (za->cdir->comment_len != TORRENT_SIG_LEN+8 + || strncmp(za->cdir->comment, TORRENT_SIG, TORRENT_SIG_LEN) != 0) + return; + + memcpy(buf, za->cdir->comment+TORRENT_SIG_LEN, 8); + buf[8] = '\0'; + errno = 0; + crc_should = strtoul(buf, &end, 16); + if ((crc_should == UINT_MAX && errno != 0) || (end && *end)) + return; + + if (_zip_filerange_crc(za->zp, za->cdir->offset, za->cdir->size, + &crc_got, NULL) < 0) + return; + + if (crc_got == crc_should) + za->flags |= ZIP_AFL_TORRENT; +} + + + + +/* _zip_headercomp: + compares two headers h1 and h2; if they are local headers, set + local1p or local2p respectively to 1, else 0. Return 0 if they + are identical, -1 if not. */ + +static int +_zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2, + int local2p) +{ + if ((h1->version_needed != h2->version_needed) +#if 0 + /* some zip-files have different values in local + and global headers for the bitflags */ + || (h1->bitflags != h2->bitflags) +#endif + || (h1->comp_method != h2->comp_method) + || (h1->last_mod != h2->last_mod) + || (h1->filename_len != h2->filename_len) + || !h1->filename || !h2->filename + || strcmp(h1->filename, h2->filename)) + return -1; + + /* check that CRC and sizes are zero if data descriptor is used */ + if ((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local1p + && (h1->crc != 0 + || h1->comp_size != 0 + || h1->uncomp_size != 0)) + return -1; + if ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local2p + && (h2->crc != 0 + || h2->comp_size != 0 + || h2->uncomp_size != 0)) + return -1; + + /* check that CRC and sizes are equal if no data descriptor is used */ + if (((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local1p == 0) + && ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local2p == 0)) { + if ((h1->crc != h2->crc) + || (h1->comp_size != h2->comp_size) + || (h1->uncomp_size != h2->uncomp_size)) + return -1; + } + + if ((local1p == local2p) + && ((h1->extrafield_len != h2->extrafield_len) + || (h1->extrafield_len && h2->extrafield + && memcmp(h1->extrafield, h2->extrafield, + h1->extrafield_len)))) + return -1; + + /* if either is local, nothing more to check */ + if (local1p || local2p) + return 0; + + if ((h1->version_madeby != h2->version_madeby) + || (h1->disk_number != h2->disk_number) + || (h1->int_attrib != h2->int_attrib) + || (h1->ext_attrib != h2->ext_attrib) + || (h1->offset != h2->offset) + || (h1->comment_len != h2->comment_len) + || (h1->comment_len && h2->comment + && memcmp(h1->comment, h2->comment, h1->comment_len))) + return -1; + + return 0; +} + + + +static struct zip * +_zip_allocate_new(const char *fn, int *zep) +{ + struct zip *za; + struct zip_error error; + + if ((za=_zip_new(&error)) == NULL) { + set_error(zep, &error, 0); + return NULL; + } + + if (fn == NULL) + za->zn = NULL; + else { + za->zn = strdup(fn); + if (!za->zn) { + _zip_free(za); + set_error(zep, NULL, ZIP_ER_MEMORY); + return NULL; + } + } + return za; +} + + + +static int +_zip_file_exists(const char *fn, int flags, int *zep) +{ + struct stat st; + + if (fn == NULL) { + set_error(zep, NULL, ZIP_ER_INVAL); + return -1; + } + + if (stat(fn, &st) != 0) { + if (flags & ZIP_CREATE || flags & ZIP_OVERWRITE) + return 0; + else { + set_error(zep, NULL, ZIP_ER_OPEN); + return -1; + } + } + else if ((flags & ZIP_EXCL)) { + set_error(zep, NULL, ZIP_ER_EXISTS); + return -1; + } + /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, + just like open() */ + + return 1; +} + + + +static struct zip_cdir * +_zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len) +{ + struct zip_cdir *cdir, *cdirnew; + unsigned char *buf, *match; + off_t buf_offset; + int a, best, buflen, i; + struct zip_error zerr; + + i = fseeko(fp, -(len < CDBUFSIZE ? len : CDBUFSIZE), SEEK_END); + if (i == -1 && errno != EFBIG) { + /* seek before start of file on my machine */ + set_error(zep, NULL, ZIP_ER_SEEK); + return NULL; + } + buf_offset = ftello(fp); + + /* 64k is too much for stack */ + if ((buf=(unsigned char *)malloc(CDBUFSIZE)) == NULL) { + set_error(zep, NULL, ZIP_ER_MEMORY); + return NULL; + } + + clearerr(fp); + buflen = fread(buf, 1, CDBUFSIZE, fp); + + if (ferror(fp)) { + set_error(zep, NULL, ZIP_ER_READ); + free(buf); + return NULL; + } + + best = -1; + cdir = NULL; + match = buf; + _zip_error_set(&zerr, ZIP_ER_NOZIP, 0); + + while ((match=_zip_memmem(match, buflen-(match-buf)-18, + (const unsigned char *)EOCD_MAGIC, 4))!=NULL) { + /* found match -- check, if good */ + /* to avoid finding the same match all over again */ + match++; + if ((cdirnew=_zip_readcdir(fp, buf_offset, buf, match-1, buflen, flags, + &zerr)) == NULL) + continue; + + if (cdir) { + if (best <= 0) + best = _zip_checkcons(fp, cdir, &zerr); + a = _zip_checkcons(fp, cdirnew, &zerr); + if (best < a) { + _zip_cdir_free(cdir); + cdir = cdirnew; + best = a; + } + else + _zip_cdir_free(cdirnew); + } + else { + cdir = cdirnew; + if (flags & ZIP_CHECKCONS) + best = _zip_checkcons(fp, cdir, &zerr); + else + best = 0; + } + cdirnew = NULL; + } + + free(buf); + + if (best < 0) { + set_error(zep, &zerr, 0); + _zip_cdir_free(cdir); + return NULL; + } + + return cdir; +} + + + +static unsigned char * +_zip_memmem(const unsigned char *big, int biglen, const unsigned char *little, + int littlelen) +{ + const unsigned char *p; + + if ((biglen < littlelen) || (littlelen == 0)) + return NULL; + p = big-1; + while ((p=(const unsigned char *) + memchr(p+1, little[0], (size_t)(big-(p+1)+biglen-littlelen+1))) + != NULL) { + if (memcmp(p+1, little+1, littlelen-1)==0) + return (unsigned char *)p; + } + + return NULL; +} diff --git a/ext/zip/lib/zip_rename.c b/ext/zip/lib/zip_rename.c new file mode 100644 index 0000000..6b5a035 --- /dev/null +++ b/ext/zip/lib/zip_rename.c @@ -0,0 +1,70 @@ +/* + zip_rename.c -- rename file in zip archive + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <string.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_rename(struct zip *za, zip_uint64_t idx, const char *name) +{ + const char *old_name; + int old_is_dir, new_is_dir; + + if (idx >= za->nentry || name[0] == '\0') { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((old_name=zip_get_name(za, idx, 0)) == NULL) + return -1; + + new_is_dir = (name[strlen(name)-1] == '/'); + old_is_dir = (old_name[strlen(old_name)-1] == '/'); + + if (new_is_dir != old_is_dir) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_set_name(za, idx, name); +} diff --git a/ext/zip/lib/zip_replace.c b/ext/zip/lib/zip_replace.c new file mode 100644 index 0000000..6dc3dd5 --- /dev/null +++ b/ext/zip/lib/zip_replace.c @@ -0,0 +1,85 @@ +/* + zip_replace.c -- replace file via callback function + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_replace(struct zip *za, zip_uint64_t idx, struct zip_source *source) +{ + if (idx >= za->nentry || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_replace(za, idx, NULL, source) == -1) + return -1; + + return 0; +} + + + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_replace(struct zip *za, zip_uint64_t idx, const char *name, + struct zip_source *source) +{ + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (idx == ZIP_UINT64_MAX) { + if (_zip_entry_new(za) == NULL) + return -1; + + idx = za->nentry - 1; + } + + _zip_unchange_data(za->entry+idx); + + if (name && _zip_set_name(za, idx, name) != 0) + return -1; + + za->entry[idx].state = ((za->cdir == NULL || idx >= za->cdir->nentry) + ? ZIP_ST_ADDED : ZIP_ST_REPLACED); + za->entry[idx].source = source; + + return idx; +} diff --git a/ext/zip/lib/zip_set_archive_comment.c b/ext/zip/lib/zip_set_archive_comment.c new file mode 100644 index 0000000..3cd069c --- /dev/null +++ b/ext/zip/lib/zip_set_archive_comment.c @@ -0,0 +1,70 @@ +/* + zip_set_archive_comment.c -- set archive comment + Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_set_archive_comment(struct zip *za, const char *comment, int len) +{ + char *tmpcom; + + if (len < 0 || len > MAXCOMLEN + || (len > 0 && comment == NULL)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (len > 0) { + if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL) + return -1; + } + else + tmpcom = NULL; + + free(za->ch_comment); + za->ch_comment = tmpcom; + za->ch_comment_len = len; + + return 0; +} diff --git a/ext/zip/lib/zip_set_archive_flag.c b/ext/zip/lib/zip_set_archive_flag.c new file mode 100644 index 0000000..07bcfbe --- /dev/null +++ b/ext/zip/lib/zip_set_archive_flag.c @@ -0,0 +1,69 @@ +/* + zip_get_archive_flag.c -- set archive global flag + Copyright (C) 2008-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_set_archive_flag(struct zip *za, int flag, int value) +{ + unsigned int new_flags; + + if (value) + new_flags = za->ch_flags | flag; + else + new_flags = za->ch_flags & ~flag; + + if (new_flags == za->ch_flags) + return 0; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((flag & ZIP_AFL_RDONLY) && value + && (za->ch_flags & ZIP_AFL_RDONLY) == 0) { + if (_zip_changed(za, NULL)) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } + } + + za->ch_flags = new_flags; + + return 0; +} diff --git a/ext/zip/lib/zip_set_default_password.c b/ext/zip/lib/zip_set_default_password.c new file mode 100644 index 0000000..c274d11 --- /dev/null +++ b/ext/zip/lib/zip_set_default_password.c @@ -0,0 +1,62 @@ +/* + zip_set_default_password.c -- set default password for decryption + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_set_default_password(struct zip *za, const char *passwd) +{ + if (za == NULL) + return -1; + + if (za->default_password) + free(za->default_password); + + if (passwd) { + if ((za->default_password=strdup(passwd)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + else + za->default_password = NULL; + + return 0; +} diff --git a/ext/zip/lib/zip_set_file_comment.c b/ext/zip/lib/zip_set_file_comment.c new file mode 100644 index 0000000..5e63dc2 --- /dev/null +++ b/ext/zip/lib/zip_set_file_comment.c @@ -0,0 +1,72 @@ +/* + zip_set_file_comment.c -- set comment for file in archive + Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_set_file_comment(struct zip *za, zip_uint64_t idx, + const char *comment, int len) +{ + char *tmpcom; + + if (idx >= za->nentry + || len < 0 || len > MAXCOMLEN + || (len > 0 && comment == NULL)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (len > 0) { + if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL) + return -1; + } + else + tmpcom = NULL; + + free(za->entry[idx].ch_comment); + za->entry[idx].ch_comment = tmpcom; + za->entry[idx].ch_comment_len = len; + + return 0; +} diff --git a/ext/zip/lib/zip_set_file_extra.c b/ext/zip/lib/zip_set_file_extra.c new file mode 100644 index 0000000..db829e2 --- /dev/null +++ b/ext/zip/lib/zip_set_file_extra.c @@ -0,0 +1,72 @@ +/* + zip_set_file_extra.c -- set extra field for file in archive + Copyright (C) 2006-2010 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_set_file_extra(struct zip *za, zip_uint64_t idx, + const char *extra, int len) +{ + char *tmpext; + + if (idx >= za->nentry + || len < 0 || len > MAXEXTLEN + || (len > 0 && extra == NULL)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (len > 0) { + if ((tmpext=(char *)_zip_memdup(extra, len, &za->error)) == NULL) + return -1; + } + else + tmpext = NULL; + + free(za->entry[idx].ch_extra); + za->entry[idx].ch_extra = tmpext; + za->entry[idx].ch_extra_len = len; + + return 0; +} diff --git a/ext/zip/lib/zip_set_name.c b/ext/zip/lib/zip_set_name.c new file mode 100644 index 0000000..2a90601 --- /dev/null +++ b/ext/zip/lib/zip_set_name.c @@ -0,0 +1,75 @@ +/* + zip_set_name.c -- rename helper function + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + + + +int +_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name) +{ + char *s; + zip_int64_t i; + + if (idx >= za->nentry || name == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((i=_zip_name_locate(za, name, 0, NULL)) != -1 && i != idx) { + _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + + /* no effective name change */ + if (i == idx) + return 0; + + if ((s=strdup(name)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (za->entry[idx].state == ZIP_ST_UNCHANGED) + za->entry[idx].state = ZIP_ST_RENAMED; + + free(za->entry[idx].ch_filename); + za->entry[idx].ch_filename = s; + + return 0; +} diff --git a/ext/zip/lib/zip_source_buffer.c b/ext/zip/lib/zip_source_buffer.c new file mode 100644 index 0000000..8c9154c --- /dev/null +++ b/ext/zip/lib/zip_source_buffer.c @@ -0,0 +1,163 @@ +/* + zip_source_buffer.c -- create zip data source from buffer + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct read_data { + const char *buf, *data, *end; + time_t mtime; + int freep; +}; + +static zip_int64_t read_data(void *, void *, zip_uint64_t, enum zip_source_cmd); + + + +ZIP_EXTERN(struct zip_source *) +zip_source_buffer(struct zip *za, const void *data, zip_uint64_t len, int freep) +{ + struct read_data *f; + struct zip_source *zs; + + if (za == NULL) + return NULL; + + if (data == NULL && len > 0) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((f=(struct read_data *)malloc(sizeof(*f))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + f->data = (const char *)data; + f->end = ((const char *)data)+len; + f->freep = freep; + f->mtime = time(NULL); + + if ((zs=zip_source_function(za, read_data, f)) == NULL) { + free(f); + return NULL; + } + + return zs; +} + + + +static zip_int64_t +read_data(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct read_data *z; + char *buf; + zip_uint64_t n; + + z = (struct read_data *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + z->buf = z->data; + return 0; + + case ZIP_SOURCE_READ: + /* XXX: return error if (len > ZIP_INT64_MAX) */ + + n = z->end - z->buf; + if (n > len) + n = len; + + if (n) { + memcpy(buf, z->buf, n); + z->buf += n; + } + + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + if (len < sizeof(*st)) + return -1; + + st = (struct zip_stat *)data; + + zip_stat_init(st); + st->mtime = z->mtime; + st->size = z->end - z->data; + st->comp_size = st->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid = ZIP_STAT_MTIME|ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE + |ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD; + + return sizeof(*st); + } + + case ZIP_SOURCE_ERROR: + { + int *e; + + if (len < sizeof(int)*2) + return -1; + + e = (int *)data; + e[0] = e[1] = 0; + } + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + if (z->freep) { + free((void *)z->data); + z->data = NULL; + } + free(z); + return 0; + + default: + ; + } + + return -1; +} diff --git a/ext/zip/lib/zip_source_close.c b/ext/zip/lib/zip_source_close.c new file mode 100644 index 0000000..a3bf7e5 --- /dev/null +++ b/ext/zip/lib/zip_source_close.c @@ -0,0 +1,54 @@ +/* + zip_source_close.c -- close zip_source (stop reading) + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_source_close(struct zip_source *src) +{ + if (!src->is_open) + return; + + if (src->src == NULL) + (void)src->cb.f(src->ud, NULL, 0, ZIP_SOURCE_CLOSE); + else { + (void)src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_CLOSE); + zip_source_close(src->src); + } + + src->is_open = 0; +} diff --git a/ext/zip/lib/zip_source_crc.c b/ext/zip/lib/zip_source_crc.c new file mode 100644 index 0000000..7fd78f5 --- /dev/null +++ b/ext/zip/lib/zip_source_crc.c @@ -0,0 +1,159 @@ +/* + zip_source_crc.c -- pass-through source that calculates CRC32 and size + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct crc { + int eof; + int validate; + int e[2]; + zip_uint64_t size; + zip_uint32_t crc; +}; + +static zip_int64_t crc_read(struct zip_source *, void *, void * + , zip_uint64_t, enum zip_source_cmd); + + + +ZIP_EXTERN(struct zip_source *) +zip_source_crc(struct zip *za, struct zip_source *src, int validate) +{ + struct crc *ctx; + + if (src == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx=(struct crc *)malloc(sizeof(*ctx))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->validate = validate; + + return zip_source_layered(za, src, crc_read, ctx); +} + + + +static zip_int64_t +crc_read(struct zip_source *src, void *_ctx, void *data, + zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct crc *ctx; + zip_int64_t n; + + ctx = (struct crc *)_ctx; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->eof = 0; + ctx->crc = crc32(0, NULL, 0); + ctx->size = 0; + + return 0; + + case ZIP_SOURCE_READ: + if (ctx->eof || len == 0) + return 0; + + if ((n=zip_source_read(src, data, len)) < 0) + return ZIP_SOURCE_ERR_LOWER; + + if (n == 0) { + ctx->eof = 1; + if (ctx->validate) { + struct zip_stat st; + + if (zip_source_stat(src, &st) < 0) + return ZIP_SOURCE_ERR_LOWER; + + if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { + ctx->e[0] = ZIP_ER_CRC; + ctx->e[1] = 0; + + return -1; + } + if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { + ctx->e[0] = ZIP_ER_INCONS; + ctx->e[1] = 0; + + return -1; + } + } + } + else { + ctx->size += n; + ctx->crc = crc32(ctx->crc, data, n); + } + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + st = (struct zip_stat *)data; + + if (ctx->eof) { + /* XXX: Set comp_size, comp_method, encryption_method? + After all, this only works for uncompressed data. */ + st->size = ctx->size; + st->crc = ctx->crc; + st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC; + } + } + return 0; + + case ZIP_SOURCE_ERROR: + memcpy(data, ctx->e, sizeof(ctx->e)); + return 0; + + case ZIP_SOURCE_FREE: + free(ctx); + return 0; + + default: + return -1; + } + +} diff --git a/ext/zip/lib/zip_source_deflate.c b/ext/zip/lib/zip_source_deflate.c new file mode 100644 index 0000000..5d9c5e6 --- /dev/null +++ b/ext/zip/lib/zip_source_deflate.c @@ -0,0 +1,394 @@ +/* + zip_source_deflate.c -- deflate (de)compressoin routines + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct deflate { + int e[2]; + + int eof; + int mem_level; + zip_uint64_t size; + char buffer[BUFSIZE]; + z_stream zstr; +}; + +static zip_int64_t compress_read(struct zip_source *, struct deflate *, + void *, zip_uint64_t); +static zip_int64_t decompress_read(struct zip_source *, struct deflate *, + void *, zip_uint64_t); +static zip_int64_t deflate_compress(struct zip_source *, void *, void *, + zip_uint64_t, enum zip_source_cmd); +static zip_int64_t deflate_decompress(struct zip_source *, void *, void *, + zip_uint64_t, enum zip_source_cmd); +static void deflate_free(struct deflate *); + + + +ZIP_EXTERN(struct zip_source *) +zip_source_deflate(struct zip *za, struct zip_source *src, + zip_uint16_t cm, int flags) +{ + struct deflate *ctx; + struct zip_source *s2; + + if (src == NULL || cm != ZIP_CM_DEFLATE) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->e[0] = ctx->e[1] = 0; + ctx->eof = 0; + if (flags & ZIP_CODEC_ENCODE) { + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + ctx->mem_level = TORRENT_MEM_LEVEL; + else + ctx->mem_level = MAX_MEM_LEVEL; + } + + if ((s2=zip_source_layered(za, src, + ((flags & ZIP_CODEC_ENCODE) + ? deflate_compress : deflate_decompress), + ctx)) == NULL) { + deflate_free(ctx); + return NULL; + } + + return s2; +} + + + +static zip_int64_t +compress_read(struct zip_source *src, struct deflate *ctx, + void *data, zip_uint64_t len) +{ + int end, ret; + zip_int64_t n; + + if (ctx->e[0] != 0) + return -1; + + if (len == 0) + return 0; + + ctx->zstr.next_out = (Bytef *)data; + ctx->zstr.avail_out = len; + + end = 0; + while (!end) { + ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0); + + switch (ret) { + case Z_OK: + case Z_STREAM_END: + /* all ok */ + + if (ctx->zstr.avail_out == 0 + || (ctx->eof && ctx->zstr.avail_in == 0)) + end = 1; + break; + + case Z_BUF_ERROR: + if (ctx->zstr.avail_in == 0) { + if (ctx->eof) { + end = 1; + break; + } + + if ((n=zip_source_read(src, ctx->buffer, + sizeof(ctx->buffer))) < 0) { + zip_source_error(src, ctx->e, ctx->e+1); + end = 1; + break; + } + else if (n == 0) { + ctx->eof = 1; + ctx->size = ctx->zstr.total_in; + /* XXX: check against stat of src? */ + } + else { + ctx->zstr.next_in = (Bytef *)ctx->buffer; + ctx->zstr.avail_in = n; + } + continue; + } + /* fallthrough */ + case Z_NEED_DICT: + case Z_DATA_ERROR: + case Z_STREAM_ERROR: + case Z_MEM_ERROR: + ctx->e[0] = ZIP_ER_ZLIB; + ctx->e[1] = ret; + + end = 1; + break; + } + } + + if (ctx->zstr.avail_out < len) + return len - ctx->zstr.avail_out; + + return (ctx->e[0] == 0) ? 0 : -1; +} + + + +static zip_int64_t +decompress_read(struct zip_source *src, struct deflate *ctx, + void *data, zip_uint64_t len) +{ + int end, ret; + zip_int64_t n; + + if (ctx->e[0] != 0) + return -1; + + if (len == 0) + return 0; + + ctx->zstr.next_out = (Bytef *)data; + ctx->zstr.avail_out = len; + + end = 0; + while (!end && ctx->zstr.avail_out) { + ret = inflate(&ctx->zstr, Z_SYNC_FLUSH); + + switch (ret) { + case Z_OK: + break; + + case Z_STREAM_END: + ctx->eof = 1; + end = 1; + break; + + case Z_BUF_ERROR: + if (ctx->zstr.avail_in == 0) { + if (ctx->eof) { + end = 1; + break; + } + + if ((n=zip_source_read(src, ctx->buffer, + sizeof(ctx->buffer))) < 0) { + zip_source_error(src, ctx->e, ctx->e+1); + end = 1; + break; + } + else if (n == 0) + ctx->eof = 1; + else { + ctx->zstr.next_in = (Bytef *)ctx->buffer; + ctx->zstr.avail_in = n; + } + continue; + } + /* fallthrough */ + case Z_NEED_DICT: + case Z_DATA_ERROR: + case Z_STREAM_ERROR: + case Z_MEM_ERROR: + ctx->e[0] = ZIP_ER_ZLIB; + ctx->e[1] = ret; + end = 1; + break; + } + } + + if (ctx->zstr.avail_out < len) + return len - ctx->zstr.avail_out; + + return (ctx->e[0] == 0) ? 0 : -1; +} + + + +static zip_int64_t +deflate_compress(struct zip_source *src, void *ud, void *data, + zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct deflate *ctx; + int ret; + + ctx = (struct deflate *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->zstr.zalloc = Z_NULL; + ctx->zstr.zfree = Z_NULL; + ctx->zstr.opaque = NULL; + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + /* negative value to tell zlib not to write a header */ + if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED, + -MAX_WBITS, ctx->mem_level, + Z_DEFAULT_STRATEGY)) != Z_OK) { + ctx->e[0] = ZIP_ER_ZLIB; + ctx->e[1] = ret; + return -1; + } + + return 0; + + case ZIP_SOURCE_READ: + return compress_read(src, ctx, data, len); + + case ZIP_SOURCE_CLOSE: + deflateEnd(&ctx->zstr); + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + st = (struct zip_stat *)data; + + st->comp_method = ZIP_CM_DEFLATE; + st->valid |= ZIP_STAT_COMP_METHOD; + if (ctx->eof) { + st->comp_size = ctx->size; + st->valid |= ZIP_STAT_COMP_SIZE; + } + else + st->valid &= ~ZIP_STAT_COMP_SIZE; + } + return 0; + + case ZIP_SOURCE_ERROR: + memcpy(data, ctx->e, sizeof(int)*2); + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + deflate_free(ctx); + return 0; + + default: + ctx->e[0] = ZIP_ER_INVAL; + ctx->e[1] = 0; + return -1; + } +} + + + +static zip_int64_t +deflate_decompress(struct zip_source *src, void *ud, void *data, + zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct deflate *ctx; + zip_int64_t n; + int ret; + + ctx = (struct deflate *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) + return ZIP_SOURCE_ERR_LOWER; + + ctx->zstr.zalloc = Z_NULL; + ctx->zstr.zfree = Z_NULL; + ctx->zstr.opaque = NULL; + ctx->zstr.next_in = (Bytef *)ctx->buffer; + ctx->zstr.avail_in = n; + + /* negative value to tell zlib that there is no header */ + if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) { + ctx->e[0] = ZIP_ER_ZLIB; + ctx->e[1] = ret; + + return -1; + } + return 0; + + case ZIP_SOURCE_READ: + return decompress_read(src, ctx, data, len); + + case ZIP_SOURCE_CLOSE: + inflateEnd(&ctx->zstr); + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + st = (struct zip_stat *)data; + + st->comp_method = ZIP_CM_STORE; + if (st->comp_size > 0 && st->size > 0) + st->comp_size = st->size; + } + return 0; + + case ZIP_SOURCE_ERROR: + if (len < sizeof(int)*2) + return -1; + + memcpy(data, ctx->e, sizeof(int)*2); + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + /* XXX: inflateEnd if close was not called */ + free(ctx); + return 0; + + default: + ctx->e[0] = ZIP_ER_INVAL; + ctx->e[1] = 0; + return -1; + } + +} + + + +static void +deflate_free(struct deflate *ctx) +{ + /* XXX: deflateEnd if close was not called */ + free(ctx); +} diff --git a/ext/zip/lib/zip_source_error.c b/ext/zip/lib/zip_source_error.c new file mode 100644 index 0000000..ffb4652 --- /dev/null +++ b/ext/zip/lib/zip_source_error.c @@ -0,0 +1,87 @@ +/* + zip_source_error.c -- get last error from zip_source + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_source_error(struct zip_source *src, int *ze, int *se) +{ + int e[2]; + + if (src->src == NULL) { + } + else { + switch (src->error_source) { + case ZIP_LES_NONE: + if (src->src == NULL) { + if (src->cb.f(src->ud, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { + e[0] = ZIP_ER_INTERNAL; + e[1] = 0; + } + } + else + e[0] = e[1] = 0; + break; + + case ZIP_LES_INVAL: + e[0] = ZIP_ER_INVAL; + e[1] = 0; + break; + + case ZIP_LES_LOWER: + zip_source_error(src->src, ze, se); + return; + + case ZIP_LES_UPPER: + if (src->cb.l(src->src, src->ud, e, sizeof(e), + ZIP_SOURCE_ERROR) < 0) { + e[0] = ZIP_ER_INTERNAL; + e[1] = 0; + } + break; + + default: + e[0] = ZIP_ER_INTERNAL; + e[1] = 0; + } + } + + if (ze) + *ze = e[0]; + if (se) + *se = e[1]; +} diff --git a/ext/zip/lib/zip_source_file.c b/ext/zip/lib/zip_source_file.c new file mode 100644 index 0000000..681cc2f --- /dev/null +++ b/ext/zip/lib/zip_source_file.c @@ -0,0 +1,56 @@ +/* + zip_source_file.c -- create data source from file + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <errno.h> +#include <stdio.h> + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip_source *) +zip_source_file(struct zip *za, const char *fname, zip_uint64_t start, + zip_int64_t len) +{ + if (za == NULL) + return NULL; + + if (fname == NULL || len < -1) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + return _zip_source_file_or_p(za, fname, NULL, start, len, 1, NULL); +} diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c new file mode 100644 index 0000000..4d896a4 --- /dev/null +++ b/ext/zip/lib/zip_source_filep.c @@ -0,0 +1,247 @@ +/* + zip_source_filep.c -- create data source from FILE * + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <sys/stat.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct read_file { + char *fname; /* name of file to copy from */ + FILE *f; /* file to copy from */ + int closep; /* close f */ + struct zip_stat st; /* stat information passed in */ + + zip_uint64_t off; /* start offset of */ + zip_int64_t len; /* length of data to copy */ + zip_int64_t remain; /* bytes remaining to be copied */ + int e[2]; /* error codes */ +}; + +static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, + enum zip_source_cmd cmd); + + + +ZIP_EXTERN(struct zip_source *) +zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start, + zip_int64_t len) +{ + if (za == NULL) + return NULL; + + if (file == NULL || start < 0 || len < -1) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + return _zip_source_file_or_p(za, NULL, file, start, len, 1, NULL); +} + + + +struct zip_source * +_zip_source_file_or_p(struct zip *za, const char *fname, FILE *file, + zip_uint64_t start, zip_int64_t len, int closep, + const struct zip_stat *st) +{ + struct read_file *f; + struct zip_source *zs; + + if (file == NULL && fname == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + f->fname = NULL; + if (fname) { + if ((f->fname=strdup(fname)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + free(f); + return NULL; + } + } + f->f = file; + f->off = start; + f->len = (len ? len : -1); + f->closep = f->fname ? 1 : closep; + if (st) + memcpy(&f->st, st, sizeof(f->st)); + else + zip_stat_init(&f->st); + + if ((zs=zip_source_function(za, read_file, f)) == NULL) { + free(f); + return NULL; + } + + return zs; +} + + + +static zip_int64_t +read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct read_file *z; + char *buf; + int i, n; + + z = (struct read_file *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + if (z->fname) { + if ((z->f=fopen(z->fname, "rb")) == NULL) { + z->e[0] = ZIP_ER_OPEN; + z->e[1] = errno; + return -1; + } + } + + if (z->closep) { + if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) { + z->e[0] = ZIP_ER_SEEK; + z->e[1] = errno; + return -1; + } + } + z->remain = z->len; + return 0; + + case ZIP_SOURCE_READ: + /* XXX: return INVAL if len > size_t max */ + if (z->remain != -1) + n = len > z->remain ? z->remain : len; + else + n = len; + + if (!z->closep) { + /* we might share this file with others, so let's be safe */ + if (fseeko(z->f, (off_t)(z->off + z->len-z->remain), + SEEK_SET) < 0) { + z->e[0] = ZIP_ER_SEEK; + z->e[1] = errno; + return -1; + } + } + + if ((i=fread(buf, 1, n, z->f)) < 0) { + z->e[0] = ZIP_ER_READ; + z->e[1] = errno; + return -1; + } + + if (z->remain != -1) + z->remain -= i; + + return i; + + case ZIP_SOURCE_CLOSE: + if (z->fname) { + fclose(z->f); + z->f = NULL; + } + return 0; + + case ZIP_SOURCE_STAT: + { + if (len < sizeof(z->st)) + return -1; + + if (z->st.valid != 0) + memcpy(data, &z->st, sizeof(z->st)); + else { + struct zip_stat *st; + struct stat fst; + int err; + + if (z->f) + err = fstat(fileno(z->f), &fst); + else + err = stat(z->fname, &fst); + + if (err != 0) { + z->e[0] = ZIP_ER_READ; /* best match */ + z->e[1] = errno; + return -1; + } + + st = (struct zip_stat *)data; + + zip_stat_init(st); + st->mtime = fst.st_mtime; + st->valid |= ZIP_STAT_MTIME; + if (z->len != -1) { + st->size = z->len; + st->valid |= ZIP_STAT_SIZE; + } + else if ((fst.st_mode&S_IFMT) == S_IFREG) { + st->size = fst.st_size; + st->valid |= ZIP_STAT_SIZE; + } + } + return sizeof(z->st); + } + + case ZIP_SOURCE_ERROR: + if (len < sizeof(int)*2) + return -1; + + memcpy(data, z->e, sizeof(int)*2); + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + free(z->fname); + if (z->closep && z->f) + fclose(z->f); + free(z); + return 0; + + default: + ; + } + + return -1; +} diff --git a/ext/zip/lib/zip_source_free.c b/ext/zip/lib/zip_source_free.c new file mode 100644 index 0000000..f71c71e --- /dev/null +++ b/ext/zip/lib/zip_source_free.c @@ -0,0 +1,59 @@ +/* + zip_source_free.c -- free zip data source + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_source_free(struct zip_source *src) +{ + if (src == NULL) + return; + + if (src->is_open) + zip_source_close(src); + + if (src->src == NULL) + (void)src->cb.f(src->ud, NULL, 0, ZIP_SOURCE_FREE); + else { + (void)src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_FREE); + zip_source_free(src->src); + } + + free(src); +} diff --git a/ext/zip/lib/zip_source_function.c b/ext/zip/lib/zip_source_function.c new file mode 100644 index 0000000..984b107 --- /dev/null +++ b/ext/zip/lib/zip_source_function.c @@ -0,0 +1,78 @@ +/* + zip_source_function.c -- create zip data source from callback function + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip_source *) +zip_source_function(struct zip *za, zip_source_callback zcb, void *ud) +{ + struct zip_source *zs; + + if (za == NULL) + return NULL; + + if ((zs=_zip_source_new(za)) == NULL) + return NULL; + + zs->cb.f = zcb; + zs->ud = ud; + + return zs; +} + + + +struct zip_source * +_zip_source_new(struct zip *za) +{ + struct zip_source *src; + + if ((src=(struct zip_source *)malloc(sizeof(*src))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + src->src = NULL; + src->cb.f = NULL; + src->ud = NULL; + src->error_source = ZIP_LES_NONE; + src->is_open = 0; + + return src; +} diff --git a/ext/zip/lib/zip_source_layered.c b/ext/zip/lib/zip_source_layered.c new file mode 100644 index 0000000..86ed420 --- /dev/null +++ b/ext/zip/lib/zip_source_layered.c @@ -0,0 +1,59 @@ +/* + zip_source_layered.c -- create layered source + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip_source *) +zip_source_layered(struct zip *za, struct zip_source *src, + zip_source_layered_callback cb, void *ud) +{ + struct zip_source *zs; + + if (za == NULL) + return NULL; + + if ((zs=_zip_source_new(za)) == NULL) + return NULL; + + zs->src = src; + zs->cb.l = cb; + zs->ud = ud; + + return zs; +} diff --git a/ext/zip/lib/zip_source_open.c b/ext/zip/lib/zip_source_open.c new file mode 100644 index 0000000..2c768f7 --- /dev/null +++ b/ext/zip/lib/zip_source_open.c @@ -0,0 +1,76 @@ +/* + zip_source_open.c -- open zip_source (prepare for reading) + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_source_open(struct zip_source *src) +{ + zip_int64_t ret; + + if (src->is_open) { + src->error_source = ZIP_LES_INVAL; + return -1; + } + + if (src->src == NULL) { + if (src->cb.f(src->ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) + return -1; + } + else { + if (zip_source_open(src->src) < 0) { + src->error_source = ZIP_LES_LOWER; + return -1; + } + + ret = src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_OPEN); + + if (ret < 0) { + (void)zip_source_close(src->src); + + if (ret == ZIP_SOURCE_ERR_LOWER) + src->error_source = ZIP_LES_LOWER; + else + src->error_source = ZIP_LES_UPPER; + return -1; + } + } + + src->is_open = 1; + + return 0; +} diff --git a/ext/zip/lib/zip_source_pkware.c b/ext/zip/lib/zip_source_pkware.c new file mode 100644 index 0000000..83b5cc5 --- /dev/null +++ b/ext/zip/lib/zip_source_pkware.c @@ -0,0 +1,241 @@ +/* + zip_source_pkware.c -- Traditional PKWARE de/encryption routines + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct trad_pkware { + int e[2]; + + zip_uint32_t key[3]; +}; + +#define HEADERLEN 12 +#define KEY0 305419896 +#define KEY1 591751049 +#define KEY2 878082192 + +static const uLongf *crc = NULL; + +#define CRC32(c, b) (crc[((c) ^ (b)) & 0xff] ^ ((c) >> 8)) + + + +static void decrypt(struct trad_pkware *, zip_uint8_t *, + const zip_uint8_t *, zip_uint64_t, int); +static int decrypt_header(struct zip_source *, struct trad_pkware *); +static zip_int64_t pkware_decrypt(struct zip_source *, void *, void *, + zip_uint64_t, enum zip_source_cmd); +static void pkware_free(struct trad_pkware *); + + + +ZIP_EXTERN(struct zip_source *) +zip_source_pkware(struct zip *za, struct zip_source *src, + zip_uint16_t em, int flags, const char *password) +{ + struct trad_pkware *ctx; + struct zip_source *s2; + + if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if (flags & ZIP_CODEC_ENCODE) { + _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + if (crc == NULL) + crc = get_crc_table(); + + if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->e[0] = ctx->e[1] = 0; + + ctx->key[0] = KEY0; + ctx->key[1] = KEY1; + ctx->key[2] = KEY2; + decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1); + + if ((s2=zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) { + pkware_free(ctx); + return NULL; + } + + return s2; +} + + + +static void +decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, + zip_uint64_t len, int update_only) +{ + zip_uint16_t tmp; + zip_uint64_t i; + Bytef b; + + for (i=0; i<len; i++) { + b = in[i]; + + if (!update_only) { + /* decrypt next byte */ + tmp = ctx->key[2] | 2; + tmp = (tmp * (tmp ^ 1)) >> 8; + b ^= tmp; + } + + /* store cleartext */ + if (out) + out[i] = b; + + /* update keys */ + ctx->key[0] = CRC32(ctx->key[0], b); + ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1; + b = ctx->key[1] >> 24; + ctx->key[2] = CRC32(ctx->key[2], b); + } +} + + + +static int +decrypt_header(struct zip_source *src, struct trad_pkware *ctx) +{ + zip_uint8_t header[HEADERLEN]; + struct zip_stat st; + zip_int64_t n; + unsigned short dostime, dosdate; + + if ((n=zip_source_read(src, header, HEADERLEN)) < 0) { + zip_source_error(src, ctx->e, ctx->e+1); + return -1; + } + + if (n != HEADERLEN) { + ctx->e[0] = ZIP_ER_EOF; + ctx->e[1] = 0; + return -1; + } + + decrypt(ctx, header, header, HEADERLEN, 0); + + if (zip_source_stat(src, &st) < 0) { + /* stat failed, skip password validation */ + return 0; + } + + _zip_u2d_time(st.mtime, &dostime, &dosdate); + + if (header[HEADERLEN-1] != st.crc>>24 + && header[HEADERLEN-1] != dostime>>8) { + ctx->e[0] = ZIP_ER_WRONGPASSWD; + ctx->e[1] = 0; + return -1; + } + + return 0; +} + + + +static zip_int64_t +pkware_decrypt(struct zip_source *src, void *ud, void *data, + zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct trad_pkware *ctx; + zip_int64_t n; + + ctx = (struct trad_pkware *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + if (decrypt_header(src, ctx) < 0) + return -1; + return 0; + + case ZIP_SOURCE_READ: + if ((n=zip_source_read(src, data, len)) < 0) + return ZIP_SOURCE_ERR_LOWER; + + decrypt(ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, + 0); + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + st = (struct zip_stat *)data; + + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + /* XXX: deduce HEADERLEN from size for uncompressed */ + if (st->valid & ZIP_STAT_COMP_SIZE) + st->comp_size -= HEADERLEN; + } + return 0; + + case ZIP_SOURCE_ERROR: + memcpy(data, ctx->e, sizeof(int)*2); + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + pkware_free(ctx); + return 0; + + default: + ctx->e[0] = ZIP_ER_INVAL; + ctx->e[1] = 0; + return -1; + } +} + + + +static void +pkware_free(struct trad_pkware *ctx) +{ + free(ctx); +} diff --git a/ext/zip/lib/zip_source_pop.c b/ext/zip/lib/zip_source_pop.c new file mode 100644 index 0000000..4060938 --- /dev/null +++ b/ext/zip/lib/zip_source_pop.c @@ -0,0 +1,63 @@ +/* + zip_source_pop.c -- pop top layer from zip data source + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(struct zip_source *) +zip_source_pop(struct zip_source *src) +{ + struct zip_source *lower; + + if (src == NULL) + return NULL; + + lower = src->src; + + if (lower == NULL) + zip_source_free(src); + else { + if (src->is_open) + (void)src->cb.l(src, src->ud, NULL, 0, ZIP_SOURCE_CLOSE); + (void)src->cb.l(src, src->ud, NULL, 0, ZIP_SOURCE_FREE); + + free(src); + } + + return lower; +} diff --git a/ext/zip/lib/zip_source_read.c b/ext/zip/lib/zip_source_read.c new file mode 100644 index 0000000..7246f9c --- /dev/null +++ b/ext/zip/lib/zip_source_read.c @@ -0,0 +1,64 @@ +/* + zip_source_read.c -- read data from zip_source + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(zip_int64_t) +zip_source_read(struct zip_source *src, void *data, zip_uint64_t len) +{ + zip_int64_t ret; + + if (!src->is_open || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) { + src->error_source = ZIP_LES_INVAL; + return -1; + } + + if (src->src == NULL) + return src->cb.f(src->ud, data, len, ZIP_SOURCE_READ); + + ret = src->cb.l(src->src, src->ud, data, len, ZIP_SOURCE_READ); + + if (ret < 0) { + if (ret == ZIP_SOURCE_ERR_LOWER) + src->error_source = ZIP_LES_LOWER; + else + src->error_source = ZIP_LES_UPPER; + return -1; + } + + return ret; +} diff --git a/ext/zip/lib/zip_source_stat.c b/ext/zip/lib/zip_source_stat.c new file mode 100644 index 0000000..662779e --- /dev/null +++ b/ext/zip/lib/zip_source_stat.c @@ -0,0 +1,72 @@ +/* + zip_source_stat.c -- get meta information from zip_source + Copyright (C) 2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_source_stat(struct zip_source *src, struct zip_stat *st) +{ + zip_int64_t ret; + + if (st == NULL) { + src->error_source = ZIP_LES_INVAL; + return -1; + } + + if (src->src == NULL) { + if (src->cb.f(src->ud, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) + return -1; + return 0; + } + + if (zip_source_stat(src->src, st) < 0) { + src->error_source = ZIP_LES_LOWER; + return -1; + } + + ret = src->cb.l(src->src, src->ud, st, sizeof(*st), ZIP_SOURCE_STAT); + + if (ret < 0) { + if (ret == ZIP_SOURCE_ERR_LOWER) + src->error_source = ZIP_LES_LOWER; + else + src->error_source = ZIP_LES_UPPER; + return -1; + } + + return 0; +} diff --git a/ext/zip/lib/zip_source_zip.c b/ext/zip/lib/zip_source_zip.c new file mode 100644 index 0000000..228803c --- /dev/null +++ b/ext/zip/lib/zip_source_zip.c @@ -0,0 +1,190 @@ +/* + zip_source_zip.c -- create data source from zip file + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct read_zip { + struct zip_file *zf; + struct zip_stat st; + zip_uint64_t off; + zip_int64_t len; +}; + +static zip_int64_t read_zip(void *st, void *data, zip_uint64_t len, + enum zip_source_cmd cmd); + + + +ZIP_EXTERN(struct zip_source *) +zip_source_zip(struct zip *za, struct zip *srcza, zip_uint64_t srcidx, + int flags, zip_uint64_t start, zip_int64_t len) +{ + struct zip_error error; + struct zip_source *zs; + struct read_zip *p; + + /* XXX: ZIP_FL_RECOMPRESS */ + + if (za == NULL) + return NULL; + + if (srcza == NULL || len < -1 || srcidx < 0 || srcidx >= srcza->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx)) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return NULL; + } + + if (len == 0) + len = -1; + + if (start == 0 && len == -1 && (flags & ZIP_FL_RECOMPRESS) == 0) + flags |= ZIP_FL_COMPRESSED; + else + flags &= ~ZIP_FL_COMPRESSED; + + if ((p=(struct read_zip *)malloc(sizeof(*p))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + _zip_error_copy(&error, &srcza->error); + + if (zip_stat_index(srcza, srcidx, flags, &p->st) < 0 + || (p->zf=zip_fopen_index(srcza, srcidx, flags)) == NULL) { + free(p); + _zip_error_copy(&za->error, &srcza->error); + _zip_error_copy(&srcza->error, &error); + + return NULL; + } + p->off = start; + p->len = len; + + if ((flags & ZIP_FL_COMPRESSED) == 0) { + p->st.size = p->st.comp_size = len; + p->st.comp_method = ZIP_CM_STORE; + p->st.crc = 0; + } + + if ((zs=zip_source_function(za, read_zip, p)) == NULL) { + free(p); + return NULL; + } + + return zs; +} + + + +static zip_int64_t +read_zip(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd) +{ + struct read_zip *z; + char b[8192], *buf; + int i; + zip_uint64_t n; + + z = (struct read_zip *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + for (n=0; n<z->off; n+= i) { + i = (z->off-n > sizeof(b) ? sizeof(b) : z->off-n); + if ((i=zip_fread(z->zf, b, i)) < 0) { + zip_fclose(z->zf); + z->zf = NULL; + return -1; + } + } + return 0; + + case ZIP_SOURCE_READ: + if (z->len != -1) + n = len > z->len ? z->len : len; + else + n = len; + + + if ((i=zip_fread(z->zf, buf, n)) < 0) + return -1; + + if (z->len != -1) + z->len -= i; + + return i; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + if (len < sizeof(z->st)) + return -1; + len = sizeof(z->st); + + memcpy(data, &z->st, len); + return len; + + case ZIP_SOURCE_ERROR: + { + int *e; + + if (len < sizeof(int)*2) + return -1; + + e = (int *)data; + zip_file_error_get(z->zf, e, e+1); + } + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + zip_fclose(z->zf); + free(z); + return 0; + + default: + ; + } + + return -1; +} diff --git a/ext/zip/lib/zip_stat.c b/ext/zip/lib/zip_stat.c new file mode 100644 index 0000000..c8a25e1 --- /dev/null +++ b/ext/zip/lib/zip_stat.c @@ -0,0 +1,49 @@ +/* + zip_stat.c -- get information about file by name + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_stat(struct zip *za, const char *fname, int flags, struct zip_stat *st) +{ + int idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return -1; + + return zip_stat_index(za, idx, flags, st); +} diff --git a/ext/zip/lib/zip_stat_index.c b/ext/zip/lib/zip_stat_index.c new file mode 100644 index 0000000..8faa8cc --- /dev/null +++ b/ext/zip/lib/zip_stat_index.c @@ -0,0 +1,94 @@ +/* + zip_stat_index.c -- get information about file by index + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_stat_index(struct zip *za, zip_uint64_t index, int flags, + struct zip_stat *st) +{ + const char *name; + + if (index >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((name=zip_get_name(za, index, flags)) == NULL) + return -1; + + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(za->entry+index)) { + if (zip_source_stat(za->entry[index].source, st) < 0) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } + } + else { + if (za->cdir == NULL || index >= za->cdir->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + zip_stat_init(st); + + st->crc = za->cdir->entry[index].crc; + st->size = za->cdir->entry[index].uncomp_size; + st->mtime = za->cdir->entry[index].last_mod; + st->comp_size = za->cdir->entry[index].comp_size; + st->comp_method = za->cdir->entry[index].comp_method; + if (za->cdir->entry[index].bitflags & ZIP_GPBF_ENCRYPTED) { + if (za->cdir->entry[index].bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { + /* XXX */ + st->encryption_method = ZIP_EM_UNKNOWN; + } + else + st->encryption_method = ZIP_EM_TRAD_PKWARE; + } + else + st->encryption_method = ZIP_EM_NONE; + st->valid = ZIP_STAT_CRC|ZIP_STAT_SIZE|ZIP_STAT_MTIME + |ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD; + } + + st->index = index; + st->name = name; + st->valid |= ZIP_STAT_INDEX|ZIP_STAT_NAME; + + return 0; +} diff --git a/ext/zip/lib/zip_stat_init.c b/ext/zip/lib/zip_stat_init.c new file mode 100644 index 0000000..74e1ffd --- /dev/null +++ b/ext/zip/lib/zip_stat_init.c @@ -0,0 +1,52 @@ +/* + zip_stat_init.c -- initialize struct zip_stat. + Copyright (C) 2006-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN(void) +zip_stat_init(struct zip_stat *st) +{ + st->valid = 0; + st->name = NULL; + st->index = ZIP_UINT64_MAX; + st->crc = 0; + st->mtime = (time_t)-1; + st->size = 0; + st->comp_size = 0; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; +} diff --git a/ext/zip/lib/zip_strerror.c b/ext/zip/lib/zip_strerror.c new file mode 100644 index 0000000..ad23baf --- /dev/null +++ b/ext/zip/lib/zip_strerror.c @@ -0,0 +1,43 @@ +/* + zip_sterror.c -- get string representation of zip error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + +ZIP_EXTERN(const char *) +zip_strerror(struct zip *za) +{ + return _zip_error_strerror(&za->error); +} diff --git a/ext/zip/lib/zip_unchange.c b/ext/zip/lib/zip_unchange.c new file mode 100644 index 0000000..550e8b9 --- /dev/null +++ b/ext/zip/lib/zip_unchange.c @@ -0,0 +1,85 @@ +/* + zip_unchange.c -- undo changes to file in zip archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_unchange(struct zip *za, zip_uint64_t idx) +{ + return _zip_unchange(za, idx, 0); +} + + + +int +_zip_unchange(struct zip *za, zip_uint64_t idx, int allow_duplicates) +{ + int i; + + if (idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (za->entry[idx].ch_filename) { + if (!allow_duplicates) { + i = _zip_name_locate(za, + _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), + 0, NULL); + if (i != -1 && i != idx) { + _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + } + + free(za->entry[idx].ch_filename); + za->entry[idx].ch_filename = NULL; + } + + free(za->entry[idx].ch_extra); + za->entry[idx].ch_extra = NULL; + za->entry[idx].ch_extra_len = -1; + free(za->entry[idx].ch_comment); + za->entry[idx].ch_comment = NULL; + za->entry[idx].ch_comment_len = -1; + + _zip_unchange_data(za->entry+idx); + + return 0; +} diff --git a/ext/zip/lib/zip_unchange_all.c b/ext/zip/lib/zip_unchange_all.c new file mode 100644 index 0000000..01282f8 --- /dev/null +++ b/ext/zip/lib/zip_unchange_all.c @@ -0,0 +1,54 @@ +/* + zip_unchange.c -- undo changes to all files in zip archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_unchange_all(struct zip *za) +{ + int ret, i; + + ret = 0; + for (i=0; i<za->nentry; i++) + ret |= _zip_unchange(za, i, 1); + + ret |= zip_unchange_archive(za); + + return ret; +} diff --git a/ext/zip/lib/zip_unchange_archive.c b/ext/zip/lib/zip_unchange_archive.c new file mode 100644 index 0000000..ca2b678 --- /dev/null +++ b/ext/zip/lib/zip_unchange_archive.c @@ -0,0 +1,52 @@ +/* + zip_unchange_archive.c -- undo global changes to ZIP archive + Copyright (C) 2006-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + + + +ZIP_EXTERN(int) +zip_unchange_archive(struct zip *za) +{ + free(za->ch_comment); + za->ch_comment = NULL; + za->ch_comment_len = -1; + + za->ch_flags = za->flags; + + return 0; +} diff --git a/ext/zip/lib/zip_unchange_data.c b/ext/zip/lib/zip_unchange_data.c new file mode 100644 index 0000000..7dd93b7 --- /dev/null +++ b/ext/zip/lib/zip_unchange_data.c @@ -0,0 +1,52 @@ +/* + $NiH: zip_unchange_data.c,v 1.14 2004/11/30 23:02:47 wiz Exp $ + + zip_unchange_data.c -- undo helper function + Copyright (C) 1999, 2004 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdlib.h> + +#include "zipint.h" + +void +_zip_unchange_data(struct zip_entry *ze) +{ + if (ze->source) { + zip_source_free(ze->source); + ze->source = NULL; + } + + ze->state = ze->ch_filename ? ZIP_ST_RENAMED : ZIP_ST_UNCHANGED; +} + diff --git a/ext/zip/lib/zip_win32.h b/ext/zip/lib/zip_win32.h new file mode 100644 index 0000000..ff28d28 --- /dev/null +++ b/ext/zip/lib/zip_win32.h @@ -0,0 +1,31 @@ +#define _POSIX_ +#include <windows.h> +#include <io.h> +#include <fcntl.h> +#include <string.h> +#include <zconf.h> + +#ifndef strcasecmp +# define strcmpi _strcmpi +#endif + +#ifndef ssize_t +# define ssize_t SSIZE_T +#endif + +#ifndef mode_t +# define mode_t int +#endif + +#ifndef snprintf +# define snprintf _snprintf +#endif + +#ifndef mkstemp +# define mkstemp(t) _creat(_mktemp(t), _S_IREAD|_S_IWRITE) +#endif +/* +#ifndef fseeko +# define fseeko fseek +#endif +*/ diff --git a/ext/zip/lib/zipconf.h b/ext/zip/lib/zipconf.h new file mode 100644 index 0000000..2b4340c --- /dev/null +++ b/ext/zip/lib/zipconf.h @@ -0,0 +1,51 @@ +#ifndef _HAD_ZIPCONF_H +#define _HAD_ZIPCONF_H + +/* + zipconf.h -- platform specific include file + + This file was generated automatically by ./make_zipconf.sh + based on ../config.h. + */ + +#define LIBZIP_VERSION "0.10.1" +#define LIBZIP_VERSION_MAJOR 0 +#define LIBZIP_VERSION_MINOR 10 +#define LIBZIP_VERSION_MICRO 0 + +#ifdef PHP_WIN32 +#include <win32/php_stdint.h> +#else +#include <inttypes.h> +#endif + +typedef int8_t zip_int8_t; +#define ZIP_INT8_MIN INT8_MIN +#define ZIP_INT8_MAX INT8_MAX + +typedef uint8_t zip_uint8_t; +#define ZIP_UINT8_MAX UINT8_MAX + +typedef int16_t zip_int16_t; +#define ZIP_INT16_MIN INT16_MIN +#define ZIP_INT16_MAX INT16_MAX + +typedef uint16_t zip_uint16_t; +#define ZIP_UINT16_MAX UINT16_MAX + +typedef int32_t zip_int32_t; +#define ZIP_INT32_MIN INT32_MIN +#define ZIP_INT32_MAX INT32_MAX + +typedef uint32_t zip_uint32_t; +#define ZIP_UINT32_MAX UINT32_MAX + +typedef int64_t zip_int64_t; +#define ZIP_INT64_MIN INT64_MIN +#define ZIP_INT64_MAX INT64_MAX + +typedef uint64_t zip_uint64_t; +#define ZIP_UINT64_MAX UINT64_MAX + + +#endif /* zipconf.h */ diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h new file mode 100644 index 0000000..ea21ddd --- /dev/null +++ b/ext/zip/lib/zipint.h @@ -0,0 +1,344 @@ +#ifndef _HAD_ZIPINT_H +#define _HAD_ZIPINT_H + +/* + zipint.h -- internal declarations. + Copyright (C) 1999-2011 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <zlib.h> + +#include "zip.h" + +#ifndef HAVE_FSEEKO +#define fseeko(s, o, w) (fseek((s), (long int)(o), (w))) +#endif + +#ifndef HAVE_FTELLO +#define ftello(s) ((long)ftell((s))) +#endif + +#ifndef PHP_WIN32 +#ifndef HAVE_MKSTEMP +int _zip_mkstemp(char *); +#define mkstemp _zip_mkstemp +#endif +#endif + +#ifdef PHP_WIN32 +#include <windows.h> +#include <wchar.h> +#define _zip_rename(s, t) \ + (!MoveFileExA((s), (t), \ + MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) + +/* for dup(), close(), etc. */ +#include <io.h> + +#if !defined(HAVE_OPEN) +#if defined(HAVE__OPEN) +#define open(a, b, c) _open((a), (b)) +#endif +#endif + +#else +#define _zip_rename rename +#endif + +#ifndef strcasecmp +# define strcmpi strcasecmp +#endif + + + + +#define CENTRAL_MAGIC "PK\1\2" +#define LOCAL_MAGIC "PK\3\4" +#define EOCD_MAGIC "PK\5\6" +#define DATADES_MAGIC "PK\7\8" +#define TORRENT_SIG "TORRENTZIPPED-" +#define TORRENT_SIG_LEN 14 +#define TORRENT_CRC_LEN 8 +#define TORRENT_MEM_LEVEL 8 +#define CDENTRYSIZE 46u +#define LENTRYSIZE 30 +#undef MAXCOMLEN /* defined as 19 on BSD for max command name */ +#define MAXCOMLEN 65536 +#define MAXEXTLEN 65536 +#define EOCDLEN 22 +#define CDBUFSIZE (MAXCOMLEN+EOCDLEN) +#define BUFSIZE 8192 + + + +/* This section contains API that won't materialize like this. It's + placed in the internal section, pending cleanup. */ + +typedef struct zip_source *(*zip_compression_implementation)(struct zip *, + struct zip_source *, + zip_uint16_t, int); +typedef struct zip_source *(*zip_encryption_implementation)(struct zip *, + struct zip_source *, + zip_uint16_t, int, + const char *); + +ZIP_EXTERN(zip_compression_implementation) zip_get_compression_implementation( + zip_uint16_t); +ZIP_EXTERN(zip_encryption_implementation) zip_get_encryption_implementation( + zip_uint16_t); + + + + +/* This section contains API that is of limited use until support for + user-supplied compression/encryption implementation is finished. + Thus we will keep it private for now. */ + +typedef zip_int64_t (*zip_source_layered_callback)(struct zip_source *, void *, + void *, zip_uint64_t, + enum zip_source_cmd); + +ZIP_EXTERN(void) zip_source_close(struct zip_source *); +ZIP_EXTERN(struct zip_source *)zip_source_crc(struct zip *, struct zip_source *, + int); +ZIP_EXTERN(struct zip_source *)zip_source_deflate(struct zip *, + struct zip_source *, + zip_uint16_t, int); +ZIP_EXTERN(void) zip_source_error(struct zip_source *, int *, int *); +ZIP_EXTERN(struct zip_source *)zip_source_layered(struct zip *, + struct zip_source *, + zip_source_layered_callback, + void *); +ZIP_EXTERN(int) zip_source_open(struct zip_source *); +ZIP_EXTERN(struct zip_source *)zip_source_pkware(struct zip *, + struct zip_source *, + zip_uint16_t, int, + const char *); +ZIP_EXTERN(zip_int64_t) zip_source_read(struct zip_source *, void *, + zip_uint64_t); +ZIP_EXTERN(int) zip_source_stat(struct zip_source *, struct zip_stat *); + + +/* This function will probably remain private. It is not needed to + implement compression/encryption routines. (We should probably + rename it to _zip_source_pop.) */ + +ZIP_EXTERN(struct zip_source *)zip_source_pop(struct zip_source *); + + + +/* state of change of a file in zip archive */ + +enum zip_state { ZIP_ST_UNCHANGED, ZIP_ST_DELETED, ZIP_ST_REPLACED, + ZIP_ST_ADDED, ZIP_ST_RENAMED }; + +/* error source for layered sources */ + +enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL }; + +/* directory entry: general purpose bit flags */ + +#define ZIP_GPBF_ENCRYPTED 0x0001 /* is encrypted */ +#define ZIP_GPBF_DATA_DESCRIPTOR 0x0008 /* crc/size after file data */ +#define ZIP_GPBF_STRONG_ENCRYPTION 0x0040 /* uses strong encryption */ + +/* error information */ + +struct zip_error { + int zip_err; /* libzip error code (ZIP_ER_*) */ + int sys_err; /* copy of errno (E*) or zlib error code */ + char *str; /* string representation or NULL */ +}; + +/* zip archive, part of API */ + +struct zip { + char *zn; /* file name */ + FILE *zp; /* file */ + struct zip_error error; /* error information */ + + unsigned int flags; /* archive global flags */ + unsigned int ch_flags; /* changed archive global flags */ + + char *default_password; /* password used when no other supplied */ + + struct zip_cdir *cdir; /* central directory */ + char *ch_comment; /* changed archive comment */ + int ch_comment_len; /* length of changed zip archive + * comment, -1 if unchanged */ + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ + struct zip_entry *entry; /* entries */ + int nfile; /* number of opened files within archive */ + int nfile_alloc; /* number of files allocated */ + struct zip_file **file; /* opened files within archive */ +}; + +/* file in zip archive, part of API */ + +struct zip_file { + struct zip *za; /* zip archive containing this file */ + struct zip_error error; /* error information */ + int eof; + struct zip_source *src; /* data source */ +}; + +/* zip archive directory entry (central or local) */ + +struct zip_dirent { + unsigned short version_madeby; /* (c) version of creator */ + unsigned short version_needed; /* (cl) version needed to extract */ + unsigned short bitflags; /* (cl) general purpose bit flag */ + unsigned short comp_method; /* (cl) compression method used */ + time_t last_mod; /* (cl) time of last modification */ + unsigned int crc; /* (cl) CRC-32 of uncompressed data */ + unsigned int comp_size; /* (cl) size of commpressed data */ + unsigned int uncomp_size; /* (cl) size of uncommpressed data */ + char *filename; /* (cl) file name (NUL-terminated) */ + unsigned short filename_len; /* (cl) length of filename (w/o NUL) */ + char *extrafield; /* (cl) extra field */ + unsigned short extrafield_len; /* (cl) length of extra field */ + char *comment; /* (c) file comment */ + unsigned short comment_len; /* (c) length of file comment */ + unsigned short disk_number; /* (c) disk number start */ + unsigned short int_attrib; /* (c) internal file attributes */ + unsigned int ext_attrib; /* (c) external file attributes */ + unsigned int offset; /* (c) offset of local header */ +}; + +/* zip archive central directory */ + +struct zip_cdir { + struct zip_dirent *entry; /* directory entries */ + int nentry; /* number of entries */ + + unsigned int size; /* size of central direcotry */ + unsigned int offset; /* offset of central directory in file */ + char *comment; /* zip archive comment */ + unsigned short comment_len; /* length of zip archive comment */ +}; + + + +struct zip_source { + struct zip_source *src; + union { + zip_source_callback f; + zip_source_layered_callback l; + } cb; + void *ud; + enum zip_les error_source; + int is_open; +}; + +/* entry in zip archive directory */ + +struct zip_entry { + enum zip_state state; + struct zip_source *source; + char *ch_filename; + char *ch_extra; + int ch_extra_len; + char *ch_comment; + int ch_comment_len; +}; + + + +extern const char * const _zip_err_str[]; +extern const int _zip_nerr_str; +extern const int _zip_err_type[]; + + + +#define ZIP_ENTRY_DATA_CHANGED(x) \ + ((x)->state == ZIP_ST_REPLACED \ + || (x)->state == ZIP_ST_ADDED) + +#define ZIP_IS_RDONLY(za) ((za)->ch_flags & ZIP_AFL_RDONLY) + + + +int _zip_cdir_compute_crc(struct zip *, uLong *); +void _zip_cdir_free(struct zip_cdir *); +int _zip_cdir_grow(struct zip_cdir *, int, struct zip_error *); +struct zip_cdir *_zip_cdir_new(int, struct zip_error *); +int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *); + +void _zip_dirent_finalize(struct zip_dirent *); +void _zip_dirent_init(struct zip_dirent *); +int _zip_dirent_read(struct zip_dirent *, FILE *, unsigned char **, + zip_uint32_t *, int, struct zip_error *); +void _zip_dirent_torrent_normalize(struct zip_dirent *); +int _zip_dirent_write(struct zip_dirent *, FILE *, int, struct zip_error *); + +void _zip_entry_free(struct zip_entry *); +void _zip_entry_init(struct zip *, int); +struct zip_entry *_zip_entry_new(struct zip *); + +void _zip_error_clear(struct zip_error *); +void _zip_error_copy(struct zip_error *, struct zip_error *); +void _zip_error_fini(struct zip_error *); +void _zip_error_get(struct zip_error *, int *, int *); +void _zip_error_init(struct zip_error *); +void _zip_error_set(struct zip_error *, int, int); +void _zip_error_set_from_source(struct zip_error *, struct zip_source *); +const char *_zip_error_strerror(struct zip_error *); + +int _zip_file_fillbuf(void *, size_t, struct zip_file *); +unsigned int _zip_file_get_offset(struct zip *, int); + +int _zip_filerange_crc(FILE *, off_t, off_t, uLong *, struct zip_error *); + +struct zip *_zip_open(const char *, FILE *, int, int, int *); + +struct zip_source *_zip_source_file_or_p(struct zip *, const char *, FILE *, + zip_uint64_t, zip_int64_t, int, + const struct zip_stat *); +struct zip_source *_zip_source_new(struct zip *); + +int _zip_changed(struct zip *, int *); +void _zip_free(struct zip *); +const char *_zip_get_name(struct zip *, zip_uint64_t, int, struct zip_error *); +int _zip_local_header_read(struct zip *, int); +void *_zip_memdup(const void *, size_t, struct zip_error *); +int _zip_name_locate(struct zip *, const char *, int, struct zip_error *); +struct zip *_zip_new(struct zip_error *); +unsigned short _zip_read2(unsigned char **); +unsigned int _zip_read4(unsigned char **); +zip_int64_t _zip_replace(struct zip *, zip_uint64_t, const char *, + struct zip_source *); +int _zip_set_name(struct zip *, zip_uint64_t, const char *); +void _zip_u2d_time(time_t, unsigned short *, unsigned short *); +int _zip_unchange(struct zip *, zip_uint64_t, int); +void _zip_unchange_data(struct zip_entry *); + +#endif /* zipint.h */ diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c new file mode 100644 index 0000000..5683b32 --- /dev/null +++ b/ext/zip/php_zip.c @@ -0,0 +1,2884 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Piere-Alain Joye <pierre@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: 727cc853ca1ae15d995c3520c5719784ddc1e292 $ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "ext/standard/file.h" +#include "ext/standard/php_string.h" +#include "ext/pcre/php_pcre.h" +#include "php_zip.h" +#include "lib/zip.h" +#include "lib/zipint.h" + +/* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */ +static PHP_NAMED_FUNCTION(zif_zip_open); +static PHP_NAMED_FUNCTION(zif_zip_read); +static PHP_NAMED_FUNCTION(zif_zip_close); +static PHP_NAMED_FUNCTION(zif_zip_entry_read); +static PHP_NAMED_FUNCTION(zif_zip_entry_filesize); +static PHP_NAMED_FUNCTION(zif_zip_entry_name); +static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize); +static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod); +static PHP_NAMED_FUNCTION(zif_zip_entry_open); +static PHP_NAMED_FUNCTION(zif_zip_entry_close); + +#ifdef HAVE_GLOB +#ifndef PHP_WIN32 +#include <glob.h> +#else +#include "win32/glob.h" +#endif +#endif + +/* {{{ Resource le */ +static int le_zip_dir; +#define le_zip_dir_name "Zip Directory" +static int le_zip_entry; +#define le_zip_entry_name "Zip Entry" +/* }}} */ + +/* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */ +#define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \ + if (zip_stat_index(za, index, flags, &sb) != 0) { \ + RETURN_FALSE; \ + } +/* }}} */ + +/* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */ +#define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \ + if (path_len < 1) { \ + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); \ + RETURN_FALSE; \ + } \ + if (zip_stat(za, path, flags, &sb) != 0) { \ + RETURN_FALSE; \ + } +/* }}} */ + +/* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */ +#define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \ + if (comment_len == 0) { \ + /* Passing NULL remove the existing comment */ \ + if (zip_set_file_comment(intern, index, NULL, 0) < 0) { \ + RETURN_FALSE; \ + } \ + } else if (zip_set_file_comment(intern, index, comment, comment_len) < 0) { \ + RETURN_FALSE; \ + } \ + RETURN_TRUE; +/* }}} */ + +#if (PHP_MAJOR_VERSION < 6) +# define add_ascii_assoc_string add_assoc_string +# define add_ascii_assoc_long add_assoc_long +#endif + +/* Flatten a path by making a relative path (to .)*/ +static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */ +{ + char *path_begin = path; + size_t i; + + if (IS_SLASH(path[0])) { + return path + 1; + } + + if (path_len < 1 || path == NULL) { + return NULL; + } + + i = path_len; + + while (1) { + while (i > 0 && !IS_SLASH(path[i])) { + i--; + } + + if (!i) { + return path; + } + + if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) { + /* i is the position of . or :, add 1 for / */ + path_begin = path + i + 1; + break; + } + i--; + } + + return path_begin; +} +/* }}} */ + +#ifdef PHP_ZIP_USE_OO +/* {{{ php_zip_extract_file */ +static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC) +{ + php_stream_statbuf ssb; + struct zip_file *zf; + struct zip_stat sb; + char b[8192]; + int n, len, ret; + php_stream *stream; + char *fullpath; + char *file_dirname_fullpath; + char file_dirname[MAXPATHLEN]; + size_t dir_len; + char *file_basename; + size_t file_basename_len; + int is_dir_only = 0; + char *path_cleaned; + size_t path_cleaned_len; + cwd_state new_state; + + new_state.cwd = (char*)malloc(1); + new_state.cwd[0] = '\0'; + new_state.cwd_length = 0; + + /* Clean/normlize the path and then transform any path (absolute or relative) + to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt) + */ + virtual_file_ex(&new_state, file, NULL, CWD_EXPAND TSRMLS_CC); + path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length); + if(!path_cleaned) { + return 0; + } + path_cleaned_len = strlen(path_cleaned); + + if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) { + return 0; + } + + /* it is a directory only, see #40228 */ + if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) { + len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file); + is_dir_only = 1; + } else { + memcpy(file_dirname, path_cleaned, path_cleaned_len); + dir_len = php_dirname(file_dirname, path_cleaned_len); + + if (dir_len <= 0 || (dir_len == 1 && file_dirname[0] == '.')) { + len = spprintf(&file_dirname_fullpath, 0, "%s", dest); + } else { + len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname); + } + + php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (size_t *)&file_basename_len TSRMLS_CC); + + if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) { + efree(file_dirname_fullpath); + efree(file_basename); + free(new_state.cwd); + return 0; + } + } + + /* let see if the path already exists */ + if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) { + +#if defined(PHP_WIN32) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1) + char *e; + e = file_dirname_fullpath; + while (*e) { + if (*e == '/') { + *e = DEFAULT_SLASH; + } + e++; + } +#endif + + ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL); + if (!ret) { + efree(file_dirname_fullpath); + if (!is_dir_only) { + efree(file_basename); + free(new_state.cwd); + } + return 0; + } + } + + /* it is a standalone directory, job done */ + if (is_dir_only) { + efree(file_dirname_fullpath); + free(new_state.cwd); + return 1; + } + + len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, file_basename); + if (!len) { + efree(file_dirname_fullpath); + efree(file_basename); + free(new_state.cwd); + return 0; + } else if (len > MAXPATHLEN) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN); + efree(file_dirname_fullpath); + efree(file_basename); + free(new_state.cwd); + return 0; + } + + /* check again the full path, not sure if it + * is required, does a file can have a different + * safemode status as its parent folder? + */ + if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) { + efree(fullpath); + efree(file_dirname_fullpath); + efree(file_basename); + free(new_state.cwd); + return 0; + } + +#if PHP_API_VERSION < 20100412 + stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL); +#else + stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL); +#endif + + if (stream == NULL) { + n = -1; + goto done; + } + + zf = zip_fopen(za, file, 0); + if (zf == NULL) { + n = -1; + php_stream_close(stream); + goto done; + } + + n = 0; + + while ((n=zip_fread(zf, b, sizeof(b))) > 0) { + php_stream_write(stream, b, n); + } + + php_stream_close(stream); + n = zip_fclose(zf); + +done: + efree(fullpath); + efree(file_basename); + efree(file_dirname_fullpath); + free(new_state.cwd); + + if (n<0) { + return 0; + } else { + return 1; + } +} +/* }}} */ + +static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len, + char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */ +{ + struct zip_source *zs; + int cur_idx; + char resolved_path[MAXPATHLEN]; + + + if (ZIP_OPENBASEDIR_CHECKPATH(filename)) { + return -1; + } + + if (!expand_filepath(filename, resolved_path TSRMLS_CC)) { + return -1; + } + + zs = zip_source_file(za, resolved_path, offset_start, offset_len); + if (!zs) { + return -1; + } + + cur_idx = zip_name_locate(za, (const char *)entry_name, 0); + /* TODO: fix _zip_replace */ + if (cur_idx<0) { + /* reset the error */ + if (za->error.str) { + _zip_error_fini(&za->error); + } + _zip_error_init(&za->error); + } else { + if (zip_delete(za, cur_idx) == -1) { + zip_source_free(zs); + return -1; + } + } + + if (zip_add(za, entry_name, zs) == -1) { + return -1; + } else { + return 1; + } +} +/* }}} */ + +static int php_zip_parse_options(zval *options, long *remove_all_path, + char **remove_path, int *remove_path_len, char **add_path, int *add_path_len TSRMLS_DC) /* {{{ */ +{ + zval **option; + if (zend_hash_find(HASH_OF(options), "remove_all_path", sizeof("remove_all_path"), (void **)&option) == SUCCESS) { + long opt; + if (Z_TYPE_PP(option) != IS_LONG) { + zval tmp = **option; + zval_copy_ctor(&tmp); + convert_to_long(&tmp); + opt = Z_LVAL(tmp); + } else { + opt = Z_LVAL_PP(option); + } + *remove_all_path = opt; + } + + /* If I add more options, it would make sense to create a nice static struct and loop over it. */ + if (zend_hash_find(HASH_OF(options), "remove_path", sizeof("remove_path"), (void **)&option) == SUCCESS) { + if (Z_TYPE_PP(option) != IS_STRING) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path option expected to be a string"); + return -1; + } + + if (Z_STRLEN_PP(option) < 1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as remove_path option"); + return -1; + } + + if (Z_STRLEN_PP(option) >= MAXPATHLEN) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)", + MAXPATHLEN - 1, Z_STRLEN_PP(option)); + return -1; + } + *remove_path_len = Z_STRLEN_PP(option); + *remove_path = Z_STRVAL_PP(option); + } + + if (zend_hash_find(HASH_OF(options), "add_path", sizeof("add_path"), (void **)&option) == SUCCESS) { + if (Z_TYPE_PP(option) != IS_STRING) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path option expected to be a string"); + return -1; + } + + if (Z_STRLEN_PP(option) < 1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as the add_path option"); + return -1; + } + + if (Z_STRLEN_PP(option) >= MAXPATHLEN) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)", + MAXPATHLEN - 1, Z_STRLEN_PP(option)); + return -1; + } + *add_path_len = Z_STRLEN_PP(option); + *add_path = Z_STRVAL_PP(option); + } + return 1; +} +/* }}} */ + +/* {{{ REGISTER_ZIP_CLASS_CONST_LONG */ +#define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \ + zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC); +/* }}} */ + +/* {{{ ZIP_FROM_OBJECT */ +#define ZIP_FROM_OBJECT(intern, object) \ + { \ + ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \ + intern = obj->za; \ + if (!intern) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized Zip object"); \ + RETURN_FALSE; \ + } \ + } +/* }}} */ + +/* {{{ RETURN_SB(sb) */ +#define RETURN_SB(sb) \ + { \ + array_init(return_value); \ + add_ascii_assoc_string(return_value, "name", (char *)(sb)->name, 1); \ + add_ascii_assoc_long(return_value, "index", (long) (sb)->index); \ + add_ascii_assoc_long(return_value, "crc", (long) (sb)->crc); \ + add_ascii_assoc_long(return_value, "size", (long) (sb)->size); \ + add_ascii_assoc_long(return_value, "mtime", (long) (sb)->mtime); \ + add_ascii_assoc_long(return_value, "comp_size", (long) (sb)->comp_size); \ + add_ascii_assoc_long(return_value, "comp_method", (long) (sb)->comp_method); \ + } +/* }}} */ + +static int php_zip_status(struct zip *za TSRMLS_DC) /* {{{ */ +{ + int zep, syp; + + zip_error_get(za, &zep, &syp); + return zep; +} +/* }}} */ + +static int php_zip_status_sys(struct zip *za TSRMLS_DC) /* {{{ */ +{ + int zep, syp; + + zip_error_get(za, &zep, &syp); + return syp; +} +/* }}} */ + +static int php_zip_get_num_files(struct zip *za TSRMLS_DC) /* {{{ */ +{ + return zip_get_num_files(za); +} +/* }}} */ + +static char * php_zipobj_get_filename(ze_zip_object *obj TSRMLS_DC) /* {{{ */ +{ + + if (!obj) { + return NULL; + } + + if (obj->filename) { + return obj->filename; + } + return NULL; +} +/* }}} */ + +static char * php_zipobj_get_zip_comment(struct zip *za, int *len TSRMLS_DC) /* {{{ */ +{ + if (za) { + return (char *)zip_get_archive_comment(za, len, 0); + } + return NULL; +} +/* }}} */ + +#ifdef HAVE_GLOB /* {{{ */ +#ifndef GLOB_ONLYDIR +#define GLOB_ONLYDIR (1<<30) +#define GLOB_EMULATE_ONLYDIR +#define GLOB_FLAGMASK (~GLOB_ONLYDIR) +#else +#define GLOB_FLAGMASK (~0) +#endif +#ifndef GLOB_BRACE +# define GLOB_BRACE 0 +#endif +#ifndef GLOB_MARK +# define GLOB_MARK 0 +#endif +#ifndef GLOB_NOSORT +# define GLOB_NOSORT 0 +#endif +#ifndef GLOB_NOCHECK +# define GLOB_NOCHECK 0 +#endif +#ifndef GLOB_NOESCAPE +# define GLOB_NOESCAPE 0 +#endif +#ifndef GLOB_ERR +# define GLOB_ERR 0 +#endif + +/* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */ +#define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR) + +#endif /* }}} */ + +int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value TSRMLS_DC) /* {{{ */ +{ +#ifdef HAVE_GLOB + char cwd[MAXPATHLEN]; + int cwd_skip = 0; +#ifdef ZTS + char work_pattern[MAXPATHLEN]; + char *result; +#endif + glob_t globbuf; + int n; + int ret; + + if (pattern_len >= MAXPATHLEN) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN); + return -1; + } + + if ((GLOB_AVAILABLE_FLAGS & flags) != flags) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform"); + return -1; + } + +#ifdef ZTS + if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) { + result = VCWD_GETCWD(cwd, MAXPATHLEN); + if (!result) { + cwd[0] = '\0'; + } +#ifdef PHP_WIN32 + if (IS_SLASH(*pattern)) { + cwd[2] = '\0'; + } +#endif + cwd_skip = strlen(cwd)+1; + + snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern); + pattern = work_pattern; + } +#endif + + globbuf.gl_offs = 0; + if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) { +#ifdef GLOB_NOMATCH + if (GLOB_NOMATCH == ret) { + /* Some glob implementation simply return no data if no matches + were found, others return the GLOB_NOMATCH error code. + We don't want to treat GLOB_NOMATCH as an error condition + so that PHP glob() behaves the same on both types of + implementations and so that 'foreach (glob() as ...' + can be used for simple glob() calls without further error + checking. + */ + array_init(return_value); + return 0; + } +#endif + return 0; + } + + /* now catch the FreeBSD style of "no matches" */ + if (!globbuf.gl_pathc || !globbuf.gl_pathv) { + array_init(return_value); + return 0; + } + + /* we assume that any glob pattern will match files from one directory only + so checking the dirname of the first match should be sufficient */ + strncpy(cwd, globbuf.gl_pathv[0], MAXPATHLEN); + if (ZIP_OPENBASEDIR_CHECKPATH(cwd)) { + return -1; + } + + array_init(return_value); + for (n = 0; n < globbuf.gl_pathc; n++) { + /* we need to do this everytime since GLOB_ONLYDIR does not guarantee that + * all directories will be filtered. GNU libc documentation states the + * following: + * If the information about the type of the file is easily available + * non-directories will be rejected but no extra work will be done to + * determine the information for each file. I.e., the caller must still be + * able to filter directories out. + */ + if (flags & GLOB_ONLYDIR) { + struct stat s; + + if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) { + continue; + } + + if (S_IFDIR != (s.st_mode & S_IFMT)) { + continue; + } + } + add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip, 1); + } + + globfree(&globbuf); + return globbuf.gl_pathc; +#else + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Glob support is not available"); + return 0; +#endif /* HAVE_GLOB */ +} +/* }}} */ + +int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *return_value TSRMLS_DC) /* {{{ */ +{ +#ifdef ZTS + char cwd[MAXPATHLEN]; + int cwd_skip = 0; + char work_path[MAXPATHLEN]; + char *result; +#endif + int files_cnt; + char **namelist; + +#ifdef ZTS + if (!IS_ABSOLUTE_PATH(path, path_len)) { + result = VCWD_GETCWD(cwd, MAXPATHLEN); + if (!result) { + cwd[0] = '\0'; + } +#ifdef PHP_WIN32 + if (IS_SLASH(*path)) { + cwd[2] = '\0'; + } +#endif + cwd_skip = strlen(cwd)+1; + + snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path); + path = work_path; + } +#endif + + if (ZIP_OPENBASEDIR_CHECKPATH(path)) { + return -1; + } + + files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort); + + if (files_cnt > 0) { + pcre *re = NULL; + pcre_extra *pcre_extra = NULL; + int preg_options = 0, i; + + re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC); + if (!re) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid expression"); + return -1; + } + + array_init(return_value); + + /* only the files, directories are ignored */ + for (i = 0; i < files_cnt; i++) { + struct stat s; + char fullpath[MAXPATHLEN]; + int ovector[3]; + int matches; + int namelist_len = strlen(namelist[i]); + + + if ((namelist_len == 1 && namelist[i][0] == '.') || + (namelist_len == 2 && namelist[i][0] == '.' && namelist[i][1] == '.')) { + efree(namelist[i]); + continue; + } + + if ((path_len + namelist_len + 1) >= MAXPATHLEN) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)", + MAXPATHLEN - 1, (path_len + namelist_len + 1)); + efree(namelist[i]); + break; + } + + snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, namelist[i]); + + if (0 != VCWD_STAT(fullpath, &s)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot read <%s>", fullpath); + efree(namelist[i]); + continue; + } + + if (S_IFDIR == (s.st_mode & S_IFMT)) { + efree(namelist[i]); + continue; + } + + matches = pcre_exec(re, NULL, namelist[i], strlen(namelist[i]), 0, 0, ovector, 3); + /* 0 means that the vector is too small to hold all the captured substring offsets */ + if (matches < 0) { + efree(namelist[i]); + continue; + } + + add_next_index_string(return_value, fullpath, 1); + efree(namelist[i]); + } + efree(namelist); + } + return files_cnt; +} +/* }}} */ + +#endif + +/* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1) + ZEND_ARG_INFO(0, filename) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_close, 0, 0, 1) + ZEND_ARG_INFO(0, zip) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_read, 0, 0, 1) + ZEND_ARG_INFO(0, zip) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_open, 0, 0, 2) + ZEND_ARG_INFO(0, zip_dp) + ZEND_ARG_INFO(0, zip_entry) + ZEND_ARG_INFO(0, mode) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_close, 0, 0, 1) + ZEND_ARG_INFO(0, zip_ent) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_read, 0, 0, 1) + ZEND_ARG_INFO(0, zip_entry) + ZEND_ARG_INFO(0, len) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_name, 0, 0, 1) + ZEND_ARG_INFO(0, zip_entry) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressedsize, 0, 0, 1) + ZEND_ARG_INFO(0, zip_entry) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_filesize, 0, 0, 1) + ZEND_ARG_INFO(0, zip_entry) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressionmethod, 0, 0, 1) + ZEND_ARG_INFO(0, zip_entry) +ZEND_END_ARG_INFO() +/* }}} */ + +/* {{{ zend_function_entry */ +static const zend_function_entry zip_functions[] = { + ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0) + ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0) + ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0) + PHP_FE(zip_entry_open, arginfo_zip_entry_open) + PHP_FE(zip_entry_close, arginfo_zip_entry_close) + PHP_FE(zip_entry_read, arginfo_zip_entry_read) + PHP_FE(zip_entry_filesize, arginfo_zip_entry_filesize) + PHP_FE(zip_entry_name, arginfo_zip_entry_name) + PHP_FE(zip_entry_compressedsize, arginfo_zip_entry_compressedsize) + PHP_FE(zip_entry_compressionmethod, arginfo_zip_entry_compressionmethod) + PHP_FE_END +}; +/* }}} */ + +/* {{{ ZE2 OO definitions */ +#ifdef PHP_ZIP_USE_OO +static zend_class_entry *zip_class_entry; +static zend_object_handlers zip_object_handlers; + +static HashTable zip_prop_handlers; + +typedef int (*zip_read_int_t)(struct zip *za TSRMLS_DC); +typedef char *(*zip_read_const_char_t)(struct zip *za, int *len TSRMLS_DC); +typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj TSRMLS_DC); + +typedef struct _zip_prop_handler { + zip_read_int_t read_int_func; + zip_read_const_char_t read_const_char_func; + zip_read_const_char_from_ze_t read_const_char_from_obj_func; + + int type; +} zip_prop_handler; +#endif +/* }}} */ + +#ifdef PHP_ZIP_USE_OO +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) /* {{{ */ +{ + zip_prop_handler hnd; + + hnd.read_const_char_func = read_char_func; + hnd.read_int_func = read_int_func; + hnd.read_const_char_from_obj_func = read_char_from_obj_func; + hnd.type = rettype; + zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(zip_prop_handler), NULL); +} +/* }}} */ + +static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval **retval, int newzval TSRMLS_DC) /* {{{ */ +{ + const char *retchar = NULL; + int retint = 0; + int len = 0; + + if (obj && obj->za != NULL) { + if (hnd->read_const_char_func) { + retchar = hnd->read_const_char_func(obj->za, &len TSRMLS_CC); + } else { + if (hnd->read_int_func) { + retint = hnd->read_int_func(obj->za TSRMLS_CC); + if (retint == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal zip error returned"); + return FAILURE; + } + } else { + if (hnd->read_const_char_from_obj_func) { + retchar = hnd->read_const_char_from_obj_func(obj TSRMLS_CC); + len = strlen(retchar); + } + } + } + } + + if (newzval) { + ALLOC_ZVAL(*retval); + } + + switch (hnd->type) { + case IS_STRING: + if (retchar) { + ZVAL_STRINGL(*retval, (char *) retchar, len, 1); + } else { + ZVAL_EMPTY_STRING(*retval); + } + break; + case IS_BOOL: + ZVAL_BOOL(*retval, (long)retint); + break; + case IS_LONG: + ZVAL_LONG(*retval, (long)retint); + break; + default: + ZVAL_NULL(*retval); + } + + return SUCCESS; +} +/* }}} */ + +static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */ +{ + ze_zip_object *obj; + zval tmp_member; + zval **retval = NULL; + + zip_prop_handler *hnd; + zend_object_handlers *std_hnd; + int ret; + + if (member->type != IS_STRING) { + tmp_member = *member; + zval_copy_ctor(&tmp_member); + convert_to_string(&tmp_member); + member = &tmp_member; + key = NULL; + } + + ret = FAILURE; + obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); + + if (obj->prop_handler != NULL) { + if (key) { + ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd); + } else { + ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); + } + } + + + if (ret == FAILURE) { + std_hnd = zend_get_std_object_handlers(); + retval = std_hnd->get_property_ptr_ptr(object, member, key TSRMLS_CC); + } + + if (member == &tmp_member) { + zval_dtor(member); + } + return retval; +} +/* }}} */ + +static zval* php_zip_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ +{ + ze_zip_object *obj; + zval tmp_member; + zval *retval; + zip_prop_handler *hnd; + zend_object_handlers *std_hnd; + int ret; + + if (member->type != IS_STRING) { + tmp_member = *member; + zval_copy_ctor(&tmp_member); + convert_to_string(&tmp_member); + member = &tmp_member; + key = NULL; + } + + ret = FAILURE; + obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); + + if (obj->prop_handler != NULL) { + if (key) { + ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd); + } else { + ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); + } + } + + if (ret == SUCCESS) { + ret = php_zip_property_reader(obj, hnd, &retval, 1 TSRMLS_CC); + if (ret == SUCCESS) { + /* ensure we're creating a temporary variable */ + Z_SET_REFCOUNT_P(retval, 0); + } else { + retval = EG(uninitialized_zval_ptr); + } + } else { + std_hnd = zend_get_std_object_handlers(); + retval = std_hnd->read_property(object, member, type, key TSRMLS_CC); + } + + if (member == &tmp_member) { + zval_dtor(member); + } + return retval; +} +/* }}} */ + +static int php_zip_has_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ +{ + ze_zip_object *obj; + zval tmp_member; + zip_prop_handler *hnd; + zend_object_handlers *std_hnd; + int ret, retval = 0; + + if (member->type != IS_STRING) { + tmp_member = *member; + zval_copy_ctor(&tmp_member); + convert_to_string(&tmp_member); + member = &tmp_member; + key = NULL; + } + + ret = FAILURE; + obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); + + if (obj->prop_handler != NULL) { + if (key) { + ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd); + } else { + ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); + } + } + + if (ret == SUCCESS) { + zval *tmp; + ALLOC_INIT_ZVAL(tmp); + + if (type == 2) { + retval = 1; + } else if (php_zip_property_reader(obj, hnd, &tmp, 0 TSRMLS_CC) == SUCCESS) { + Z_SET_REFCOUNT_P(tmp, 1); + Z_UNSET_ISREF_P(tmp); + if (type == 1) { + retval = zend_is_true(tmp); + } else if (type == 0) { + retval = (Z_TYPE_P(tmp) != IS_NULL); + } + } + + zval_ptr_dtor(&tmp); + } else { + std_hnd = zend_get_std_object_handlers(); + retval = std_hnd->has_property(object, member, type, key TSRMLS_CC); + } + + if (member == &tmp_member) { + zval_dtor(member); + } + return retval; +} +/* }}} */ + +static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */ +{ + ze_zip_object *obj; + zip_prop_handler *hnd; + HashTable *props; + zval *val; + int ret; + char *key; + uint key_len; + HashPosition pos; + ulong num_key; + + obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC); + props = zend_std_get_properties(object TSRMLS_CC); + + if (obj->prop_handler == NULL) { + return NULL; + } + zend_hash_internal_pointer_reset_ex(obj->prop_handler, &pos); + + while (zend_hash_get_current_data_ex(obj->prop_handler, (void**)&hnd, &pos) == SUCCESS) { + zend_hash_get_current_key_ex(obj->prop_handler, &key, &key_len, &num_key, 0, &pos); + MAKE_STD_ZVAL(val); + ret = php_zip_property_reader(obj, hnd, &val, 0 TSRMLS_CC); + if (ret != SUCCESS) { + val = EG(uninitialized_zval_ptr); + } + zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL); + zend_hash_move_forward_ex(obj->prop_handler, &pos); + } + return props; +} +/* }}} */ + +static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */ +{ + ze_zip_object * intern = (ze_zip_object *) object; + int i; + + if (!intern) { + return; + } + if (intern->za) { + if (zip_close(intern->za) != 0) { + _zip_free(intern->za); + } + intern->za = NULL; + } + + if (intern->buffers_cnt>0) { + for (i=0; i<intern->buffers_cnt; i++) { + efree(intern->buffers[i]); + } + efree(intern->buffers); + } + + intern->za = NULL; + +#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) + zend_object_std_dtor(&intern->zo TSRMLS_CC); +#else + if (intern->zo.guards) { + zend_hash_destroy(intern->zo.guards); + FREE_HASHTABLE(intern->zo.guards); + } + + if (intern->zo.properties) { + zend_hash_destroy(intern->zo.properties); + FREE_HASHTABLE(intern->zo.properties); + } +#endif + + if (intern->filename) { + efree(intern->filename); + } + efree(intern); +} +/* }}} */ + +static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ +{ + ze_zip_object *intern; + zend_object_value retval; + + intern = emalloc(sizeof(ze_zip_object)); + memset(&intern->zo, 0, sizeof(zend_object)); + + intern->za = NULL; + intern->buffers = NULL; + intern->filename = NULL; + intern->buffers_cnt = 0; + intern->prop_handler = &zip_prop_handlers; + +#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2)) + zend_object_std_init(&intern->zo, class_type TSRMLS_CC); +#else + ALLOC_HASHTABLE(intern->zo.properties); + zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0); + intern->zo.ce = class_type; +#endif + + object_properties_init(&intern->zo, class_type); + + retval.handle = zend_objects_store_put(intern, + NULL, + (zend_objects_free_object_storage_t) php_zip_object_free_storage, + NULL TSRMLS_CC); + + retval.handlers = (zend_object_handlers *) & zip_object_handlers; + + return retval; +} +/* }}} */ +#endif + +/* {{{ Resource dtors */ + +/* {{{ php_zip_free_dir */ +static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr; + + if (zip_int) { + if (zip_int->za) { + if (zip_close(zip_int->za) != 0) { + _zip_free(zip_int->za); + } + zip_int->za = NULL; + } + + efree(rsrc->ptr); + + rsrc->ptr = NULL; + } +} +/* }}} */ + +/* {{{ php_zip_free_entry */ +static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr; + + if (zr_rsrc) { + if (zr_rsrc->zf) { + if (zr_rsrc->zf->za) { + zip_fclose(zr_rsrc->zf); + } else { + if (zr_rsrc->zf->src) + zip_source_free(zr_rsrc->zf->src); + free(zr_rsrc->zf); + } + zr_rsrc->zf = NULL; + } + efree(zr_rsrc); + rsrc->ptr = NULL; + } +} +/* }}} */ + +/* }}}*/ + +/* reset macro */ + +/* {{{ function prototypes */ +static PHP_MINIT_FUNCTION(zip); +static PHP_MSHUTDOWN_FUNCTION(zip); +static PHP_MINFO_FUNCTION(zip); +/* }}} */ + +/* {{{ zip_module_entry + */ +zend_module_entry zip_module_entry = { + STANDARD_MODULE_HEADER, + "zip", + zip_functions, + PHP_MINIT(zip), + PHP_MSHUTDOWN(zip), + NULL, + NULL, + PHP_MINFO(zip), + PHP_ZIP_VERSION_STRING, + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_ZIP +ZEND_GET_MODULE(zip) +#endif +/* set macro */ + +/* {{{ proto resource zip_open(string filename) +Create new zip using source uri for output */ +static PHP_NAMED_FUNCTION(zif_zip_open) +{ + char *filename; + int filename_len; + char resolved_path[MAXPATHLEN + 1]; + zip_rsrc *rsrc_int; + int err = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { + return; + } + + if (filename_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source"); + RETURN_FALSE; + } + + if (ZIP_OPENBASEDIR_CHECKPATH(filename)) { + RETURN_FALSE; + } + + if(!expand_filepath(filename, resolved_path TSRMLS_CC)) { + RETURN_FALSE; + } + + rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc)); + + rsrc_int->za = zip_open(resolved_path, 0, &err); + if (rsrc_int->za == NULL) { + efree(rsrc_int); + RETURN_LONG((long)err); + } + + rsrc_int->index_current = 0; + rsrc_int->num_files = zip_get_num_files(rsrc_int->za); + + ZEND_REGISTER_RESOURCE(return_value, rsrc_int, le_zip_dir); +} +/* }}} */ + +/* {{{ proto void zip_close(resource zip) + Close a Zip archive */ +static PHP_NAMED_FUNCTION(zif_zip_close) +{ + zval * zip; + zip_rsrc *z_rsrc = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir); + + /* really close the zip will break BC :-D */ + zend_list_delete(Z_LVAL_P(zip)); +} +/* }}} */ + +/* {{{ proto resource zip_read(resource zip) + Returns the next file in the archive */ +static PHP_NAMED_FUNCTION(zif_zip_read) +{ + zval *zip_dp; + zip_read_rsrc *zr_rsrc; + int ret; + zip_rsrc *rsrc_int; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_dp) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(rsrc_int, zip_rsrc *, &zip_dp, -1, le_zip_dir_name, le_zip_dir); + + if (rsrc_int && rsrc_int->za) { + if (rsrc_int->index_current >= rsrc_int->num_files) { + RETURN_FALSE; + } + + zr_rsrc = emalloc(sizeof(zip_read_rsrc)); + + ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb); + + if (ret != 0) { + efree(zr_rsrc); + RETURN_FALSE; + } + + zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0); + if (zr_rsrc->zf) { + rsrc_int->index_current++; + ZEND_REGISTER_RESOURCE(return_value, zr_rsrc, le_zip_entry); + } else { + efree(zr_rsrc); + RETURN_FALSE; + } + + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode]) + Open a Zip File, pointed by the resource entry */ +/* Dummy function to follow the old API */ +static PHP_NAMED_FUNCTION(zif_zip_entry_open) +{ + zval * zip; + zval * zip_entry; + char *mode = NULL; + int mode_len = 0; + zip_read_rsrc * zr_rsrc; + zip_rsrc *z_rsrc; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry); + ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir); + + if (zr_rsrc->zf != NULL) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool zip_entry_close(resource zip_ent) + Close a zip entry */ +static PHP_NAMED_FUNCTION(zif_zip_entry_close) +{ + zval * zip_entry; + zip_read_rsrc * zr_rsrc; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry); + + RETURN_BOOL(SUCCESS == zend_list_delete(Z_LVAL_P(zip_entry))); +} +/* }}} */ + +/* {{{ proto mixed zip_entry_read(resource zip_entry [, int len]) + Read from an open directory entry */ +static PHP_NAMED_FUNCTION(zif_zip_entry_read) +{ + zval * zip_entry; + long len = 0; + zip_read_rsrc * zr_rsrc; + char *buffer; + int n = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zip_entry, &len) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry); + + if (len <= 0) { + len = 1024; + } + + if (zr_rsrc->zf) { + buffer = safe_emalloc(len, 1, 1); + n = zip_fread(zr_rsrc->zf, buffer, len); + if (n > 0) { + buffer[n] = 0; + RETURN_STRINGL(buffer, n, 0); + } else { + efree(buffer); + RETURN_EMPTY_STRING() + } + } else { + RETURN_FALSE; + } +} +/* }}} */ + +static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */ +{ + zval * zip_entry; + zip_read_rsrc * zr_rsrc; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry); + + if (!zr_rsrc->zf) { + RETURN_FALSE; + } + + switch (opt) { + case 0: + RETURN_STRING((char *)zr_rsrc->sb.name, 1); + break; + case 1: + RETURN_LONG((long) (zr_rsrc->sb.comp_size)); + break; + case 2: + RETURN_LONG((long) (zr_rsrc->sb.size)); + break; + case 3: + switch (zr_rsrc->sb.comp_method) { + case 0: + RETURN_STRING("stored", 1); + break; + case 1: + RETURN_STRING("shrunk", 1); + break; + case 2: + case 3: + case 4: + case 5: + RETURN_STRING("reduced", 1); + break; + case 6: + RETURN_STRING("imploded", 1); + break; + case 7: + RETURN_STRING("tokenized", 1); + break; + case 8: + RETURN_STRING("deflated", 1); + break; + case 9: + RETURN_STRING("deflatedX", 1); + break; + case 10: + RETURN_STRING("implodedX", 1); + break; + default: + RETURN_FALSE; + } + RETURN_LONG((long) (zr_rsrc->sb.comp_method)); + break; + } + +} +/* }}} */ + +/* {{{ proto string zip_entry_name(resource zip_entry) + Return the name given a ZZip entry */ +static PHP_NAMED_FUNCTION(zif_zip_entry_name) +{ + php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto int zip_entry_compressedsize(resource zip_entry) + Return the compressed size of a ZZip entry */ +static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize) +{ + php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + +/* {{{ proto int zip_entry_filesize(resource zip_entry) + Return the actual filesize of a ZZip entry */ +static PHP_NAMED_FUNCTION(zif_zip_entry_filesize) +{ + php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2); +} +/* }}} */ + +/* {{{ proto string zip_entry_compressionmethod(resource zip_entry) + Return a string containing the compression method used on a particular entry */ +static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod) +{ + php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3); +} +/* }}} */ + +#ifdef PHP_ZIP_USE_OO +/* {{{ proto mixed ZipArchive::open(string source [, int flags]) +Create new zip using source uri for output, return TRUE on success or the error code */ +static ZIPARCHIVE_METHOD(open) +{ + struct zip *intern; + char *filename; + int filename_len; + int err = 0; + long flags = 0; + char resolved_path[MAXPATHLEN]; + + zval *this = getThis(); + ze_zip_object *ze_obj = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) { + return; + } + + if (this) { + /* We do not use ZIP_FROM_OBJECT, zip init function here */ + ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC); + } + + if (filename_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source"); + RETURN_FALSE; + } + + if (ZIP_OPENBASEDIR_CHECKPATH(filename)) { + RETURN_FALSE; + } + + if (!expand_filepath(filename, resolved_path TSRMLS_CC)) { + RETURN_FALSE; + } + + if (ze_obj->za) { + /* we already have an opened zip, free it */ + if (zip_close(ze_obj->za) != 0) { + _zip_free(ze_obj->za); + } + ze_obj->za = NULL; + } + if (ze_obj->filename) { + efree(ze_obj->filename); + ze_obj->filename = NULL; + } + + intern = zip_open(resolved_path, flags, &err); + if (!intern || err) { + RETURN_LONG((long)err); + } + ze_obj->filename = estrdup(resolved_path); + ze_obj->filename_len = filename_len; + ze_obj->za = intern; + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool ZipArchive::close() +close the zip archive */ +static ZIPARCHIVE_METHOD(close) +{ + struct zip *intern; + zval *this = getThis(); + ze_zip_object *ze_obj; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC); + + if (zip_close(intern)) { + RETURN_FALSE; + } + + efree(ze_obj->filename); + ze_obj->filename = NULL; + ze_obj->filename_len = 0; + ze_obj->za = NULL; + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string ZipArchive::getStatusString() + * Returns the status error message, system and/or zip messages */ +static ZIPARCHIVE_METHOD(getStatusString) +{ + struct zip *intern; + zval *this = getThis(); + int zep, syp, len; + char error_string[128]; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + zip_error_get(intern, &zep, &syp); + + len = zip_error_to_str(error_string, 128, zep, syp); + RETVAL_STRINGL(error_string, len, 1); +} +/* }}} */ + +/* {{{ proto bool ZipArchive::createEmptyDir(string dirname) +Returns the index of the entry named filename in the archive */ +static ZIPARCHIVE_METHOD(addEmptyDir) +{ + struct zip *intern; + zval *this = getThis(); + char *dirname; + int dirname_len; + int idx; + struct zip_stat sb; + char *s; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", + &dirname, &dirname_len) == FAILURE) { + return; + } + + if (dirname_len<1) { + RETURN_FALSE; + } + + if (dirname[dirname_len-1] != '/') { + s=(char *)emalloc(dirname_len+2); + strcpy(s, dirname); + s[dirname_len] = '/'; + s[dirname_len+1] = '\0'; + } else { + s = dirname; + } + + idx = zip_stat(intern, s, 0, &sb); + if (idx >= 0) { + RETVAL_FALSE; + } else { + if (zip_add_dir(intern, (const char *)s) == -1) { + RETVAL_FALSE; + } + RETVAL_TRUE; + } + + if (s != dirname) { + efree(s); + } +} +/* }}} */ + +static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ +{ + struct zip *intern; + zval *this = getThis(); + char *pattern; + char *path = NULL; + char *remove_path = NULL; + char *add_path = NULL; + int pattern_len, add_path_len, remove_path_len, path_len = 0; + long remove_all_path = 0; + long flags = 0; + zval *options = NULL; + int found; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + /* 1 == glob, 2==pcre */ + if (type == 1) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la", + &pattern, &pattern_len, &flags, &options) == FAILURE) { + return; + } + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa", + &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) { + return; + } + } + + if (pattern_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as pattern"); + RETURN_FALSE; + } + if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len, + &add_path, &add_path_len TSRMLS_CC) < 0)) { + RETURN_FALSE; + } + + if (remove_path && remove_path_len > 1 && (remove_path[strlen(remove_path) - 1] == '/' || + remove_path[strlen(remove_path) - 1] == '\\')) { + remove_path[strlen(remove_path) - 1] = '\0'; + } + + if (type == 1) { + found = php_zip_glob(pattern, pattern_len, flags, return_value TSRMLS_CC); + } else { + found = php_zip_pcre(pattern, pattern_len, path, path_len, return_value TSRMLS_CC); + } + + if (found > 0) { + int i; + zval **zval_file = NULL; + + for (i = 0; i < found; i++) { + char *file, *file_stripped, *entry_name; + size_t entry_name_len, file_stripped_len; + char entry_name_buf[MAXPATHLEN]; + char *basename = NULL; + + if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) { + file = Z_STRVAL_PP(zval_file); + if (remove_all_path) { + php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0, + &basename, (size_t *)&file_stripped_len TSRMLS_CC); + file_stripped = basename; + } else if (remove_path && strstr(Z_STRVAL_PP(zval_file), remove_path) != NULL) { + file_stripped = Z_STRVAL_PP(zval_file) + remove_path_len + 1; + file_stripped_len = Z_STRLEN_PP(zval_file) - remove_path_len - 1; + } else { + file_stripped = Z_STRVAL_PP(zval_file); + file_stripped_len = Z_STRLEN_PP(zval_file); + } + + if (add_path) { + if ((add_path_len + file_stripped_len) > MAXPATHLEN) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)", + MAXPATHLEN - 1, (add_path_len + file_stripped_len)); + zval_dtor(return_value); + RETURN_FALSE; + } + + snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped); + entry_name = entry_name_buf; + entry_name_len = strlen(entry_name); + } else { + entry_name = Z_STRVAL_PP(zval_file); + entry_name_len = Z_STRLEN_PP(zval_file); + } + if (basename) { + efree(basename); + basename = NULL; + } + if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), + entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) { + zval_dtor(return_value); + RETURN_FALSE; + } + } + } + } +} +/* }}} */ + +/* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]]) +Add files matching the glob pattern. See php's glob for the pattern syntax. */ +static ZIPARCHIVE_METHOD(addGlob) +{ + php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + +/* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]]) +Add files matching the pcre pattern. See php's pcre for the pattern syntax. */ +static ZIPARCHIVE_METHOD(addPattern) +{ + php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2); +} +/* }}} */ + +/* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]]) +Add a file in a Zip archive using its path and the name to use. */ +static ZIPARCHIVE_METHOD(addFile) +{ + struct zip *intern; + zval *this = getThis(); + char *filename; + int filename_len; + char *entry_name = NULL; + int entry_name_len = 0; + long offset_start = 0, offset_len = 0; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll", + &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) { + return; + } + + if (filename_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as filename"); + RETURN_FALSE; + } + + if (entry_name_len == 0) { + entry_name = filename; + entry_name_len = filename_len; + } + + if (php_zip_add_file(intern, filename, filename_len, + entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto bool ZipArchive::addFromString(string name, string content) +Add a file using content and the entry name */ +static ZIPARCHIVE_METHOD(addFromString) +{ + struct zip *intern; + zval *this = getThis(); + char *buffer, *name; + int buffer_len, name_len; + ze_zip_object *ze_obj; + struct zip_source *zs; + int pos = 0; + int cur_idx; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", + &name, &name_len, &buffer, &buffer_len) == FAILURE) { + return; + } + + ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC); + if (ze_obj->buffers_cnt) { + ze_obj->buffers = (char **)erealloc(ze_obj->buffers, sizeof(char *) * (ze_obj->buffers_cnt+1)); + pos = ze_obj->buffers_cnt++; + } else { + ze_obj->buffers = (char **)emalloc(sizeof(char *)); + ze_obj->buffers_cnt++; + pos = 0; + } + ze_obj->buffers[pos] = (char *)emalloc(buffer_len + 1); + memcpy(ze_obj->buffers[pos], buffer, buffer_len + 1); + + zs = zip_source_buffer(intern, ze_obj->buffers[pos], buffer_len, 0); + + if (zs == NULL) { + RETURN_FALSE; + } + + cur_idx = zip_name_locate(intern, (const char *)name, 0); + /* TODO: fix _zip_replace */ + if (cur_idx >= 0) { + if (zip_delete(intern, cur_idx) == -1) { + RETURN_FALSE; + } + } + + if (zip_add(intern, name, zs) == -1) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto array ZipArchive::statName(string filename[, int flags]) +Returns the information about a the zip entry filename */ +static ZIPARCHIVE_METHOD(statName) +{ + struct zip *intern; + zval *this = getThis(); + char *name; + int name_len; + long flags = 0; + struct zip_stat sb; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", + &name, &name_len, &flags) == FAILURE) { + return; + } + + PHP_ZIP_STAT_PATH(intern, name, name_len, flags, sb); + + RETURN_SB(&sb); +} +/* }}} */ + +/* {{{ proto resource ZipArchive::statIndex(int index[, int flags]) +Returns the zip entry informations using its index */ +static ZIPARCHIVE_METHOD(statIndex) +{ + struct zip *intern; + zval *this = getThis(); + long index, flags = 0; + + struct zip_stat sb; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", + &index, &flags) == FAILURE) { + return; + } + + if (zip_stat_index(intern, index, flags, &sb) != 0) { + RETURN_FALSE; + } + RETURN_SB(&sb); +} +/* }}} */ + +/* {{{ proto int ZipArchive::locateName(string filename[, int flags]) +Returns the index of the entry named filename in the archive */ +static ZIPARCHIVE_METHOD(locateName) +{ + struct zip *intern; + zval *this = getThis(); + char *name; + int name_len; + long flags = 0; + long idx = -1; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", + &name, &name_len, &flags) == FAILURE) { + return; + } + if (name_len<1) { + RETURN_FALSE; + } + + idx = (long)zip_name_locate(intern, (const char *)name, flags); + + if (idx >= 0) { + RETURN_LONG(idx); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto string ZipArchive::getNameIndex(int index [, int flags]) +Returns the name of the file at position index */ +static ZIPARCHIVE_METHOD(getNameIndex) +{ + struct zip *intern; + zval *this = getThis(); + const char *name; + long flags = 0, index = 0; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", + &index, &flags) == FAILURE) { + return; + } + + name = zip_get_name(intern, (int) index, flags); + + if (name) { + RETVAL_STRING((char *)name, 1); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool ZipArchive::setArchiveComment(string comment) +Set or remove (NULL/'') the comment of the archive */ +static ZIPARCHIVE_METHOD(setArchiveComment) +{ + struct zip *intern; + zval *this = getThis(); + int comment_len; + char * comment; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &comment, &comment_len) == FAILURE) { + return; + } + if (zip_set_archive_comment(intern, (const char *)comment, (int)comment_len)) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto string ZipArchive::getArchiveComment([int flags]) +Returns the comment of an entry using its index */ +static ZIPARCHIVE_METHOD(getArchiveComment) +{ + struct zip *intern; + zval *this = getThis(); + long flags = 0; + const char * comment; + int comment_len = 0; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) { + return; + } + + comment = zip_get_archive_comment(intern, &comment_len, (int)flags); + if(comment==NULL) { + RETURN_FALSE; + } + RETURN_STRINGL((char *)comment, (long)comment_len, 1); +} +/* }}} */ + +/* {{{ proto bool ZipArchive::setCommentName(string name, string comment) +Set or remove (NULL/'') the comment of an entry using its Name */ +static ZIPARCHIVE_METHOD(setCommentName) +{ + struct zip *intern; + zval *this = getThis(); + int comment_len, name_len; + char * comment, *name; + int idx; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", + &name, &name_len, &comment, &comment_len) == FAILURE) { + return; + } + + if (name_len < 1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); + } + + idx = zip_name_locate(intern, name, 0); + if (idx < 0) { + RETURN_FALSE; + } + PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len); +} +/* }}} */ + +/* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment) +Set or remove (NULL/'') the comment of an entry using its index */ +static ZIPARCHIVE_METHOD(setCommentIndex) +{ + struct zip *intern; + zval *this = getThis(); + long index; + int comment_len; + char * comment; + struct zip_stat sb; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", + &index, &comment, &comment_len) == FAILURE) { + return; + } + + PHP_ZIP_STAT_INDEX(intern, index, 0, sb); + PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len); +} +/* }}} */ + +/* {{{ proto string ZipArchive::getCommentName(string name[, int flags]) +Returns the comment of an entry using its name */ +static ZIPARCHIVE_METHOD(getCommentName) +{ + struct zip *intern; + zval *this = getThis(); + int name_len, idx; + long flags = 0; + int comment_len = 0; + const char * comment; + char *name; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", + &name, &name_len, &flags) == FAILURE) { + return; + } + if (name_len < 1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); + RETURN_FALSE; + } + + idx = zip_name_locate(intern, name, 0); + if (idx < 0) { + RETURN_FALSE; + } + + comment = zip_get_file_comment(intern, idx, &comment_len, (int)flags); + RETURN_STRINGL((char *)comment, (long)comment_len, 1); +} +/* }}} */ + +/* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags]) +Returns the comment of an entry using its index */ +static ZIPARCHIVE_METHOD(getCommentIndex) +{ + struct zip *intern; + zval *this = getThis(); + long index, flags = 0; + const char * comment; + int comment_len = 0; + struct zip_stat sb; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", + &index, &flags) == FAILURE) { + return; + } + + PHP_ZIP_STAT_INDEX(intern, index, 0, sb); + comment = zip_get_file_comment(intern, index, &comment_len, (int)flags); + RETURN_STRINGL((char *)comment, (long)comment_len, 1); +} +/* }}} */ + +/* {{{ proto bool ZipArchive::deleteIndex(int index) +Delete a file using its index */ +static ZIPARCHIVE_METHOD(deleteIndex) +{ + struct zip *intern; + zval *this = getThis(); + long index; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { + return; + } + + if (index < 0) { + RETURN_FALSE; + } + + if (zip_delete(intern, index) < 0) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool ZipArchive::deleteName(string name) +Delete a file using its index */ +static ZIPARCHIVE_METHOD(deleteName) +{ + struct zip *intern; + zval *this = getThis(); + int name_len; + char *name; + struct zip_stat sb; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { + return; + } + if (name_len < 1) { + RETURN_FALSE; + } + + PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb); + if (zip_delete(intern, sb.index)) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool ZipArchive::renameIndex(int index, string new_name) +Rename an entry selected by its index to new_name */ +static ZIPARCHIVE_METHOD(renameIndex) +{ + struct zip *intern; + zval *this = getThis(); + + char *new_name; + int new_name_len; + long index; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &index, &new_name, &new_name_len) == FAILURE) { + return; + } + + if (index < 0) { + RETURN_FALSE; + } + + if (new_name_len < 1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name"); + RETURN_FALSE; + } + if (zip_rename(intern, index, (const char *)new_name) != 0) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool ZipArchive::renameName(string name, string new_name) +Rename an entry selected by its name to new_name */ +static ZIPARCHIVE_METHOD(renameName) +{ + struct zip *intern; + zval *this = getThis(); + struct zip_stat sb; + char *name, *new_name; + int name_len, new_name_len; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) { + return; + } + + if (new_name_len < 1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name"); + RETURN_FALSE; + } + + PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb); + + if (zip_rename(intern, sb.index, (const char *)new_name)) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto bool ZipArchive::unchangeIndex(int index) +Changes to the file at position index are reverted */ +static ZIPARCHIVE_METHOD(unchangeIndex) +{ + struct zip *intern; + zval *this = getThis(); + long index; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { + return; + } + + if (index < 0) { + RETURN_FALSE; + } + + if (zip_unchange(intern, index) != 0) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto bool ZipArchive::unchangeName(string name) +Changes to the file named 'name' are reverted */ +static ZIPARCHIVE_METHOD(unchangeName) +{ + struct zip *intern; + zval *this = getThis(); + struct zip_stat sb; + char *name; + int name_len; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { + return; + } + + if (name_len < 1) { + RETURN_FALSE; + } + + PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb); + + if (zip_unchange(intern, sb.index) != 0) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto bool ZipArchive::unchangeAll() +All changes to files and global information in archive are reverted */ +static ZIPARCHIVE_METHOD(unchangeAll) +{ + struct zip *intern; + zval *this = getThis(); + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zip_unchange_all(intern) != 0) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto bool ZipArchive::unchangeArchive() +Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */ +static ZIPARCHIVE_METHOD(unchangeArchive) +{ + struct zip *intern; + zval *this = getThis(); + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zip_unchange_archive(intern) != 0) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files]) +Extract one or more file from a zip archive */ +/* TODO: + * - allow index or array of indeces + * - replace path + * - patterns + */ +static ZIPARCHIVE_METHOD(extractTo) +{ + struct zip *intern; + + zval *this = getThis(); + zval *zval_files = NULL; + zval **zval_file = NULL; + php_stream_statbuf ssb; + char *pathto; + int pathto_len; + int ret, i; + + int nelems; + + if (!this) { + RETURN_FALSE; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &pathto, &pathto_len, &zval_files) == FAILURE) { + return; + } + + if (pathto_len < 1) { + RETURN_FALSE; + } + + if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) { + ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL); + if (!ret) { + RETURN_FALSE; + } + } + + ZIP_FROM_OBJECT(intern, this); + if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) { + switch (Z_TYPE_P(zval_files)) { + case IS_STRING: + if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files) TSRMLS_CC)) { + RETURN_FALSE; + } + break; + case IS_ARRAY: + nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files)); + if (nelems == 0 ) { + RETURN_FALSE; + } + for (i = 0; i < nelems; i++) { + if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) { + switch (Z_TYPE_PP(zval_file)) { + case IS_LONG: + break; + case IS_STRING: + if (!php_zip_extract_file(intern, pathto, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file) TSRMLS_CC)) { + RETURN_FALSE; + } + break; + } + } + } + break; + case IS_LONG: + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings"); + break; + } + } else { + /* Extract all files */ + int filecount = zip_get_num_files(intern); + + if (filecount == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive"); + RETURN_FALSE; + } + + for (i = 0; i < filecount; i++) { + char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED); + if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) { + RETURN_FALSE; + } + } + } + RETURN_TRUE; +} +/* }}} */ + +static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ +{ + struct zip *intern; + zval *this = getThis(); + + struct zip_stat sb; + struct zip_file *zf; + + char *filename; + int filename_len; + long index = -1; + long flags = 0; + long len = 0; + + char *buffer; + int n = 0; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (type == 1) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) { + return; + } + PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb); + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &index, &len, &flags) == FAILURE) { + return; + } + PHP_ZIP_STAT_INDEX(intern, index, 0, sb); + } + + if (sb.size < 1) { + RETURN_EMPTY_STRING(); + } + + if (len < 1) { + len = sb.size; + } + if (index >= 0) { + zf = zip_fopen_index(intern, index, flags); + } else { + zf = zip_fopen(intern, filename, flags); + } + + if (zf == NULL) { + RETURN_FALSE; + } + + buffer = safe_emalloc(len, 1, 2); + n = zip_fread(zf, buffer, len); + if (n < 1) { + efree(buffer); + RETURN_EMPTY_STRING(); + } + + zip_fclose(zf); + buffer[n] = 0; + RETURN_STRINGL(buffer, n, 0); +} +/* }}} */ + +/* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]]) +get the contents of an entry using its name */ +static ZIPARCHIVE_METHOD(getFromName) +{ + php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + +/* {{{ proto string ZipArchive::getFromIndex(int index[, int len [, int flags]]) +get the contents of an entry using its index */ +static ZIPARCHIVE_METHOD(getFromIndex) +{ + php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto resource ZipArchive::getStream(string entryname) +get a stream for an entry using its name */ +static ZIPARCHIVE_METHOD(getStream) +{ + struct zip *intern; + zval *this = getThis(); + struct zip_stat sb; + char *filename; + int filename_len; + char *mode = "rb"; + php_stream *stream; + ze_zip_object *obj; + + if (!this) { + RETURN_FALSE; + } + + ZIP_FROM_OBJECT(intern, this); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { + return; + } + + if (zip_stat(intern, filename, 0, &sb) != 0) { + RETURN_FALSE; + } + + obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC); + + stream = php_stream_zip_open(obj->filename, filename, mode STREAMS_CC TSRMLS_CC); + if (stream) { + php_stream_to_zval(stream, return_value); + } +} +/* }}} */ + +/* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1) + ZEND_ARG_INFO(0, filename) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addemptydir, 0, 0, 1) + ZEND_ARG_INFO(0, dirname) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addglob, 0, 0, 1) + ZEND_ARG_INFO(0, pattern) + ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addpattern, 0, 0, 1) + ZEND_ARG_INFO(0, pattern) + ZEND_ARG_INFO(0, path) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfile, 0, 0, 1) + ZEND_ARG_INFO(0, filepath) + ZEND_ARG_INFO(0, entryname) + ZEND_ARG_INFO(0, start) + ZEND_ARG_INFO(0, length) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfromstring, 0, 0, 2) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, content) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statname, 0, 0, 1) + ZEND_ARG_INFO(0, filename) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statindex, 0, 0, 1) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setarchivecomment, 0, 0, 1) + ZEND_ARG_INFO(0, comment) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentindex, 0, 0, 2) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, comment) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentname, 0, 0, 1) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentindex, 0, 0, 1) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renameindex, 0, 0, 2) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, new_name) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renamename, 0, 0, 2) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, new_name) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangeindex, 0, 0, 1) + ZEND_ARG_INFO(0, index) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangename, 0, 0, 1) + ZEND_ARG_INFO(0, name) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_extractto, 0, 0, 1) + ZEND_ARG_INFO(0, pathto) + ZEND_ARG_INFO(0, files) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromname, 0, 0, 1) + ZEND_ARG_INFO(0, entryname) + ZEND_ARG_INFO(0, len) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromindex, 0, 0, 1) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, len) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getarchivecomment, 0, 0, 0) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentname, 0, 0, 2) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, comment) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getstream, 0, 0, 1) + ZEND_ARG_INFO(0, entryname) +ZEND_END_ARG_INFO() +/* }}} */ + +/* {{{ ze_zip_object_class_functions */ +static const zend_function_entry zip_class_functions[] = { + ZIPARCHIVE_ME(open, arginfo_ziparchive_open, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(close, arginfo_ziparchive__void, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getStatusString, arginfo_ziparchive__void, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(addEmptyDir, arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(addFromString, arginfo_ziparchive_addfromstring, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(addFile, arginfo_ziparchive_addfile, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(addGlob, arginfo_ziparchive_addglob, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(addPattern, arginfo_ziparchive_addpattern, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(renameIndex, arginfo_ziparchive_renameindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(renameName, arginfo_ziparchive_renamename, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(setArchiveComment, arginfo_ziparchive_setarchivecomment, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getArchiveComment, arginfo_ziparchive_getarchivecomment, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(setCommentIndex, arginfo_ziparchive_setcommentindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(setCommentName, arginfo_ziparchive_setcommentname, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getCommentIndex, arginfo_ziparchive_getcommentindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getCommentName, arginfo_ziparchive_getcommentname, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(deleteIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(deleteName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(statName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(statIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(locateName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getNameIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(unchangeArchive, arginfo_ziparchive__void, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(unchangeAll, arginfo_ziparchive__void, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(unchangeIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(unchangeName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(extractTo, arginfo_ziparchive_extractto, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getFromName, arginfo_ziparchive_getfromname, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getFromIndex, arginfo_ziparchive_getfromindex, ZEND_ACC_PUBLIC) + ZIPARCHIVE_ME(getStream, arginfo_ziparchive_getstream, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; +/* }}} */ +#endif + +/* {{{ PHP_MINIT_FUNCTION */ +static PHP_MINIT_FUNCTION(zip) +{ +#ifdef PHP_ZIP_USE_OO + zend_class_entry ce; + + memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zip_object_handlers.clone_obj = NULL; + zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr; + + zip_object_handlers.get_properties = php_zip_get_properties; + zip_object_handlers.read_property = php_zip_read_property; + zip_object_handlers.has_property = php_zip_has_property; + + INIT_CLASS_ENTRY(ce, "ZipArchive", zip_class_functions); + ce.create_object = php_zip_object_new; + zip_class_entry = zend_register_internal_class(&ce TSRMLS_CC); + + zend_hash_init(&zip_prop_handlers, 0, NULL, NULL, 1); + php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, NULL, IS_LONG TSRMLS_CC); + php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG TSRMLS_CC); + php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, NULL, IS_LONG TSRMLS_CC); + php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC); + php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC); + + REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE); + REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL); + REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS); + REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE); + + REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE); + REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR); + REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED); + REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED); + REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT); + REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE); + REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK); + REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1); + REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2); + REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3); + REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4); + REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE); + REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE); + REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64); + REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE); + REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2); + REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA); + REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE); + REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77); + REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK); + REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD); + + /* Error code */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */ + REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */ + + php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC); +#endif + + le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number); + le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number); + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +static PHP_MSHUTDOWN_FUNCTION(zip) +{ +#ifdef PHP_ZIP_USE_OO + zend_hash_destroy(&zip_prop_handlers); + php_unregister_url_stream_wrapper("zip" TSRMLS_CC); +#endif + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +static PHP_MINFO_FUNCTION(zip) +{ + php_info_print_table_start(); + + php_info_print_table_row(2, "Zip", "enabled"); + php_info_print_table_row(2, "Extension Version","$Id: 727cc853ca1ae15d995c3520c5719784ddc1e292 $"); + php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING); + php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION); + + php_info_print_table_end(); +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h new file mode 100644 index 0000000..7dd9ff0 --- /dev/null +++ b/ext/zip/php_zip.h @@ -0,0 +1,99 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Pierre-Alain Joye <pajoye@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_ZIP_H +#define PHP_ZIP_H + +extern zend_module_entry zip_module_entry; +#define phpext_zip_ptr &zip_module_entry + +#ifdef ZTS +#include "TSRM.h" +#endif + +#include "lib/zip.h" + +#define PHP_ZIP_VERSION_STRING "1.11.0" + +#if ((PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION >= 6) +# define PHP_ZIP_USE_OO 1 +#endif + +#ifndef Z_SET_REFCOUNT_P +# if PHP_MAJOR_VERSION < 6 && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) +# define Z_SET_REFCOUNT_P(pz, rc) pz->refcount = rc +# define Z_UNSET_ISREF_P(pz) pz->is_ref = 0 +# endif +#endif + +/* {{{ ZIP_OPENBASEDIR_CHECKPATH(filename) */ +#if PHP_API_VERSION < 20100412 +# define ZIP_OPENBASEDIR_CHECKPATH(filename) \ + (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC) +#else +#define ZIP_OPENBASEDIR_CHECKPATH(filename) \ + php_check_open_basedir(filename TSRMLS_CC) +#endif +/* }}} */ + +typedef struct _ze_zip_rsrc { + struct zip *za; + int index_current; + int num_files; +} zip_rsrc; + +typedef zip_rsrc * zip_rsrc_ptr; + +typedef struct _ze_zip_read_rsrc { + struct zip_file *zf; + struct zip_stat sb; +} zip_read_rsrc; + +#ifdef PHP_ZIP_USE_OO +#define ZIPARCHIVE_ME(name, arg_info, flags) ZEND_FENTRY(name, c_ziparchive_ ##name, arg_info, flags) +#define ZIPARCHIVE_METHOD(name) ZEND_NAMED_FUNCTION(c_ziparchive_##name) + +/* Extends zend object */ +typedef struct _ze_zip_object { + zend_object zo; + struct zip *za; + int buffers_cnt; + char **buffers; + HashTable *prop_handler; + char *filename; + int filename_len; +} ze_zip_object; + +php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_DC TSRMLS_DC); + +extern php_stream_wrapper php_stream_zip_wrapper; +#endif + +#endif /* PHP_ZIP_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/zip/tests/001.phpt b/ext/zip/tests/001.phpt new file mode 100644 index 0000000..37dccc0 --- /dev/null +++ b/ext/zip/tests/001.phpt @@ -0,0 +1,12 @@ +--TEST-- +Check for zip presence +--SKIPIF-- +<?php if (!extension_loaded("zip")) print "skip"; ?> +--POST-- +--GET-- +--FILE-- +<?php +echo "zip extension is available"; +?> +--EXPECT-- +zip extension is available diff --git a/ext/zip/tests/binarynull.zip b/ext/zip/tests/binarynull.zip Binary files differnew file mode 100644 index 0000000..9da004e --- /dev/null +++ b/ext/zip/tests/binarynull.zip diff --git a/ext/zip/tests/bug11216.phpt b/ext/zip/tests/bug11216.phpt new file mode 100644 index 0000000..7601e6a --- /dev/null +++ b/ext/zip/tests/bug11216.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #11216 (::addEmptyDir() crashes when the directory already exists) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); + ?> +--FILE-- +<?php +$archive = new ZipArchive(); +$archive->open('__test.zip', ZIPARCHIVE::CREATE); +var_dump($archive->addEmptyDir('test')); +print_r($archive); +var_dump($archive->addEmptyDir('test')); +$archive->close(); +unlink('__test.zip'); +?> +--EXPECTF-- +bool(true) +ZipArchive Object +( + [status] => 0 + [statusSys] => 0 + [numFiles] => 1 + [filename] => %s + [comment] => +) +bool(false) diff --git a/ext/zip/tests/bug14962.phpt b/ext/zip/tests/bug14962.phpt new file mode 100644 index 0000000..0006fd4 --- /dev/null +++ b/ext/zip/tests/bug14962.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #14962 (::extractTo second argument is not really optional) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +$dir = dirname(__FILE__); +$file = '__tmp14962.txt'; +$fullpath = $dir . '/' . $file; +$za = new ZipArchive; +$za->open($dir . '/__14962.zip', ZIPARCHIVE::CREATE); +$za->addFromString($file, '1234'); +$za->close(); + +if (!is_file($dir . "/__14962.zip")) { + die('failed to create the archive'); +} +$za = new ZipArchive; +$za->open($dir . '/__14962.zip'); +$za->extractTo($dir, NULL); +$za->close(); + +if (is_file($fullpath)) { + unlink($fullpath); + echo "Ok"; +} +unlink($dir . '/' . '__14962.zip'); +?> +--EXPECT-- +Ok diff --git a/ext/zip/tests/bug38943.phpt b/ext/zip/tests/bug38943.phpt new file mode 100644 index 0000000..c5e2284 --- /dev/null +++ b/ext/zip/tests/bug38943.phpt @@ -0,0 +1,50 @@ +--TEST-- +#38943, properties in extended class cannot be set (5.3+) +--SKIPIF-- +<?php +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +class myZip extends ZipArchive { + private $test = 0; + public $testp = 1; + private $testarray = array(); + + public function __construct() { + $this->testarray[] = 1; + var_dump($this->testarray); + } +} + +$z = new myZip; +$z->testp = "foobar"; +var_dump($z); + +?> +--EXPECTF-- +array(1) { + [0]=> + int(1) +} +object(myZip)#1 (%d) { + ["test":"myZip":private]=> + int(0) + ["testp"]=> + string(6) "foobar" + ["testarray":"myZip":private]=> + array(1) { + [0]=> + int(1) + } + ["status"]=> + int(0) + ["statusSys"]=> + int(0) + ["numFiles"]=> + int(0) + ["filename"]=> + string(0) "" + ["comment"]=> + string(0) "" +} diff --git a/ext/zip/tests/bug38944.phpt b/ext/zip/tests/bug38944.phpt new file mode 100644 index 0000000..7cff60c --- /dev/null +++ b/ext/zip/tests/bug38944.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #38944 (newly created ZipArchive segfaults when accessing comment property) +--SKIPIF-- +<?php if (!extension_loaded("zip")) print "skip"; ?> +--FILE-- +<?php + +$arc_name = dirname(__FILE__)."/bug38944.zip"; +$foo = new ZipArchive; +$foo->open($arc_name, ZIPARCHIVE::CREATE);; + +var_dump($foo->status); +var_dump($foo->statusSys); +var_dump($foo->numFiles); +var_dump($foo->filename); +var_dump($foo->comment); + +var_dump($foo); + +echo "Done\n"; +?> +--EXPECTF-- +int(0) +int(0) +int(0) +string(%d) "%s" +string(0) "" +object(ZipArchive)#%d (5) { + ["status"]=> + int(0) + ["statusSys"]=> + int(0) + ["numFiles"]=> + int(0) + ["filename"]=> + string(%d) "%s" + ["comment"]=> + string(0) "" +} +Done diff --git a/ext/zip/tests/bug40228.phpt b/ext/zip/tests/bug40228.phpt new file mode 100644 index 0000000..fec2963 --- /dev/null +++ b/ext/zip/tests/bug40228.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #40228 (extractTo does not create recursive empty path) +--SKIPIF-- +<?php if (!extension_loaded("zip")) print "skip"; ?> +--FILE-- +<?php +$dest = dirname(__FILE__); +$arc_name = $dest . "/bug40228.zip"; +$zip = new ZipArchive; +$zip->open($arc_name, ZIPARCHIVE::CREATE);; +$zip->extractTo($dest); +if (is_dir($dest . '/test/empty')) { + echo "Ok\n"; + rmdir($dest . '/test/empty'); + rmdir($dest . '/test'); +} else { + echo "Failed.\n"; +} +echo "Done\n"; +?> +--EXPECT-- +Ok +Done diff --git a/ext/zip/tests/bug40228.zip b/ext/zip/tests/bug40228.zip Binary files differnew file mode 100644 index 0000000..bbcd951 --- /dev/null +++ b/ext/zip/tests/bug40228.zip diff --git a/ext/zip/tests/bug47667.phpt b/ext/zip/tests/bug47667.phpt new file mode 100644 index 0000000..9c17de6 --- /dev/null +++ b/ext/zip/tests/bug47667.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug #47667 (ZipArchive::OVERWRITE seems to have no effect) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$thisdir = dirname(__FILE__); +$filename = $thisdir . "/bug47667.zip"; + +$zip = new ZipArchive(); +if ($zip->open($filename, ZipArchive::CREATE) !== true) { + exit("Unable to open the zip file"); +} else { + $zip->addFromString('foo.txt', 'foo bar foobar'); + $zip->close(); +} + +for ($i = 0; $i < 10; $i++) { + $zip = new ZipArchive(); + if ($zip->open($filename, ZipArchive::OVERWRITE) !== true) { + exit("Unable to open the zip file"); + } + $zip->addFromString("foo_{$i}.txt", 'foo bar foobar'); + $zip->close(); +} + +$zip = new ZipArchive(); +if ($zip->open($filename, ZipArchive::CREATE) !== true) { + exit("Unable to open the zip file"); +} + +echo "files: " , $zip->numFiles; +$zip->close(); + +unlink($filename); + +--EXPECT-- +files: 1 diff --git a/ext/zip/tests/bug49072.phpt b/ext/zip/tests/bug49072.phpt new file mode 100644 index 0000000..04bd06e --- /dev/null +++ b/ext/zip/tests/bug49072.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #49072 (feof never returns true for damaged file in zip) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$f = dirname(__FILE__) . '/bug49072.zip'; +$o = new ZipArchive(); +if (! $o->open($f, ZipArchive::CHECKCONS)) { + exit ('error can\'t open'); +} +$r = $o->getStream('file1'); // this file has a wrong crc +if (!$r)die('failed to open a stream for file1'); +$s = ''; +while (! feof($r)) { + $s .= fread($r,1024); +} +?> +--EXPECTF-- + +Warning: fread(): Zip stream error: CRC error in %s on line %d diff --git a/ext/zip/tests/bug49072.zip b/ext/zip/tests/bug49072.zip Binary files differnew file mode 100644 index 0000000..16bbcd0 --- /dev/null +++ b/ext/zip/tests/bug49072.zip diff --git a/ext/zip/tests/bug51353.phpt b/ext/zip/tests/bug51353.phpt new file mode 100644 index 0000000..560945f --- /dev/null +++ b/ext/zip/tests/bug51353.phpt @@ -0,0 +1,54 @@ +--TEST-- +Bug #51353 ZIP64 problem, archive with 100000 items +--SKIPIF-- +<?php +if(!extension_loaded('zip')) die('skip'); +die('skip the test might get very long, activate it manually'); +--FILE-- +<?php +/* This test might get very long depending on the mashine it's running on. Therefore +adding an explicit skip, remove it to run this test. */ +set_time_limit(0); + +$base_path = dirname(__FILE__); + +/* Either we ship a file with 100000 entries which would be >12M big, + or create it dynamically. */ +$zip = new ZipArchive; +$r = $zip->open("$base_path/51353.zip", ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); +if ($r) { + for ($i = 0; $i < 100000; $i++) { + $zip->addFromString("$i.txt", '1'); + } + $zip->close(); +} else { + die("failed"); +} + +$zip = new ZipArchive; +$r = $zip->open("$base_path/51353.zip"); +if ($r) { + $zip->extractTo("$base_path/51353_unpack"); + $zip->close(); + + $a = glob("$base_path/51353_unpack/*.txt"); + echo count($a) . "\n"; +} else { + die("failed"); +} + +echo "OK"; +--CLEAN-- +<?php +$base_path = dirname(__FILE__); + +unlink("$base_path/51353.zip"); + +$a = glob("$base_path/51353_unpack/*.txt"); +foreach($a as $f) { + unlink($f); +} +rmdir("$base_path/51353_unpack"); +--EXPECT-- +100000 +OK diff --git a/ext/zip/tests/bug53579.phpt b/ext/zip/tests/bug53579.phpt new file mode 100644 index 0000000..1d53330 --- /dev/null +++ b/ext/zip/tests/bug53579.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #53579 (stream_get_contents() segfaults on ziparchive streams) +--SKIPIF-- +<?php +/* $Id: oo_stream.phpt 260091 2008-05-21 09:27:41Z pajoye $ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . 'test_with_comment.zip'; +include $dirname . 'utils.inc'; +$zip = new ZipArchive; +if (!$zip->open($file)) { + exit('failed'); +} +$fp = $zip->getStream('foo'); + +var_dump($fp); +if(!$fp) exit("\n"); +$contents = stream_get_contents($fp); + +fclose($fp); +$zip->close(); +var_dump($contents); + + +$fp = fopen('zip://' . dirname(__FILE__) . '/test_with_comment.zip#foo', 'rb'); +if (!$fp) { + exit("cannot open\n"); +} +$contents = stream_get_contents($fp); +var_dump($contents); +fclose($fp); + +?> +--EXPECTF-- +resource(%d) of type (stream) +string(5) "foo + +" +string(5) "foo + +" diff --git a/ext/zip/tests/bug53603.phpt b/ext/zip/tests/bug53603.phpt new file mode 100644 index 0000000..f8ff1b4 --- /dev/null +++ b/ext/zip/tests/bug53603.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #53603 (ZipArchive should quiet stat errors) +--SKIPIF-- +<?php +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +class TestStream { + function url_stat($path, $flags) { + if (!($flags & STREAM_URL_STAT_QUIET)) + trigger_error("not quiet"); + return array(); + } +} + +stream_wrapper_register("teststream", "TestStream"); + +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . 'test_with_comment.zip'; +$zip = new ZipArchive; +if ($zip->open($file) !== TRUE) { + echo "open failed.\n"; + exit('failed'); +} + +$a = $zip->extractTo('teststream://test'); +var_dump($a); + +--EXPECTF-- + +Warning: ZipArchive::extractTo(teststream://test/foo): failed to open stream: "TestStream::stream_open" call failed in %s on line %d +bool(false) + diff --git a/ext/zip/tests/bug53854.phpt b/ext/zip/tests/bug53854.phpt new file mode 100644 index 0000000..cd8ae7e --- /dev/null +++ b/ext/zip/tests/bug53854.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #53854 (Missing constants for compression type) +--SKIPIF-- +<?php +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +var_dump(ZipArchive::CM_DEFAULT); +var_dump(ZipArchive::CM_STORE); +var_dump(ZipArchive::CM_SHRINK); +var_dump(ZipArchive::CM_REDUCE_1); +var_dump(ZipArchive::CM_REDUCE_2); +var_dump(ZipArchive::CM_REDUCE_3); +var_dump(ZipArchive::CM_REDUCE_4); +var_dump(ZipArchive::CM_IMPLODE); +var_dump(ZipArchive::CM_DEFLATE); +var_dump(ZipArchive::CM_DEFLATE64); +var_dump(ZipArchive::CM_PKWARE_IMPLODE); +var_dump(ZipArchive::CM_BZIP2); +var_dump(ZipArchive::CM_LZMA); +var_dump(ZipArchive::CM_TERSE); +var_dump(ZipArchive::CM_LZ77); +var_dump(ZipArchive::CM_WAVPACK); +var_dump(ZipArchive::CM_PPMD); +--EXPECT-- +int(-1) +int(0) +int(1) +int(2) +int(3) +int(4) +int(5) +int(6) +int(8) +int(9) +int(10) +int(12) +int(14) +int(18) +int(19) +int(97) +int(98) diff --git a/ext/zip/tests/bug53885.phpt b/ext/zip/tests/bug53885.phpt new file mode 100644 index 0000000..1b3fcb9 --- /dev/null +++ b/ext/zip/tests/bug53885.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #53885 (ZipArchive segfault with FL_UNCHANGED on empty archive) +--SKIPIF-- +<?php +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$fname = dirname(__FILE__)."/test53885.zip"; +if(file_exists($fname)) unlink($fname); +touch($fname); +$nx=new ZipArchive(); +$nx->open($fname); +$nx->locateName("a",ZIPARCHIVE::FL_UNCHANGED); +$nx->statName("a",ZIPARCHIVE::FL_UNCHANGED); +?> +==DONE== +--CLEAN-- +<?php +$fname = dirname(__FILE__)."/test53885.zip"; +unlink($fname); +?> +--EXPECTF-- +==DONE== diff --git a/ext/zip/tests/bug7214.phpt b/ext/zip/tests/bug7214.phpt new file mode 100644 index 0000000..f791b79 --- /dev/null +++ b/ext/zip/tests/bug7214.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #7214 (zip_entry_read() binary safe) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); + ?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/binarynull.zip"); +if (!is_resource($zip)) die("Failure"); +$entries = 0; +$entry = zip_read($zip); +$contents = zip_entry_read($entry, zip_entry_filesize($entry)); +if (strlen($contents) == zip_entry_filesize($entry)) { + echo "Ok"; +} else { + echo "failed"; +} + +?> +--EXPECT-- +Ok diff --git a/ext/zip/tests/bug7658.odt b/ext/zip/tests/bug7658.odt Binary files differnew file mode 100644 index 0000000..527e09f --- /dev/null +++ b/ext/zip/tests/bug7658.odt diff --git a/ext/zip/tests/bug7658.phpt b/ext/zip/tests/bug7658.phpt new file mode 100644 index 0000000..56fd00f --- /dev/null +++ b/ext/zip/tests/bug7658.phpt @@ -0,0 +1,55 @@ +--TEST-- +Bug #7658 (modify archive with general bit flag 3 set) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$expect = array( + "mimetype", + "Configurations2/statusbar/", + "Configurations2/accelerator/current.xml", + "Configurations2/floater/", + "Configurations2/popupmenu/", + "Configurations2/progressbar/", + "Configurations2/menubar/", + "Configurations2/toolbar/", + "Configurations2/images/Bitmaps/", + "content.xml", + "styles.xml", + "meta.xml", + "Thumbnails/thumbnail.png", + "settings.xml", + "META-INF/manifest.xml", +); +$dirname = dirname(__FILE__) . '/'; +include $dirname . 'utils.inc'; +$file = $dirname . '__tmp_bug7658.odt'; +$zip = new ZipArchive(); +copy($dirname . 'bug7658.odt', $file); +if(!$zip->open($file)) { + echo 'failed'; +} + + +$zip->deleteName('content.xml'); +$zip->addFile($dirname . "bug7658.xml","content.xml"); +$zip->close(); +echo "\n"; +$zip->open($file); + +for($i=0; $i < $zip->numFiles; $i++) { + $sb = $zip->statIndex($i); + $found[] = $sb['name']; +} +$ar = array_diff($found, $expect); + +var_dump($ar); +unset($zip); +unlink($file); +?> +--EXPECTF-- +array(0) { +} diff --git a/ext/zip/tests/bug7658.xml b/ext/zip/tests/bug7658.xml new file mode 100644 index 0000000..98076f1 --- /dev/null +++ b/ext/zip/tests/bug7658.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.0"><office:scripts/><office:font-face-decls><style:font-face style:name="Tahoma1" svg:font-family="Tahoma"/><style:font-face style:name="Arial Unicode MS" svg:font-family="'Arial Unicode MS'" style:font-pitch="variable"/><style:font-face style:name="Estrangelo Edessa" svg:font-family="'Estrangelo Edessa'" style:font-pitch="variable"/><style:font-face style:name="MS Mincho" svg:font-family="'MS Mincho'" style:font-pitch="variable"/><style:font-face style:name="Miriam CLM" svg:font-family="'Miriam CLM'" style:font-pitch="variable"/><style:font-face style:name="Tahoma" svg:font-family="Tahoma" style:font-pitch="variable"/><style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/><style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/></office:font-face-decls><office:automatic-styles><style:style style:name="Tabella1" style:family="table"><style:table-properties style:width="6.6924in" table:align="margins"/></style:style><style:style style:name="Tabella1.A" style:family="table-column"><style:table-column-properties style:column-width="4.8556in" style:rel-column-width="47546*"/></style:style><style:style style:name="Tabella1.B" style:family="table-column"><style:table-column-properties style:column-width="1.8368in" style:rel-column-width="17989*"/></style:style><style:style style:name="Tabella1.A1" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border-left="0.0007in solid #000000" fo:border-right="none" fo:border-top="0.0007in solid #000000" fo:border-bottom="0.0007in solid #000000"/></style:style><style:style style:name="Tabella1.B1" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border="0.0007in solid #000000"/></style:style><style:style style:name="Tabella1.A2" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border-left="0.0007in solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.0007in solid #000000"/></style:style><style:style style:name="Tabella1.B2" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border-left="0.0007in solid #000000" fo:border-right="0.0007in solid #000000" fo:border-top="none" fo:border-bottom="0.0007in solid #000000"/></style:style><style:style style:name="Tabella2" style:family="table"><style:table-properties style:width="6.6924in" table:align="margins"/></style:style><style:style style:name="Tabella2.A" style:family="table-column"><style:table-column-properties style:column-width="2.584in" style:rel-column-width="25303*"/></style:style><style:style style:name="Tabella2.C" style:family="table-column"><style:table-column-properties style:column-width="1.5243in" style:rel-column-width="14929*"/></style:style><style:style style:name="Tabella2.A1" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border-left="0.0007in solid #000000" fo:border-right="none" fo:border-top="0.0007in solid #000000" fo:border-bottom="0.0007in solid #000000"/></style:style><style:style style:name="Tabella2.C1" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border="0.0007in solid #000000"/></style:style><style:style style:name="Tabella2.A2" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border-left="0.0007in solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.0007in solid #000000"/></style:style><style:style style:name="Tabella2.C2" style:family="table-cell"><style:table-cell-properties fo:padding="0.0382in" fo:border-left="0.0007in solid #000000" fo:border-right="0.0007in solid #000000" fo:border-top="none" fo:border-bottom="0.0007in solid #000000"/></style:style><style:style style:name="P1" style:family="paragraph" style:parent-style-name="Table_20_Heading"><style:text-properties style:font-name="Estrangelo Edessa" fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-style-complex="italic" style:font-weight-complex="bold"/></style:style><style:style style:name="P2" style:family="paragraph" style:parent-style-name="Table_20_Heading"><style:paragraph-properties fo:padding="0.0193in" fo:border="0.0008in solid #000000" style:shadow="none"/><style:text-properties style:font-name="Estrangelo Edessa" fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-style-complex="italic" style:font-weight-complex="bold"/></style:style><style:style style:name="P3" style:family="paragraph" style:parent-style-name="Table_20_Contents"><style:text-properties fo:color="#ff0000" style:font-name="Miriam CLM" fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-style-complex="italic" style:font-weight-complex="bold"/></style:style></office:automatic-styles><office:body><office:text><office:forms form:automatic-focus="false" form:apply-design-mode="false"/><text:sequence-decls><text:sequence-decl text:display-outline-level="0" text:name="Illustration"/><text:sequence-decl text:display-outline-level="0" text:name="Table"/><text:sequence-decl text:display-outline-level="0" text:name="Text"/><text:sequence-decl text:display-outline-level="0" text:name="Drawing"/></text:sequence-decls><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard">Other text Silvio Berlusconi, le ricordo che ha in prestito i seguenti libri</text:p><text:p text:style-name="Standard"/><table:table table:name="Tabella1" table:style-name="Tabella1"><table:table-column table:style-name="Tabella1.A"/><table:table-column table:style-name="Tabella1.B"/><table:table-header-rows><table:table-row><table:table-cell table:style-name="Tabella1.A1" office:value-type="string"><text:p text:style-name="P1">Titolo</text:p></table:table-cell><table:table-cell table:style-name="Tabella1.B1" office:value-type="string"><text:p text:style-name="P1">Inventario</text:p></table:table-cell></table:table-row></table:table-header-rows><table:table-row><table:table-cell table:style-name="Tabella1.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">Codice Da Vinci</text:p></table:table-cell><table:table-cell table:style-name="Tabella1.B2" office:value-type="string"><text:p text:style-name="Table_20_Contents">112345678</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella1.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">Lo Zen e il tiro con l'arco</text:p></table:table-cell><table:table-cell table:style-name="Tabella1.B2" office:value-type="string"><text:p text:style-name="Table_20_Contents">1020304</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella1.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">Lo Zen e l'arte della manutenzione della motocicletta</text:p></table:table-cell><table:table-cell table:style-name="Tabella1.B2" office:value-type="string"><text:p text:style-name="Table_20_Contents">1020305</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella1.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">101 Storie Zen</text:p></table:table-cell><table:table-cell table:style-name="Tabella1.B2" office:value-type="string"><text:p text:style-name="Table_20_Contents">1020306</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella1.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">Antani di Blinda come fosse di Cappotto</text:p></table:table-cell><table:table-cell table:style-name="Tabella1.B2" office:value-type="string"><text:p text:style-name="Table_20_Contents">4112345</text:p></table:table-cell></table:table-row></table:table><text:p text:style-name="Standard"/><text:p text:style-name="Standard">peraltro, sottolineiamo la perentorietà della restituzione anche dei vieppiù interessanti testi:</text:p><text:p text:style-name="Standard"/><table:table table:name="Tabella2" table:style-name="Tabella2"><table:table-column table:style-name="Tabella2.A" table:number-columns-repeated="2"/><table:table-column table:style-name="Tabella2.C"/><table:table-header-rows><table:table-row><table:table-cell table:style-name="Tabella2.A1" office:value-type="string"><text:p text:style-name="P2">Titolo</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.A1" office:value-type="string"><text:p text:style-name="P2">Autore</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.C1" office:value-type="string"><text:p text:style-name="P2">Inventario</text:p></table:table-cell></table:table-row></table:table-header-rows><table:table-row><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">Angeli e Demoni</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="P3">Dan Brown</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.C2" office:value-type="string"><text:p text:style-name="Table_20_Contents">12131415</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">La versione di Barney</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="P3">Mordecai Richler</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.C2" office:value-type="string"><text:p text:style-name="Table_20_Contents">2010322</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">Manuale PHP</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="P3">Varii</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.C2" office:value-type="string"><text:p text:style-name="Table_20_Contents">32413543</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">La prematurata supercazzola negli anni a venire</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="P3">Ugo Tognazzi</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.C2" office:value-type="string"><text:p text:style-name="Table_20_Contents">31213243</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="Table_20_Contents">La sbiriguda in vicesindaco</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.A2" office:value-type="string"><text:p text:style-name="P3">Ugo Tognazzi</text:p></table:table-cell><table:table-cell table:style-name="Tabella2.C2" office:value-type="string"><text:p text:style-name="Table_20_Contents">1324354654</text:p></table:table-cell></table:table-row></table:table><text:p text:style-name="Standard"/><text:p text:style-name="Standard"/><text:p text:style-name="Standard">Gentili saluti, la sua biblioteca</text:p></office:text></office:body></office:document-content> diff --git a/ext/zip/tests/bug8009.phpt b/ext/zip/tests/bug8009.phpt new file mode 100644 index 0000000..5dd363d --- /dev/null +++ b/ext/zip/tests/bug8009.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #8009 (cannot add again same entry to an archive) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$thisdir = dirname(__FILE__); +$src = $thisdir . "/bug8009.zip"; +$filename = $thisdir . "/tmp8009.zip"; +copy($src, $filename); + +$zip = new ZipArchive(); + +if (!$zip->open($filename)) { + exit("cannot open $filename\n"); +} +$zip->addFromString("2.txt", "=)"); +$zip->close(); +unlink($filename); +echo "status: " . $zip->status . "\n"; +echo "\n"; + +--EXPECT-- +status: 0 diff --git a/ext/zip/tests/bug8009.zip b/ext/zip/tests/bug8009.zip Binary files differnew file mode 100644 index 0000000..45bedcb --- /dev/null +++ b/ext/zip/tests/bug8009.zip diff --git a/ext/zip/tests/bug8700.phpt b/ext/zip/tests/bug8700.phpt new file mode 100644 index 0000000..c394cf0 --- /dev/null +++ b/ext/zip/tests/bug8700.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #8700 (getFromIndex(0) fails) +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$thisdir = dirname(__FILE__); +$filename = $thisdir . "/bug8009.zip"; + +$zip = new ZipArchive(); + +if ($zip->open($filename) === FALSE) { + exit("cannot open $filename\n"); +} +$contents_from_idx = $zip->getFromIndex(0); +$contents_from_name = $zip->getFromName('1.txt'); +if ($contents_from_idx != $contents_from_name) { + echo "failed:"; + var_dump($content_from_idx, $content_from_name); +} + +$zip->close(); +echo "status: " . $zip->status . "\n"; +echo "\n"; + +--EXPECT-- +status: 0 diff --git a/ext/zip/tests/oo_addemptydir.phpt b/ext/zip/tests/oo_addemptydir.phpt new file mode 100644 index 0000000..cb57b5b --- /dev/null +++ b/ext/zip/tests/oo_addemptydir.phpt @@ -0,0 +1,36 @@ +--TEST-- +ziparchive::addEmptyDir +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +$dirname = dirname(__FILE__) . '/'; +include $dirname . 'utils.inc'; +$file = $dirname . '__tmp_oo_addfile.zip'; + +copy($dirname . 'test.zip', $file); + +$zip = new ZipArchive; +if (!$zip->open($file)) { + exit('failed'); +} + +$zip->addEmptyDir('emptydir'); +if ($zip->status == ZIPARCHIVE::ER_OK) { + dump_entries_name($zip); + $zip->close(); +} else { + echo "failed\n"; +} +@unlink($file); +?> +--EXPECTF-- +0 bar +1 foobar/ +2 foobar/baz +3 entry1.txt +4 emptydir/ diff --git a/ext/zip/tests/oo_addfile.phpt b/ext/zip/tests/oo_addfile.phpt new file mode 100644 index 0000000..ab79780 --- /dev/null +++ b/ext/zip/tests/oo_addfile.phpt @@ -0,0 +1,37 @@ +--TEST-- +ziparchive::addFile() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +$dirname = dirname(__FILE__) . '/'; +include $dirname . 'utils.inc'; +$file = $dirname . '__tmp_oo_addfile.zip'; + +copy($dirname . 'test.zip', $file); + +$zip = new ZipArchive; +if (!$zip->open($file)) { + exit('failed'); +} +if (!$zip->addFile($dirname . 'utils.inc', 'test.php')) { + echo "failed\n"; +} +if ($zip->status == ZIPARCHIVE::ER_OK) { + dump_entries_name($zip); + $zip->close(); +} else { + echo "failed\n"; +} +@unlink($file); +?> +--EXPECTF-- +0 bar +1 foobar/ +2 foobar/baz +3 entry1.txt +4 test.php diff --git a/ext/zip/tests/oo_close.phpt b/ext/zip/tests/oo_close.phpt new file mode 100644 index 0000000..ea67dcd --- /dev/null +++ b/ext/zip/tests/oo_close.phpt @@ -0,0 +1,25 @@ +--TEST-- +zip::close() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +$dirname = dirname(__FILE__) . '/'; +$zip = new ZipArchive; +if (!$zip->open($dirname . 'test.zip')) { + exit('failed'); +} + +if ($zip->status == ZIPARCHIVE::ER_OK) { + $zip->close(); + echo "ok\n"; +} else { + echo "failed\n"; +} +?> +--EXPECTF-- +ok diff --git a/ext/zip/tests/oo_delete.phpt b/ext/zip/tests/oo_delete.phpt new file mode 100644 index 0000000..9eac821 --- /dev/null +++ b/ext/zip/tests/oo_delete.phpt @@ -0,0 +1,81 @@ +--TEST-- +Delete entries +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . '__tmp_oo_delete.zip'; +if (file_exists($file)) { + unlink($file); +} + +$zip = new ZipArchive; +if (!$zip->open($file, ZIPARCHIVE::CREATE)) { + exit('failed'); +} +$zip->addFromString('entry1.txt', 'entry #1'); +$zip->addFromString('entry2.txt', 'entry #2'); +$zip->addFromString('dir/entry2.txt', 'entry #2'); + +if ($zip->status == ZIPARCHIVE::ER_OK) { + $zip->close(); + echo "ok\n"; +} else { + var_dump($zip); + echo "failed\n"; +} + +if (!$zip->open($file, ZIPARCHIVE::CREATE)) { + exit('failed'); +} + +if ($zip->deleteIndex(0)) { + echo "ok\n"; +} + +if ($zip->deleteName('entry2.txt')) { + echo "ok\n"; +} else { + echo "failed 3\n"; +} + +if ($zip->deleteName('dir/entry2.txt')) { + echo "ok\n"; +} else { + echo "failed 3\n"; +} + +if (!$zip->deleteIndex(123)) { + echo "ok\n"; +} else { + print_r($zip); + echo "failed\n"; +} + + +$sb = $zip->statIndex(0); +var_dump($sb); +$sb = $zip->statIndex(1); +var_dump($sb); +$sb = $zip->statIndex(2); +var_dump($sb); +$zip->close(); +unset($zip); + +if (file_exists($file)) { + unlink($file); +} +?> +--EXPECTF-- +ok +ok +ok +ok +ok +bool(false) +bool(false) +bool(false) diff --git a/ext/zip/tests/oo_ext_zip.phpt b/ext/zip/tests/oo_ext_zip.phpt new file mode 100644 index 0000000..739a671 --- /dev/null +++ b/ext/zip/tests/oo_ext_zip.phpt @@ -0,0 +1,27 @@ +--TEST-- +Extending Zip class and array property +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +class myZip extends ZipArchive { + private $test = 0; + public $testp = 1; + private $testarray = array(); + + public function __construct() { + $this->testarray[] = 1; + var_dump($this->testarray); + } +} + +$z = new myZip; +?> +--EXPECTF-- +array(1) { + [0]=> + int(1) +} diff --git a/ext/zip/tests/oo_extract.phpt b/ext/zip/tests/oo_extract.phpt new file mode 100644 index 0000000..7ca39ee --- /dev/null +++ b/ext/zip/tests/oo_extract.phpt @@ -0,0 +1,95 @@ +--TEST-- +extractTo +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . 'test_with_comment.zip'; +include $dirname . 'utils.inc'; +$zip = new ZipArchive; +if ($zip->open($file) !== TRUE) { + echo "open failed.\n"; + exit('failed'); +} + +$zip->extractTo($dirname . '__oo_extract_tmp'); +if (!is_dir($dirname . '__oo_extract_tmp')) { + echo "failed. mkdir\n"; +} + +if (!is_dir($dirname .'__oo_extract_tmp/foobar')) { + echo "failed. mkdir foobar\n"; +} + +if (!file_exists($dirname . '__oo_extract_tmp/foobar/baz')) { + echo "failed. extract foobar/baz\n"; +} else { + echo file_get_contents($dirname . '__oo_extract_tmp/foobar/baz') . "\n"; +} + +if (!file_exists($dirname . '__oo_extract_tmp/bar')) { + echo "failed. bar file\n"; +} else { + echo file_get_contents($dirname . '__oo_extract_tmp/bar') . "\n"; +} + +if (!file_exists($dirname . '__oo_extract_tmp/foo')) { + echo "failed. foo file\n"; +} else { + echo file_get_contents($dirname . '__oo_extract_tmp/foo') . "\n"; +} + + +/* extract one file */ +$zip->extractTo($dirname . '__oo_extract_tmp', 'bar'); +if (!file_exists($dirname . '__oo_extract_tmp/bar')) { + echo "failed. extract bar file\n"; +} else { + echo file_get_contents($dirname . '__oo_extract_tmp/bar') . "\n"; +} + +/* extract two files */ +$zip->extractTo($dirname . '__oo_extract_tmp', array('bar','foo')); +if (!file_exists($dirname . '__oo_extract_tmp/bar')) { + echo "failed. extract bar file\n"; +} else { + echo file_get_contents($dirname . '__oo_extract_tmp/bar') . "\n"; +} +if (!file_exists($dirname . '__oo_extract_tmp/foo')) { + echo "failed. extract foo file\n"; +} else { + echo file_get_contents($dirname . '__oo_extract_tmp/foo') . "\n"; +} + +rmdir_rf($dirname . '__oo_extract_tmp'); +?> +--EXPECTF-- +blabla laber rababer sülz + +bar + +foo + + +bar + +bar + +foo +--UEXPECTF-- +blabla laber rababer sülz + +bar + +foo + + +bar + +bar + +foo diff --git a/ext/zip/tests/oo_getcomment.phpt b/ext/zip/tests/oo_getcomment.phpt new file mode 100644 index 0000000..d05385c --- /dev/null +++ b/ext/zip/tests/oo_getcomment.phpt @@ -0,0 +1,36 @@ +--TEST-- +getComment +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . 'test_with_comment.zip'; +include $dirname . 'utils.inc'; +$zip = new ZipArchive; +if (!$zip->open($file)) { + exit('failed'); +} +echo $zip->getArchiveComment() . "\n"; + +$idx = $zip->locateName('foo'); +echo $zip->getCommentName('foo') . "\n"; +echo $zip->getCommentIndex($idx); + +echo $zip->getCommentName('') . "\n"; +echo $zip->getCommentName() . "\n"; + +$zip->close(); + +?> +--EXPECTF-- +Zip archive comment +foo comment +foo comment +Notice: ZipArchive::getCommentName(): Empty string as entry name in %s on line %d + + +Warning: ZipArchive::getCommentName() expects at least 1 parameter, 0 given in %s on line %d diff --git a/ext/zip/tests/oo_getnameindex.phpt b/ext/zip/tests/oo_getnameindex.phpt new file mode 100644 index 0000000..cd4c9db --- /dev/null +++ b/ext/zip/tests/oo_getnameindex.phpt @@ -0,0 +1,47 @@ +--TEST-- +getNameIndex +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +include $dirname . 'utils.inc'; +$file = $dirname . '__tmp_oo_rename.zip'; + +@unlink($file); + +$zip = new ZipArchive; +if (!$zip->open($file, ZIPARCHIVE::CREATE)) { + exit('failed'); +} + +$zip->addFromString('entry1.txt', 'entry #1'); +$zip->addFromString('entry2.txt', 'entry #2'); +$zip->addFromString('dir/entry2d.txt', 'entry #2'); + +if (!$zip->status == ZIPARCHIVE::ER_OK) { + echo "failed to write zip\n"; +} +$zip->close(); + +if (!$zip->open($file)) { + exit('failed'); +} + + +var_dump($zip->getNameIndex(0)); +var_dump($zip->getNameIndex(1)); +var_dump($zip->getNameIndex(2)); +var_dump($zip->getNameIndex(3)); + +$zip->close(); + +?> +--EXPECTF-- +string(10) "entry1.txt" +string(10) "entry2.txt" +string(15) "dir/entry2d.txt" +bool(false) diff --git a/ext/zip/tests/oo_getstatusstring.phpt b/ext/zip/tests/oo_getstatusstring.phpt new file mode 100644 index 0000000..efd19e3 --- /dev/null +++ b/ext/zip/tests/oo_getstatusstring.phpt @@ -0,0 +1,28 @@ +--TEST-- +This test will test getStatusString method in ZipArchive +--CREDITS-- +Ole-Petter Wikene <olepw@redpill-linpro.com> +#PHPTestFest2009 Norway 2009-06-09 \o/ +--SKIPIF-- +<?php if (!extension_loaded("zip")) { echo "skip extension not available"; } ?> +--FILE-- +<?php + +$dirname = dirname(__FILE__) . '/'; +$arch = new ZipArchive; +$arch->open($dirname.'foo.zip',ZIPARCHIVE::CREATE); +var_dump($arch->getStatusString()); +//delete an index that does not exist - trigger error +$arch->deleteIndex(2); +var_dump($arch->getStatusString()); +$arch->close(); + +?> +--CLEAN-- +<?php +unlink($dirname.'foo.zip'); +?> +--EXPECT-- +string(8) "No error" +string(16) "Invalid argument" + diff --git a/ext/zip/tests/oo_namelocate.phpt b/ext/zip/tests/oo_namelocate.phpt new file mode 100644 index 0000000..bbe7ec5 --- /dev/null +++ b/ext/zip/tests/oo_namelocate.phpt @@ -0,0 +1,46 @@ +--TEST-- +Locate entries by name +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +include $dirname . 'utils.inc'; +$file = $dirname . '__tmp_oo_rename.zip'; + +@unlink($file); + +$zip = new ZipArchive; +if (!$zip->open($file, ZIPARCHIVE::CREATE)) { + exit('failed'); +} + +$zip->addFromString('entry1.txt', 'entry #1'); +$zip->addFromString('entry2.txt', 'entry #2'); +$zip->addFromString('dir/entry2d.txt', 'entry #2'); + +if (!$zip->status == ZIPARCHIVE::ER_OK) { + echo "failed to write zip\n"; +} +$zip->close(); + +if (!$zip->open($file)) { + exit('failed'); +} + + +var_dump($zip->locateName('entry1.txt')); +var_dump($zip->locateName('eNtry2.txt')); +var_dump($zip->locateName('eNtry2.txt', ZIPARCHIVE::FL_NOCASE)); +var_dump($zip->locateName('enTRy2d.txt', ZIPARCHIVE::FL_NOCASE|ZIPARCHIVE::FL_NODIR)); +$zip->close(); + +?> +--EXPECTF-- +int(0) +bool(false) +int(1) +int(2) diff --git a/ext/zip/tests/oo_open.phpt b/ext/zip/tests/oo_open.phpt new file mode 100644 index 0000000..0760db3 --- /dev/null +++ b/ext/zip/tests/oo_open.phpt @@ -0,0 +1,46 @@ +--TEST-- +zip::open() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +$dirname = dirname(__FILE__) . '/'; +$zip = new ZipArchive; +$r = $zip->open($dirname . 'nofile'); +if ($r !== TRUE) { + echo "ER_OPEN: ok\n"; +} else { + echo "ER_OPEN: FAILED\n"; +} + +$r = $zip->open($dirname . 'nofile', ZIPARCHIVE::CREATE); +if (!$r) { + echo "create: failed\n"; +} else { + echo "create: ok\n"; +} +@unlink($dirname . 'nofile'); + +$zip = new ZipArchive; +$zip->open(''); + +if (!$zip->open($dirname . 'test.zip')) { + exit("failed 1\n"); +} + +if ($zip->status == ZIPARCHIVE::ER_OK) { + echo "OK\n"; +} else { + echo "failed\n"; +} +?> +--EXPECTF-- +ER_OPEN: ok +create: ok + +Warning: ZipArchive::open(): Empty string as source in %s on line %d +OK diff --git a/ext/zip/tests/oo_properties.phpt b/ext/zip/tests/oo_properties.phpt new file mode 100644 index 0000000..886317b --- /dev/null +++ b/ext/zip/tests/oo_properties.phpt @@ -0,0 +1,60 @@ +--TEST-- +ziparchive::properties isset()/empty() checks +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php + +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . '__property_test.zip'; + +copy($dirname . 'test_with_comment.zip', $file); + +$zip = new ZipArchive; +if (!$zip->open($file)) { + exit('failed'); +} + +printf("zip->status (%d):\n\tempty(): %d\n\tisset(): %d\n", $zip->status, empty($zip->status), isset($zip->status)); +printf("zip->numFiles (%d):\n\tempty(): %d\n\tisset(): %d\n", $zip->numFiles, empty($zip->numFiles), isset($zip->numFiles)); +printf("zip->bogus (%d):\n\tempty(): %d\n\tisset(): %d\n", $zip->bogus, empty($zip->bogus), isset($zip->bogus)); + + +$zip->addEmptyDir('emptydir'); + +printf("zip->status (%d):\n\tempty(): %d\n\tisset(): %d\n", $zip->status, empty($zip->status), isset($zip->status)); +printf("zip->numFiles (%d):\n\tempty(): %d\n\tisset(): %d\n", $zip->numFiles, empty($zip->numFiles), isset($zip->numFiles)); +printf("zip->filename (%d):\n\tempty(): %d\n\tisset(): %d\n", strlen($zip->filename), empty($zip->filename), isset($zip->filename)); +printf("zip->comment (%d):\n\tempty(): %d\n\tisset(): %d\n", strlen($zip->comment), empty($zip->comment), isset($zip->comment)); + +unset($zip); //close the file before unlinking +@unlink($file); +?> +--EXPECTF-- +zip->status (0): + empty(): 1 + isset(): 1 +zip->numFiles (4): + empty(): 0 + isset(): 1 + +Notice: Undefined property: ZipArchive::$bogus in %s on line %d +zip->bogus (0): + empty(): 1 + isset(): 0 +zip->status (0): + empty(): 1 + isset(): 1 +zip->numFiles (5): + empty(): 0 + isset(): 1 +zip->filename (%d): + empty(): 0 + isset(): 1 +zip->comment (19): + empty(): 0 + isset(): 1 + diff --git a/ext/zip/tests/oo_rename.phpt b/ext/zip/tests/oo_rename.phpt new file mode 100644 index 0000000..98489ae --- /dev/null +++ b/ext/zip/tests/oo_rename.phpt @@ -0,0 +1,58 @@ +--TEST-- +Rename entries +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +include $dirname . 'utils.inc'; +$file = $dirname . '__tmp_oo_rename.zip'; + +@unlink($file); + +$zip = new ZipArchive; +if (!$zip->open($file, ZIPARCHIVE::CREATE)) { + exit('failed'); +} + +$zip->addFromString('entry1.txt', 'entry #1'); +$zip->addFromString('entry2.txt', 'entry #2'); +$zip->addFromString('dir/entry2.txt', 'entry #2'); + +if (!$zip->status == ZIPARCHIVE::ER_OK) { + var_dump($zip); + echo "failed\n"; +} + +$zip->close(); + +if (!$zip->open($file)) { + exit('failed'); +} + +dump_entries_name($zip); +echo "\n"; + +if (!$zip->renameIndex(0, 'ren_entry1.txt')) { + echo "failed index 0\n"; +} + +if (!$zip->renameName('dir/entry2.txt', 'dir3/ren_entry2.txt')) { + echo "failed name dir/entry2.txt\n"; +} +dump_entries_name($zip); +$zip->close(); + +@unlink($file); +?> +--EXPECTF-- +0 entry1.txt +1 entry2.txt +2 dir/entry2.txt + +0 ren_entry1.txt +1 entry2.txt +2 dir3/ren_entry2.txt diff --git a/ext/zip/tests/oo_setcomment.phpt b/ext/zip/tests/oo_setcomment.phpt new file mode 100644 index 0000000..89d6e8e --- /dev/null +++ b/ext/zip/tests/oo_setcomment.phpt @@ -0,0 +1,71 @@ +--TEST-- +setComment +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +include $dirname . 'utils.inc'; +$file = $dirname . '__tmp_oo_set_comment.zip'; + +@unlink($file); + +$zip = new ZipArchive; +if (!$zip->open($file, ZIPARCHIVE::CREATE)) { + exit('failed'); +} + +$zip->addFromString('entry1.txt', 'entry #1'); +$zip->addFromString('entry2.txt', 'entry #2'); +$zip->addFromString('dir/entry2d.txt', 'entry #2'); +$zip->addFromString('entry4.txt', 'entry #1'); +$zip->addFromString('entry5.txt', 'entry #2'); + + +var_dump($zip->setCommentName('entry1.txt', 'entry1.txt')); +var_dump($zip->setCommentName('entry2.txt', 'entry2.txt')); +var_dump($zip->setCommentName('dir/entry2d.txt', 'dir/entry2d.txt')); +var_dump($zip->setArchiveComment('archive')); + +var_dump($zip->setCommentIndex(3, 'entry4.txt')); +var_dump($zip->setCommentIndex(4, 'entry5.txt')); +var_dump($zip->setArchiveComment('archive')); + +if (!$zip->status == ZIPARCHIVE::ER_OK) { + echo "failed to write zip\n"; +} +$zip->close(); + +if (!$zip->open($file)) { + @unlink($file); + exit('failed'); +} + +var_dump($zip->getCommentIndex(0)); +var_dump($zip->getCommentIndex(1)); +var_dump($zip->getCommentIndex(2)); +var_dump($zip->getCommentIndex(3)); +var_dump($zip->getCommentIndex(4)); +var_dump($zip->getArchiveComment()); + +$zip->close(); +@unlink($file); + +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +string(10) "entry1.txt" +string(10) "entry2.txt" +string(15) "dir/entry2d.txt" +string(10) "entry4.txt" +string(10) "entry5.txt" +string(7) "archive" diff --git a/ext/zip/tests/oo_stream.phpt b/ext/zip/tests/oo_stream.phpt new file mode 100644 index 0000000..126e78f --- /dev/null +++ b/ext/zip/tests/oo_stream.phpt @@ -0,0 +1,50 @@ +--TEST-- +getStream +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . 'test_with_comment.zip'; +include $dirname . 'utils.inc'; +$zip = new ZipArchive; +if (!$zip->open($file)) { + exit('failed'); +} +$fp = $zip->getStream('foo'); + +var_dump($fp); +if(!$fp) exit("\n"); +$contents = ''; +while (!feof($fp)) { + $contents .= fread($fp, 255); +} + +fclose($fp); +$zip->close(); +var_dump($contents); + + +$fp = fopen('zip://' . dirname(__FILE__) . '/test_with_comment.zip#foo', 'rb'); +if (!$fp) { + exit("cannot open\n"); +} +$contents = ''; +while (!feof($fp)) { + $contents .= fread($fp, 2); +} +var_dump($contents); +fclose($fp); + +?> +--EXPECTF-- +resource(%d) of type (stream) +string(5) "foo + +" +string(5) "foo + +" diff --git a/ext/zip/tests/pecl12414.phpt b/ext/zip/tests/pecl12414.phpt new file mode 100644 index 0000000..6154638 --- /dev/null +++ b/ext/zip/tests/pecl12414.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #12414 ( extracting files from damaged archives) +--SKIPIF-- +<?php +/*$ */ +if(!extension_loaded('zip')) die('skip'); + ?> +--FILE-- +<?php +$filename = 'MYLOGOV2.GFX'; +$zipname = dirname(__FILE__) . "/pecl12414.zip"; +$za = new ZipArchive(); +$res =$za->open($zipname); +if ($res === TRUE) { + $finfo=$za->statName($filename); + $file_size=$finfo['size']; + + if($file_size>0) { + $contents=$za->getFromName($filename); + + echo "ZIP contents size: " . strlen($contents) . "\n"; + if(strlen($contents)!=$file_size) { + echo "zip_readfile recorded data does not match unpacked size: " . $zipname . " : " . $filename; + } + } else { + $contents=false; + echo "zip_readfile could not open stream from zero length file " . $zipname . " : " .$filename; + } + + $za->close(); +} else { + echo "zip_readfile could not read from " . $zipname . " : " . $filename; +} + +?> +--DONE-- +--EXPECTF-- +zip_readfile could not read from %specl12414.zip : MYLOGOV2.GFX diff --git a/ext/zip/tests/pecl12414.zip b/ext/zip/tests/pecl12414.zip Binary files differnew file mode 100644 index 0000000..6cbc60f --- /dev/null +++ b/ext/zip/tests/pecl12414.zip diff --git a/ext/zip/tests/stream_meta_data.phpt b/ext/zip/tests/stream_meta_data.phpt new file mode 100644 index 0000000..bd08098 --- /dev/null +++ b/ext/zip/tests/stream_meta_data.phpt @@ -0,0 +1,74 @@ +--TEST-- +stream_get_meta_data() on zip stream +--SKIPIF-- +<?php +/* $Id: oo_stream.phpt 260091 2008-05-21 09:27:41Z pajoye $ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$dirname = dirname(__FILE__) . '/'; +$file = $dirname . 'test_with_comment.zip'; +include $dirname . 'utils.inc'; +$zip = new ZipArchive; +if (!$zip->open($file)) { + exit('failed'); +} +$fp = $zip->getStream('foo'); + +if(!$fp) exit("\n"); + +var_dump(stream_get_meta_data($fp)); + +fclose($fp); +$zip->close(); + + +$fp = fopen('zip://' . dirname(__FILE__) . '/test_with_comment.zip#foo', 'rb'); +if (!$fp) { + exit("cannot open\n"); +} + +var_dump(stream_get_meta_data($fp)); +fclose($fp); + +?> +--EXPECTF-- +array(8) { + ["stream_type"]=> + string(3) "zip" + ["mode"]=> + string(2) "rb" + ["unread_bytes"]=> + int(0) + ["seekable"]=> + bool(false) + ["uri"]=> + string(3) "foo" + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) +} +array(9) { + ["wrapper_type"]=> + string(11) "zip wrapper" + ["stream_type"]=> + string(3) "zip" + ["mode"]=> + string(2) "rb" + ["unread_bytes"]=> + int(0) + ["seekable"]=> + bool(false) + ["uri"]=> + string(%d) "zip://%stest_with_comment.zip#foo" + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) +} diff --git a/ext/zip/tests/test.zip b/ext/zip/tests/test.zip Binary files differnew file mode 100644 index 0000000..35bd5ee --- /dev/null +++ b/ext/zip/tests/test.zip diff --git a/ext/zip/tests/test_procedural.zip b/ext/zip/tests/test_procedural.zip Binary files differnew file mode 100644 index 0000000..6b98694 --- /dev/null +++ b/ext/zip/tests/test_procedural.zip diff --git a/ext/zip/tests/test_with_comment.zip b/ext/zip/tests/test_with_comment.zip Binary files differnew file mode 100644 index 0000000..d68f761 --- /dev/null +++ b/ext/zip/tests/test_with_comment.zip diff --git a/ext/zip/tests/utils.inc b/ext/zip/tests/utils.inc new file mode 100644 index 0000000..02e37f6 --- /dev/null +++ b/ext/zip/tests/utils.inc @@ -0,0 +1,24 @@ +<?php +/* $Id$ */ +function dump_entries_name($z) { + for($i=0; $i<$z->numFiles; $i++) { + $sb = $z->statIndex($i); + echo $i . ' ' . $sb['name'] . "\n"; + } +} +/* recursively remove a directoryy */ +function rmdir_rf($dir) { + if ($handle = opendir($dir)) { + while (false !== ($item = readdir($handle))) { + if ($item != "." && $item != "..") { + if (is_dir($dir . '/' . $item)) { + rmdir_rf($dir . '/' . $item); + } else { + unlink($dir . '/' . $item); + } + } + } + closedir($handle); + rmdir($dir); + } +} diff --git a/ext/zip/tests/zip_close.phpt b/ext/zip/tests/zip_close.phpt new file mode 100644 index 0000000..7f9d09a --- /dev/null +++ b/ext/zip/tests/zip_close.phpt @@ -0,0 +1,17 @@ +--TEST-- +zip_close() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +if (!is_resource($zip)) die("Failure"); +zip_close($zip); +echo "OK"; + +?> +--EXPECT-- +OK diff --git a/ext/zip/tests/zip_entry_compressedsize.phpt b/ext/zip/tests/zip_entry_compressedsize.phpt new file mode 100644 index 0000000..fefa6e5 --- /dev/null +++ b/ext/zip/tests/zip_entry_compressedsize.phpt @@ -0,0 +1,23 @@ +--TEST-- +zip_entry_compressedsize() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +if (!is_resource($zip)) die("Failure"); +$entries = 0; +while ($entry = zip_read($zip)) { + echo zip_entry_compressedsize($entry)."\n"; +} +zip_close($zip); + +?> +--EXPECT-- +5 +4 +0 +24 diff --git a/ext/zip/tests/zip_entry_compressionmethod.phpt b/ext/zip/tests/zip_entry_compressionmethod.phpt new file mode 100644 index 0000000..cabdbb7 --- /dev/null +++ b/ext/zip/tests/zip_entry_compressionmethod.phpt @@ -0,0 +1,24 @@ +--TEST-- +zip_entry_compressionmethod() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +if (!is_resource($zip)) die("Failure"); +$entries = 0; +while ($entry = zip_read($zip)) { + echo zip_entry_compressionmethod($entry)."\n"; +} +zip_close($zip); + +?> +--EXPECT-- +stored +stored +stored +deflated + diff --git a/ext/zip/tests/zip_entry_filesize.phpt b/ext/zip/tests/zip_entry_filesize.phpt new file mode 100644 index 0000000..b8d8820 --- /dev/null +++ b/ext/zip/tests/zip_entry_filesize.phpt @@ -0,0 +1,23 @@ +--TEST-- +zip_entry_filesize() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +if (!is_resource($zip)) die("Failure"); +$entries = 0; +while ($entry = zip_read($zip)) { + echo zip_entry_filesize($entry)."\n"; +} +zip_close($zip); + +?> +--EXPECT-- +5 +4 +0 +27 diff --git a/ext/zip/tests/zip_entry_name.phpt b/ext/zip/tests/zip_entry_name.phpt new file mode 100644 index 0000000..1916e25 --- /dev/null +++ b/ext/zip/tests/zip_entry_name.phpt @@ -0,0 +1,23 @@ +--TEST-- +zip_entry_name() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +if (!is_resource($zip)) die("Failure"); +$entries = 0; +while ($entry = zip_read($zip)) { + echo zip_entry_name($entry)."\n"; +} +zip_close($zip); + +?> +--EXPECT-- +foo +bar +foobar/ +foobar/baz diff --git a/ext/zip/tests/zip_entry_open.phpt b/ext/zip/tests/zip_entry_open.phpt new file mode 100644 index 0000000..c32fe57 --- /dev/null +++ b/ext/zip/tests/zip_entry_open.phpt @@ -0,0 +1,18 @@ +--TEST-- +zip_entry_open() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +$entry = zip_read($zip); +echo zip_entry_open($zip, $entry, "r") ? "OK" : "Failure"; +zip_entry_close($entry); +zip_close($zip); + +?> +--EXPECT-- +OK diff --git a/ext/zip/tests/zip_entry_read.phpt b/ext/zip/tests/zip_entry_read.phpt new file mode 100644 index 0000000..d876f03 --- /dev/null +++ b/ext/zip/tests/zip_entry_read.phpt @@ -0,0 +1,19 @@ +--TEST-- +zip_entry_read() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +$entry = zip_read($zip); +if (!zip_entry_open($zip, $entry, "r")) die("Failure"); +echo zip_entry_read($entry); +zip_entry_close($entry); +zip_close($zip); + +?> +--EXPECT-- +foo diff --git a/ext/zip/tests/zip_open.phpt b/ext/zip/tests/zip_open.phpt new file mode 100644 index 0000000..91474bc --- /dev/null +++ b/ext/zip/tests/zip_open.phpt @@ -0,0 +1,16 @@ +--TEST-- +zip_open() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); + +echo is_resource($zip) ? "OK" : "Failure"; + +?> +--EXPECT-- +OK diff --git a/ext/zip/tests/zip_open_error.phpt b/ext/zip/tests/zip_open_error.phpt new file mode 100644 index 0000000..eaa1d97 --- /dev/null +++ b/ext/zip/tests/zip_open_error.phpt @@ -0,0 +1,28 @@ +--TEST-- +zip_open() error conditions +--CREDITS-- +Birgitte Kvarme <bitta@redpill-linpro.com> +#PHPTestFest2009 Norway 2009-06-09 \o/ +--SKIPIF-- +<?php +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +echo "Test case 1:"; +$zip = zip_open(""); + +echo "Test case 2:"; +$zip = zip_open("i_dont_care_about_this_parameter", "this_is_one_to_many"); + +echo "Test case 3:\n"; +$zip = zip_open("/non_exisitng_directory/test_procedural.zip"); +echo is_resource($zip) ? "OK" : "Failure"; +?> +--EXPECTF-- +Test case 1: +Warning: zip_open(): Empty string as source in %s on line %d +Test case 2: +Warning: zip_open() expects exactly 1 parameter, 2 given in %s on line %d +Test case 3: +Failure diff --git a/ext/zip/tests/zip_read.phpt b/ext/zip/tests/zip_read.phpt new file mode 100644 index 0000000..5cadb2d --- /dev/null +++ b/ext/zip/tests/zip_read.phpt @@ -0,0 +1,21 @@ +--TEST-- +zip_read() function +--SKIPIF-- +<?php +/* $Id$ */ +if(!extension_loaded('zip')) die('skip'); +?> +--FILE-- +<?php +$zip = zip_open(dirname(__FILE__)."/test_procedural.zip"); +if (!is_resource($zip)) die("Failure"); +$entries = 0; +while ($entry = zip_read($zip)) { + $entries++; +} +zip_close($zip); +echo "$entries entries"; + +?> +--EXPECT-- +4 entries diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c new file mode 100644 index 0000000..400edd6 --- /dev/null +++ b/ext/zip/zip_stream.c @@ -0,0 +1,338 @@ +/* $Id$ */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "php.h" +#if HAVE_ZIP +#ifdef ZEND_ENGINE_2 + +#include "lib/zip.h" + +#include "php_streams.h" +#include "ext/standard/file.h" +#include "ext/standard/php_string.h" +#include "fopen_wrappers.h" +#include "php_zip.h" + +#include "ext/standard/url.h" + +struct php_zip_stream_data_t { + struct zip *za; + struct zip_file *zf; + size_t cursor; + php_stream *stream; +}; + +#define STREAM_DATA_FROM_STREAM() \ + struct php_zip_stream_data_t *self = (struct php_zip_stream_data_t *) stream->abstract; + + +/* {{{ php_zip_ops_read */ +static size_t php_zip_ops_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) +{ + ssize_t n = 0; + STREAM_DATA_FROM_STREAM(); + + if (self->za && self->zf) { + n = zip_fread(self->zf, buf, count); + if (n < 0) { + int ze, se; + zip_file_error_get(self->zf, &ze, &se); + stream->eof = 1; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zip stream error: %s", zip_file_strerror(self->zf)); + return 0; + } + /* cast count to signed value to avoid possibly negative n + * being cast to unsigned value */ + if (n == 0 || n < (ssize_t)count) { + stream->eof = 1; + } else { + self->cursor += n; + } + } + return (n < 1 ? 0 : (size_t)n); +} +/* }}} */ + +/* {{{ php_zip_ops_write */ +static size_t php_zip_ops_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) +{ + if (!stream) { + return 0; + } + + return count; +} +/* }}} */ + +/* {{{ php_zip_ops_close */ +static int php_zip_ops_close(php_stream *stream, int close_handle TSRMLS_DC) +{ + STREAM_DATA_FROM_STREAM(); + if (close_handle) { + if (self->zf) { + zip_fclose(self->zf); + self->zf = NULL; + } + + if (self->za) { + zip_close(self->za); + self->za = NULL; + } + } + efree(self); + stream->abstract = NULL; + return EOF; +} +/* }}} */ + +/* {{{ php_zip_ops_flush */ +static int php_zip_ops_flush(php_stream *stream TSRMLS_DC) +{ + if (!stream) { + return 0; + } + + return 0; +} +/* }}} */ + +static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) /* {{{ */ +{ + struct zip_stat sb; + const char *path = stream->orig_path; + int path_len = strlen(stream->orig_path); + char *file_basename; + size_t file_basename_len; + char file_dirname[MAXPATHLEN]; + struct zip *za; + char *fragment; + int fragment_len; + int err; + + fragment = strchr(path, '#'); + if (!fragment) { + return -1; + } + + + if (strncasecmp("zip://", path, 6) == 0) { + path += 6; + } + + fragment_len = strlen(fragment); + + if (fragment_len < 1) { + return -1; + } + path_len = strlen(path); + if (path_len >= MAXPATHLEN) { + return -1; + } + + memcpy(file_dirname, path, path_len - fragment_len); + file_dirname[path_len - fragment_len] = '\0'; + + php_basename((char *)path, path_len - fragment_len, NULL, 0, &file_basename, &file_basename_len TSRMLS_CC); + fragment++; + + if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) { + efree(file_basename); + return -1; + } + + za = zip_open(file_dirname, ZIP_CREATE, &err); + if (za) { + memset(ssb, 0, sizeof(php_stream_statbuf)); + if (zip_stat(za, fragment, ZIP_FL_NOCASE, &sb) != 0) { + efree(file_basename); + return -1; + } + zip_close(za); + + if (path[path_len-1] != '/') { + ssb->sb.st_size = sb.size; + ssb->sb.st_mode |= S_IFREG; /* regular file */ + } else { + ssb->sb.st_size = 0; + ssb->sb.st_mode |= S_IFDIR; /* regular directory */ + } + + ssb->sb.st_mtime = sb.mtime; + ssb->sb.st_atime = sb.mtime; + ssb->sb.st_ctime = sb.mtime; + ssb->sb.st_nlink = 1; + ssb->sb.st_rdev = -1; +#ifndef PHP_WIN32 + ssb->sb.st_blksize = -1; + ssb->sb.st_blocks = -1; +#endif + ssb->sb.st_ino = -1; + } + efree(file_basename); + return 0; +} +/* }}} */ + +php_stream_ops php_stream_zipio_ops = { + php_zip_ops_write, php_zip_ops_read, + php_zip_ops_close, php_zip_ops_flush, + "zip", + NULL, /* seek */ + NULL, /* cast */ + php_zip_ops_stat, /* stat */ + NULL /* set_option */ +}; + +/* {{{ php_stream_zip_open */ +php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_DC TSRMLS_DC) +{ + struct zip_file *zf = NULL; + int err = 0; + + php_stream *stream = NULL; + struct php_zip_stream_data_t *self; + struct zip *stream_za; + + if (strncmp(mode,"r", strlen("r")) != 0) { + return NULL; + } + + if (filename) { + if (ZIP_OPENBASEDIR_CHECKPATH(filename)) { + return NULL; + } + + /* duplicate to make the stream za independent (esp. for MSHUTDOWN) */ + stream_za = zip_open(filename, ZIP_CREATE, &err); + if (!stream_za) { + return NULL; + } + + zf = zip_fopen(stream_za, path, 0); + if (zf) { + self = emalloc(sizeof(*self)); + + self->za = stream_za; + self->zf = zf; + self->stream = NULL; + self->cursor = 0; + stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode); + stream->orig_path = estrdup(path); + } else { + zip_close(stream_za); + } + } + + if (!stream) { + return NULL; + } else { + return stream; + } + +} +/* }}} */ + +/* {{{ php_stream_zip_opener */ +php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, + char *path, + char *mode, + int options, + char **opened_path, + php_stream_context *context STREAMS_DC TSRMLS_DC) +{ + int path_len; + + char *file_basename; + size_t file_basename_len; + char file_dirname[MAXPATHLEN]; + + struct zip *za; + struct zip_file *zf = NULL; + char *fragment; + int fragment_len; + int err; + + php_stream *stream = NULL; + struct php_zip_stream_data_t *self; + + fragment = strchr(path, '#'); + if (!fragment) { + return NULL; + } + + if (strncasecmp("zip://", path, 6) == 0) { + path += 6; + } + + fragment_len = strlen(fragment); + + if (fragment_len < 1) { + return NULL; + } + path_len = strlen(path); + if (path_len >= MAXPATHLEN || mode[0] != 'r') { + return NULL; + } + + memcpy(file_dirname, path, path_len - fragment_len); + file_dirname[path_len - fragment_len] = '\0'; + + php_basename(path, path_len - fragment_len, NULL, 0, &file_basename, &file_basename_len TSRMLS_CC); + fragment++; + + if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) { + efree(file_basename); + return NULL; + } + + za = zip_open(file_dirname, ZIP_CREATE, &err); + if (za) { + zf = zip_fopen(za, fragment, 0); + if (zf) { + self = emalloc(sizeof(*self)); + + self->za = za; + self->zf = zf; + self->stream = NULL; + self->cursor = 0; + stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode); + + if (opened_path) { + *opened_path = estrdup(path); + } + } else { + zip_close(za); + } + } + + efree(file_basename); + + if (!stream) { + return NULL; + } else { + return stream; + } +} +/* }}} */ + +static php_stream_wrapper_ops zip_stream_wops = { + php_stream_zip_opener, + NULL, /* close */ + NULL, /* fstat */ + NULL, /* stat */ + NULL, /* opendir */ + "zip wrapper", + NULL, /* unlink */ + NULL, /* rename */ + NULL, /* mkdir */ + NULL /* rmdir */ +}; + +php_stream_wrapper php_stream_zip_wrapper = { + &zip_stream_wops, + NULL, + 0 /* is_url */ +}; +#endif /* ZEND_ENGINE_2 */ +#endif /* HAVE_ZIP */ |