mirror of
https://github.com/php-win-ext/php-rar.git
synced 2026-03-24 04:52:07 +01:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6545fdd215 | ||
|
|
08f8190e49 | ||
|
|
544f55920a | ||
|
|
24b421e0e6 | ||
|
|
05a48cbbeb | ||
|
|
6d0e583ef9 | ||
|
|
714f15cb06 | ||
|
|
58bb195ae3 | ||
|
|
5293a8f07e | ||
|
|
61edb08973 | ||
|
|
adc9fe7d39 | ||
|
|
5eb1055447 | ||
|
|
7ca7561e09 | ||
|
|
61eca15136 | ||
|
|
dc8ee65999 | ||
|
|
656c3fa69d | ||
|
|
a6bea8fec8 | ||
|
|
3b405bea8e | ||
|
|
18cd0568aa | ||
|
|
dc298847c7 | ||
|
|
246a80fdeb | ||
|
|
4b6fd31d08 | ||
|
|
44e35b8f6a | ||
|
|
fe4a94305b | ||
|
|
4f821913ad | ||
|
|
6939711766 | ||
|
|
c499b4d2d2 | ||
|
|
a191673249 | ||
|
|
c6f8765250 | ||
|
|
5402805db0 | ||
|
|
e6e481cfb2 | ||
|
|
a3c0236a7d | ||
|
|
f8ee7cc273 | ||
|
|
e699b159cf | ||
|
|
41875e7bd6 | ||
|
|
3a2688b3eb | ||
|
|
524d195253 | ||
|
|
e1609b9dfd | ||
|
|
4f804014ca | ||
|
|
abe9816391 | ||
|
|
5876366b26 | ||
|
|
c1e389af0d | ||
|
|
73972e070d | ||
|
|
74aed951bb | ||
|
|
26929db6a9 | ||
|
|
4fb28f3858 | ||
|
|
4e04320979 | ||
|
|
b72aaff789 | ||
|
|
3b2d2eb296 | ||
|
|
166fe908ad | ||
|
|
0265686bbd | ||
|
|
f650a6e340 | ||
|
|
358432a7eb | ||
|
|
bbeab2dc4e | ||
|
|
5f81d8688f | ||
|
|
d6dfd5054c | ||
|
|
5d1e369c38 | ||
|
|
2f36bd7cac | ||
|
|
34859cf5b4 | ||
|
|
99cb19e838 | ||
|
|
f19f569f44 | ||
|
|
762b1ae3b0 | ||
|
|
fe2d2f46e4 | ||
|
|
6391dc21ca | ||
|
|
98bcf3697a | ||
|
|
4cda46d212 | ||
|
|
b2bc8dc586 | ||
|
|
96eec2b31c | ||
|
|
d5f04a3a88 | ||
|
|
13cb064031 | ||
|
|
a238d20430 | ||
|
|
66e2666696 | ||
|
|
55a328ff22 | ||
|
|
e632e338ef |
38
.gitignore
vendored
38
.gitignore
vendored
@@ -1,38 +0,0 @@
|
||||
*.o
|
||||
*.lo
|
||||
/tests/*.sh
|
||||
/tests/*.exp
|
||||
/tests/*.diff
|
||||
/tests/*.log
|
||||
/tests/*.php
|
||||
/tests/*.out
|
||||
/run-tests.php
|
||||
/modules
|
||||
/missing
|
||||
/.deps
|
||||
/.libs
|
||||
/Makefile
|
||||
/Makefile.fragments
|
||||
/Makefile.global
|
||||
/Makefile.objects
|
||||
/acinclude.m4
|
||||
/aclocal.m4
|
||||
/autom4te.cache
|
||||
/build
|
||||
/config.guess
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.nice
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/configure.in
|
||||
/install-sh
|
||||
/intl.la
|
||||
/libtool
|
||||
/mkinstalldirs
|
||||
/ltmain.sh
|
||||
/.cproject
|
||||
/.project
|
||||
/.settings
|
||||
12
README
12
README
@@ -1,12 +0,0 @@
|
||||
PHP extension for reading RAR archives using the bundled UnRAR library.
|
||||
|
||||
This extension uses a modified version of the UnRAR library. The UnRAR library
|
||||
is an official open-source library by RARLabs, an auto generated subset of the
|
||||
RAR codebase. It is available from http://www.rarlab.com/rar_add.htm
|
||||
Please note that it has a more restrictive license than the PHP bindings,
|
||||
barring using it to re-create the RAR compression algorithm. See
|
||||
unrar/LICENSE.txt for details.
|
||||
|
||||
Some modifications have been applied to the UnRAR library, mainly to allow
|
||||
streaming extraction of files without using threads.
|
||||
|
||||
32
config.m4
32
config.m4
@@ -1,32 +0,0 @@
|
||||
dnl $Id$
|
||||
dnl config.m4 for extension rar
|
||||
|
||||
PHP_ARG_ENABLE(rar, whether to enable rar support,
|
||||
[ --enable-rar Enable rar support])
|
||||
|
||||
unrar_sources="unrar/rar.cpp unrar/strlist.cpp unrar/strfn.cpp \
|
||||
unrar/pathfn.cpp unrar/smallfn.cpp unrar/savepos.cpp \
|
||||
unrar/global.cpp unrar/file.cpp unrar/filefn.cpp \
|
||||
unrar/filcreat.cpp unrar/archive.cpp unrar/arcread.cpp \
|
||||
unrar/unicode.cpp unrar/system.cpp unrar/isnt.cpp \
|
||||
unrar/crypt.cpp unrar/crc.cpp unrar/rawread.cpp \
|
||||
unrar/encname.cpp unrar/resource.cpp unrar/match.cpp \
|
||||
unrar/timefn.cpp unrar/rdwrfn.cpp unrar/consio.cpp \
|
||||
unrar/options.cpp unrar/ulinks.cpp unrar/errhnd.cpp \
|
||||
unrar/rarvm.cpp unrar/rijndael.cpp unrar/getbits.cpp \
|
||||
unrar/sha1.cpp unrar/extinfo.cpp unrar/extract.cpp \
|
||||
unrar/volume.cpp unrar/find.cpp \
|
||||
unrar/unpack.cpp unrar/cmddata.cpp unrar/dll.cpp \
|
||||
unrar/filestr.cpp unrar/recvol.cpp unrar/rs.cpp \
|
||||
unrar/scantree.cpp unrar/log.cpp unrar/extractchunk.cpp \
|
||||
unrar/secpassword.cpp"
|
||||
|
||||
if test "$PHP_RAR" != "no"; then
|
||||
AC_DEFINE(HAVE_RAR, 1, [Whether you have rar support])
|
||||
PHP_SUBST(RAR_SHARED_LIBADD)
|
||||
PHP_REQUIRE_CXX()
|
||||
PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", RAR_SHARED_LIBADD)
|
||||
|
||||
PHP_NEW_EXTENSION(rar, rar.c rar_error.c rararch.c rarentry.c rar_stream.c rar_navigation.c $unrar_sources, $ext_shared,,-DRARDLL -DGUI -DSILENT -Wno-write-strings -Wno-logical-op-parentheses -I@ext_srcdir@/unrar)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
|
||||
fi
|
||||
28
config.w32
28
config.w32
@@ -1,28 +0,0 @@
|
||||
// $Id$
|
||||
// vim:ft=javascript
|
||||
|
||||
ARG_ENABLE("rar", "Rar support", "no");
|
||||
|
||||
if (PHP_RAR != "no") {
|
||||
EXTENSION("rar", "rar.c rar_error.c rararch.c rarentry.c rar_stream.c rar_navigation.c", PHP_RAR_SHARED, "/DRARDLL /DGUI /DSILENT /EHsc /D_WSTDIO_DEFINED");
|
||||
ADD_SOURCES(configure_module_dirname + "/unrar",
|
||||
"rar.cpp strlist.cpp strfn.cpp \
|
||||
pathfn.cpp smallfn.cpp savepos.cpp \
|
||||
global.cpp file.cpp filefn.cpp \
|
||||
filcreat.cpp archive.cpp arcread.cpp \
|
||||
unicode.cpp system.cpp isnt.cpp \
|
||||
crypt.cpp crc.cpp rawread.cpp \
|
||||
encname.cpp resource.cpp match.cpp \
|
||||
timefn.cpp rdwrfn.cpp consio.cpp \
|
||||
options.cpp ulinks.cpp errhnd.cpp \
|
||||
rarvm.cpp rijndael.cpp getbits.cpp \
|
||||
sha1.cpp extinfo.cpp extract.cpp \
|
||||
volume.cpp find.cpp \
|
||||
unpack.cpp cmddata.cpp dll.cpp \
|
||||
filestr.cpp recvol.cpp rs.cpp \
|
||||
scantree.cpp extractchunk.cpp log.cpp", "rar");
|
||||
|
||||
AC_DEFINE("HAVE_RAR", 1, "Rar support");
|
||||
}
|
||||
|
||||
|
||||
22
example.php
22
example.php
@@ -1,22 +0,0 @@
|
||||
<?
|
||||
|
||||
$archive_name = '/full/path/to/file.rar'
|
||||
$entry_name = 'path/to/archive/entry.txt'; //notice: no slash at the beginning
|
||||
$dir_to_extract_to = '/path/to/extract/dir';
|
||||
$new_entry_name = 'some.txt';
|
||||
|
||||
|
||||
$rar = rar_open($archive_name) OR die('failed to open ' . $archive_name);
|
||||
$entry = rar_entry_get($rar, $entry_name) OR die('failed to find ' . $entry_name . ' in ' . $archive_name);
|
||||
|
||||
// this will create all necessary subdirs under $dir_to_extract_to
|
||||
$entry->extract($dir_to_extract_to);
|
||||
/* OR */
|
||||
|
||||
// this will create only one new file $new_entry_name in $dir_to_extract_to
|
||||
$entry->extract('', $dir_to_extract_to.'/'.$new_entry_name);
|
||||
|
||||
// this line is really not necessary
|
||||
rar_close($rar);
|
||||
|
||||
?>
|
||||
62
extflow.txt
62
extflow.txt
@@ -1,62 +0,0 @@
|
||||
(some information is outdated)
|
||||
|
||||
rar_open/RarArchive::open()
|
||||
gives
|
||||
RarArchive object
|
||||
-
|
||||
. stores 2 open data structs (are used to tell the lib e.g. which file to open and the lib in return stores some data in them)
|
||||
- list_open_data has open mode RAR_OM_LIST_INCSPLIT and is used to list the contents of the archive
|
||||
- extract_open_data has open mode RAR_OM_EXTRACT and is used by RarEntry::extract
|
||||
. stores one opened archive handle, opened with the list_open_data struct. This handle remains
|
||||
open until the archive is closed or the object is destroyed
|
||||
. a RarArchive object is considered closed when the opened archive handle created here is set to NULL
|
||||
|
||||
|
||||
rar_list()/RarArchive::getEntries()
|
||||
gives
|
||||
RarEntry objects
|
||||
-
|
||||
. CALL _rar_list_files, which fills the lazy cache rar->entries by using the opened archive handle to retrieve ALL the RarHeaderDataEx headers
|
||||
. CALL _rar_raw_entries_to_files to turn the rar->entries RarHeaderDataEx headers into zvals
|
||||
- in turn, _rar_raw_entries_to_files creates the zval and sets the property that holds the zval reference to the RarArchive object (see below)
|
||||
- calculates the packed size by summing over all the headers that concern each file (a file may have more than one header in case there are volumes)
|
||||
- then CALLs _rar_entry_to_zval with the last header for each file and the packed size so that it can fill the remaining properties
|
||||
. each of the RarEntry objects store a zval referencing the RarArchive object. The RarArchive object is not destroyed until all its spawned RarEntry objects are destroyed (it can however be closed)
|
||||
|
||||
|
||||
rar_entry_get()/RarArchive::getEntry()
|
||||
gives
|
||||
RarEntry object
|
||||
-
|
||||
. CALL _rar_list_files, if it's necessary to fill the lazy cache rar->entries
|
||||
. CALL _rar_raw_entries_to_files, which traverses rar->entries until it finds the request filename, the header(s) are then converted into one zval
|
||||
. again, the RarEntry object stores a reference to the RarArchive object
|
||||
|
||||
|
||||
RarArchive traversal with an iterator
|
||||
gives
|
||||
RarEntry objects (one at a time)
|
||||
-
|
||||
. iterator creation CALLs_rar_list_files, if it's necessary to fill the lazy cache rar->entries
|
||||
. iterator stores the index (with respect to the rar->entries array) of the last header in rar->entries that is to be read (starts with 0)
|
||||
. iterator CALLs _rar_raw_entries_to_files, which here stops after reading each file and advances the index
|
||||
|
||||
|
||||
RarEntry::extract()
|
||||
extracts the file
|
||||
-
|
||||
. uses the extract_open_data that's stored in the parent RarArchive object
|
||||
. makes a shallow copy of parent RarArchive's rar->cb_userdata, eventually modified with the given file password.
|
||||
. passes them to _rar_find_file to open the file with RAR_OM_EXTRACT and skip to the desired entry
|
||||
. extracts the file
|
||||
. closes the rar handle
|
||||
|
||||
|
||||
RarEntry::getStream()
|
||||
obtains stream
|
||||
-
|
||||
. CALL php_stream_rar_open with the archive name (obtained from parent RarArchive object's extract_open_data->ArcName), the filename of the entry and a shallow copy of parent RarArchive's rar->cb_userdata, eventually modified with the given file password.
|
||||
. in turn, php_stream_rar_open CALLs _rar_find_file with a brand new rar open data struct with RAR_OM_EXTRACT. _rar_find_file opens the RAR archive and skips to the desired entry
|
||||
. the resulting stream has no connection to the original RarArchive object or to the RarEntry object
|
||||
. the rar archive is not closed until the stream is destroyed or closed
|
||||
|
||||
495
package.xml
495
package.xml
@@ -1,495 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.5.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
|
||||
http://pear.php.net/dtd/tasks-1.0.xsd
|
||||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>rar</name>
|
||||
<channel>pecl.php.net</channel>
|
||||
<summary>rar extension</summary>
|
||||
<description>PHP extension for reading RAR archives using bundled unRAR library.
|
||||
</description>
|
||||
|
||||
<lead>
|
||||
<name>Gustavo Lopes</name>
|
||||
<user>cataphract</user>
|
||||
<email>cataphract@php.net</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
|
||||
<developer>
|
||||
<name>Antony Dovgal</name>
|
||||
<user>tony2001</user>
|
||||
<email>tony@daylessday.org</email>
|
||||
<active>no</active>
|
||||
</developer>
|
||||
|
||||
<date>2013-10-11</date>
|
||||
<time>13:00:00</time>
|
||||
<version>
|
||||
<release>3.0.2</release>
|
||||
<api>3.0.0</api>
|
||||
</version>
|
||||
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>- Fixed build with PHP 5.5.
|
||||
- Upgraded bundled unrar to version 4.2.4.
|
||||
</notes>
|
||||
<contents>
|
||||
<dir name="/">
|
||||
<dir name="tests">
|
||||
<file role="test" name="001.phpt"/>
|
||||
<file role="test" name="002.phpt"/>
|
||||
<file role="test" name="003.phpt"/>
|
||||
<file role="test" name="004.phpt"/>
|
||||
<file role="test" name="4mb.rar"/>
|
||||
<file role="test" name="005.phpt"/>
|
||||
<file role="test" name="006.phpt"/>
|
||||
<file role="test" name="007.phpt"/>
|
||||
<file role="test" name="008.phpt"/>
|
||||
<file role="test" name="009.phpt"/>
|
||||
<file role="test" name="010.phpt"/>
|
||||
<file role="test" name="011.phpt"/>
|
||||
<file role="test" name="012.phpt"/>
|
||||
<file role="test" name="013.phpt"/>
|
||||
<file role="test" name="014.phpt"/>
|
||||
<file role="test" name="015.phpt"/>
|
||||
<file role="test" name="016.phpt"/>
|
||||
<file role="test" name="017.phpt"/>
|
||||
<file role="test" name="018.phpt"/>
|
||||
<file role="test" name="019.phpt"/>
|
||||
<file role="test" name="020.phpt"/>
|
||||
<file role="test" name="021.phpt"/>
|
||||
<file role="test" name="022.phpt"/>
|
||||
<file role="test" name="023.phpt"/>
|
||||
<file role="test" name="024.phpt"/>
|
||||
<file role="test" name="025.phpt"/>
|
||||
<file role="test" name="026.phpt"/>
|
||||
<file role="test" name="027.phpt"/>
|
||||
<file role="test" name="028.phpt"/>
|
||||
<file role="test" name="029.phpt"/>
|
||||
<file role="test" name="030.phpt"/>
|
||||
<file role="test" name="031.phpt"/>
|
||||
<file role="test" name="032.phpt"/>
|
||||
<file role="test" name="033.phpt"/>
|
||||
<file role="test" name="034.phpt"/>
|
||||
<file role="test" name="035.phpt"/>
|
||||
<file role="test" name="036.phpt"/>
|
||||
<file role="test" name="037.phpt"/>
|
||||
<file role="test" name="038.phpt"/>
|
||||
<file role="test" name="039.phpt"/>
|
||||
<file role="test" name="040.phpt"/>
|
||||
<file role="test" name="041.phpt"/>
|
||||
<file role="test" name="042.phpt"/>
|
||||
<file role="test" name="043.phpt"/>
|
||||
<file role="test" name="044.phpt"/>
|
||||
<file role="test" name="045.phpt"/>
|
||||
<file role="test" name="046.phpt"/>
|
||||
<file role="test" name="047.phpt"/>
|
||||
<file role="test" name="048.phpt"/>
|
||||
<file role="test" name="049.phpt"/>
|
||||
<file role="test" name="050.phpt"/>
|
||||
<file role="test" name="051.phpt"/>
|
||||
<file role="test" name="052.phpt"/>
|
||||
<file role="test" name="053.phpt"/>
|
||||
<file role="test" name="054.phpt"/>
|
||||
<file role="test" name="055.phpt"/>
|
||||
<file role="test" name="056.phpt"/>
|
||||
<file role="test" name="057.phpt"/>
|
||||
<file role="test" name="058.phpt"/>
|
||||
<file role="test" name="059.phpt"/>
|
||||
<file role="test" name="060.phpt"/>
|
||||
<file role="test" name="061.phpt"/>
|
||||
<file role="test" name="062.phpt"/>
|
||||
<file role="test" name="063.phpt"/>
|
||||
<file role="test" name="064.phpt"/>
|
||||
<file role="test" name="065.phpt"/>
|
||||
<file role="test" name="066.phpt"/>
|
||||
<file role="test" name="067.phpt"/>
|
||||
<file role="test" name="068.phpt"/>
|
||||
<file role="test" name="069.phpt"/>
|
||||
<file role="test" name="070.phpt"/>
|
||||
<file role="test" name="071.phpt"/>
|
||||
<file role="test" name="072.phpt"/>
|
||||
<file role="test" name="073.phpt"/>
|
||||
<file role="test" name="074.phpt"/>
|
||||
<file role="test" name="075.phpt"/>
|
||||
<file role="test" name="076.phpt"/>
|
||||
<file role="test" name="077.phpt"/>
|
||||
<file role="test" name="078.phpt"/>
|
||||
<file role="test" name="079.phpt"/>
|
||||
<file role="test" name="080.phpt"/>
|
||||
<file role="test" name="081.phpt"/>
|
||||
<file role="test" name="082.phpt"/>
|
||||
<file role="test" name="083.phpt"/>
|
||||
<file role="test" name="084.phpt"/>
|
||||
<file role="test" name="085.phpt"/>
|
||||
<file role="test" name="086.phpt"/>
|
||||
<file role="test" name="087.phpt"/>
|
||||
<file role="test" name="088.phpt"/>
|
||||
<file role="test" name="089.phpt"/>
|
||||
<file role="test" name="090.phpt"/>
|
||||
<file role="test" name="091.phpt"/>
|
||||
<file role="test" name="092.phpt"/>
|
||||
<file role="test" name="093.phpt"/>
|
||||
<file role="test" name="094.phpt"/>
|
||||
<file role="test" name="095.phpt"/>
|
||||
<file role="test" name="096.phpt"/>
|
||||
<file role="test" name="097.phpt"/>
|
||||
<file role="test" name="098.phpt"/>
|
||||
<file role="test" name="099.phpt"/>
|
||||
<file role="test" name="commented.rar"/>
|
||||
<file role="test" name="corrupted.rar"/>
|
||||
<file role="test" name="directories.rar"/>
|
||||
<file role="test" name="dirlink_unix.rar"/>
|
||||
<file role="test" name="dirs_and_extra_headers.rar"/>
|
||||
<file role="test" name="empty_file.rar"/>
|
||||
<file role="test" name="encrypted_headers.rar"/>
|
||||
<file role="test" name="encrypted_only_files.rar"/>
|
||||
<file role="test" name="garbage.part03.rar"/>
|
||||
<file role="test" name="latest_winrar.rar"/>
|
||||
<file role="test" name="linux_rar.rar"/>
|
||||
<file role="test" name="multi.part1.rar"/>
|
||||
<file role="test" name="multi.part2.rar"/>
|
||||
<file role="test" name="multi.part3.rar"/>
|
||||
<file role="test" name="multi_broken.part1.rar"/>
|
||||
<file role="test" name="rar_notrar.rar"/>
|
||||
<file role="test" name="rar_unicode.rar"/>
|
||||
<file role="test" name="repeated_name.rar"/>
|
||||
<file role="test" name="secret-crypted-none.rar"/>
|
||||
<file role="test" name="secret-none.rar"/>
|
||||
<file role="test" name="solid.rar"/>
|
||||
<file role="test" name="sparsefiles_rar.rar"/>
|
||||
<file role="test" name="store_method.rar"/>
|
||||
</dir> <!-- /tests -->
|
||||
<dir name="unrar">
|
||||
<file name="acknow.txt" role="doc" />
|
||||
<file name="arccmt.cpp" role="src" />
|
||||
<file name="archive.cpp" role="src" />
|
||||
<file name="archive.hpp" role="src" />
|
||||
<file name="arcread.cpp" role="src" />
|
||||
<file name="array.hpp" role="src" />
|
||||
<file name="beosea.cpp" role="src" />
|
||||
<file name="cmddata.cpp" role="src" />
|
||||
<file name="cmddata.hpp" role="src" />
|
||||
<file name="coder.cpp" role="src" />
|
||||
<file name="coder.hpp" role="src" />
|
||||
<file name="compress.hpp" role="src" />
|
||||
<file name="consio.cpp" role="src" />
|
||||
<file name="consio.hpp" role="src" />
|
||||
<file name="crc.cpp" role="src" />
|
||||
<file name="crc.hpp" role="src" />
|
||||
<file name="crypt.cpp" role="src" />
|
||||
<file name="crypt.hpp" role="src" />
|
||||
<file name="dll.cpp" role="src" />
|
||||
<file name="dll.hpp" role="src" />
|
||||
<file name="encname.cpp" role="src" />
|
||||
<file name="encname.hpp" role="src" />
|
||||
<file name="errhnd.cpp" role="src" />
|
||||
<file name="errhnd.hpp" role="src" />
|
||||
<file name="extinfo.cpp" role="src" />
|
||||
<file name="extinfo.hpp" role="src" />
|
||||
<file name="extract.cpp" role="src" />
|
||||
<file name="extract.hpp" role="src" />
|
||||
<file name="extractchunk.cpp" role="src" />
|
||||
<file name="filcreat.cpp" role="src" />
|
||||
<file name="filcreat.hpp" role="src" />
|
||||
<file name="file.cpp" role="src" />
|
||||
<file name="file.hpp" role="src" />
|
||||
<file name="filefn.cpp" role="src" />
|
||||
<file name="filefn.hpp" role="src" />
|
||||
<file name="filestr.cpp" role="src" />
|
||||
<file name="filestr.hpp" role="src" />
|
||||
<file name="find.cpp" role="src" />
|
||||
<file name="find.hpp" role="src" />
|
||||
<file name="getbits.cpp" role="src" />
|
||||
<file name="getbits.hpp" role="src" />
|
||||
<file name="global.cpp" role="src" />
|
||||
<file name="global.hpp" role="src" />
|
||||
<file name="headers.hpp" role="src" />
|
||||
<file name="isnt.cpp" role="src" />
|
||||
<file name="isnt.hpp" role="src" />
|
||||
<file name="LICENSE.txt" role="doc" />
|
||||
<file name="list.cpp" role="src" />
|
||||
<file name="list.hpp" role="src" />
|
||||
<file name="loclang.hpp" role="src" />
|
||||
<file name="log.cpp" role="src" />
|
||||
<file name="log.hpp" role="src" />
|
||||
<file name="match.cpp" role="src" />
|
||||
<file name="match.hpp" role="src" />
|
||||
<file name="model.cpp" role="src" />
|
||||
<file name="model.hpp" role="src" />
|
||||
<file name="options.cpp" role="src" />
|
||||
<file name="options.hpp" role="src" />
|
||||
<file name="os.hpp" role="src" />
|
||||
<file name="os2ea.cpp" role="src" />
|
||||
<file name="pathfn.cpp" role="src" />
|
||||
<file name="pathfn.hpp" role="src" />
|
||||
<file name="rar.cpp" role="src" />
|
||||
<file name="rar.hpp" role="src" />
|
||||
<file name="rardefs.hpp" role="src" />
|
||||
<file name="rarlang.hpp" role="src" />
|
||||
<file name="raros.hpp" role="src" />
|
||||
<file name="rartypes.hpp" role="src" />
|
||||
<file name="rarvm.cpp" role="src" />
|
||||
<file name="rarvm.hpp" role="src" />
|
||||
<file name="rarvmtbl.cpp" role="src" />
|
||||
<file name="rawread.cpp" role="src" />
|
||||
<file name="rawread.hpp" role="src" />
|
||||
<file name="rdwrfn.cpp" role="src" />
|
||||
<file name="rdwrfn.hpp" role="src" />
|
||||
<file name="README.txt" role="doc" />
|
||||
<file name="recvol.cpp" role="src" />
|
||||
<file name="recvol.hpp" role="src" />
|
||||
<file name="resource.cpp" role="src" />
|
||||
<file name="resource.hpp" role="src" />
|
||||
<file name="rijndael.cpp" role="src" />
|
||||
<file name="rijndael.hpp" role="src" />
|
||||
<file name="rs.cpp" role="src" />
|
||||
<file name="rs.hpp" role="src" />
|
||||
<file name="savepos.cpp" role="src" />
|
||||
<file name="savepos.hpp" role="src" />
|
||||
<file name="scantree.cpp" role="src" />
|
||||
<file name="scantree.hpp" role="src" />
|
||||
<file name="secpassword.cpp" role="src" />
|
||||
<file name="secpassword.hpp" role="src" />
|
||||
<file name="sha1.cpp" role="src" />
|
||||
<file name="sha1.hpp" role="src" />
|
||||
<file name="smallfn.cpp" role="src" />
|
||||
<file name="smallfn.hpp" role="src" />
|
||||
<file name="strfn.cpp" role="src" />
|
||||
<file name="strfn.hpp" role="src" />
|
||||
<file name="strlist.cpp" role="src" />
|
||||
<file name="strlist.hpp" role="src" />
|
||||
<file name="suballoc.cpp" role="src" />
|
||||
<file name="suballoc.hpp" role="src" />
|
||||
<file name="system.cpp" role="src" />
|
||||
<file name="system.hpp" role="src" />
|
||||
<file name="timefn.cpp" role="src" />
|
||||
<file name="timefn.hpp" role="src" />
|
||||
<file name="ulinks.cpp" role="src" />
|
||||
<file name="ulinks.hpp" role="src" />
|
||||
<file name="unicode.cpp" role="src" />
|
||||
<file name="unicode.hpp" role="src" />
|
||||
<file name="unios2.cpp" role="src" />
|
||||
<file name="unpack.cpp" role="src" />
|
||||
<file name="unpack.hpp" role="src" />
|
||||
<file name="unpack15.cpp" role="src" />
|
||||
<file name="unpack20.cpp" role="src" />
|
||||
<file name="uowners.cpp" role="src" />
|
||||
<file name="version.hpp" role="src" />
|
||||
<file name="volume.cpp" role="src" />
|
||||
<file name="volume.hpp" role="src" />
|
||||
<file name="win32acl.cpp" role="src" />
|
||||
<file name="win32stm.cpp" role="src" />
|
||||
</dir> <!-- /unrar -->
|
||||
<file name="config.m4" role="src" />
|
||||
<file name="config.w32" role="src" />
|
||||
<file name="CREDITS" role="doc" />
|
||||
<file name="README" role="doc" />
|
||||
<file name="example.php" role="doc" />
|
||||
<file name="php_rar.h" role="src" />
|
||||
<file name="rar.c" role="src" />
|
||||
<file name="rar_stream.c" role="src" />
|
||||
<file name="rararch.c" role="src" />
|
||||
<file name="rarentry.c" role="src" />
|
||||
<file name="rar_error.c" role="src" />
|
||||
<file role="src" name="rar_navigation.c"/>
|
||||
</dir> <!-- / -->
|
||||
</contents>
|
||||
|
||||
<dependencies>
|
||||
<required>
|
||||
<php>
|
||||
<min>5.2.0</min>
|
||||
</php>
|
||||
<pearinstaller>
|
||||
<min>1.4.0</min>
|
||||
</pearinstaller>
|
||||
</required>
|
||||
</dependencies>
|
||||
|
||||
<providesextension>rar</providesextension>
|
||||
|
||||
<extsrcrelease />
|
||||
|
||||
<changelog>
|
||||
<release>
|
||||
<version>
|
||||
<release>3.0.1</release>
|
||||
<api>3.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<date>2012-07-29</date>
|
||||
<notes>Changes in this version:
|
||||
- Merge changes made to unrar up to version 4.2.2.
|
||||
- Fix leak in PHP >= 5.3.11, = 5.4.0 and compile error in master.
|
||||
- Fix some tests failing if TZ != Europe/Lisbon.
|
||||
- Fix bad pointer in an error message.
|
||||
- Added test for bug #59939 (can't reproduce).
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<version>
|
||||
<release>2.0.0</release>
|
||||
<api>2.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<date>2010-04-20</date>
|
||||
<notes>Changes with respect to release 2.0.0RC1:
|
||||
- Fixed infinite loop when opening RAR archive missing a volume (later report in bug #17177).
|
||||
- Fixed bug #17025 (changed the name of method RarArchive::list into RarArchive::getEntries). If backwards compatibility with the release candidate is required, RarArchive::list can be reintroduced by defining RAR_ARCHIVE_LIST_ALIAS.
|
||||
Incompatible changes with respect to release 1.0.0:
|
||||
PHP Support:
|
||||
- Support for PHP 4.3 dropped. PHP 5.2.x or 5.3.x is required.
|
||||
API backwards incompatible changes:
|
||||
- Handles unicode filenames (uses UTF-8 external encoding). The file names inside the RAR archives are always returned in UTF-8. This will probably break your scripts.
|
||||
- Calling rar_close/RarArchive::close() invalidates RarEntry objects (actually, only extraction is forbidden, but don't rely on it).
|
||||
For the other changes, see the changelog for version 2.0.0RC1.
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<version>
|
||||
<release>2.0.0RC1</release>
|
||||
<api>2.0.0RC1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2010-01-17</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>Changes in respect to release 1.0.0:
|
||||
PHP SUPPORT:
|
||||
- Support for PHP 4.3 dropped. PHP 5.2.x or 5.3.x is required.
|
||||
API BACKWARDS INCOMPATIBLE CHANGES:
|
||||
- Handles unicode filenames (uses UTF-8 external encoding). The file names inside the RAR archives are always returned in UTF-8. This will probably break your scripts.
|
||||
- Calling rar_close/RarArchive::close() invalidates RarEntry objects (actually, only extraction is forbidden, but don't rely on it).
|
||||
API backwards compatible changes:
|
||||
- Supports streaming from RAR archives. See RarEntry::getStream() method.
|
||||
- Added a bunch of constants to RarEntry.
|
||||
- Added RarEntry::__toString() method.
|
||||
- Added RarEntry::isDirectory() method.
|
||||
- Added RarEntry::isEncrypted() method.
|
||||
- Added OOP interface for rar_* functions with the RarArchive class.
|
||||
- Added rar_comment_get/RarArchive::getComment().
|
||||
- Added RarArchive::isSolid()/rar_solid_is().
|
||||
- Added RarArchive::__toString() method.
|
||||
- Added RarException class.
|
||||
- Exception throwing for expectable errors can be turned on by calling RarException::setUsingExceptions(). To check whether exception throwing is turned on, RarException::isUsingExceptions() can be used.
|
||||
Bug fixes:
|
||||
- Fixed by PECL bug #8821 (relative paths not working).
|
||||
- Fixed PECL bug #9470 (wrong CRC on multi-volume archives).
|
||||
- Fixed PECL bug #9649 (rar_close() not closing file descriptors if there were undestroyed RarEntry objects)
|
||||
- Fixed volumes opened with middle volumes showing files continued from previous volume with incorrect packed and unpacked sizes.
|
||||
- Fixed bug in UnRAR library that could cause a read out of buffer bounds on some corrupted RAR files.
|
||||
- Fixed RarEntry::getPackedSize() and RarEntry::getUnpackedSize() giving incorrect results for files > 2 GiB. Still, on platforms with 32-bit integers, MAX_INT will be returned for such files, othwerwise the correct value is given.
|
||||
Other changes:
|
||||
- Updated bundled UnRAR library to version 3.9.7 (RAR 3.9.1).
|
||||
- Changed bundled UnRAR library to allow partial file extraction.
|
||||
- All RarEntry properties are now private. This doesn't break the API because those properties were never part of the contract.
|
||||
- rar_open gives more detailed error messages on failure.
|
||||
- Extension now uses extended UnRAR library structures.
|
||||
- Added arginfo.
|
||||
- Added a bunch of tests.
|
||||
- A lot of refactoring and compilation as C, not C++.
|
||||
</notes>
|
||||
</release>
|
||||
|
||||
<release>
|
||||
<version>
|
||||
<release>1.0.0</release>
|
||||
<api>1.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<date>2008-02-26</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>- Upgraded bundled UnRar to version 3.7.8.
|
||||
- Updated source code to use new parameter parsing API.
|
||||
- Fixed PECL bug #9002 (rar_list invalidates rar resource)
|
||||
- Fixed PECL bug #11430 (rar_extract() doesn't close handles gracefully)
|
||||
- rar_open() now throws an error when failed to open the specified file.
|
||||
</notes>
|
||||
</release>
|
||||
|
||||
<release>
|
||||
<version>
|
||||
<release>0.3.1</release>
|
||||
<api>0.3.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2006-08-28</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>- Updated bundled unrar to version 3.6.8.
|
||||
- Fixed PHP4 compatibility.
|
||||
</notes>
|
||||
</release>
|
||||
|
||||
<release>
|
||||
<version>
|
||||
<release>0.3.0</release>
|
||||
<api>0.3.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2006-06-06</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>- Updated bundled unrar to version 3.6.2 (fixes compile errors with GCC4).
|
||||
- Several minor fixes.
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<version>
|
||||
<release>0.2</release>
|
||||
<api>0.2</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2004-12-02</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>1) Added open_basedir and safe_mode checks.
|
||||
2) Fixed Win32 build issues (thanks to Edin).
|
||||
Currently only 5.x builds are available.
|
||||
3) Added OS constants.
|
||||
4) Fixed 0 bugs. There are no bugs, wee =)
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<version>
|
||||
<release>0.1</release>
|
||||
<api>0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>alpha</release>
|
||||
<api>alpha</api>
|
||||
</stability>
|
||||
<date>2004-06-11</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>1) Initial release
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
</package>
|
||||
<!--
|
||||
vim:et:ts=1:sw=1
|
||||
-->
|
||||
304
php_rar.h
304
php_rar.h
@@ -1,304 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 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_0.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. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states, that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* TODO: metadata block reading */
|
||||
/* TODO: correct support for symlinks inside RAR files. This includes:
|
||||
* - Respecting PHP_STREAM_URL_STAT_LINK in the url_stater
|
||||
* - Following the symlinks when asked to open one inside the RAR
|
||||
* Sym link support on windows will be more complicated */
|
||||
/* TODO: add support for opening RAR files in a persisten fashion */
|
||||
/* TODO: consider making struct rar opaque, outside rararch.c only
|
||||
* RarEntry::extract/getStream access the fields */
|
||||
/* TODO: consider using a php memory/tmpfile stream to serve as buffer for
|
||||
* rar file streams */
|
||||
/* TODO: improve RAR archive cache key for url_stater/dir_opener, so that it
|
||||
* can detect file modification */
|
||||
/* TODO: make configurable the capacity of the url_stater/dir_opener cache */
|
||||
/* TODO: optimize _rar_nav_directory_match with the depth */
|
||||
/* TODO: tests with truncated RAR archive (for which _rar_list_files fails) */
|
||||
|
||||
#ifndef PHP_RAR_H
|
||||
#define PHP_RAR_H
|
||||
|
||||
extern zend_module_entry rar_module_entry;
|
||||
#define phpext_rar_ptr &rar_module_entry
|
||||
|
||||
#define PHP_RAR_VERSION "3.0.2"
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define PHP_RAR_API __declspec(dllexport)
|
||||
#else
|
||||
#define PHP_RAR_API
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
/* causes linking errors (multiple definitions) in functions
|
||||
that were requested inlining but were not inlined by the compiler */
|
||||
/* #include "unrar/rar.hpp */
|
||||
/* only these includes are necessary anyway: */
|
||||
#include "unrar/raros.hpp"
|
||||
/* no need to reinclude windows.h or new.h */
|
||||
#define LEAN_RAR_INCLUDES
|
||||
#include "unrar/os.hpp"
|
||||
#include "unrar/dll.hpp"
|
||||
#include "unrar/version.hpp"
|
||||
/* These are in unrar/headers.hpp, but that header depends on several other */
|
||||
enum HOST_SYSTEM {
|
||||
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
|
||||
HOST_BEOS=5,HOST_MAX
|
||||
};
|
||||
#define LHD_WINDOWMASK 0x00e0U
|
||||
#define LHD_DIRECTORY 0x00e0U
|
||||
|
||||
/* maximum comment size if 64KB */
|
||||
#define RAR_MAX_COMMENT_SIZE 65536
|
||||
|
||||
typedef struct _rar_cb_user_data {
|
||||
char *password; /* can be NULL */
|
||||
zval *callable; /* can be NULL */
|
||||
} rar_cb_user_data;
|
||||
|
||||
typedef struct rar {
|
||||
zend_object_handle id;
|
||||
struct _rar_entries *entries;
|
||||
struct RAROpenArchiveDataEx *list_open_data;
|
||||
struct RAROpenArchiveDataEx *extract_open_data;
|
||||
/* archive handle opened with RAR_OM_LIST_INCSPLIT open mode */
|
||||
void *arch_handle;
|
||||
/* user data to pass the RAR callback */
|
||||
rar_cb_user_data cb_userdata;
|
||||
int allow_broken;
|
||||
} rar_file_t;
|
||||
|
||||
/* Misc */
|
||||
#ifdef ZTS
|
||||
# define RAR_TSRMLS_TC , void ***
|
||||
#else
|
||||
# define RAR_TSRMLS_TC
|
||||
#endif
|
||||
|
||||
#define RAR_RETNULL_ON_ARGS() \
|
||||
if (zend_parse_parameters_none() == FAILURE) { \
|
||||
RETURN_NULL(); \
|
||||
}
|
||||
|
||||
/* Per-request cache or make last the duration of the PHP lifespan?
|
||||
* - per-request advantages: we can re-use rar_open and store close RarArchive
|
||||
* objects. We store either pointers to the objects directly and manipulate
|
||||
* the refcount in the store or we store zvals. Either way, we must decrement
|
||||
* the refcounts on request shutdown. Also, the memory usage is best kept
|
||||
* in check because the memory is freed after each request.
|
||||
* - per PHP lifespan advantages: more cache hits. We can also re-use rar_open,
|
||||
* but then we have to copy rar->entries and rar->entries_idx into
|
||||
* persistently allocated buffers since the RarArchive objects cannot be made
|
||||
* persistent themselves.
|
||||
*
|
||||
* I'll go with per-request and store zval pointers with a cache key that
|
||||
* considers filename, modificaion time and stream context (currently only
|
||||
* filename).
|
||||
* I'll also go with a FIFO eviction policy because it's simpler to implement
|
||||
* (just delete the first element of the HashTable).
|
||||
*/
|
||||
typedef struct _rar_contents_cache {
|
||||
int max_size;
|
||||
HashTable *data; /* persistent HashTable, will hold rar_cache_entry */
|
||||
int hits;
|
||||
int misses;
|
||||
/* args: cache key, cache key size, cached object) */
|
||||
void (*put)(const char *, uint, zval * RAR_TSRMLS_TC);
|
||||
zval *(*get)(const char *, uint RAR_TSRMLS_TC);
|
||||
} rar_contents_cache;
|
||||
|
||||
/* Module globals, currently used for dir wrappers cache */
|
||||
ZEND_BEGIN_MODULE_GLOBALS(rar)
|
||||
rar_contents_cache contents_cache;
|
||||
ZEND_END_MODULE_GLOBALS(rar)
|
||||
|
||||
ZEND_EXTERN_MODULE_GLOBALS(rar);
|
||||
|
||||
#ifdef ZTS
|
||||
# define RAR_G(v) TSRMG(rar_globals_id, zend_rar_globals *, v)
|
||||
#else
|
||||
# define RAR_G(v) (rar_globals.v)
|
||||
#endif
|
||||
|
||||
/* PHP 5.2 compatibility */
|
||||
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3
|
||||
#define zend_parse_parameters_none() \
|
||||
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")
|
||||
#define Z_DELREF_P ZVAL_DELREF
|
||||
# define STREAM_ASSUME_REALPATH 0
|
||||
# define ALLOC_PERMANENT_ZVAL(z) \
|
||||
(z) = (zval*) malloc(sizeof(zval));
|
||||
# define OPENBASEDIR_CHECKPATH(filename) \
|
||||
(PG(safe_mode) && \
|
||||
(!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) \
|
||||
|| php_check_open_basedir(filename TSRMLS_CC)
|
||||
# undef ZEND_BEGIN_ARG_INFO_EX
|
||||
# define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
|
||||
static const zend_arg_info name[] = { \
|
||||
{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
|
||||
#endif
|
||||
|
||||
/* Other compatibility quirks */
|
||||
#if !defined(HAVE_STRNLEN) || !HAVE_STRNLEN
|
||||
size_t _rar_strnlen(const char *s, size_t maxlen);
|
||||
# define strnlen _rar_strnlen
|
||||
#else
|
||||
# define _rar_strnlen strnlen
|
||||
#endif
|
||||
|
||||
/* rar.c */
|
||||
PHP_MINIT_FUNCTION(rar);
|
||||
PHP_MSHUTDOWN_FUNCTION(rar);
|
||||
PHP_RINIT_FUNCTION(rar);
|
||||
PHP_RSHUTDOWN_FUNCTION(rar);
|
||||
PHP_MINFO_FUNCTION(rar);
|
||||
|
||||
PHP_FUNCTION(rar_bogus_ctor);
|
||||
|
||||
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size);
|
||||
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size);
|
||||
void _rar_destroy_userdata(rar_cb_user_data *udata);
|
||||
int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
const char *const utf_file_name, /* IN */
|
||||
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
|
||||
void **arc_handle, /* OUT: where to store rar archive handle */
|
||||
int *found, /* OUT */
|
||||
struct RARHeaderDataEx *header_data /* OUT, can be null */
|
||||
);
|
||||
int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
const wchar_t *const file_name, /* IN */
|
||||
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
|
||||
void **arc_handle, /* OUT: where to store rar archive handle */
|
||||
int *found, /* OUT */
|
||||
struct RARHeaderDataEx *header_data /* OUT, can be null */
|
||||
);
|
||||
int _rar_find_file_p(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
size_t position, /* IN */
|
||||
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
|
||||
void **arc_handle, /* OUT: where to store rar archive handle */
|
||||
int *found, /* OUT */
|
||||
struct RARHeaderDataEx *header_data /* OUT, can be null */
|
||||
);
|
||||
int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2);
|
||||
|
||||
/* rar_error.c */
|
||||
extern zend_class_entry *rarexception_ce_ptr;
|
||||
int _rar_handle_error(int errcode TSRMLS_DC);
|
||||
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC);
|
||||
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...);
|
||||
int _rar_using_exceptions(TSRMLS_D);
|
||||
const char * _rar_error_to_string(int errcode);
|
||||
void minit_rarerror(TSRMLS_D);
|
||||
|
||||
/* rar_navigation.c */
|
||||
|
||||
int _rar_list_files(rar_file_t *rar TSRMLS_DC);
|
||||
void _rar_delete_entries(rar_file_t *rar TSRMLS_DC);
|
||||
size_t _rar_entry_count(rar_file_t *rar);
|
||||
|
||||
/* entry search API {{{ */
|
||||
typedef struct _rar_find_output {
|
||||
int found;
|
||||
size_t position;
|
||||
struct RARHeaderDataEx * header;
|
||||
unsigned long packed_size;
|
||||
int eof;
|
||||
} rar_find_output;
|
||||
#define RAR_SEARCH_INDEX 0x01U
|
||||
#define RAR_SEARCH_TRAVERSE 0x01U
|
||||
#define RAR_SEARCH_DIRECTORY 0x02U
|
||||
#define RAR_SEARCH_NAME 0x02U
|
||||
void _rar_entry_search_start(rar_file_t *rar,
|
||||
unsigned mode,
|
||||
rar_find_output **state TSRMLS_DC);
|
||||
void _rar_entry_search_end(rar_find_output *state);
|
||||
void _rar_entry_search_seek(rar_find_output *state, size_t pos);
|
||||
void _rar_entry_search_rewind(rar_find_output *state);
|
||||
void _rar_entry_search_advance(rar_find_output *state,
|
||||
const wchar_t * const file, /* NULL = give next */
|
||||
size_t file_size, /* length + 1 */
|
||||
int directory_match);
|
||||
/* end entry search API }}} */
|
||||
|
||||
/* rararch.c */
|
||||
int _rar_create_rararch_obj(const char* resolved_path,
|
||||
const char* open_password,
|
||||
zval *volume_callback, /* must be callable or NULL */
|
||||
zval *object,
|
||||
int *err_code TSRMLS_DC);
|
||||
void _rar_close_file_resource(rar_file_t *rar);
|
||||
|
||||
/* Fetches the rar_file_t part of the RarArchive object in order to use the
|
||||
* operations above and (discouraged) to have direct access to the fields
|
||||
* RarEntry::extract/getStream access extract_open_dat and cb_userdata */
|
||||
int _rar_get_file_resource(zval *zval_file, rar_file_t **rar_file TSRMLS_DC);
|
||||
int _rar_get_file_resource_ex(zval *zval_file, rar_file_t **rar_file, int silent TSRMLS_DC);
|
||||
void minit_rararch(TSRMLS_D);
|
||||
|
||||
PHP_FUNCTION(rar_open);
|
||||
PHP_FUNCTION(rar_list);
|
||||
PHP_FUNCTION(rar_entry_get);
|
||||
PHP_FUNCTION(rar_solid_is);
|
||||
PHP_FUNCTION(rar_comment_get);
|
||||
PHP_FUNCTION(rar_broken_is);
|
||||
PHP_FUNCTION(rar_allow_broken_set);
|
||||
PHP_FUNCTION(rar_close);
|
||||
|
||||
/* rarentry.c */
|
||||
extern zend_class_entry *rar_class_entry_ptr;
|
||||
void minit_rarentry(TSRMLS_D);
|
||||
void _rar_entry_to_zval(zval *parent,
|
||||
struct RARHeaderDataEx *entry,
|
||||
unsigned long packed_size,
|
||||
size_t index,
|
||||
zval *entry_object TSRMLS_DC);
|
||||
|
||||
/* rar_stream.c */
|
||||
php_stream *php_stream_rar_open(char *arc_name,
|
||||
size_t position,
|
||||
rar_cb_user_data *cb_udata_ptr /* will be copied */
|
||||
STREAMS_DC TSRMLS_DC);
|
||||
extern php_stream_wrapper php_stream_rar_wrapper;
|
||||
|
||||
#endif /* PHP_RAR_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
|
||||
*/
|
||||
789
rar.c
789
rar.c
@@ -1,789 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 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_0.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. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include <php.h>
|
||||
#include <php_ini.h>
|
||||
#include <zend_exceptions.h>
|
||||
#include <ext/standard/info.h>
|
||||
#include <ext/spl/spl_exceptions.h>
|
||||
|
||||
#if HAVE_RAR
|
||||
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Function prototypes for functions with internal linkage */
|
||||
static void _rar_fix_wide(wchar_t *str, size_t max_size);
|
||||
static int _rar_unrar_volume_user_callback(char* dst_buffer,
|
||||
zend_fcall_info *fci,
|
||||
zend_fcall_info_cache *cache
|
||||
TSRMLS_DC);
|
||||
static int _rar_make_userdata_fcall(zval *callable,
|
||||
zend_fcall_info *fci,
|
||||
zend_fcall_info_cache *cache TSRMLS_DC);
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Functions with external linkage */
|
||||
#if !defined(HAVE_STRNLEN) || !HAVE_STRNLEN
|
||||
size_t _rar_strnlen(const char *s, size_t maxlen) /* {{{ */
|
||||
{
|
||||
char *r = memchr(s, '\0', maxlen);
|
||||
return r ? r-s : maxlen;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
/* From unicode.cpp
|
||||
* I can't use that one directy because it takes a const wchar, not wchar_t.
|
||||
* And I shouldn't because it's not a public API.
|
||||
*/
|
||||
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size) /* {{{ */
|
||||
{
|
||||
long dsize= (long) dest_size;
|
||||
dsize--;
|
||||
while (*src != 0 && --dsize >= 0) {
|
||||
uint c =*(src++);
|
||||
if (c < 0x80)
|
||||
*(dest++) = (char) c;
|
||||
else if (c < 0x800 && --dsize >= 0) {
|
||||
*(dest++) = (char) (0xc0 | (c >> 6));
|
||||
*(dest++) = (0x80 | (c & 0x3f));
|
||||
}
|
||||
else if (c < 0x10000 && (dsize -= 2) >= 0) {
|
||||
*(dest++) = (char) (0xe0 | (c >> 12));
|
||||
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
|
||||
*(dest++) = (0x80 | (c & 0x3f));
|
||||
}
|
||||
else if (c < 0x200000 && (dsize -= 3) >= 0) {
|
||||
*(dest++) = (char) (0xf0 | (c >> 18));
|
||||
*(dest++) = (0x80 | ((c >> 12) & 0x3f));
|
||||
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
|
||||
*(dest++) = (0x80 | (c & 0x3f));
|
||||
}
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* idem */
|
||||
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size) /* {{{ */
|
||||
{
|
||||
long dsize = (long) dest_size;
|
||||
dsize--;
|
||||
while (*src != 0) {
|
||||
uint c = (unsigned char) *(src++),
|
||||
d;
|
||||
if (c < 0x80)
|
||||
d = c;
|
||||
else if ((c >> 5) == 6) {
|
||||
if ((*src & 0xc0) != 0x80)
|
||||
break;
|
||||
d=((c & 0x1f) << 6)|(*src & 0x3f);
|
||||
src++;
|
||||
}
|
||||
else if ((c>>4)==14) {
|
||||
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80)
|
||||
break;
|
||||
d = ((c & 0xf) << 12) | ((src[0] & 0x3f) << 6) | (src[1] & 0x3f);
|
||||
src += 2;
|
||||
}
|
||||
else if ((c>>3)==30) {
|
||||
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80)
|
||||
break;
|
||||
d = ((c & 7) << 18) | ((src[0] & 0x3f) << 12) | ((src[1] & 0x3f) << 6) | (src[2] & 0x3f);
|
||||
src += 3;
|
||||
}
|
||||
else
|
||||
break;
|
||||
if (--dsize < 0)
|
||||
break;
|
||||
if (d > 0xffff) {
|
||||
if (--dsize < 0 || d > 0x10ffff)
|
||||
break;
|
||||
*(dest++) = (wchar_t) (((d - 0x10000) >> 10) + 0xd800);
|
||||
*(dest++) = (d & 0x3ff) + 0xdc00;
|
||||
}
|
||||
else
|
||||
*(dest++) = (wchar_t) d;
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void _rar_destroy_userdata(rar_cb_user_data *udata) /* {{{ */
|
||||
{
|
||||
assert(udata != NULL);
|
||||
|
||||
if (udata->password != NULL) {
|
||||
efree(udata->password);
|
||||
}
|
||||
|
||||
if (udata->callable != NULL)
|
||||
zval_ptr_dtor(&udata->callable);
|
||||
|
||||
udata->password = NULL;
|
||||
udata->callable = NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
const char *const utf_file_name, /* IN */
|
||||
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
|
||||
void **arc_handle, /* OUT: where to store rar archive handle */
|
||||
int *found, /* OUT */
|
||||
struct RARHeaderDataEx *header_data /* OUT, can be null */
|
||||
) /* {{{ */
|
||||
{
|
||||
wchar_t *file_name = NULL;
|
||||
size_t utf_file_name_len = strlen(utf_file_name);
|
||||
int ret;
|
||||
|
||||
file_name = ecalloc(utf_file_name_len + 1, sizeof *file_name);
|
||||
_rar_utf_to_wide(utf_file_name, file_name, utf_file_name_len + 1);
|
||||
ret = _rar_find_file_w(open_data, file_name, cb_udata, arc_handle, found,
|
||||
header_data);
|
||||
efree(file_name);
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* WARNING: It's the caller who must close the archive and manage the lifecycle
|
||||
of cb_udata (must be valid while the archive is opened). */
|
||||
/*
|
||||
* This function opens a RAR file and looks for the file with the
|
||||
* name utf_file_name.
|
||||
* If the operation is sucessful, arc_handle is populated with the RAR file
|
||||
* handle, found is set to TRUE if the file is found and FALSE if it is not
|
||||
* found; additionaly, the optional header_data is populated with the first
|
||||
* header that corresponds to the request file. If the file is not found and
|
||||
* header_data is specified, its values are undefined.
|
||||
* Note that even when the file is not found, the caller must still close
|
||||
* the archive.
|
||||
*/
|
||||
int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
const wchar_t *const file_name, /* IN */
|
||||
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
|
||||
void **arc_handle, /* OUT: where to store rar archive handle */
|
||||
int *found, /* OUT */
|
||||
struct RARHeaderDataEx *header_data /* OUT, can be null */
|
||||
) /* {{{ */
|
||||
{
|
||||
int result,
|
||||
process_result;
|
||||
struct RARHeaderDataEx *used_header_data;
|
||||
int retval = 0; /* success in rar parlance */
|
||||
|
||||
assert(open_data != NULL);
|
||||
assert(file_name != NULL);
|
||||
assert(arc_handle != NULL);
|
||||
assert(found != NULL);
|
||||
*found = FALSE;
|
||||
*arc_handle = NULL;
|
||||
used_header_data = header_data != NULL ?
|
||||
header_data :
|
||||
ecalloc(1, sizeof *used_header_data);
|
||||
|
||||
*arc_handle = RAROpenArchiveEx(open_data);
|
||||
if (*arc_handle == NULL) {
|
||||
retval = open_data->OpenResult;
|
||||
goto cleanup;
|
||||
}
|
||||
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) cb_udata);
|
||||
|
||||
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
|
||||
#if WCHAR_MAX > 0xffff
|
||||
_rar_fix_wide(used_header_data->FileNameW, NM);
|
||||
#endif
|
||||
|
||||
if (wcsncmp(used_header_data->FileNameW, file_name, NM) == 0) {
|
||||
*found = TRUE;
|
||||
goto cleanup;
|
||||
} else {
|
||||
process_result = RARProcessFile(*arc_handle, RAR_SKIP, NULL, NULL);
|
||||
}
|
||||
if (process_result != 0) {
|
||||
retval = process_result;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != 0 && result != 1) {
|
||||
/* 0 indicates success, 1 indicates normal end of file */
|
||||
retval = result;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (header_data == NULL)
|
||||
efree(used_header_data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int _rar_find_file_p(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
size_t position, /* IN */
|
||||
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
|
||||
void **arc_handle, /* OUT: where to store rar archive handle */
|
||||
int *found, /* OUT */
|
||||
struct RARHeaderDataEx *header_data /* OUT, can be null */
|
||||
) /* {{{ */
|
||||
{
|
||||
int result,
|
||||
process_result;
|
||||
struct RARHeaderDataEx *used_header_data;
|
||||
int retval = 0; /* success in rar parlance */
|
||||
size_t curpos = 0;
|
||||
|
||||
assert(open_data != NULL);
|
||||
assert(arc_handle != NULL);
|
||||
assert(found != NULL);
|
||||
*found = FALSE;
|
||||
*arc_handle = NULL;
|
||||
used_header_data = header_data != NULL ?
|
||||
header_data :
|
||||
ecalloc(1, sizeof *used_header_data);
|
||||
|
||||
*arc_handle = RAROpenArchiveEx(open_data);
|
||||
if (*arc_handle == NULL) {
|
||||
retval = open_data->OpenResult;
|
||||
goto cleanup;
|
||||
}
|
||||
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) cb_udata);
|
||||
|
||||
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
|
||||
/* skip entries that were split before with incrementing current pos */
|
||||
if ((used_header_data->Flags & 0x01U) || (curpos++ != position)) {
|
||||
process_result = RARProcessFile(*arc_handle, RAR_SKIP, NULL, NULL);
|
||||
} else {
|
||||
*found = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
if (process_result != 0) {
|
||||
retval = process_result;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != 0 && result != 1) {
|
||||
/* 0 indicates success, 1 indicates normal end of file */
|
||||
retval = result;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (header_data == NULL)
|
||||
efree(used_header_data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* An unRAR callback.
|
||||
* Processes requests for passwords and missing volumes
|
||||
* If there is (userland) volume find callback specified, try to use that
|
||||
* callback to retrieve the name of the missing volume. Otherwise, or if
|
||||
* the volume find callback returns null, cancel the operation. */
|
||||
int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2) /* {{{ */
|
||||
{
|
||||
rar_cb_user_data *userdata = (rar_cb_user_data*) UserData;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (msg == UCM_NEEDPASSWORD) {
|
||||
/* user data is the password or null if none */
|
||||
char *password = userdata->password;
|
||||
|
||||
if (password == NULL || password[0] == '\0') {
|
||||
/*php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Password needed, but it has not been specified");*/
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
strncpy((char *) P1, password, (size_t) P2);
|
||||
assert((size_t) P2 > 0);
|
||||
((char *) P1)[(size_t) P2 - 1] = '\0';
|
||||
}
|
||||
}
|
||||
else if (msg == UCM_CHANGEVOLUME) {
|
||||
if (((int) P2) == RAR_VOL_ASK) {
|
||||
int ret, called_cb = 0;
|
||||
if (userdata->callable == NULL) {
|
||||
/* if there's no callback, abort */
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache cache;
|
||||
/* make_userdata_fcall and volume_user_callback are chatty */
|
||||
if (_rar_make_userdata_fcall(userdata->callable, &fci, &cache
|
||||
TSRMLS_CC) == SUCCESS) {
|
||||
ret = _rar_unrar_volume_user_callback(
|
||||
(char*) P1, &fci, &cache TSRMLS_CC);
|
||||
called_cb = 1;
|
||||
}
|
||||
else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* always a warning, never an exception here */
|
||||
if (ret == -1 && !called_cb)
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Volume %s was not found", (char*) P1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_FUNCTION(rar_bogus_ctor) /* {{{ */
|
||||
{
|
||||
/* This exception should not be thrown. The point is to add this as
|
||||
* a class constructor and make it private. This code would be able to
|
||||
* run only if the constructor were made public */
|
||||
zend_throw_exception(NULL,
|
||||
"An object of this type cannot be created with the new operator.",
|
||||
0 TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_FUNCTION(rar_wrapper_cache_stats) /* {{{ */
|
||||
{
|
||||
char *result = NULL;
|
||||
int len;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE)
|
||||
return;
|
||||
|
||||
len = spprintf(&result, 0, "%u/%u (hits/misses)",
|
||||
RAR_G(contents_cache).hits, RAR_G(contents_cache).misses);
|
||||
|
||||
RETURN_STRINGL(result, len, 0);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Functions with internal linkage */
|
||||
/*
|
||||
* Only relevant when sizeof(wchar_t) > 2 (so not windows).
|
||||
* Removes the characters use value if > 0x10ffff; these are not
|
||||
* valid UTF characters.
|
||||
*/
|
||||
|
||||
static void _rar_fix_wide(wchar_t *str, size_t max_size) /* {{{ */
|
||||
{
|
||||
wchar_t *write,
|
||||
*read,
|
||||
*max_fin;
|
||||
max_fin = str + max_size;
|
||||
for (write = str, read = str; *read != L'\0' && read != max_fin; read++) {
|
||||
if ((unsigned) *read <= 0x10ffff)
|
||||
*(write++) = *read;
|
||||
}
|
||||
*write = L'\0';
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* called from the RAR callback; calls a user callback in case a volume was
|
||||
* not found
|
||||
* This function sends messages instead of calling _rar_handle_ext_error
|
||||
* because, in case we're using exceptions, we want to let an exception with
|
||||
* error code ERAR_EOPEN to be thrown.
|
||||
*/
|
||||
static int _rar_unrar_volume_user_callback(char* dst_buffer,
|
||||
zend_fcall_info *fci,
|
||||
zend_fcall_info_cache *cache
|
||||
TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *failed_vol,
|
||||
*retval_ptr = NULL,
|
||||
**params;
|
||||
int ret = -1;
|
||||
|
||||
MAKE_STD_ZVAL(failed_vol);
|
||||
ZVAL_STRING(failed_vol, dst_buffer, 1);
|
||||
params = &failed_vol;
|
||||
fci->retval_ptr_ptr = &retval_ptr;
|
||||
fci->params = ¶ms;
|
||||
fci->param_count = 1;
|
||||
|
||||
if (zend_call_function(fci, cache TSRMLS_CC) != SUCCESS ||
|
||||
fci->retval_ptr_ptr == NULL ||
|
||||
*fci->retval_ptr_ptr == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Failure to call volume find callback");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
assert(*fci->retval_ptr_ptr == retval_ptr);
|
||||
if (Z_TYPE_P(retval_ptr) == IS_NULL) {
|
||||
/* let return -1 */
|
||||
}
|
||||
else if (Z_TYPE_P(retval_ptr) == IS_STRING) {
|
||||
char *filename = Z_STRVAL_P(retval_ptr);
|
||||
char resolved_path[MAXPATHLEN];
|
||||
size_t resolved_len;
|
||||
|
||||
if (OPENBASEDIR_CHECKPATH(filename)) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Cound not expand filename %s", filename);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
resolved_len = _rar_strnlen(resolved_path, MAXPATHLEN);
|
||||
/* dst_buffer size is NM; first condition won't happen short of a bug
|
||||
* in expand_filepath */
|
||||
if (resolved_len == MAXPATHLEN || resolved_len > NM - 1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Resolved path is too big for the unRAR library");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
strncpy(dst_buffer, resolved_path, NM);
|
||||
dst_buffer[NM - 1] = '\0';
|
||||
ret = 1; /* try this new filename */
|
||||
}
|
||||
else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Wrong type returned by volume find callback, "
|
||||
"expected string or NULL");
|
||||
/* let return -1 */
|
||||
}
|
||||
|
||||
cleanup:
|
||||
zval_ptr_dtor(&failed_vol);
|
||||
if (retval_ptr != NULL)
|
||||
zval_ptr_dtor(&retval_ptr);
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_make_userdata_fcall(zval *callable,
|
||||
zend_fcall_info *fci,
|
||||
zend_fcall_info_cache *cache TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *error = NULL;
|
||||
assert(callable != NULL);
|
||||
assert(fci != NULL);
|
||||
assert(cache != NULL);
|
||||
|
||||
*cache = empty_fcall_info_cache;
|
||||
|
||||
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 2
|
||||
if (zend_fcall_info_init(callable, fci, cache TSRMLS_CC) != SUCCESS) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"The RAR file was not opened in rar_open/RarArchive::open with a "
|
||||
"valid callback.", error);
|
||||
return FAILURE;
|
||||
}
|
||||
else {
|
||||
return SUCCESS;
|
||||
}
|
||||
#else
|
||||
if (zend_fcall_info_init(callable, IS_CALLABLE_STRICT, fci, cache, NULL,
|
||||
&error TSRMLS_CC) == SUCCESS) {
|
||||
if (error) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_STRICT,
|
||||
"The RAR file was not opened with a strictly valid callback (%s)",
|
||||
error);
|
||||
efree(error);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
else {
|
||||
if (error) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_STRICT,
|
||||
"The RAR file was not opened with a valid callback (%s)",
|
||||
error);
|
||||
efree(error);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* }}} */
|
||||
|
||||
#ifdef COMPILE_DL_RAR
|
||||
ZEND_GET_MODULE(rar)
|
||||
#endif
|
||||
|
||||
/* {{{ arginfo */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_open, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_ARG_INFO(0, volume_callback)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_void_archmeth, 0, 0, 1)
|
||||
#if 0 /* don't turn on type hinting yet */
|
||||
ZEND_ARG_OBJ_INFO(0, rarfile, RarArchive, 0)
|
||||
#else
|
||||
ZEND_ARG_INFO(0, rarfile)
|
||||
#endif
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_entry_get, 0, 0, 2)
|
||||
#if 0 /* don't turn on type hinting yet */
|
||||
ZEND_ARG_OBJ_INFO(0, rarfile, RarArchive, 0)
|
||||
#else
|
||||
ZEND_ARG_INFO(0, rarfile)
|
||||
#endif
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_allow_broken_set, 0, 0, 2)
|
||||
#if 0 /* don't turn on type hinting yet */
|
||||
ZEND_ARG_OBJ_INFO(0, rarfile, RarArchive, 0)
|
||||
#else
|
||||
ZEND_ARG_INFO(0, rarfile)
|
||||
#endif
|
||||
ZEND_ARG_INFO(0, allow_broken)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_rar_wrapper_cache_stats, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rar_functions[]
|
||||
*
|
||||
*/
|
||||
static zend_function_entry rar_functions[] = {
|
||||
PHP_FE(rar_open, arginfo_rar_open)
|
||||
PHP_FE(rar_list, arginfo_rar_void_archmeth)
|
||||
PHP_FE(rar_entry_get, arginfo_rar_entry_get)
|
||||
PHP_FE(rar_solid_is, arginfo_rar_void_archmeth)
|
||||
PHP_FE(rar_comment_get, arginfo_rar_void_archmeth)
|
||||
PHP_FE(rar_broken_is, arginfo_rar_void_archmeth)
|
||||
PHP_FE(rar_allow_broken_set, arginfo_rar_allow_broken_set)
|
||||
PHP_FE(rar_close, arginfo_rar_void_archmeth)
|
||||
PHP_FE(rar_wrapper_cache_stats, arginfo_rar_wrapper_cache_stats)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Globals' related activities */
|
||||
ZEND_DECLARE_MODULE_GLOBALS(rar);
|
||||
|
||||
static int _rar_array_apply_remove_first(void *pDest TSRMLS_DC)
|
||||
{
|
||||
return (ZEND_HASH_APPLY_STOP | ZEND_HASH_APPLY_REMOVE);
|
||||
}
|
||||
|
||||
/* caller should increment zval refcount before calling this */
|
||||
static void _rar_contents_cache_put(const char *key,
|
||||
uint key_len,
|
||||
zval *zv TSRMLS_DC)
|
||||
{
|
||||
rar_contents_cache *cc = &RAR_G(contents_cache);
|
||||
int cur_size;
|
||||
|
||||
cur_size = zend_hash_num_elements(cc->data);
|
||||
if (cur_size == cc->max_size) {
|
||||
zend_hash_apply(cc->data, _rar_array_apply_remove_first TSRMLS_CC);
|
||||
assert(zend_hash_num_elements(cc->data) == cur_size - 1);
|
||||
}
|
||||
zval_add_ref(&zv);
|
||||
zend_hash_update(cc->data, key, key_len, &zv, sizeof(zv), NULL);
|
||||
}
|
||||
|
||||
static zval *_rar_contents_cache_get(const char *key,
|
||||
uint key_len TSRMLS_DC)
|
||||
{
|
||||
rar_contents_cache *cc = &RAR_G(contents_cache);
|
||||
zval **element = NULL;
|
||||
zend_hash_find(cc->data, key, key_len, (void **) &element);
|
||||
|
||||
if (element != NULL) {
|
||||
cc->hits++;
|
||||
zval_add_ref(element);
|
||||
return *element;
|
||||
}
|
||||
else {
|
||||
cc->misses++;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* ZEND_MODULE_GLOBALS_CTOR_D declares it receiving zend_rar_globals*,
|
||||
* which is incompatible; once cast into ts_allocate_ctor by the macro,
|
||||
* ZEND_INIT_MODULE_GLOBALS, it cannot (per the spec) be used. */
|
||||
static void ZEND_MODULE_GLOBALS_CTOR_N(rar)(void *arg TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_rar_globals *rar_globals = arg;
|
||||
rar_globals->contents_cache.max_size = 5; /* TODO make configurable */
|
||||
rar_globals->contents_cache.hits = 0;
|
||||
rar_globals->contents_cache.misses = 0;
|
||||
rar_globals->contents_cache.put = _rar_contents_cache_put;
|
||||
rar_globals->contents_cache.get = _rar_contents_cache_get;
|
||||
rar_globals->contents_cache.data =
|
||||
pemalloc(sizeof *rar_globals->contents_cache.data, 1);
|
||||
zend_hash_init(rar_globals->contents_cache.data,
|
||||
rar_globals->contents_cache.max_size, NULL,
|
||||
ZVAL_PTR_DTOR, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void ZEND_MODULE_GLOBALS_DTOR_N(rar)(void *arg TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_rar_globals *rar_globals = arg;
|
||||
zend_hash_destroy(rar_globals->contents_cache.data);
|
||||
pefree(rar_globals->contents_cache.data, 1);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ZEND_MODULE_STARTUP */
|
||||
ZEND_MODULE_STARTUP_D(rar)
|
||||
{
|
||||
minit_rararch(TSRMLS_C);
|
||||
minit_rarentry(TSRMLS_C);
|
||||
minit_rarerror(TSRMLS_C);
|
||||
|
||||
/* This doesn't work, it tries to call the destructor after the
|
||||
* module has been unloaded. This information is in the zend_module_entry
|
||||
* instead; that information is correctly used before the module is
|
||||
* unloaded */
|
||||
/* ZEND_INIT_MODULE_GLOBALS(rar, ZEND_MODULE_GLOBALS_CTOR_N(rar),
|
||||
ZEND_MODULE_GLOBALS_DTOR_N(rar)); */
|
||||
|
||||
php_register_url_stream_wrapper("rar", &php_stream_rar_wrapper TSRMLS_CC);
|
||||
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_MSDOS", HOST_MSDOS, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_OS2", HOST_OS2, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_WIN32", HOST_WIN32, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_UNIX", HOST_UNIX, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_MACOS", HOST_MACOS, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_BEOS", HOST_BEOS, CONST_CS | CONST_PERSISTENT);
|
||||
/* PHP < 5.3 doesn't have the PHP_MAXPATHLEN constant */
|
||||
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3
|
||||
REGISTER_LONG_CONSTANT("RAR_MAXPATHLEN", MAXPATHLEN, CONST_CS | CONST_PERSISTENT);
|
||||
#endif
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ZEND_MODULE_DEACTIVATE */
|
||||
ZEND_MODULE_DEACTIVATE_D(rar)
|
||||
{
|
||||
/* clean cache on request shutdown */
|
||||
zend_hash_clean(RAR_G(contents_cache).data);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ZEND_MODULE_INFO */
|
||||
ZEND_MODULE_INFO_D(rar)
|
||||
{
|
||||
char version[256];
|
||||
char api_version[256];
|
||||
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_header(2, "RAR support", "enabled");
|
||||
php_info_print_table_row(2, "RAR EXT version", PHP_RAR_VERSION);
|
||||
|
||||
#if RARVER_BETA != 0
|
||||
sprintf(version,"%d.%02d beta%d patch%d %d-%02d-%02d", RARVER_MAJOR,
|
||||
RARVER_MINOR, RARVER_BETA, RARVER_PATCH, RARVER_YEAR, RARVER_MONTH,
|
||||
RARVER_DAY);
|
||||
#else
|
||||
sprintf(version,"%d.%02d patch%d %d-%02d-%02d", RARVER_MAJOR, RARVER_MINOR,
|
||||
RARVER_PATCH, RARVER_YEAR, RARVER_MONTH, RARVER_DAY);
|
||||
#endif
|
||||
|
||||
sprintf(api_version,"%d extension %d", RAR_DLL_VERSION,
|
||||
RAR_DLL_EXT_VERSION);
|
||||
|
||||
php_info_print_table_row(2, "UnRAR version", version);
|
||||
php_info_print_table_row(2, "UnRAR API version", api_version);
|
||||
php_info_print_table_end();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rar_module_entry
|
||||
*/
|
||||
zend_module_entry rar_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"rar",
|
||||
rar_functions,
|
||||
ZEND_MODULE_STARTUP_N(rar),
|
||||
/* ZEND_MODULE_SHUTDOWN_N(rar), */
|
||||
NULL,
|
||||
/* ZEND_MODULE_ACTIVATE_N(rar), */
|
||||
NULL,
|
||||
ZEND_MODULE_DEACTIVATE_N(rar),
|
||||
ZEND_MODULE_INFO_N(rar),
|
||||
PHP_RAR_VERSION,
|
||||
ZEND_MODULE_GLOBALS(rar),
|
||||
ZEND_MODULE_GLOBALS_CTOR_N(rar),
|
||||
ZEND_MODULE_GLOBALS_DTOR_N(rar),
|
||||
NULL, /* post_deactivate_func */
|
||||
STANDARD_MODULE_PROPERTIES_EX,
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
#endif /* HAVE_RAR */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
238
rar_error.c
238
rar_error.c
@@ -1,238 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 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_0.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. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <php.h>
|
||||
#include <zend_exceptions.h>
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Globals with external linkage */
|
||||
zend_class_entry *rarexception_ce_ptr;
|
||||
/* }}} */
|
||||
|
||||
/* Functions with external linkage {{{ */
|
||||
/* Functions with external linkage {{{ */
|
||||
int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return _rar_handle_error_ex("", errcode TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const char *err = _rar_error_to_string(errcode);
|
||||
|
||||
if (err == NULL) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (_rar_using_exceptions(TSRMLS_C)) {
|
||||
zend_throw_exception_ex(rarexception_ce_ptr, errcode TSRMLS_CC,
|
||||
"unRAR internal error: %s%s", preamble, err);
|
||||
}
|
||||
else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s", preamble, err);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Errors not related to the unRAR library */
|
||||
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...) /* {{{ */
|
||||
{
|
||||
va_list arg;
|
||||
char *message;
|
||||
|
||||
#ifdef ZTS
|
||||
va_start(arg, TSRMLS_C);
|
||||
#else
|
||||
va_start(arg, format);
|
||||
#endif
|
||||
vspprintf(&message, 0, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (_rar_using_exceptions(TSRMLS_C))
|
||||
zend_throw_exception(rarexception_ce_ptr, message, -1L TSRMLS_CC);
|
||||
else
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
|
||||
efree(message);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int _rar_using_exceptions(TSRMLS_D)
|
||||
{
|
||||
zval *pval;
|
||||
pval = zend_read_static_property(rarexception_ce_ptr, "usingExceptions",
|
||||
sizeof("usingExceptions") -1, (zend_bool) 1 TSRMLS_CC);
|
||||
assert(Z_TYPE_P(pval) == IS_BOOL);
|
||||
|
||||
return Z_BVAL_P(pval);
|
||||
}
|
||||
|
||||
/* returns a string or NULL if not an error */
|
||||
const char * _rar_error_to_string(int errcode) /* {{{ */
|
||||
{
|
||||
const char *ret;
|
||||
switch (errcode) {
|
||||
case 0:
|
||||
/* no error */
|
||||
case 1:
|
||||
/* no error (comment completely read) */
|
||||
case ERAR_END_ARCHIVE:
|
||||
/* no error */
|
||||
ret = NULL;
|
||||
break;
|
||||
case ERAR_NO_MEMORY:
|
||||
ret = "ERAR_NO_MEMORY (not enough memory)";
|
||||
break;
|
||||
case ERAR_BAD_DATA:
|
||||
ret = "ERAR_BAD_DATA";
|
||||
break;
|
||||
case ERAR_BAD_ARCHIVE:
|
||||
ret = "ERAR_BAD_ARCHIVE";
|
||||
break;
|
||||
case ERAR_UNKNOWN_FORMAT:
|
||||
ret = "ERAR_UNKNOWN_FORMAT";
|
||||
break;
|
||||
case ERAR_EOPEN:
|
||||
ret = "ERAR_EOPEN (file open error)";
|
||||
break;
|
||||
case ERAR_ECREATE:
|
||||
ret = "ERAR_ECREATE";
|
||||
break;
|
||||
case ERAR_ECLOSE:
|
||||
ret = "ERAR_ECLOSE (error closing file)";
|
||||
break;
|
||||
case ERAR_EREAD:
|
||||
ret = "ERAR_EREAD";
|
||||
break;
|
||||
case ERAR_EWRITE:
|
||||
ret = "ERAR_EWRITE";
|
||||
break;
|
||||
case ERAR_SMALL_BUF:
|
||||
ret = "ERAR_SMALL_BUF";
|
||||
break;
|
||||
case ERAR_UNKNOWN:
|
||||
ret = "ERAR_UNKNOWN (unknown RAR error)";
|
||||
break;
|
||||
case ERAR_MISSING_PASSWORD:
|
||||
ret = "ERAR_MISSING_PASSWORD (password needed but not specified)";
|
||||
break;
|
||||
default:
|
||||
ret = "unknown RAR error (should not happen)";
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool RarException::setUsingExceptions(using_exceptions)
|
||||
Set whether exceptions are to be used */
|
||||
PHP_METHOD(rarexception, setUsingExceptions)
|
||||
{
|
||||
zend_bool argval;
|
||||
int result;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &argval) == FAILURE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = zend_update_static_property_bool(rarexception_ce_ptr,
|
||||
"usingExceptions", sizeof("usingExceptions") -1,
|
||||
(long) argval TSRMLS_CC);
|
||||
|
||||
if (result == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Could not set error handling mode. "
|
||||
"This is a bug, please report it.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool RarException::isUsingExceptions()
|
||||
Return whether exceptions are being used */
|
||||
PHP_METHOD(rarexception, isUsingExceptions)
|
||||
{
|
||||
zval **pval;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* or zend_read_static_property, which calls zend_std_get... after chg scope */
|
||||
#if PHP_VERSION_ID < 50399
|
||||
pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
|
||||
sizeof("usingExceptions") -1, (zend_bool) 0 TSRMLS_CC);
|
||||
#else
|
||||
pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
|
||||
sizeof("usingExceptions") -1, (zend_bool) 0, NULL TSRMLS_CC);
|
||||
#endif
|
||||
/* property always exists */
|
||||
assert(pval != NULL);
|
||||
assert(Z_TYPE_PP(pval) == IS_BOOL);
|
||||
|
||||
RETURN_ZVAL(*pval, 0, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ arginfo */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarexception_sue, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, using_exceptions)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_rarexception_void, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
|
||||
static zend_function_entry php_rarexception_class_functions[] = {
|
||||
PHP_ME(rarexception, setUsingExceptions, arginfo_rarexception_sue, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
|
||||
PHP_ME(rarexception, isUsingExceptions, arginfo_rarexception_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
void minit_rarerror(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "RarException", php_rarexception_class_functions);
|
||||
rarexception_ce_ptr = zend_register_internal_class_ex(&ce,
|
||||
zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
|
||||
rarexception_ce_ptr->ce_flags |= ZEND_ACC_FINAL;
|
||||
zend_declare_property_bool(rarexception_ce_ptr, "usingExceptions",
|
||||
sizeof("usingExceptions") -1, 0L /* FALSE */,
|
||||
ZEND_ACC_PRIVATE | ZEND_ACC_STATIC TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
597
rar_navigation.c
597
rar_navigation.c
@@ -1,597 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 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_0.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. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <php.h>
|
||||
#include <wchar.h>
|
||||
#include "php_rar.h"
|
||||
|
||||
#if HAVE_RAR
|
||||
|
||||
/* {{{ Structure definitions */
|
||||
|
||||
typedef struct _rar_find_state {
|
||||
rar_find_output out;
|
||||
rar_file_t *rar;
|
||||
size_t index; /* next unread in entries_array or entries_array_s */
|
||||
} rar_find_state;
|
||||
|
||||
struct _rar_unique_entry {
|
||||
size_t id; /* position in the entries_array */
|
||||
struct RARHeaderDataEx entry; /* last entry */
|
||||
unsigned long packed_size;
|
||||
int depth; /* number of directory separators */
|
||||
size_t name_wlen; /* excluding L'\0' terminator */
|
||||
};
|
||||
|
||||
/* last_accessed has the index of the last accessed entry. Its purpose is to make
|
||||
* more efficient the situation wherein the user traverses a directory and
|
||||
* stats each the gotten entry in each iteration. This gives 100% cache hits in
|
||||
* directory traversal tests 064 and 065 for exact name searches */
|
||||
struct _rar_entries {
|
||||
size_t num_entries;
|
||||
struct _rar_unique_entry **entries_array; /* shoud not be NULL */
|
||||
struct _rar_unique_entry **entries_array_s; /* sorted version for bsearch */
|
||||
struct _rar_unique_entry *last_accessed;
|
||||
int list_result; /* tell whether the archive's broken */
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ Function prototypes for functions with internal linkage */
|
||||
static void _rar_nav_get_depth_and_length(wchar_t *filenamew, const size_t file_size,
|
||||
int *depth_out, size_t *wlen_out TSRMLS_DC);
|
||||
static int _rar_nav_get_depth(const wchar_t *filenamew, const size_t file_size);
|
||||
static int _rar_nav_compare_entries(const void *op1, const void *op2 TSRMLS_DC);
|
||||
static int _rar_nav_compare_entries_std(const void *op1, const void *op2);
|
||||
static inline int _rar_nav_compare_values(const wchar_t *str1, const int depth1,
|
||||
const wchar_t *str2, const int depth2,
|
||||
const size_t max_size);
|
||||
static int _rar_nav_directory_match(const wchar_t *dir, const size_t dir_len,
|
||||
const wchar_t *entry, const size_t entry_len);
|
||||
static size_t _rar_nav_position_on_dir_start(const wchar_t *dir_name,
|
||||
int dir_depth,
|
||||
size_t dir_size,
|
||||
struct _rar_unique_entry **entries,
|
||||
size_t low, size_t high);
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ Functions with external linkage */
|
||||
|
||||
/* {{{ _rar_entry_count */
|
||||
size_t _rar_entry_count(rar_file_t *rar) {
|
||||
return rar->entries->num_entries;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rar_entry_search_start */
|
||||
void _rar_entry_search_start(rar_file_t *rar,
|
||||
unsigned mode,
|
||||
rar_find_output **state TSRMLS_DC)
|
||||
{
|
||||
rar_find_state **out = (rar_find_state **) state;
|
||||
assert(out != NULL);
|
||||
*out = ecalloc(1, sizeof **out);
|
||||
(*out)->rar = rar;
|
||||
(*out)->out.position = -1;
|
||||
assert(rar->entries != NULL);
|
||||
assert(rar->entries->num_entries == 0 || rar->entries->entries_array != NULL);
|
||||
if ((mode & 0x02U) && (rar->entries->num_entries > 0) &&
|
||||
(rar->entries->entries_array_s == NULL)) {
|
||||
rar->entries->entries_array_s = emalloc(rar->entries->num_entries *
|
||||
sizeof rar->entries->entries_array_s[0]);
|
||||
memcpy(rar->entries->entries_array_s, rar->entries->entries_array,
|
||||
rar->entries->num_entries * sizeof rar->entries->entries_array[0]);
|
||||
zend_qsort(rar->entries->entries_array_s, rar->entries->num_entries,
|
||||
sizeof *rar->entries->entries_array_s, _rar_nav_compare_entries
|
||||
TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rar_entry_search_seek */
|
||||
void _rar_entry_search_seek(rar_find_output *state, size_t pos)
|
||||
{
|
||||
rar_find_state *rstate = (rar_find_state *) state;
|
||||
assert(pos >= 0);
|
||||
rstate->out.eof = 0;
|
||||
rstate->out.found = 0;
|
||||
rstate->out.position = -1;
|
||||
rstate->out.header = NULL;
|
||||
rstate->out.packed_size = 0;
|
||||
rstate->index = pos;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rar_entry_search_end */
|
||||
void _rar_entry_search_end(rar_find_output *state)
|
||||
{
|
||||
efree(state);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rar_entry_search_rewind */
|
||||
void _rar_entry_search_rewind(rar_find_output *state)
|
||||
{
|
||||
rar_find_state *rstate = (rar_find_state *) state;
|
||||
rstate->out.eof = 0;
|
||||
rstate->out.found = 0;
|
||||
rstate->out.position = -1;
|
||||
rstate->out.header = NULL;
|
||||
rstate->out.packed_size = 0;
|
||||
rstate->index = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rar_entry_search_advance */
|
||||
void _rar_entry_search_advance(rar_find_output *state,
|
||||
const wchar_t * const file, /* NULL = give next */
|
||||
size_t file_size, /* length + 1; 0 if unknown */
|
||||
int directory_match)
|
||||
{
|
||||
rar_find_state *rstate = (rar_find_state *) state;
|
||||
struct _rar_entries *entries;
|
||||
int found = FALSE;
|
||||
int in_sorted;
|
||||
size_t filenamewsize;
|
||||
|
||||
assert(state != NULL);
|
||||
assert(file == NULL || file_size == 0 || file[file_size - 1] == L'\0');
|
||||
|
||||
entries = rstate->rar->entries;
|
||||
assert(entries != NULL);
|
||||
|
||||
if ((file != NULL) && (file_size == 0))
|
||||
file_size = wcslen(file) + 1;
|
||||
|
||||
/* reset output */
|
||||
memset(&rstate->out, 0, sizeof rstate->out);
|
||||
|
||||
filenamewsize = sizeof(entries->entries_array[0]->entry.FileNameW) /
|
||||
sizeof(entries->entries_array[0]->entry.FileNameW[0]); /* = 1024 */
|
||||
if (rstate->out.eof || (rstate->index >= entries->num_entries) ||
|
||||
(file_size > filenamewsize)) {
|
||||
rstate->out.found = 0;
|
||||
rstate->out.eof = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* three different cases:
|
||||
* (1) ask next
|
||||
* (2) ask by name
|
||||
* (3) ask next directory child */
|
||||
|
||||
if (!directory_match && (file == NULL)) {
|
||||
/* ask next */
|
||||
in_sorted = FALSE;
|
||||
found = TRUE;
|
||||
/* populate cache for exact name access */
|
||||
entries->last_accessed = entries->entries_array[rstate->index];
|
||||
}
|
||||
else if (!directory_match) {
|
||||
/* ask by exact name */
|
||||
struct _rar_unique_entry temp_entry,
|
||||
*temp_entry_ptr = &temp_entry,
|
||||
**found_entry;
|
||||
/* try to hit cache */
|
||||
if (entries->last_accessed != NULL) {
|
||||
if ((entries->last_accessed->name_wlen == file_size - 1) &&
|
||||
wmemcmp(entries->last_accessed->entry.FileNameW, file,
|
||||
file_size) == 0) {
|
||||
/* cache hit */
|
||||
in_sorted = FALSE;
|
||||
found = TRUE;
|
||||
rstate->index = entries->last_accessed->id;
|
||||
/*php_printf("cache hit\n", entries);*/
|
||||
}
|
||||
else {
|
||||
entries->last_accessed = NULL;
|
||||
/*php_printf("cache miss\n", entries);*/
|
||||
}
|
||||
}
|
||||
/*else
|
||||
php_printf("cache miss (empty)\n", entries);*/
|
||||
|
||||
if (!found) { /* the cache didn't do; use binary search */
|
||||
wmemcpy(temp_entry.entry.FileNameW, file, file_size);
|
||||
temp_entry.depth = _rar_nav_get_depth(file, file_size);
|
||||
found_entry = bsearch(&temp_entry_ptr,
|
||||
&entries->entries_array_s[rstate->index],
|
||||
entries->num_entries - rstate->index,
|
||||
sizeof entries->entries_array_s[0],
|
||||
_rar_nav_compare_entries_std);
|
||||
if (found_entry != NULL) {
|
||||
in_sorted = TRUE;
|
||||
found = TRUE;
|
||||
rstate->index = found_entry - entries->entries_array_s;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* ask by next directory child */
|
||||
struct _rar_unique_entry *cur = entries->entries_array_s[rstate->index];
|
||||
in_sorted = TRUE;
|
||||
assert(file != NULL);
|
||||
if (_rar_nav_directory_match(file, file_size - 1,
|
||||
cur->entry.FileNameW, cur->name_wlen)) {
|
||||
found = TRUE;
|
||||
/* populate cache for exact name access */
|
||||
entries->last_accessed = cur;
|
||||
}
|
||||
else {
|
||||
/* no directory match for current */
|
||||
int comp, dir_depth;
|
||||
dir_depth = _rar_nav_get_depth(file, file_size);
|
||||
comp = _rar_nav_compare_values(cur->entry.FileNameW, cur->depth,
|
||||
file, dir_depth + 1, file_size); /* guaranteed file_size <= 1024 */
|
||||
assert(comp != 0); /* because + 1 was summed to the depth */
|
||||
if (comp > 0) {
|
||||
/* past the entries of the directory */
|
||||
/* do nothing */
|
||||
}
|
||||
else {
|
||||
int pos = _rar_nav_position_on_dir_start(file, dir_depth,
|
||||
file_size, entries->entries_array_s, rstate->index,
|
||||
entries->num_entries);
|
||||
if (pos != -1) {
|
||||
found = TRUE;
|
||||
rstate->index = pos;
|
||||
/* populate cache for exact name access */
|
||||
entries->last_accessed = entries->entries_array_s[pos];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found == FALSE) {
|
||||
rstate->out.found = 0;
|
||||
rstate->out.eof = 1;
|
||||
}
|
||||
else {
|
||||
struct _rar_unique_entry *cur;
|
||||
if (in_sorted)
|
||||
cur = entries->entries_array_s[rstate->index];
|
||||
else
|
||||
cur = entries->entries_array[rstate->index];
|
||||
rstate->out.found = 1;
|
||||
rstate->out.position = cur->id;
|
||||
rstate->out.header = &cur->entry;
|
||||
rstate->out.packed_size = cur->packed_size;
|
||||
rstate->index++;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rar_delete_entries - accepts an allocated entries list */
|
||||
void _rar_delete_entries(rar_file_t *rar TSRMLS_DC)
|
||||
{
|
||||
if (rar->entries != NULL) {
|
||||
if (rar->entries->entries_array != NULL) {
|
||||
size_t i;
|
||||
for (i = 0; i < rar->entries->num_entries; i++) {
|
||||
efree(rar->entries->entries_array[i]);
|
||||
}
|
||||
efree(rar->entries->entries_array);
|
||||
|
||||
if (rar->entries->entries_array_s != NULL)
|
||||
efree(rar->entries->entries_array_s);
|
||||
}
|
||||
efree(rar->entries);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* guarantees correct initialization of rar->entries on failure
|
||||
* If the passed rar_file_t structure has the allow_broken option, it
|
||||
* always returns success (ERAR_END_ARCHIVE) */
|
||||
int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int result = 0;
|
||||
size_t capacity = 0;
|
||||
int first_file_check = TRUE;
|
||||
unsigned long packed_size = 0UL;
|
||||
struct _rar_entries *ents;
|
||||
|
||||
if (rar->entries != NULL) {
|
||||
/* we've already listed this file's entries */
|
||||
if (rar->allow_broken)
|
||||
return ERAR_END_ARCHIVE;
|
||||
else
|
||||
return rar->entries->list_result;
|
||||
}
|
||||
|
||||
assert(rar->entries == NULL);
|
||||
rar->entries = emalloc(sizeof *rar->entries);
|
||||
ents = rar->entries;
|
||||
ents->num_entries = 0;
|
||||
ents->entries_array = NULL;
|
||||
ents->entries_array_s = NULL;
|
||||
ents->last_accessed = NULL;
|
||||
|
||||
while (result == 0) {
|
||||
struct RARHeaderDataEx entry;
|
||||
result = RARReadHeaderEx(rar->arch_handle, &entry);
|
||||
/* value of 2nd argument is irrelevant in RAR_OM_LIST_[SPLIT] mode */
|
||||
if (result == 0) {
|
||||
result = RARProcessFile(rar->arch_handle, RAR_SKIP, NULL, NULL);
|
||||
}
|
||||
if (result != 0)
|
||||
break;
|
||||
|
||||
if (first_file_check) {
|
||||
if (entry.Flags & 0x01U) /* LHD_SPLIT_BEFORE */
|
||||
continue;
|
||||
else
|
||||
first_file_check = FALSE;
|
||||
}
|
||||
|
||||
/* reset packed size if not split before */
|
||||
if ((entry.Flags & 0x01U) == 0)
|
||||
packed_size = 0UL;
|
||||
|
||||
/* we would exceed size of ulong. cap at ulong_max
|
||||
* equivalent to packed_size + entry.PackSize > ULONG_MAX,
|
||||
* but without overflowing */
|
||||
if (ULONG_MAX - packed_size < entry.PackSize)
|
||||
packed_size = ULONG_MAX;
|
||||
else {
|
||||
packed_size += entry.PackSize;
|
||||
if (entry.PackSizeHigh != 0) {
|
||||
#if ULONG_MAX > 0xffffffffUL
|
||||
packed_size += ((unsigned long) entry.PackSizeHigh) << 32;
|
||||
#else
|
||||
packed_size = ULONG_MAX; /* cap */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.Flags & 0x02U) /* LHD_SPLIT_AFTER; do not commit */
|
||||
continue;
|
||||
|
||||
/* commit the entry */
|
||||
assert(capacity >= ents->num_entries);
|
||||
if (capacity == ents->num_entries) { /* 0, 2, 6, 14, 30... */
|
||||
capacity = (capacity + 1) * 2;
|
||||
ents->entries_array = safe_erealloc(ents->entries_array, capacity,
|
||||
sizeof(*ents->entries_array), 0);
|
||||
}
|
||||
assert(capacity > ents->num_entries);
|
||||
|
||||
ents->entries_array[ents->num_entries] =
|
||||
emalloc(sizeof *ents->entries_array[0]);
|
||||
memcpy(&ents->entries_array[ents->num_entries]->entry, &entry,
|
||||
sizeof ents->entries_array[0]->entry);
|
||||
ents->entries_array[ents->num_entries]->id = ents->num_entries;
|
||||
ents->entries_array[ents->num_entries]->packed_size = packed_size;
|
||||
_rar_nav_get_depth_and_length(entry.FileNameW,
|
||||
sizeof(entry.FileNameW) / sizeof(entry.FileNameW[0]), /* = 1024 */
|
||||
&ents->entries_array[ents->num_entries]->depth,
|
||||
&ents->entries_array[ents->num_entries]->name_wlen TSRMLS_CC);
|
||||
ents->num_entries++;
|
||||
}
|
||||
|
||||
rar->entries->list_result = result;
|
||||
|
||||
return rar->allow_broken ? ERAR_END_ARCHIVE : result;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* end functions with external linkage }}} */
|
||||
|
||||
|
||||
/* {{{ Functions with internal linkage */
|
||||
|
||||
static void _rar_nav_get_depth_and_length(wchar_t *filenamew, const size_t file_size,
|
||||
int *depth_out, size_t *wlen_out TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
size_t i;
|
||||
int depth = 0;
|
||||
|
||||
assert(file_size >= 1);
|
||||
|
||||
for (i = 0; i < file_size; i++) {
|
||||
if (filenamew[i] == L'\0')
|
||||
break;
|
||||
if (filenamew[i] == PATHDIVIDERW[0])
|
||||
depth++;
|
||||
}
|
||||
|
||||
if (i == file_size) { /* should not happen */
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"The library gave an unterminated file name. "
|
||||
"This is a bug, please report it.");
|
||||
i--;
|
||||
filenamew[i] = L'\0';
|
||||
}
|
||||
|
||||
if ((i >= 1) && (filenamew[i-1] == PATHDIVIDERW[0])) {
|
||||
/* entry name ended in path divider. shouldn't happen */
|
||||
i--;
|
||||
filenamew[i] = L'\0';
|
||||
depth--;
|
||||
}
|
||||
|
||||
*depth_out = depth;
|
||||
if (wlen_out != NULL)
|
||||
*wlen_out = (size_t) i;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_nav_get_depth(const wchar_t *filenamew, const size_t file_size) /* {{{ */
|
||||
{
|
||||
size_t i;
|
||||
int depth = 0;
|
||||
|
||||
for (i = 0; i < file_size; i++) {
|
||||
if (filenamew[i] == L'\0')
|
||||
break;
|
||||
if (filenamew[i] == PATHDIVIDERW[0])
|
||||
depth++;
|
||||
}
|
||||
assert(i < file_size);
|
||||
|
||||
return depth;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_nav_compare_entries(const void *op1, const void *op2 TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const struct _rar_unique_entry *a = *((struct _rar_unique_entry **) op1),
|
||||
*b = *((struct _rar_unique_entry **) op2);
|
||||
|
||||
return _rar_nav_compare_values(a->entry.FileNameW, a->depth,
|
||||
b->entry.FileNameW, b->depth,
|
||||
sizeof(a->entry.FileNameW) / sizeof(a->entry.FileNameW[0]) /*1024*/);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_nav_compare_entries_std(const void *op1, const void *op2) /* {{{ */
|
||||
{
|
||||
const struct _rar_unique_entry *a = *((struct _rar_unique_entry **) op1),
|
||||
*b = *((struct _rar_unique_entry **) op2);
|
||||
|
||||
return _rar_nav_compare_values(a->entry.FileNameW, a->depth,
|
||||
b->entry.FileNameW, b->depth,
|
||||
sizeof(a->entry.FileNameW) / sizeof(a->entry.FileNameW[0]) /*1024*/);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static inline int _rar_nav_compare_values(const wchar_t *str1, const int depth1,
|
||||
const wchar_t *str2, const int depth2,
|
||||
const size_t max_size) /* {{{ */
|
||||
{
|
||||
if (depth1 == depth2) {
|
||||
return wcsncmp(str1, str2, max_size);
|
||||
}
|
||||
else {
|
||||
return depth1 > depth2 ? 1 : -1;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* does not assume null termination */
|
||||
static int _rar_nav_directory_match(const wchar_t *dir, const size_t dir_len,
|
||||
const wchar_t *entry, const size_t entry_len) /* {{{ */
|
||||
{
|
||||
const wchar_t *chr,
|
||||
*entry_rem;
|
||||
size_t entry_rem_len;
|
||||
|
||||
/* dir does not end with the path separator */
|
||||
|
||||
if (dir_len > 0) {
|
||||
if (entry_len <= dir_len) /* don't match the dir itself */
|
||||
return FALSE;
|
||||
/* assert(entry_len > dir_len > 0) */
|
||||
if (wmemcmp(dir, entry, dir_len) != 0)
|
||||
return FALSE;
|
||||
/* directory name does not follow path sep or path sep ends the name */
|
||||
if (entry[dir_len] != PATHDIVIDERW[0] || entry_len == dir_len + 1)
|
||||
return FALSE;
|
||||
/* assert(entry_len > dir_len + 1) */
|
||||
entry_rem = &entry[dir_len + 1];
|
||||
entry_rem_len = entry_len - (dir_len + 1);
|
||||
}
|
||||
else {
|
||||
entry_rem = entry;
|
||||
entry_rem_len = entry_len;
|
||||
}
|
||||
|
||||
chr = wmemchr(entry_rem, PATHDIVIDERW[0], entry_rem_len);
|
||||
/* must have no / after the directory */
|
||||
return (chr == NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static size_t _rar_nav_position_on_dir_start(const wchar_t *dir_name,
|
||||
int dir_depth,
|
||||
size_t dir_size,
|
||||
struct _rar_unique_entry **entries,
|
||||
size_t low, size_t high) /* {{{ */
|
||||
{
|
||||
size_t mid;
|
||||
int comp;
|
||||
size_t orig_high = high;
|
||||
|
||||
if (dir_size == 1) { /* root */
|
||||
if (low >= high)
|
||||
return -1;
|
||||
|
||||
if (entries[low]->depth == 0)
|
||||
return low;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (low < high) {
|
||||
mid = low + (high - low) / 2;
|
||||
comp = _rar_nav_compare_values(dir_name, dir_depth + 1,
|
||||
entries[mid]->entry.FileNameW, entries[mid]->depth,
|
||||
dir_size);
|
||||
if (comp > 0)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
|
||||
if (low >= orig_high)
|
||||
return -1;
|
||||
|
||||
if (_rar_nav_directory_match(dir_name, dir_size - 1,
|
||||
entries[low]->entry.FileNameW, entries[low]->name_wlen))
|
||||
return low;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* end functions with internal linkage */
|
||||
|
||||
#endif /* HAVE_RAR */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
1332
rar_stream.c
1332
rar_stream.c
File diff suppressed because it is too large
Load Diff
720
rarentry.c
720
rarentry.c
@@ -1,720 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 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_0.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. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
|
||||
#include <php.h>
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Globals with external linkage */
|
||||
zend_class_entry *rar_class_entry_ptr;
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Globals with internal linkage */
|
||||
static zend_object_handlers rarentry_object_handlers;
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Function prototypes for functions with internal linkage */
|
||||
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
|
||||
int name_length, char *doc_comment,
|
||||
int doc_comment_len TSRMLS_DC);
|
||||
static zval *_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC);
|
||||
static void _rar_dos_date_to_text(int dos_time, char *date_string);
|
||||
static zend_object_value rarentry_ce_create_object(zend_class_entry *class_type TSRMLS_DC);
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Functions with external linkage */
|
||||
/* should be passed the last entry that corresponds to a given file
|
||||
* only that one has the correct CRC. Still, it may have a wrong packedSize */
|
||||
void _rar_entry_to_zval(zval *parent, /* zval to RarArchive object, will have its refcount increased */
|
||||
struct RARHeaderDataEx *entry,
|
||||
unsigned long packed_size,
|
||||
size_t position,
|
||||
zval *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char tmp_s [MAX_LENGTH_OF_LONG + 1];
|
||||
char time[50];
|
||||
char *filename;
|
||||
int filename_size, filename_len;
|
||||
long unp_size; /* zval stores PHP ints as long, so use that here */
|
||||
|
||||
object_init_ex(object, rar_class_entry_ptr);
|
||||
zend_update_property(rar_class_entry_ptr, object, "rarfile",
|
||||
sizeof("rararch") - 1, parent TSRMLS_CC);
|
||||
|
||||
#if ULONG_MAX > 0xffffffffUL
|
||||
unp_size = ((long) entry->UnpSize) + (((long) entry->UnpSizeHigh) << 32);
|
||||
#else
|
||||
/* for 32-bit long, at least don't give negative values */
|
||||
if ((unsigned long) entry->UnpSize > (unsigned long) LONG_MAX
|
||||
|| entry->UnpSizeHigh != 0)
|
||||
unp_size = LONG_MAX;
|
||||
else
|
||||
unp_size = (long) entry->UnpSize;
|
||||
#endif
|
||||
|
||||
filename_size = sizeof(entry->FileNameW) * sizeof(wchar_t);
|
||||
filename = (char*) emalloc(filename_size);
|
||||
|
||||
if (packed_size > (unsigned long) LONG_MAX)
|
||||
packed_size = LONG_MAX;
|
||||
_rar_wide_to_utf(entry->FileNameW, filename, filename_size);
|
||||
/* OK; safe usage below: */
|
||||
filename_len = _rar_strnlen(filename, filename_size);
|
||||
/* we're not in class scope, so we cannot change the class private
|
||||
* properties from here with add_property_x, or
|
||||
* direct call to rarentry_object_handlers.write_property
|
||||
* zend_update_property_x updates the scope accordingly */
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "position",
|
||||
sizeof("position") - 1, (long) position TSRMLS_CC);
|
||||
zend_update_property_stringl(rar_class_entry_ptr, object, "name",
|
||||
sizeof("name") - 1, filename, filename_len TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "unpacked_size",
|
||||
sizeof("unpacked_size") - 1, unp_size TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "packed_size",
|
||||
sizeof("packed_size") - 1, packed_size TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "host_os",
|
||||
sizeof("host_os") - 1, entry->HostOS TSRMLS_CC);
|
||||
|
||||
_rar_dos_date_to_text(entry->FileTime, time);
|
||||
zend_update_property_string(rar_class_entry_ptr, object, "file_time",
|
||||
sizeof("file_time") - 1, time TSRMLS_CC);
|
||||
|
||||
sprintf(tmp_s, "%x", entry->FileCRC);
|
||||
zend_update_property_string(rar_class_entry_ptr, object, "crc",
|
||||
sizeof("crc") - 1, tmp_s TSRMLS_CC);
|
||||
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "attr",
|
||||
sizeof("attr") - 1, entry->FileAttr TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "version",
|
||||
sizeof("version") - 1, entry->UnpVer TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "method",
|
||||
sizeof("method") - 1, entry->Method TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "flags",
|
||||
sizeof("flags") - 1, entry->Flags TSRMLS_CC);
|
||||
|
||||
efree(filename);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Helper functions and preprocessor definitions */
|
||||
#define RAR_GET_PROPERTY(var, prop_name) \
|
||||
if (!entry_obj) { \
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "this method cannot be called statically"); \
|
||||
RETURN_FALSE; \
|
||||
} \
|
||||
if ((var = _rar_entry_get_property(entry_obj, prop_name, \
|
||||
sizeof(prop_name) - 1 TSRMLS_CC)) == NULL) { \
|
||||
RETURN_FALSE; \
|
||||
}
|
||||
|
||||
#define REG_RAR_CLASS_CONST_LONG(const_name, value) \
|
||||
zend_declare_class_constant_long(rar_class_entry_ptr, const_name, \
|
||||
sizeof(const_name) - 1, (long) value TSRMLS_CC)
|
||||
|
||||
#define REG_RAR_PROPERTY(name, comment) \
|
||||
_rar_decl_priv_prop_null(rar_class_entry_ptr, name, sizeof(name) -1, \
|
||||
comment, sizeof(comment) - 1 TSRMLS_CC)
|
||||
|
||||
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
|
||||
int name_length, char *doc_comment,
|
||||
int doc_comment_len TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *property;
|
||||
ALLOC_PERMANENT_ZVAL(property);
|
||||
INIT_ZVAL(*property);
|
||||
return zend_declare_property_ex(ce, name, name_length, property,
|
||||
ZEND_ACC_PRIVATE, doc_comment, doc_comment_len TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *tmp;
|
||||
zend_class_entry *orig_scope = EG(scope);
|
||||
|
||||
EG(scope) = rar_class_entry_ptr;
|
||||
|
||||
tmp = zend_read_property(Z_OBJCE_P(entry_obj), entry_obj, name, namelen, 1 TSRMLS_CC);
|
||||
if (tmp == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Bug: unable to find property '%s'. Please report.", name);
|
||||
}
|
||||
|
||||
EG(scope) = orig_scope;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
|
||||
{
|
||||
int second, minute, hour, day, month, year;
|
||||
/* following lines were taken from timefn.cpp */
|
||||
second = (dos_time & 0x1f)*2;
|
||||
minute = (dos_time>>5) & 0x3f;
|
||||
hour = (dos_time>>11) & 0x1f;
|
||||
day = (dos_time>>16) & 0x1f;
|
||||
month = (dos_time>>21) & 0x0f;
|
||||
year = (dos_time>>25)+1980;
|
||||
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value rarentry_ce_create_object(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object_value zov;
|
||||
zend_object *zobj;
|
||||
|
||||
zobj = emalloc(sizeof *zobj);
|
||||
zend_object_std_init(zobj, class_type TSRMLS_CC);
|
||||
|
||||
#if PHP_VERSION_ID < 50399
|
||||
zend_hash_copy(zobj->properties, &(class_type->default_properties),
|
||||
(copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*));
|
||||
#else
|
||||
object_properties_init(zobj, class_type);
|
||||
#endif
|
||||
zov.handle = zend_objects_store_put(zobj,
|
||||
(zend_objects_store_dtor_t) zend_objects_destroy_object,
|
||||
(zend_objects_free_object_storage_t) zend_objects_free_object_storage,
|
||||
NULL TSRMLS_CC);
|
||||
zov.handlers = &rarentry_object_handlers;
|
||||
return zov;
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Methods */
|
||||
/* {{{ proto bool RarEntry::extract(string dir [, string filepath = ''
|
||||
[, string password = NULL [, bool extended_data = FALSE]])
|
||||
Extract file from the archive */
|
||||
PHP_METHOD(rarentry, extract)
|
||||
{ /* lots of variables, but no need to be intimidated */
|
||||
char *dir,
|
||||
*filepath = NULL,
|
||||
*password = NULL;
|
||||
int dir_len,
|
||||
filepath_len = 0,
|
||||
password_len = 0;
|
||||
char *considered_path;
|
||||
char considered_path_res[MAXPATHLEN];
|
||||
int with_second_arg;
|
||||
zend_bool process_ed = 0;
|
||||
|
||||
zval *tmp,
|
||||
*tmp_position;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
struct RARHeaderDataEx entry;
|
||||
HANDLE extract_handle = NULL;
|
||||
int result;
|
||||
int found;
|
||||
/* gotta have a new copy (shallow is enough) because we may want to use a
|
||||
* password that's different from the one stored in the rar_file_t object*/
|
||||
rar_cb_user_data cb_udata = {NULL};
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss!b", &dir,
|
||||
&dir_len, &filepath, &filepath_len, &password, &password_len,
|
||||
&process_ed) == FAILURE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "rarfile");
|
||||
if (_rar_get_file_resource(tmp, &rar TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* Decide where to extract */
|
||||
with_second_arg = (filepath_len != 0);
|
||||
|
||||
/* the arguments are mutually exclusive.
|
||||
* If the second is specified, we ignore the first */
|
||||
if (!with_second_arg) {
|
||||
if (dir_len == 0) /* both params empty */
|
||||
dir = ".";
|
||||
considered_path = dir;
|
||||
}
|
||||
else {
|
||||
considered_path = filepath;
|
||||
}
|
||||
|
||||
if (OPENBASEDIR_CHECKPATH(considered_path)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (!expand_filepath(considered_path, considered_path_res TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* Find file inside archive */
|
||||
RAR_GET_PROPERTY(tmp_position, "position");
|
||||
|
||||
/* don't set the new password now because maybe the headers are
|
||||
* encrypted with a password different from this file's (though WinRAR
|
||||
* does not support that: if you encrypt the headers, you must encrypt
|
||||
* the files with the same password). By not replacing the password
|
||||
* now, we're using the password given to rar_open, if any (which must
|
||||
* have enabled decrypting the headers or else we wouldn't be here) */
|
||||
memcpy(&cb_udata, &rar->cb_userdata, sizeof cb_udata);
|
||||
|
||||
result = _rar_find_file_p(rar->extract_open_data,
|
||||
(size_t) Z_LVAL_P(tmp_position), &cb_udata, &extract_handle, &found,
|
||||
&entry);
|
||||
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETVAL_FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
_rar_handle_ext_error("Can't find file with index %d in archive %s"
|
||||
TSRMLS_CC, Z_LVAL_P(tmp_position),
|
||||
rar->extract_open_data->ArcName);
|
||||
RETVAL_FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
RARSetProcessExtendedData(extract_handle, (int) process_ed);
|
||||
|
||||
/* now use the password given to this method. If none was given, we're
|
||||
* still stuck with the password given to rar_open, if any */
|
||||
if (password != NULL)
|
||||
cb_udata.password = password;
|
||||
|
||||
/* Do extraction */
|
||||
if (!with_second_arg)
|
||||
result = RARProcessFile(extract_handle, RAR_EXTRACT,
|
||||
considered_path_res, NULL);
|
||||
else
|
||||
result = RARProcessFile(extract_handle, RAR_EXTRACT,
|
||||
NULL, considered_path_res);
|
||||
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
else {
|
||||
RETVAL_TRUE;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (extract_handle != NULL)
|
||||
RARCloseArchive(extract_handle);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getPosiiton()
|
||||
Return position for the entry */
|
||||
PHP_METHOD(rarentry, getPosition)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "position");
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::getName()
|
||||
Return entry name */
|
||||
PHP_METHOD(rarentry, getName)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "name");
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getUnpackedSize()
|
||||
Return unpacked size of the entry */
|
||||
PHP_METHOD(rarentry, getUnpackedSize)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "unpacked_size");
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getPackedSize()
|
||||
Return packed size of the entry */
|
||||
PHP_METHOD(rarentry, getPackedSize)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "packed_size");
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getHostOs()
|
||||
Return host OS of the entry */
|
||||
PHP_METHOD(rarentry, getHostOs)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "host_os");
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::getFileTime()
|
||||
Return modification time of the entry */
|
||||
PHP_METHOD(rarentry, getFileTime)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "file_time");
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::getCrc()
|
||||
Return CRC of the entry */
|
||||
PHP_METHOD(rarentry, getCrc)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "crc");
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getAttr()
|
||||
Return attributes of the entry */
|
||||
PHP_METHOD(rarentry, getAttr)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "attr");
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getVersion()
|
||||
Return version of the archiver, used to create this entry */
|
||||
PHP_METHOD(rarentry, getVersion)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "version");
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getMethod()
|
||||
Return packing method */
|
||||
PHP_METHOD(rarentry, getMethod)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "method");
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto resource RarEntry::getStream([string password = NULL])
|
||||
Return stream for current entry */
|
||||
PHP_METHOD(rarentry, getStream)
|
||||
{
|
||||
zval *tmp,
|
||||
*position;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
php_stream *stream = NULL;
|
||||
char *password = NULL;
|
||||
int password_len; /* ignored */
|
||||
rar_cb_user_data cb_udata = {NULL};
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!",
|
||||
&password, &password_len) == FAILURE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
RAR_GET_PROPERTY(position, "position");
|
||||
RAR_GET_PROPERTY(tmp, "rarfile");
|
||||
if (_rar_get_file_resource(tmp, &rar TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* use rar_open password (stored in rar->cb_userdata) by default */
|
||||
memcpy(&cb_udata, &rar->cb_userdata, sizeof cb_udata);
|
||||
if (password != NULL)
|
||||
cb_udata.password = password;
|
||||
|
||||
/* doesn't matter that cb_udata is stack allocated, it will be copied */
|
||||
stream = php_stream_rar_open(rar->extract_open_data->ArcName,
|
||||
Z_LVAL_P(position), &cb_udata STREAMS_CC TSRMLS_CC);
|
||||
|
||||
if (stream != NULL) {
|
||||
php_stream_to_zval(stream, return_value);
|
||||
}
|
||||
else
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::isDirectory()
|
||||
Return whether the entry represents a directory */
|
||||
PHP_METHOD(rarentry, isDirectory)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_dir;
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "flags");
|
||||
flags = Z_LVAL_P(tmp);
|
||||
is_dir = ((flags & LHD_WINDOWMASK) == LHD_DIRECTORY);
|
||||
|
||||
RETURN_BOOL(is_dir);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::isEncrypted()
|
||||
Return whether the entry is encrypted and needs a password */
|
||||
PHP_METHOD(rarentry, isEncrypted)
|
||||
{
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_encrypted;
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "flags");
|
||||
flags = Z_LVAL_P(tmp);
|
||||
is_encrypted = (flags & 0x04);
|
||||
|
||||
RETURN_BOOL(is_encrypted);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::__toString()
|
||||
Return string representation for entry */
|
||||
PHP_METHOD(rarentry, __toString)
|
||||
{
|
||||
zval *flags_zval,
|
||||
*name_zval,
|
||||
*crc_zval;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_dir;
|
||||
char *name,
|
||||
*crc;
|
||||
char *restring;
|
||||
int restring_len;
|
||||
const char format[] = "RarEntry for %s \"%s\" (%s)";
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
RAR_GET_PROPERTY(flags_zval, "flags");
|
||||
flags = Z_LVAL_P(flags_zval);
|
||||
is_dir = ((flags & 0xE0) == 0xE0);
|
||||
|
||||
RAR_GET_PROPERTY(name_zval, "name");
|
||||
name = Z_STRVAL_P(name_zval);
|
||||
|
||||
RAR_GET_PROPERTY(crc_zval, "crc");
|
||||
crc = Z_STRVAL_P(crc_zval);
|
||||
|
||||
/* 2 is size of %s, 8 is size of crc */
|
||||
restring_len = (sizeof(format)-1) - 2 * 3 + (sizeof("directory")-1) +
|
||||
strlen(name) + 8 + 1;
|
||||
restring = emalloc(restring_len);
|
||||
snprintf(restring, restring_len, format, is_dir?"directory":"file",
|
||||
name, crc);
|
||||
restring[restring_len - 1] = '\0'; /* just to be safe */
|
||||
|
||||
RETURN_STRING(restring, 0);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ arginfo */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_extract, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, path)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_ARG_INFO(0, extended_data)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_getstream, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_rar_void, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
|
||||
static zend_function_entry php_rar_class_functions[] = {
|
||||
PHP_ME(rarentry, extract, arginfo_rarentry_extract, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getPosition, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getName, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getUnpackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getPackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getHostOs, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getFileTime, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getCrc, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getAttr, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getVersion, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getMethod, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getStream, arginfo_rarentry_getstream, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, isDirectory, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, isEncrypted, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, __toString, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(__construct, rar_bogus_ctor, arginfo_rar_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
void minit_rarentry(TSRMLS_D)
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
memcpy(&rarentry_object_handlers, zend_get_std_object_handlers(),
|
||||
sizeof rarentry_object_handlers);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "RarEntry", php_rar_class_functions);
|
||||
rar_class_entry_ptr = zend_register_internal_class(&ce TSRMLS_CC);
|
||||
rar_class_entry_ptr->ce_flags |= ZEND_ACC_FINAL_CLASS;
|
||||
rar_class_entry_ptr->clone = NULL;
|
||||
/* Custom creation currently not really needed, but you never know... */
|
||||
rar_class_entry_ptr->create_object = &rarentry_ce_create_object;
|
||||
|
||||
REG_RAR_PROPERTY("rarfile", "Associated RAR archive");
|
||||
REG_RAR_PROPERTY("position", "Position inside the RAR archive");
|
||||
REG_RAR_PROPERTY("name", "File or directory name with path");
|
||||
REG_RAR_PROPERTY("unpacked_size", "Size of file when unpacked");
|
||||
REG_RAR_PROPERTY("packed_size", "Size of the packed file inside the archive");
|
||||
REG_RAR_PROPERTY("host_os", "OS used to pack the file");
|
||||
REG_RAR_PROPERTY("file_time", "Entry's time of last modification");
|
||||
REG_RAR_PROPERTY("crc", "CRC checksum for the unpacked file");
|
||||
REG_RAR_PROPERTY("attr", "OS-dependent file attributes");
|
||||
REG_RAR_PROPERTY("version", "RAR version needed to extract entry");
|
||||
REG_RAR_PROPERTY("method", "Identifier for packing method");
|
||||
REG_RAR_PROPERTY("flags", "Entry header flags");
|
||||
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_MSDOS", HOST_MSDOS);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_OS2", HOST_OS2);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_WIN32", HOST_WIN32);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_UNIX", HOST_UNIX);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_MACOS", HOST_MACOS);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_BEOS", HOST_BEOS);
|
||||
|
||||
/* see WinNT.h */
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_READONLY", 0x00001L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_HIDDEN", 0x00002L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SYSTEM", 0x00004L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DIRECTORY", 0x00010L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ARCHIVE", 0x00020L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DEVICE", 0x00040L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NORMAL", 0x00080L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_TEMPORARY", 0x00100L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SPARSE_FILE", 0x00200L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_REPARSE_POINT", 0x00400L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_COMPRESSED", 0x00800L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_OFFLINE", 0x01000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NOT_CONTENT_INDEXED", 0x02000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ENCRYPTED", 0x04000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_VIRTUAL", 0x10000L);
|
||||
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_EXECUTE", 0x00001L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_WRITE", 0x00002L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_READ", 0x00004L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_EXECUTE", 0x00008L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_WRITE", 0x00010L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_READ", 0x00020L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_EXECUTE", 0x00040L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_WRITE", 0x00080L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_READ", 0x00100L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_STICKY", 0x00200L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETGID", 0x00400L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETUID", 0x00800L);
|
||||
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FINAL_QUARTET", 0x0F000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FIFO", 0x01000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_CHAR_DEV", 0x02000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_DIRECTORY", 0x04000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_BLOCK_DEV", 0x06000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_REGULAR_FILE", 0x08000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SYM_LINK", 0x0A000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SOCKET", 0x0C000L);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
275
technote.txt
275
technote.txt
@@ -1,275 +0,0 @@
|
||||
|
||||
RAR version 3.93 - Technical information
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
THE ARCHIVE FORMAT DESCRIBED BELOW IS ONLY VALID FOR VERSIONS SINCE 1.50
|
||||
|
||||
==========================================================================
|
||||
RAR archive file format
|
||||
==========================================================================
|
||||
|
||||
Archive file consists of variable length blocks. The order of these
|
||||
blocks may vary, but the first block must be a marker block followed by
|
||||
an archive header block.
|
||||
|
||||
Each block begins with the following fields:
|
||||
|
||||
HEAD_CRC 2 bytes CRC of total block or block part
|
||||
HEAD_TYPE 1 byte Block type
|
||||
HEAD_FLAGS 2 bytes Block flags
|
||||
HEAD_SIZE 2 bytes Block size
|
||||
ADD_SIZE 4 bytes Optional field - added block size
|
||||
|
||||
Field ADD_SIZE present only if (HEAD_FLAGS & 0x8000) != 0
|
||||
|
||||
Total block size is HEAD_SIZE if (HEAD_FLAGS & 0x8000) == 0
|
||||
and HEAD_SIZE+ADD_SIZE if the field ADD_SIZE is present - when
|
||||
(HEAD_FLAGS & 0x8000) != 0.
|
||||
|
||||
In each block the followings bits in HEAD_FLAGS have the same meaning:
|
||||
|
||||
0x4000 - if set, older RAR versions will ignore the block
|
||||
and remove it when the archive is updated.
|
||||
if clear, the block is copied to the new archive
|
||||
file when the archive is updated;
|
||||
|
||||
0x8000 - if set, ADD_SIZE field is present and the full block
|
||||
size is HEAD_SIZE+ADD_SIZE.
|
||||
|
||||
Declared block types:
|
||||
|
||||
HEAD_TYPE=0x72 marker block
|
||||
HEAD_TYPE=0x73 archive header
|
||||
HEAD_TYPE=0x74 file header
|
||||
HEAD_TYPE=0x75 old style comment header
|
||||
HEAD_TYPE=0x76 old style authenticity information
|
||||
HEAD_TYPE=0x77 old style subblock
|
||||
HEAD_TYPE=0x78 old style recovery record
|
||||
HEAD_TYPE=0x79 old style authenticity information
|
||||
HEAD_TYPE=0x7a subblock
|
||||
|
||||
Comment block is actually used only within other blocks and doesn't
|
||||
exist separately.
|
||||
|
||||
Archive processing is made in the following manner:
|
||||
|
||||
1. Read and check marker block
|
||||
2. Read archive header
|
||||
3. Read or skip HEAD_SIZE-sizeof(MAIN_HEAD) bytes
|
||||
4. If end of archive encountered then terminate archive processing,
|
||||
else read 7 bytes into fields HEAD_CRC, HEAD_TYPE, HEAD_FLAGS,
|
||||
HEAD_SIZE.
|
||||
5. Check HEAD_TYPE.
|
||||
if HEAD_TYPE==0x74
|
||||
read file header ( first 7 bytes already read )
|
||||
read or skip HEAD_SIZE-sizeof(FILE_HEAD) bytes
|
||||
if (HEAD_FLAGS & 0x100)
|
||||
read or skip HIGH_PACK_SIZE*0x100000000+PACK_SIZE bytes
|
||||
else
|
||||
read or skip PACK_SIZE bytes
|
||||
else
|
||||
read corresponding HEAD_TYPE block:
|
||||
read HEAD_SIZE-7 bytes
|
||||
if (HEAD_FLAGS & 0x8000)
|
||||
read ADD_SIZE bytes
|
||||
6. go to 4.
|
||||
|
||||
|
||||
==========================================================================
|
||||
Block Formats
|
||||
==========================================================================
|
||||
|
||||
|
||||
Marker block ( MARK_HEAD )
|
||||
|
||||
|
||||
HEAD_CRC Always 0x6152
|
||||
2 bytes
|
||||
|
||||
HEAD_TYPE Header type: 0x72
|
||||
1 byte
|
||||
|
||||
HEAD_FLAGS Always 0x1a21
|
||||
2 bytes
|
||||
|
||||
HEAD_SIZE Block size = 0x0007
|
||||
2 bytes
|
||||
|
||||
The marker block is actually considered as a fixed byte
|
||||
sequence: 0x52 0x61 0x72 0x21 0x1a 0x07 0x00
|
||||
|
||||
|
||||
|
||||
Archive header ( MAIN_HEAD )
|
||||
|
||||
|
||||
HEAD_CRC CRC of fields HEAD_TYPE to RESERVED2
|
||||
2 bytes
|
||||
|
||||
HEAD_TYPE Header type: 0x73
|
||||
1 byte
|
||||
|
||||
HEAD_FLAGS Bit flags:
|
||||
2 bytes
|
||||
0x0001 - Volume attribute (archive volume)
|
||||
0x0002 - Archive comment present
|
||||
RAR 3.x uses the separate comment block
|
||||
and does not set this flag.
|
||||
|
||||
0x0004 - Archive lock attribute
|
||||
0x0008 - Solid attribute (solid archive)
|
||||
0x0010 - New volume naming scheme ('volname.partN.rar')
|
||||
0x0020 - Authenticity information present
|
||||
RAR 3.x does not set this flag.
|
||||
|
||||
0x0040 - Recovery record present
|
||||
0x0080 - Block headers are encrypted
|
||||
0x0100 - First volume (set only by RAR 3.0 and later)
|
||||
|
||||
other bits in HEAD_FLAGS are reserved for
|
||||
internal use
|
||||
|
||||
HEAD_SIZE Archive header total size including archive comments
|
||||
2 bytes
|
||||
|
||||
RESERVED1 Reserved
|
||||
2 bytes
|
||||
|
||||
RESERVED2 Reserved
|
||||
4 bytes
|
||||
|
||||
|
||||
|
||||
File header (File in archive)
|
||||
|
||||
|
||||
HEAD_CRC CRC of fields from HEAD_TYPE to FILEATTR
|
||||
2 bytes and file name
|
||||
|
||||
HEAD_TYPE Header type: 0x74
|
||||
1 byte
|
||||
|
||||
HEAD_FLAGS Bit flags:
|
||||
2 bytes
|
||||
0x01 - file continued from previous volume
|
||||
0x02 - file continued in next volume
|
||||
0x04 - file encrypted with password
|
||||
|
||||
0x08 - file comment present
|
||||
RAR 3.x uses the separate comment block
|
||||
and does not set this flag.
|
||||
|
||||
0x10 - information from previous files is used (solid flag)
|
||||
(for RAR 2.0 and later)
|
||||
|
||||
bits 7 6 5 (for RAR 2.0 and later)
|
||||
|
||||
0 0 0 - dictionary size 64 KB
|
||||
0 0 1 - dictionary size 128 KB
|
||||
0 1 0 - dictionary size 256 KB
|
||||
0 1 1 - dictionary size 512 KB
|
||||
1 0 0 - dictionary size 1024 KB
|
||||
1 0 1 - dictionary size 2048 KB
|
||||
1 1 0 - dictionary size 4096 KB
|
||||
1 1 1 - file is directory
|
||||
|
||||
0x100 - HIGH_PACK_SIZE and HIGH_UNP_SIZE fields
|
||||
are present. These fields are used to archive
|
||||
only very large files (larger than 2Gb),
|
||||
for smaller files these fields are absent.
|
||||
|
||||
0x200 - FILE_NAME contains both usual and encoded
|
||||
Unicode name separated by zero. In this case
|
||||
NAME_SIZE field is equal to the length
|
||||
of usual name plus encoded Unicode name plus 1.
|
||||
|
||||
If this flag is present, but FILE_NAME does not
|
||||
contain zero bytes, it means that file name
|
||||
is encoded using UTF-8.
|
||||
|
||||
0x400 - the header contains additional 8 bytes
|
||||
after the file name, which are required to
|
||||
increase encryption security (so called 'salt').
|
||||
|
||||
0x800 - Version flag. It is an old file version,
|
||||
a version number is appended to file name as ';n'.
|
||||
|
||||
0x1000 - Extended time field present.
|
||||
|
||||
0x8000 - this bit always is set, so the complete
|
||||
block size is HEAD_SIZE + PACK_SIZE
|
||||
(and plus HIGH_PACK_SIZE, if bit 0x100 is set)
|
||||
|
||||
HEAD_SIZE File header full size including file name and comments
|
||||
2 bytes
|
||||
|
||||
PACK_SIZE Compressed file size
|
||||
4 bytes
|
||||
|
||||
UNP_SIZE Uncompressed file size
|
||||
4 bytes
|
||||
|
||||
HOST_OS Operating system used for archiving
|
||||
1 byte 0 - MS DOS
|
||||
1 - OS/2
|
||||
2 - Win32
|
||||
3 - Unix
|
||||
4 - Mac OS
|
||||
5 - BeOS
|
||||
|
||||
FILE_CRC File CRC
|
||||
4 bytes
|
||||
|
||||
FTIME Date and time in standard MS DOS format
|
||||
4 bytes
|
||||
|
||||
UNP_VER RAR version needed to extract file
|
||||
1 byte
|
||||
Version number is encoded as
|
||||
10 * Major version + minor version.
|
||||
|
||||
METHOD Packing method
|
||||
1 byte
|
||||
0x30 - storing
|
||||
0x31 - fastest compression
|
||||
0x32 - fast compression
|
||||
0x33 - normal compression
|
||||
0x34 - good compression
|
||||
0x35 - best compression
|
||||
|
||||
NAME_SIZE File name size
|
||||
2 bytes
|
||||
|
||||
ATTR File attributes
|
||||
4 bytes
|
||||
|
||||
HIGH_PACK_SIZE High 4 bytes of 64 bit value of compressed file size.
|
||||
4 bytes Optional value, presents only if bit 0x100 in HEAD_FLAGS
|
||||
is set.
|
||||
|
||||
HIGH_UNP_SIZE High 4 bytes of 64 bit value of uncompressed file size.
|
||||
4 bytes Optional value, presents only if bit 0x100 in HEAD_FLAGS
|
||||
is set.
|
||||
|
||||
FILE_NAME File name - string of NAME_SIZE bytes size
|
||||
|
||||
SALT present if (HEAD_FLAGS & 0x400) != 0
|
||||
8 bytes
|
||||
|
||||
EXT_TIME present if (HEAD_FLAGS & 0x1000) != 0
|
||||
variable size
|
||||
|
||||
other new fields may appear here.
|
||||
|
||||
|
||||
==========================================================================
|
||||
Application notes
|
||||
==========================================================================
|
||||
|
||||
1. To process an SFX archive you need to skip the SFX module searching
|
||||
for the marker block in the archive. There is no marker block sequence (0x52
|
||||
0x61 0x72 0x21 0x1a 0x07 0x00) in the SFX module itself.
|
||||
|
||||
2. The CRC is calculated using the standard polynomial 0xEDB88320. In
|
||||
case the size of the CRC is less than 4 bytes, only the low order bytes
|
||||
are used.
|
||||
@@ -1,27 +0,0 @@
|
||||
--TEST--
|
||||
rar_open() function
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
|
||||
var_dump($rar_file1);
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
var_dump($rar_file2);
|
||||
|
||||
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
|
||||
var_dump($rar_file3);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
|
||||
Warning: rar_open(): Failed to open %sno_such_file.rar: ERAR_EOPEN (file open error) in %s on line %d
|
||||
bool(false)
|
||||
Done
|
||||
144
tests/002.phpt
144
tests/002.phpt
@@ -1,144 +0,0 @@
|
||||
--TEST--
|
||||
rar_list() function
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
|
||||
$list1 = rar_list($rar_file1);
|
||||
var_dump($list1);
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$list2 = rar_list($rar_file2);
|
||||
var_dump($list2);
|
||||
|
||||
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
|
||||
$list3 = rar_list($rar_file3);
|
||||
var_dump($list3);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%s (%s) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(0)
|
||||
["name%sprivate%s=>
|
||||
string(9) "plain.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(15)
|
||||
["packed_size%sprivate%s=>
|
||||
int(25)
|
||||
["host_os%sprivate%s=>
|
||||
int(3)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 11:01:24"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "7728b6fe"
|
||||
["attr%sprivate%s=>
|
||||
int(33188)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
}
|
||||
[1]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (0) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(1)
|
||||
["name%sprivate%s=>
|
||||
string(30) "test file with whitespaces.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(14)
|
||||
["packed_size%sprivate%s=>
|
||||
int(20)
|
||||
["host_os%sprivate%s=>
|
||||
int(3)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 11:01:32"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "21890dd9"
|
||||
["attr%sprivate%s=>
|
||||
int(33188)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
}
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(0)
|
||||
["name%sprivate%s=>
|
||||
string(5) "1.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size%sprivate%s=>
|
||||
int(17)
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:18"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "a0de71c0"
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(36992)
|
||||
}
|
||||
[1]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(1)
|
||||
["name%sprivate%s=>
|
||||
string(5) "2.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size%sprivate%s=>
|
||||
int(16)
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:26"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "45a918de"
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
}
|
||||
}
|
||||
|
||||
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: rar_list() expects parameter 1 to be RarArchive, boolean given in %s on line %d
|
||||
NULL
|
||||
Done
|
||||
@@ -1,82 +0,0 @@
|
||||
--TEST--
|
||||
rar_entry_get() function
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
|
||||
$entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
|
||||
var_dump($entry1);
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$entry2 = rar_entry_get($rar_file2, '2.txt');
|
||||
var_dump($entry2);
|
||||
|
||||
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
|
||||
$entry3 = rar_entry_get($rar_file3, '2.txt');
|
||||
var_dump($entry3);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(1)
|
||||
["name%sprivate%s=>
|
||||
string(30) "test file with whitespaces.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(14)
|
||||
["packed_size%sprivate%s=>
|
||||
int(20)
|
||||
["host_os%sprivate%s=>
|
||||
int(3)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 11:01:32"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "21890dd9"
|
||||
["attr%sprivate%s=>
|
||||
int(33188)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
}
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(1)
|
||||
["name%sprivate%s=>
|
||||
string(5) "2.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size%sprivate%s=>
|
||||
int(16)
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:26"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "45a918de"
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
}
|
||||
|
||||
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: rar_entry_get() expects parameter 1 to be RarArchive, boolean given in %s on line %d
|
||||
NULL
|
||||
Done
|
||||
@@ -1,84 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract() method
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
|
||||
$entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
|
||||
|
||||
$entry1->extract(dirname(__FILE__));
|
||||
$contents11 = file_get_contents(dirname(__FILE__).'/test file with whitespaces.txt');
|
||||
echo $contents11."\n";
|
||||
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
|
||||
|
||||
$entry1->extract(false,dirname(__FILE__).'/1.txt');
|
||||
$contents12 = file_get_contents(dirname(__FILE__).'/1.txt');
|
||||
echo $contents12."\n";
|
||||
@unlink(dirname(__FILE__).'/1.txt');
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$entry2 = rar_entry_get($rar_file2, '2.txt');
|
||||
|
||||
$entry2->extract(dirname(__FILE__));
|
||||
$contents21 = file_get_contents(dirname(__FILE__).'/2.txt');
|
||||
echo $contents21."\n";
|
||||
@unlink(dirname(__FILE__).'/2.txt');
|
||||
|
||||
$entry2->extract(false,dirname(__FILE__).'/some.txt');
|
||||
$contents22 = file_get_contents(dirname(__FILE__).'/some.txt');
|
||||
echo $contents22."\n";
|
||||
@unlink(dirname(__FILE__).'/some.txt');
|
||||
|
||||
$entry2->extract(dirname(__FILE__));
|
||||
var_dump(file_get_contents(dirname(__FILE__).'/2.txt'));
|
||||
@unlink(dirname(__FILE__).'/2.txt');
|
||||
|
||||
$oldcwd = getcwd();
|
||||
chdir(dirname(__FILE__));
|
||||
|
||||
var_dump($entry2);
|
||||
var_dump($entry2->extract("",""));
|
||||
|
||||
@unlink('2.txt');
|
||||
|
||||
chdir($oldcwd);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
blah-blah-blah
|
||||
blah-blah-blah
|
||||
22222
|
||||
22222
|
||||
string(5) "22222"
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#3 (0) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(1)
|
||||
["name%sprivate%s=>
|
||||
string(5) "2.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size%sprivate%s=>
|
||||
int(16)
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:26"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "45a918de"
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
}
|
||||
bool(true)
|
||||
Done
|
||||
@@ -1,36 +0,0 @@
|
||||
--TEST--
|
||||
rar_comment_get() function
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/commented.rar');
|
||||
var_export(rar_comment_get($rar_file1));
|
||||
echo "\n";
|
||||
var_export(rar_comment_get($rar_file1));
|
||||
echo "\n";
|
||||
var_export($rar_file1->getComment());
|
||||
echo "\n";
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/linux_rar.rar');
|
||||
var_export(rar_comment_get($rar_file2));
|
||||
echo "\n";
|
||||
rar_close($rar_file2);
|
||||
var_export(rar_comment_get($rar_file2));
|
||||
echo "\n";
|
||||
|
||||
|
||||
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
'This is the comment of the file commented.rar.'
|
||||
'This is the comment of the file commented.rar.'
|
||||
'This is the comment of the file commented.rar.'
|
||||
NULL
|
||||
|
||||
Warning: rar_comment_get(): The archive is already closed in %s on line %d
|
||||
false
|
||||
Done
|
||||
@@ -1,22 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getCrc() method in multi-volume archives (PECL bug #9470)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
|
||||
$list = rar_list($rar_file1);
|
||||
echo $list[0]->getCrc()."\n";
|
||||
echo $list[1]->getCrc()."\n";
|
||||
echo $list[2]->getCrc()."\n";
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
52b28202
|
||||
f2c79881
|
||||
bcbce32e
|
||||
|
||||
Done
|
||||
@@ -1,18 +0,0 @@
|
||||
--TEST--
|
||||
rar_open() function with a non-RAR
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_notrar.rar');
|
||||
var_dump($rar_file1);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: rar_open(): Failed to open %s: ERAR_BAD_ARCHIVE in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Done
|
||||
@@ -1,34 +0,0 @@
|
||||
--TEST--
|
||||
rar_entry_get() function
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
|
||||
$entry = rar_entry_get($rar_file1, "file1.txt");
|
||||
echo "$entry\n";
|
||||
$entry = rar_entry_get($rar_file1, "nonexistent_file.txt");
|
||||
var_dump($entry);
|
||||
echo "\n";
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/nonexistent.rar');
|
||||
$entry = rar_entry_get($rar_file2, "file1.txt");
|
||||
var_dump($entry);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RarEntry for file "file1.txt" (52b28202)
|
||||
|
||||
Warning: rar_entry_get(): cannot find file "nonexistent_file.txt" in Rar archive "%s" in %s on line %d
|
||||
bool(false)
|
||||
|
||||
|
||||
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: rar_entry_get() expects parameter 1 to be RarArchive, boolean given in %s on line %d
|
||||
NULL
|
||||
|
||||
Done
|
||||
@@ -1,19 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getName() function with unicode filenames
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
$name = reset($entries)->getName();
|
||||
var_dump($name);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(13) "file1À۞.txt"
|
||||
|
||||
Done
|
||||
@@ -1,32 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (good RAR file, one volume)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().":\n";
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 8192);
|
||||
}
|
||||
echo "\n\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
2 files:
|
||||
|
||||
1.txt:
|
||||
11111
|
||||
|
||||
2.txt:
|
||||
22222
|
||||
|
||||
Done
|
||||
@@ -1,42 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (good RAR file, several volumes)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
if ($stream === false) {
|
||||
die("Failed to get stream.\n");
|
||||
break;
|
||||
}
|
||||
echo $e->getName().": ";
|
||||
$a = "";
|
||||
while (!feof($stream)) {
|
||||
$a .= fread($stream, 8192);
|
||||
}
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
3 files:
|
||||
|
||||
file1.txt: 18 bytes, CRC 52B28202
|
||||
|
||||
file2.txt: 17704 bytes, CRC F2C79881
|
||||
|
||||
file3.txt: 18 bytes, CRC BCBCE32E
|
||||
|
||||
Done
|
||||
@@ -1,41 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (bad RAR file)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files (will test only the first 4):\n\n";
|
||||
//var_dump($entries);
|
||||
$i = 0;
|
||||
foreach ($entries as $e) {
|
||||
if ($i++ >= 2)
|
||||
break;
|
||||
//$e->extract(false, dirname(__FILE__).'/temp.txt');
|
||||
//echo "now stream\n";
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
if ($stream === false) {
|
||||
echo "Could not get stream.\n\n";
|
||||
continue;
|
||||
}
|
||||
while (!feof($stream) && $i != 2) {
|
||||
echo fread($stream, 8192);
|
||||
}
|
||||
fclose($stream);
|
||||
echo "\n";
|
||||
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
51 files (will test only the first 4):
|
||||
|
||||
: The great battle of Gunprex versus Optiter!!!!!1
|
||||
Gunprex, Fire!
|
||||
So long, Optiter!
|
||||
|
||||
:
|
||||
Done
|
||||
@@ -1,20 +0,0 @@
|
||||
--TEST--
|
||||
rar_entry_get() and RarEntry::getName() coherence
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
$name = reset($entries)->getName();
|
||||
$entryback = rar_entry_get($rar_file1, $name);
|
||||
echo "$entryback\n";
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RarEntry for file "file1À۞.txt" (52b28202)
|
||||
|
||||
Done
|
||||
@@ -1,26 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() on unicode entry
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entry = rar_entry_get($rar_file1, "file1À۞.txt");
|
||||
echo $entry."\n";
|
||||
echo "\n";
|
||||
$stream = $entry->getStream();
|
||||
if ($stream !== false)
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 8192);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RarEntry for file "file1À۞.txt" (52b28202)
|
||||
|
||||
contents of file 1
|
||||
Done
|
||||
@@ -1,30 +0,0 @@
|
||||
--TEST--
|
||||
rar_close() liberates resource (PECL bug #9649)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
copy(dirname(__FILE__).'/latest_winrar.rar', dirname(__FILE__).'/temp.rar');
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/temp.rar');
|
||||
echo $rar_file1."\n";
|
||||
$entries = rar_list($rar_file1);
|
||||
$entry1 = reset($entries);
|
||||
unset($entries);
|
||||
echo $entry1."\n";
|
||||
echo "\n";
|
||||
|
||||
rar_close($rar_file1);
|
||||
echo $rar_file1."\n";
|
||||
$entry1->extract(".");
|
||||
unlink(dirname(__FILE__).'/temp.rar');
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RAR Archive "%s"
|
||||
RarEntry for file "1.txt" (a0de71c0)
|
||||
|
||||
RAR Archive "%s" (closed)
|
||||
|
||||
Warning: RarEntry::extract(): The archive is already closed in %s on line %d
|
||||
Done
|
||||
@@ -1,50 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract() method (corrupt RAR file)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files (will test only the first 4):\n\n";
|
||||
//var_dump($entries);
|
||||
$i = 0;
|
||||
foreach ($entries as $e) {
|
||||
if ($i++ >= 4)
|
||||
break;
|
||||
echo "Extraction of file #$i:\n";
|
||||
$ret = $e->extract(false, dirname(__FILE__).'/temp.txt');
|
||||
if ($ret)
|
||||
echo "\tSUCCESS\n";
|
||||
else
|
||||
echo "\tFAILED\n";
|
||||
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
@unlink(dirname(__FILE__).'/temp.txt');
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
51 files (will test only the first 4):
|
||||
|
||||
Extraction of file #1:
|
||||
SUCCESS
|
||||
|
||||
Extraction of file #2:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
FAILED
|
||||
|
||||
Extraction of file #3:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
FAILED
|
||||
|
||||
Extraction of file #4:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
FAILED
|
||||
|
||||
Done
|
||||
@@ -1,22 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract() with unicode files
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
$e = reset($entries);
|
||||
|
||||
$e->extract(false, dirname(__FILE__).'/temp.txt');
|
||||
|
||||
echo file_get_contents(dirname(__FILE__).'/temp.txt');
|
||||
echo "\n";
|
||||
|
||||
@unlink(dirname(__FILE__).'/temp.txt');
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
contents of file 1
|
||||
Done
|
||||
@@ -1,24 +0,0 @@
|
||||
--TEST--
|
||||
rar_list()/rar_entry_get() with not first volume
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part2.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo "Number of entries: " . count($entries) . "\n";
|
||||
echo reset($entries)."\n";
|
||||
$e = rar_entry_get($rar_file1, "file2.txt");
|
||||
var_dump($e);
|
||||
$e = rar_entry_get($rar_file1, "file3.txt");
|
||||
echo $e."\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Number of entries: 1
|
||||
RarEntry for file "file3.txt" (bcbce32e)
|
||||
|
||||
Warning: rar_entry_get(): cannot find file "file2.txt" in Rar archive "%s in %s on line %d
|
||||
bool(false)
|
||||
RarEntry for file "file3.txt" (bcbce32e)
|
||||
Done
|
||||
@@ -1,34 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (store method)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/store_method.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
$a = "";
|
||||
while (!feof($stream)) {
|
||||
$a .= fread($stream, 512);
|
||||
}
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
1 files:
|
||||
|
||||
tese.txt: 787 bytes, CRC 23B93A7A
|
||||
|
||||
Done
|
||||
@@ -1,36 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (solid archive)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/solid.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
$a = "";
|
||||
while (!feof($stream)) {
|
||||
$a .= fread($stream, 8192);
|
||||
}
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
2 files:
|
||||
|
||||
tese.txt: 787 bytes, CRC 23B93A7A
|
||||
|
||||
unrardll.txt: 19192 bytes, CRC 2ED64B6E
|
||||
|
||||
Done
|
||||
@@ -1,19 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::isDirectory() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
|
||||
foreach ($entries as $e) {
|
||||
echo "{$e->getName()} is ". ($e->isDirectory()?"":"not ") . "a directory.\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
dirwithsth%cfileindir.txt is not a directory.
|
||||
dirwithsth is a directory.
|
||||
emptydir is a directory.
|
||||
Done
|
||||
@@ -1,40 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract() with directory
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
|
||||
$e = rar_entry_get($rar_file1, "emptydir");
|
||||
|
||||
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydir";
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
$extrres = $e->extract(dirname(__FILE__));
|
||||
var_dump($extrres);
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
@rmdir($dir);
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydircust";
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
$extrres = $e->extract(false, $dir);
|
||||
var_dump($extrres);
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
@rmdir($dir);
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
Done
|
||||
@@ -1,21 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() with directory
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
|
||||
$e = rar_entry_get($rar_file1, "emptydir");
|
||||
$stream = $e->getStream();
|
||||
var_dump($stream);
|
||||
var_dump(feof($stream));
|
||||
var_dump(fread($stream, 200));
|
||||
var_dump(feof($stream));
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
resource(%d) of type (stream)
|
||||
bool(false)
|
||||
string(0) ""
|
||||
bool(true)
|
||||
Done
|
||||
@@ -1,46 +0,0 @@
|
||||
--TEST--
|
||||
rar_open()/RarEntry::getStream() (headers level password)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "--> should fail (no password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
|
||||
echo "\n--> should fail (wrong password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'wrongpassword');
|
||||
$entries = rar_list($rar_file1);
|
||||
|
||||
echo "\n--> should work:\n";
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
|
||||
$entries = rar_list($rar_file2);
|
||||
|
||||
echo "Found " . count($entries) . " files.\n";
|
||||
echo "Content of first one follows:\n";
|
||||
//reset($entries)->extract(false, "./temp.txt");
|
||||
$stream = reset($entries)->getStream();
|
||||
var_dump($stream);
|
||||
if ($stream !== FALSE) {
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 128);
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
--> should fail (no password):
|
||||
|
||||
Warning: rar_list(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
|
||||
--> should fail (wrong password):
|
||||
|
||||
Warning: rar_list(): ERAR_BAD_DATA in %s on line %d
|
||||
|
||||
--> should work:
|
||||
Found 2 files.
|
||||
Content of first one follows:
|
||||
resource(%d) of type (stream)
|
||||
Encrypted file 1 contents.
|
||||
Done
|
||||
@@ -1,26 +0,0 @@
|
||||
--TEST--
|
||||
rar_open()/RarEntry::extract() (headers level password)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
|
||||
$entries = rar_list($rar_file2);
|
||||
|
||||
echo "Found " . count($entries) . " files.\n";
|
||||
$tempfile = dirname(__FILE__).'/temp.txt';
|
||||
@unlink($tempfile);
|
||||
var_dump(reset($entries)->extract(false, $tempfile));
|
||||
echo "Content of first one follows:\n";
|
||||
echo file_get_contents($tempfile);
|
||||
$stream = reset($entries)->getStream();
|
||||
@unlink($tempfile);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Found 2 files.
|
||||
bool(true)
|
||||
Content of first one follows:
|
||||
Encrypted file 1 contents.
|
||||
Done
|
||||
@@ -1,52 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() (file level password)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "--> should fail (no password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
var_dump(count($entries));
|
||||
var_dump($entries[0]->getStream());
|
||||
echo "\n";
|
||||
|
||||
echo "--> success (password is the same as the one given on rar_open):\n";
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar', 'samplepassword');
|
||||
$entries = rar_list($rar_file2);
|
||||
echo stream_get_contents($entries[0]->getStream());
|
||||
echo "\n\n";
|
||||
|
||||
echo "--> should give incorrect data (password of 2nd file different from the one given on rar_open):\n";
|
||||
echo rawurlencode(stream_get_contents($entries[1]->getStream()));
|
||||
echo "\n\n";
|
||||
|
||||
echo "--> should give correct data (password of 2nd file is specified):\n";
|
||||
echo stream_get_contents($entries[1]->getStream('samplepassword2'));
|
||||
echo "\n\n";
|
||||
|
||||
echo "--> success (password is the same as the one given on rar_open, which shouldn't have been forgotten):\n";
|
||||
echo stream_get_contents($entries[0]->getStream());
|
||||
echo "\n\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
--> should fail (no password):
|
||||
int(2)
|
||||
|
||||
Warning: RarEntry::getStream(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
--> success (password is the same as the one given on rar_open):
|
||||
Encrypted file 1 contents.
|
||||
|
||||
--> should give incorrect data (password of 2nd file different from the one given on rar_open):
|
||||
t%09%A6%2B%0D%1B%F6%815%5E%E7%EC%C0%0BF%5EH%3A%C0%0D%815%5E%E7%EC%C0
|
||||
|
||||
--> should give correct data (password of 2nd file is specified):
|
||||
Encrypted file 1 contents.
|
||||
|
||||
--> success (password is the same as the one given on rar_open, which shouldn't have been forgotten):
|
||||
Encrypted file 1 contents.
|
||||
|
||||
Done
|
||||
@@ -1,54 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() with Linux directories and links
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar = rar_open(dirname(__FILE__) . "/dirlink_unix.rar");
|
||||
|
||||
echo "\nDirectory\n";
|
||||
|
||||
$e = rar_entry_get($rar, "nopermdir");
|
||||
echo $e."\n";
|
||||
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n"; //no read/write/execute perms
|
||||
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n";
|
||||
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
|
||||
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
|
||||
$stream = $e->getStream();
|
||||
$cont = stream_get_contents($stream);
|
||||
echo "$cont (strlen() " . strlen($cont) . ")\n";
|
||||
|
||||
echo "\nLink\n";
|
||||
|
||||
$e = rar_entry_get($rar, "link");
|
||||
echo $e."\n";
|
||||
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n";
|
||||
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n"; //coincidence
|
||||
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
|
||||
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
|
||||
$stream = $e->getStream();
|
||||
$cont = stream_get_contents($stream);
|
||||
echo "$cont (strlen() " . strlen($cont) . ")\n"; //varies on windows and linux
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Directory
|
||||
RarEntry for directory "nopermdir" (0)
|
||||
perms: 0
|
||||
win directory bit:
|
||||
unix directory attr: 1
|
||||
unix symlink attr:
|
||||
(strlen() 0)
|
||||
|
||||
Link
|
||||
RarEntry for file "link" (43e55b49)
|
||||
perms: 777
|
||||
win directory bit: 1
|
||||
unix directory attr:
|
||||
unix symlink attr: 1
|
||||
%s
|
||||
Done
|
||||
@@ -1,14 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive::open() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
|
||||
var_dump(get_class($arch));
|
||||
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
string(10) "RarArchive"
|
||||
Done
|
||||
@@ -1,21 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive::getEntries() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
|
||||
foreach ($arch->getEntries() as $e) {
|
||||
echo $e . "\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
RarEntry for file "emptydir%clink" (36ac99f1)
|
||||
RarEntry for file "file" (b95e8411)
|
||||
RarEntry for file "link" (43e55b49)
|
||||
RarEntry for directory "emptydir" (0)
|
||||
RarEntry for directory "nopermdir" (0)
|
||||
RarEntry for directory "setuiddir" (0)
|
||||
RarEntry for directory "stickydir" (0)
|
||||
Done
|
||||
@@ -1,14 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive::getEntry() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_arch = RarArchive::open(dirname(__FILE__) . '/solid.rar');
|
||||
$rar_entry = $rar_arch->getEntry('tese.txt');
|
||||
echo $rar_entry;
|
||||
echo "\n";
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
RarEntry for file "tese.txt" (23b93a7a)
|
||||
Done
|
||||
@@ -1,13 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive::getComment() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_arch = RarArchive::open(dirname(__FILE__) . '/commented.rar');
|
||||
echo $rar_arch->getComment();
|
||||
echo "\n";
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
This is the comment of the file commented.rar.
|
||||
Done
|
||||
@@ -1,16 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive traversal with multi-part archive
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rarF = RarArchive::open(dirname(__FILE__) . '/multi.part1.rar');
|
||||
foreach ($rarF as $k => $rarE) {
|
||||
echo "$k. $rarE\n";
|
||||
}
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
0. RarEntry for file "file1.txt" (52b28202)
|
||||
1. RarEntry for file "file2.txt" (f2c79881)
|
||||
2. RarEntry for file "file3.txt" (bcbce32e)
|
||||
Done
|
||||
@@ -1,24 +0,0 @@
|
||||
--TEST--
|
||||
rar_solid_is() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arch1 = RarArchive::open(dirname(__FILE__) . "/store_method.rar");
|
||||
$arch2 = RarArchive::open(dirname(__FILE__) . "/solid.rar");
|
||||
echo "$arch1: " . ($arch1->isSolid()?'yes':'no') ."\n";
|
||||
echo "$arch2: " . (rar_solid_is($arch2)?'yes':'no') . "\n";
|
||||
|
||||
$arch2->close();
|
||||
var_dump(rar_solid_is($arch2));
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
RAR Archive "%sstore_method.rar": no
|
||||
RAR Archive "%ssolid.rar": yes
|
||||
|
||||
Warning: rar_solid_is(): The archive is already closed in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Done.
|
||||
@@ -1,16 +0,0 @@
|
||||
--TEST--
|
||||
RarException::(set/is)UsingExceptions() test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "Initial state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
|
||||
RarException::setUsingExceptions(true);
|
||||
echo "State change done.\n";
|
||||
echo "Final state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Initial state: no.
|
||||
State change done.
|
||||
Final state: yes.
|
||||
Done.
|
||||
@@ -1,19 +0,0 @@
|
||||
--TEST--
|
||||
rar_entry_get() non-existent file with exceptions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
RarException::setUsingExceptions(true);
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/latest_winrar.rar");
|
||||
try {
|
||||
$arch->getEntry('nonexistentfile.txt');
|
||||
} catch (RarException $re) {
|
||||
echo "Message: " . $re->getMessage()."\n";
|
||||
echo "Code: " . $re->getCode() ."\n";
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Message: cannot find file "nonexistentfile.txt" in Rar archive "%slatest_winrar.rar"
|
||||
Code: -1
|
||||
Done.
|
||||
@@ -1,18 +0,0 @@
|
||||
--TEST--
|
||||
rar_open() non-existent archive with exceptions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
RarException::setUsingExceptions(true);
|
||||
try {
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/nonexistentarchive.rar");
|
||||
} catch (RarException $re) {
|
||||
echo "Message: " . $re->getMessage()."\n";
|
||||
echo "Code: " . $re->getCode() ."\n";
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Message: unRAR internal error: Failed to open %snonexistentarchive.rar: ERAR_EOPEN (file open error)
|
||||
Code: 15
|
||||
Done.
|
||||
@@ -1,24 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream(), password not given, with exceptions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
RarException::setUsingExceptions(true);
|
||||
echo "--> should fail (no password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
var_dump(count($entries));
|
||||
try {
|
||||
var_dump($entries[0]->getStream());
|
||||
} catch (RarException $re) {
|
||||
echo "Message: " . $re->getMessage()."\n";
|
||||
echo "Code: " . $re->getCode() ."\n";
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
--> should fail (no password):
|
||||
int(2)
|
||||
Message: unRAR internal error: ERAR_MISSING_PASSWORD (password needed but not specified)
|
||||
Code: 22
|
||||
Done.
|
||||
@@ -1,15 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive get iterator on closed file
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rarF = RarArchive::open(dirname(__FILE__) . '/latest_winrar.rar');
|
||||
$rarF->close();
|
||||
foreach ($rarF as $k => $rarE) {
|
||||
echo "$k. $rarE\n";
|
||||
unset($rarE);
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Fatal error: main(): The archive is already closed, cannot give an iterator in %s on line %d
|
||||
@@ -1,15 +0,0 @@
|
||||
--TEST--
|
||||
Access RAR archive with missing volumes
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rarF = RarArchive::open(dirname(__FILE__) . '/multi_broken.part1.rar');
|
||||
var_dump(rar_list($rarF));
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Warning: rar_list(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: rar_list(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
bool(false)
|
||||
Done.
|
||||
@@ -1,26 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getUnpackedSize() on platforms with 32-bit longs
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platforms only");
|
||||
--FILE--
|
||||
<?php
|
||||
$fn1 = dirname(__FILE__) . '/sparsefiles_rar.rar';
|
||||
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
|
||||
$rarF = RarArchive::open($fn1);
|
||||
$t = $rarF->getEntries();
|
||||
reset($t)->extract(false, $fn2);
|
||||
$rarF2 = RarArchive::open($fn2);
|
||||
$t = $rarF2->getEntries();
|
||||
var_dump($t[0]->getUnpackedSize());
|
||||
var_dump($t[1]->getUnpackedSize());
|
||||
echo "Done.\n";
|
||||
--CLEAN--
|
||||
<?php
|
||||
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
|
||||
@unlink($fn2);
|
||||
--EXPECTF--
|
||||
int(2147483647)
|
||||
int(2147483647)
|
||||
Done.
|
||||
@@ -1,26 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getUnpackedSize() on platforms with 64-bit longs
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only");
|
||||
--FILE--
|
||||
<?php
|
||||
$fn1 = dirname(__FILE__) . '/sparsefiles_rar.rar';
|
||||
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
|
||||
$rarF = RarArchive::open($fn1);
|
||||
$t = $rarF->getEntries();
|
||||
reset($t)->extract(false, $fn2);
|
||||
$rarF2 = RarArchive::open($fn2);
|
||||
$t = $rarF2->getEntries();
|
||||
var_dump($t[0]->getUnpackedSize());
|
||||
var_dump($t[1]->getUnpackedSize());
|
||||
echo "Done.\n";
|
||||
--CLEAN--
|
||||
<?php
|
||||
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
|
||||
@unlink($fn2);
|
||||
--EXPECTF--
|
||||
int(2621440000)
|
||||
int(5368709120)
|
||||
Done.
|
||||
@@ -1,38 +0,0 @@
|
||||
--TEST--
|
||||
rar_open() with volume find callback basic test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
chdir(dirname(__FILE__));
|
||||
function volume_callback($vol) {
|
||||
if (preg_match('/_fail/', $vol))
|
||||
$ret = basename(str_replace('_fail', '', $vol));
|
||||
elseif (preg_match('/_broken/', $vol))
|
||||
$ret = basename(str_replace('_broken', '_fail', $vol));
|
||||
else
|
||||
$ret = null;
|
||||
echo "Not found:\n\t$vol\nReplacing with:\n\t$ret\n";
|
||||
return $ret;
|
||||
}
|
||||
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
|
||||
$rar = RarArchive::open($fn, null, 'volume_callback');
|
||||
foreach ($rar as $e) {
|
||||
echo "Entry: $e.\n";
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Not found:
|
||||
%smulti_broken.part2.rar
|
||||
Replacing with:
|
||||
multi_fail.part2.rar
|
||||
Not found:
|
||||
%smulti_fail.part2.rar
|
||||
Replacing with:
|
||||
multi.part2.rar
|
||||
Entry: RarEntry for file "file1.txt" (52b28202).
|
||||
Entry: RarEntry for file "file2.txt" (f2c79881).
|
||||
Entry: RarEntry for file "file3.txt" (bcbce32e).
|
||||
Done.
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
--TEST--
|
||||
rar_open() with volume find (callback variants 1)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
public static function resolve($vol) {
|
||||
if (preg_match('/_broken/', $vol))
|
||||
return str_replace('_broken', '', $vol);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public static function resolveStatic($vol) {
|
||||
echo "A::resolveStatic()\n";
|
||||
return self::resolve($vol);
|
||||
}
|
||||
|
||||
public function resolveInstance($vol) {
|
||||
echo "A::resolveInstance()\n";
|
||||
return self::resolve($vol);
|
||||
}
|
||||
}
|
||||
|
||||
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
|
||||
$rar = RarArchive::open($fn, null, "A::resolveStatic");
|
||||
$rar->getEntries();
|
||||
$rar = RarArchive::open($fn, null, array("A", "resolveStatic"));
|
||||
$rar->getEntries();
|
||||
$rar = RarArchive::open($fn, null, array(new A(), "resolveInstance"));
|
||||
$rar->getEntries();
|
||||
function testA() {
|
||||
global $fn;
|
||||
$obj = new A();
|
||||
return RarArchive::open($fn, null, array($obj, "resolveInstance"));
|
||||
}
|
||||
$rar = testA();
|
||||
$rar->getEntries();
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
A::resolveStatic()
|
||||
A::resolveStatic()
|
||||
A::resolveInstance()
|
||||
A::resolveInstance()
|
||||
Done.
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
--TEST--
|
||||
rar_open() with volume find (callback variants 2)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
if(!defined('PHP_VERSION_ID') || PHP_VERSION_ID<50300) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
public static function resolve($vol) {
|
||||
if (preg_match('/_broken/', $vol))
|
||||
return str_replace('_broken', '', $vol);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public function __invoke($vol) {
|
||||
echo "A::__invoke()\n";
|
||||
return self::resolve($vol);
|
||||
}
|
||||
}
|
||||
|
||||
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
|
||||
$f = function ($vol) {
|
||||
echo "Closure\n";
|
||||
return A::resolve($vol);
|
||||
};
|
||||
$rar = RarArchive::open($fn, null, new A());
|
||||
$rar->getEntries();
|
||||
$rar = RarArchive::open($fn, null, $f);
|
||||
$rar->getEntries();
|
||||
|
||||
$f2 = function ($vol) {
|
||||
echo "Closure (2)\n";
|
||||
return A::resolve($vol);
|
||||
};
|
||||
$rar = RarArchive::open($fn, null, $f2);
|
||||
unset($f2);
|
||||
$rar->getEntries();
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
A::__invoke()
|
||||
Closure
|
||||
Closure (2)
|
||||
Done.
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
--TEST--
|
||||
rar_open() with invalid volume callback
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
public static function resolve($vol) {
|
||||
if (preg_match('/_broken/', $vol))
|
||||
return str_replace('_broken', '', $vol);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
public function resolveInstance($vol) {
|
||||
echo "A::resolveInstance()\n";
|
||||
return self::resolve($vol);
|
||||
}
|
||||
}
|
||||
|
||||
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
|
||||
|
||||
echo "\nNot given a callback:\n";
|
||||
$rar = RarArchive::open($fn, null, new Exception());
|
||||
|
||||
echo "\nGiven static callback for instance method (test IS_CALLABLE_STRICT):\n";
|
||||
$rar = RarArchive::open($fn, null, "A::resolveInstance");
|
||||
var_dump($rar);
|
||||
|
||||
echo "\nGiven callback that takes more arguments:\n";
|
||||
$rar = RarArchive::open($fn, null, 'array_walk');
|
||||
$rar->getEntries();
|
||||
|
||||
echo "\nGiven callback that takes another kind of arguments:\n";
|
||||
$rar = RarArchive::open($fn, null, 'ksort');
|
||||
$rar->getEntries();
|
||||
|
||||
echo "\nGiven callback that returns another kind of arguments:\n";
|
||||
function testA($vol) { return true; }
|
||||
$rar = RarArchive::open($fn, null, 'testA');
|
||||
$rar->getEntries();
|
||||
|
||||
echo "\nGiven callback that throws Exception:\n";
|
||||
function testB($vol) { throw new Exception(); }
|
||||
$rar = RarArchive::open($fn, null, 'testB');
|
||||
try {
|
||||
$rar->getEntries();
|
||||
die("should have thrown exception.");
|
||||
} catch (Exception $e) {
|
||||
echo "OK, threw exception.\n";
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Not given a callback:
|
||||
|
||||
Warning: RarArchive::open(): Expected the third argument, if provided, to be a valid callback in %s on line %d
|
||||
|
||||
Given static callback for instance method (test IS_CALLABLE_STRICT):
|
||||
|
||||
Warning: RarArchive::open(): Expected the third argument, if provided, to be a valid callback in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Given callback that takes more arguments:
|
||||
|
||||
Warning: array_walk() expects at least %d parameters, 1 given in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Given callback that takes another kind of arguments:
|
||||
|
||||
Warning: ksort() expects parameter 1 to be array, string given in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntries(): Wrong type returned by volume find callback, expected string or NULL in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Given callback that returns another kind of arguments:
|
||||
|
||||
Warning: RarArchive::getEntries(): Wrong type returned by volume find callback, expected string or NULL in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Given callback that throws Exception:
|
||||
|
||||
Warning: RarArchive::getEntries(): Failure to call volume find callback in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
OK, threw exception.
|
||||
Done.
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (broken set fixed with volume callback)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
function resolve($vol) {
|
||||
if (preg_match('/_broken/', $vol))
|
||||
return str_replace('_broken', '', $vol);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi_broken.part1.rar', null, 'resolve');
|
||||
foreach ($rar_file1 as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
$a = "";
|
||||
while (is_resource($stream) && !feof($stream)) {
|
||||
$a .= fread($stream, 8192);
|
||||
}
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
file1.txt: 18 bytes, CRC 52B28202
|
||||
|
||||
file2.txt: 17704 bytes, CRC F2C79881
|
||||
|
||||
file3.txt: 18 bytes, CRC BCBCE32E
|
||||
|
||||
Done
|
||||
@@ -1,41 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract() function (broken set fixed with volume callback)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
function resolve($vol) {
|
||||
if (preg_match('/_broken/', $vol))
|
||||
return str_replace('_broken', '', $vol);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
echo "Fail:\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi_broken.part1.rar');
|
||||
$entry = $rar_file1->getEntry('file2.txt');
|
||||
|
||||
echo "\nSuccess:\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi_broken.part1.rar', null, 'resolve');
|
||||
$entry = $rar_file1->getEntry('file2.txt');
|
||||
$entry->extract(null, dirname(__FILE__) . "/temp_file2.txt");
|
||||
echo int32_to_hex(crc32(file_get_contents(dirname(__FILE__) . "/temp_file2.txt")));
|
||||
echo "\n";
|
||||
echo "Done\n";
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(dirname(__FILE__) . "/temp_file2.txt");
|
||||
--EXPECTF--
|
||||
Fail:
|
||||
|
||||
Warning: RarArchive::getEntry(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntry(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Success:
|
||||
F2C79881
|
||||
Done
|
||||
@@ -1,26 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive::open() volume callback long return (case MAXPATHLEN <= NM)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
if (!defined("PHP_MAXPATHLEN"))
|
||||
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
|
||||
if (!(PHP_MAXPATHLEN <= 1024))
|
||||
die("skip; this test is for systems where MAXPATHLEN <= 1024");
|
||||
--FILE--
|
||||
<?php
|
||||
if (!defined("PHP_MAXPATHLEN"))
|
||||
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
|
||||
|
||||
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
|
||||
|
||||
function testA($vol) { if ($vol[0] != 'a') return str_repeat("a", PHP_MAXPATHLEN); }
|
||||
$rar = RarArchive::open($fn, null, 'testA');
|
||||
$rar->getEntries();
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Warning: RarArchive::getEntries(): Cound not expand filename aaaa%s in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
Done.
|
||||
@@ -1,30 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive::open() volume callback long return (case MAXPATHLEN > NM)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
if (!defined("PHP_MAXPATHLEN"))
|
||||
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
|
||||
if (!(PHP_MAXPATHLEN > 1024))
|
||||
die("skip test is for systems where MAXPATHLEN > 1024");
|
||||
$rp = dirname(__FILE__) . "/" . str_repeat("a", 1024);
|
||||
if (strlen(dirname(__FILE__) > PHP_MAXPATHLEN - 1))
|
||||
die("skip current directory is too deep.");
|
||||
--FILE--
|
||||
<?php
|
||||
if (!defined("PHP_MAXPATHLEN"))
|
||||
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
|
||||
|
||||
chdir(dirname(__FILE__));
|
||||
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
|
||||
|
||||
function testA($vol) { if ($vol[0] != 'a') return str_repeat("a", 1024); }
|
||||
$rar = RarArchive::open($fn, null, 'testA');
|
||||
$rar->getEntries();
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Warning: RarArchive::getEntries(): Resolved path is too big for the unRAR library in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
Done.
|
||||
@@ -1,16 +0,0 @@
|
||||
--TEST--
|
||||
Stream wrapper basic test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/latest_winrar.rar' .
|
||||
"#1.txt", "r");
|
||||
var_dump(stream_get_contents($stream));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
string(5) "11111"
|
||||
Done.
|
||||
@@ -1,62 +0,0 @@
|
||||
--TEST--
|
||||
Stream wrapper relative path test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--CLEAN--
|
||||
<?php
|
||||
unlink(dirname(__FILE__) . '/temp/tmp.rar');
|
||||
rmdir(dirname(__FILE__) . "/temp");
|
||||
--FILE--
|
||||
<?php
|
||||
mkdir(dirname(__FILE__) . "/temp");
|
||||
chdir(dirname(__FILE__) . "/temp");
|
||||
|
||||
echo "Test relative to working dir:\n";
|
||||
$stream = fopen("rar://" .
|
||||
'../latest_winrar.rar' .
|
||||
"#1.txt", "r");
|
||||
var_dump(stream_get_contents($stream));
|
||||
|
||||
echo "\nTest with include path:\n";
|
||||
copy(dirname(__FILE__) . '/latest_winrar.rar',
|
||||
dirname(__FILE__) . '/temp/tmp.rar');
|
||||
chdir(dirname(__FILE__));
|
||||
|
||||
//now with include
|
||||
echo "Should fail (not in include):\n";
|
||||
$stream = fopen("rar://" .
|
||||
'tmp.rar' .
|
||||
"#1.txt", "r");
|
||||
|
||||
echo "\nShould fail (include unused):\n";
|
||||
|
||||
set_include_path(dirname(__FILE__). '/temp');
|
||||
$stream = fopen("rar://" .
|
||||
'tmp.rar' .
|
||||
"#1.txt", "r");
|
||||
|
||||
echo "\nShould succeed:\n";
|
||||
$stream = fopen("rar://" .
|
||||
'tmp.rar' .
|
||||
"#1.txt", "r", true);
|
||||
var_dump(stream_get_contents($stream));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Test relative to working dir:
|
||||
string(5) "11111"
|
||||
|
||||
Test with include path:
|
||||
Should fail (not in include):
|
||||
|
||||
Warning: fopen(rar://tmp.rar#1.txt): failed to open stream: Error opening RAR archive %stmp.rar: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Should fail (include unused):
|
||||
|
||||
Warning: fopen(rar://tmp.rar#1.txt): failed to open stream: Error opening RAR archive %stmp.rar: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Should succeed:
|
||||
string(5) "11111"
|
||||
Done.
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
--TEST--
|
||||
Stream wrapper archive/file not found
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "Archive not found :\n";
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . "/not_found.rar" .
|
||||
"#1.txt", "r");
|
||||
|
||||
echo "\nFile not found :\n";
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . "/latest_winrar.rar" .
|
||||
"#not_found.txt", "r");
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Archive not found :
|
||||
|
||||
Warning: fopen(rar://%snot_found.rar#1.txt): failed to open stream: Error opening RAR archive %snot_found.rar: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
File not found :
|
||||
|
||||
Warning: fopen(rar://%slatest_winrar.rar#not_found.txt): failed to open stream: Can't file not_found.txt in RAR archive %s on line %d
|
||||
Done.
|
||||
@@ -1,47 +0,0 @@
|
||||
--TEST--
|
||||
Stream wrapper malformed url
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "Test empty:\n";
|
||||
$stream = fopen("rar://", "r");
|
||||
|
||||
echo "\nTest no fragment:\n";
|
||||
$stream = fopen("rar://file.rar", "r");
|
||||
|
||||
echo "\nTest empty fragment:\n";
|
||||
$stream = fopen("rar://file.rar#", "r");
|
||||
|
||||
echo "\nTest no path:\n";
|
||||
|
||||
$stream = fopen("rar://#frag", "r");
|
||||
|
||||
echo "\nTest no path and empty fragment:\n";
|
||||
|
||||
$stream = fopen("rar://#", "r");
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Test empty:
|
||||
|
||||
Warning: fopen(rar://): failed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
|
||||
|
||||
Test no fragment:
|
||||
|
||||
Warning: fopen(rar://file.rar): failed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
|
||||
|
||||
Test empty fragment:
|
||||
|
||||
Warning: fopen(rar://file.rar#): failed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
|
||||
|
||||
Test no path:
|
||||
|
||||
Warning: fopen(rar://#frag): failed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
|
||||
|
||||
Test no path and empty fragment:
|
||||
|
||||
Warning: fopen(rar://#): failed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
|
||||
Done.
|
||||
@@ -1,79 +0,0 @@
|
||||
--TEST--
|
||||
Stream wrapper with header or file level passwords
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "Headers: should not work (no password):\n";
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/encrypted_headers.rar' .
|
||||
"#encfile1.txt", "r");
|
||||
|
||||
|
||||
echo "\nHeaders: should not work (password given was file_password):\n";
|
||||
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/encrypted_headers.rar' .
|
||||
"#encfile1.txt", "r", false,
|
||||
stream_context_create(array('rar'=>array('file_password'=>'samplepassword'))));
|
||||
|
||||
echo "\nHeaders: should work (password given was open_password):\n";
|
||||
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/encrypted_headers.rar' .
|
||||
"#encfile1.txt", "r", false,
|
||||
stream_context_create(array('rar'=>array('open_password'=>'samplepassword'))));
|
||||
var_dump(stream_get_contents($stream));
|
||||
|
||||
//////////////////////
|
||||
|
||||
echo "\n\nFiles: should not work (no password):\n";
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/encrypted_only_files.rar' .
|
||||
"#encfile1.txt", "r");
|
||||
|
||||
|
||||
echo "\nFiles: should not work (password given was open_password):\n";
|
||||
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/encrypted_only_files.rar' .
|
||||
"#encfile1.txt", "r", false,
|
||||
stream_context_create(array('rar'=>array('open_password'=>'samplepassword'))));
|
||||
|
||||
echo "\nFiles: should work (password given was file_password):\n";
|
||||
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/encrypted_only_files.rar' .
|
||||
"#encfile1.txt", "r", false,
|
||||
stream_context_create(array('rar'=>array('file_password'=>'samplepassword'))));
|
||||
var_dump(stream_get_contents($stream));
|
||||
|
||||
echo "\nDone.\n";
|
||||
|
||||
--EXPECTF--
|
||||
Headers: should not work (no password):
|
||||
|
||||
Warning: fopen(rar://%sencrypted_headers.rar#encfile1.txt): failed to open stream: Error opening RAR archive %sencrypted_headers.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
|
||||
Headers: should not work (password given was file_password):
|
||||
|
||||
Warning: fopen(rar://%sencrypted_headers.rar#encfile1.txt): failed to open stream: Error opening RAR archive %sencrypted_headers.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
|
||||
Headers: should work (password given was open_password):
|
||||
string(26) "Encrypted file 1 contents."
|
||||
|
||||
|
||||
Files: should not work (no password):
|
||||
|
||||
Warning: fopen(rar://%sencrypted_only_files.rar#encfile1.txt): failed to open stream: Error opening file encfile1.txt inside RAR archive %sencrypted_only_files.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
|
||||
Files: should not work (password given was open_password):
|
||||
|
||||
Warning: fopen(rar://%sencrypted_only_files.rar#encfile1.txt): failed to open stream: Error opening file encfile1.txt inside RAR archive %sencrypted_only_files.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
|
||||
Files: should work (password given was file_password):
|
||||
string(26) "Encrypted file 1 contents."
|
||||
|
||||
Done.
|
||||
@@ -1,30 +0,0 @@
|
||||
--TEST--
|
||||
Stream wrapper with volume find callback
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
function resolve($vol) {
|
||||
if (preg_match('/_broken/', $vol))
|
||||
return str_replace('_broken', '', $vol);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/multi_broken.part1.rar' .
|
||||
"#file2.txt", "r", false,
|
||||
stream_context_create(array('rar'=>array('volume_callback'=>'resolve'))));
|
||||
$a = stream_get_contents($stream);
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
17704 bytes, CRC F2C79881
|
||||
|
||||
Done.
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
--TEST--
|
||||
RAR file stream stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--ENV--
|
||||
TZ=Europe/Lisbon
|
||||
--FILE--
|
||||
<?php
|
||||
umask(0);
|
||||
$stream = fopen("rar://" .
|
||||
dirname(__FILE__) . '/latest_winrar.rar' .
|
||||
"#1.txt", "r");
|
||||
print_r(array_slice(fstat($stream), 13));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Array
|
||||
(
|
||||
[dev] => 0
|
||||
[ino] => 0
|
||||
[mode] => 33206
|
||||
[nlink] => 1
|
||||
[uid] => 0
|
||||
[gid] => 0
|
||||
[rdev] => 0
|
||||
[size] => 5
|
||||
[atime] => 0
|
||||
[mtime] => 1086948439
|
||||
[ctime] => 0
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
)
|
||||
Done.
|
||||
@@ -1,21 +0,0 @@
|
||||
--TEST--
|
||||
RAR file stream stat consistency with url stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/latest_winrar.rar' .
|
||||
"#1.txt";
|
||||
$stream = fopen($u, "r");
|
||||
$fs = (fstat($stream));
|
||||
|
||||
$us = stat($u);
|
||||
|
||||
var_dump($fs == $us);
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
Done.
|
||||
@@ -1,24 +0,0 @@
|
||||
--TEST--
|
||||
RAR file stream stat applied to directory consistency with url stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar' .
|
||||
"#emptydir";
|
||||
$stream = fopen($u, "r");
|
||||
$fs = (fstat($stream));
|
||||
|
||||
$us = stat($u);
|
||||
|
||||
var_dump($fs == $us);
|
||||
|
||||
var_dump(is_dir($u));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
bool(true)
|
||||
Done.
|
||||
136
tests/059.phpt
136
tests/059.phpt
@@ -1,136 +0,0 @@
|
||||
--TEST--
|
||||
url stat test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--ENV--
|
||||
TZ=Europe/Lisbon
|
||||
--FILE--
|
||||
<?php
|
||||
umask(0);
|
||||
$inex_rar = "rar://" .
|
||||
dirname(__FILE__) . '/not_found.rar' .
|
||||
"#emptydir";
|
||||
|
||||
echo "RAR not found:\n";
|
||||
var_dump(stat($inex_rar));
|
||||
|
||||
$inex_entry = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar' .
|
||||
"#inexistent entry";
|
||||
|
||||
echo "\nRAR entry not found:\n";
|
||||
var_dump(stat($inex_entry));
|
||||
|
||||
$root1 = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar';
|
||||
|
||||
echo "\nRAR root:\n";
|
||||
$statr1 = stat($root1);
|
||||
print_r(array_slice($statr1, 13));
|
||||
echo "\nRAR root is dir:\n";
|
||||
var_dump(is_dir($root1));
|
||||
|
||||
$root2 = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar#';
|
||||
|
||||
echo "\nRAR root variant 2 matches:\n";
|
||||
var_dump(stat($root2) == $statr1);
|
||||
|
||||
$root3 = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar#/';
|
||||
echo "\nRAR root variant 3 matches:\n";
|
||||
var_dump(stat($root3) == $statr1);
|
||||
|
||||
$file = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar' .
|
||||
"#file";
|
||||
|
||||
echo "\nRegular file:\n";
|
||||
print_r(array_slice(stat($file), 13));
|
||||
|
||||
$dir = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar' .
|
||||
"#emptydir";
|
||||
echo "\nRegular file:\n";
|
||||
print_r(array_slice(stat($dir), 13));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
RAR not found:
|
||||
|
||||
Warning: stat(): Failed to open %snot_found.rar: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: stat(): stat failed for rar://%s/not_found.rar#emptydir in %s on line %d
|
||||
bool(false)
|
||||
|
||||
RAR entry not found:
|
||||
|
||||
Warning: stat(): Found no entry inexistent entry in archive %sdirlink_unix.rar in %s on line %d
|
||||
|
||||
Warning: stat(): stat failed for rar://%s/dirlink_unix.rar#inexistent entry in %s on line %d
|
||||
bool(false)
|
||||
|
||||
RAR root:
|
||||
Array
|
||||
(
|
||||
[dev] => 0
|
||||
[ino] => 0
|
||||
[mode] => 16895
|
||||
[nlink] => 1
|
||||
[uid] => 0
|
||||
[gid] => 0
|
||||
[rdev] => 0
|
||||
[size] => 0
|
||||
[atime] => 0
|
||||
[mtime] => 312768000
|
||||
[ctime] => 0
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
)
|
||||
|
||||
RAR root is dir:
|
||||
bool(true)
|
||||
|
||||
RAR root variant 2 matches:
|
||||
bool(true)
|
||||
|
||||
RAR root variant 3 matches:
|
||||
bool(true)
|
||||
|
||||
Regular file:
|
||||
Array
|
||||
(
|
||||
[dev] => 0
|
||||
[ino] => 0
|
||||
[mode] => 33188
|
||||
[nlink] => 1
|
||||
[uid] => 0
|
||||
[gid] => 0
|
||||
[rdev] => 0
|
||||
[size] => 8
|
||||
[atime] => 0
|
||||
[mtime] => 1259625512
|
||||
[ctime] => 0
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
)
|
||||
|
||||
Regular file:
|
||||
Array
|
||||
(
|
||||
[dev] => 0
|
||||
[ino] => 0
|
||||
[mode] => 16877
|
||||
[nlink] => 1
|
||||
[uid] => 0
|
||||
[gid] => 0
|
||||
[rdev] => 0
|
||||
[size] => 0
|
||||
[atime] => 0
|
||||
[mtime] => 1259625807
|
||||
[ctime] => 0
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
)
|
||||
Done.
|
||||
@@ -1,61 +0,0 @@
|
||||
--TEST--
|
||||
RAR directory stream basic test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "Root entries unencoded:\n";
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirs_and_extra_headers.rar*';
|
||||
|
||||
$d = dir($u);
|
||||
while (false !== ($entry = $d->read())) {
|
||||
echo $entry."\n";
|
||||
}
|
||||
$d->close();
|
||||
|
||||
echo "\nRoot entries encoded:\n";
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirs_and_extra_headers.rar';
|
||||
|
||||
$d = dir($u);
|
||||
while (false !== ($entry = $d->read())) {
|
||||
echo $entry."\n";
|
||||
}
|
||||
$d->close();
|
||||
|
||||
echo "\nSub-root directory entries unencoded:\n";
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirs_and_extra_headers.rar*#%EF%AC%B0';
|
||||
|
||||
$d = dir($u);
|
||||
while (false !== ($entry = $d->read())) {
|
||||
echo $entry."\n";
|
||||
}
|
||||
|
||||
echo "\nDone.\n";
|
||||
--EXPECTF--
|
||||
Root entries unencoded:
|
||||
allow_everyone_ni
|
||||
file1.txt
|
||||
file2_אּ.txt
|
||||
with_streams.txt
|
||||
אּ
|
||||
|
||||
Root entries encoded:
|
||||
allow_everyone_ni
|
||||
file1.txt
|
||||
file2_%EF%AC%B0.txt
|
||||
with_streams.txt
|
||||
%EF%AC%B0
|
||||
|
||||
Sub-root directory entries unencoded:
|
||||
%2Fempty%2E
|
||||
empty
|
||||
file3.txt
|
||||
file4_אּ.txt
|
||||
אּ_2
|
||||
|
||||
Done.
|
||||
@@ -1,17 +0,0 @@
|
||||
--TEST--
|
||||
RAR directory stream attempt on file
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar' .
|
||||
"#file";
|
||||
var_dump(opendir($u));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Warning: opendir(rar://%sdirlink_unix.rar#file): failed to open dir: Archive %sdirlink_unix.rar has an entry named file, but it is not a directory in %s on line %d
|
||||
bool(false)
|
||||
Done.
|
||||
@@ -1,63 +0,0 @@
|
||||
--TEST--
|
||||
RAR directory stream stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--ENV--
|
||||
TZ=Europe/Lisbon
|
||||
--FILE--
|
||||
<?php
|
||||
umask(0);
|
||||
|
||||
echo "Root:\n";
|
||||
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirs_and_extra_headers.rar';
|
||||
|
||||
print_r(array_slice(fstat(opendir($u)), 13));
|
||||
|
||||
echo "\nSub-root directory:\n";
|
||||
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirs_and_extra_headers.rar#%EF%AC%B0';
|
||||
|
||||
print_r(array_slice(fstat(opendir($u)), 13));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Root:
|
||||
Array
|
||||
(
|
||||
[dev] => 0
|
||||
[ino] => 0
|
||||
[mode] => 16895
|
||||
[nlink] => 1
|
||||
[uid] => 0
|
||||
[gid] => 0
|
||||
[rdev] => 0
|
||||
[size] => 0
|
||||
[atime] => 0
|
||||
[mtime] => 312768000
|
||||
[ctime] => 0
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
)
|
||||
|
||||
Sub-root directory:
|
||||
Array
|
||||
(
|
||||
[dev] => 0
|
||||
[ino] => 0
|
||||
[mode] => 16895
|
||||
[nlink] => 1
|
||||
[uid] => 0
|
||||
[gid] => 0
|
||||
[rdev] => 0
|
||||
[size] => 0
|
||||
[atime] => 1272938643
|
||||
[mtime] => 1272938643
|
||||
[ctime] => 1272813170
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
)
|
||||
Done.
|
||||
@@ -1,30 +0,0 @@
|
||||
--TEST--
|
||||
RAR directory stream stat consistency with url stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "Root:\n";
|
||||
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirs_and_extra_headers.rar';
|
||||
|
||||
var_dump(fstat(opendir($u)) == stat($u));
|
||||
|
||||
echo "\nSub-root directory:\n";
|
||||
|
||||
$u = "rar://" .
|
||||
dirname(__FILE__) . '/dirs_and_extra_headers.rar#%EF%AC%B0';
|
||||
|
||||
var_dump(fstat(opendir($u)) == stat($u));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Root:
|
||||
bool(true)
|
||||
|
||||
Sub-root directory:
|
||||
bool(true)
|
||||
Done.
|
||||
@@ -1,51 +0,0 @@
|
||||
--TEST--
|
||||
RAR directory-aware traversal with directory streams
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
$a = "rar://" . dirname(__FILE__) . '/dirs_and_extra_headers.rar';
|
||||
$stack = array();
|
||||
$dh = opendir($a);
|
||||
if ($dh) {
|
||||
array_push($stack, array("", $dh));
|
||||
}
|
||||
$indent = 0;
|
||||
while (!empty($stack)) {
|
||||
$arr = array_pop($stack);
|
||||
$prefix = $arr[0];
|
||||
$cd = $arr[1];
|
||||
while (($file = readdir($cd)) !== false) {
|
||||
$u = $a . "#" . $prefix . "/" . $file;
|
||||
$isdir = is_dir($u);
|
||||
echo str_repeat(" ", $indent) .
|
||||
"- ".rawurldecode($file)." ". ($isdir?"(dir)":""). "\n";
|
||||
if ($isdir) {
|
||||
if (($dh = opendir($u)) === false)
|
||||
die("could not open $u");
|
||||
$indent++;
|
||||
array_push($stack, array($prefix, $cd));
|
||||
$cd = $dh;
|
||||
$prefix = $prefix . "/" . $file;
|
||||
}
|
||||
}
|
||||
$indent--;
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
- allow_everyone_ni (dir)
|
||||
- file1.txt
|
||||
- file2_אּ.txt
|
||||
- with_streams.txt
|
||||
- אּ (dir)
|
||||
- %2Fempty%2E (dir)
|
||||
- file7.txt
|
||||
- empty (dir)
|
||||
- file3.txt
|
||||
- file4_אּ.txt
|
||||
- אּ_2 (dir)
|
||||
- file5.txt
|
||||
- file6_אּ.txt
|
||||
Done.
|
||||
@@ -1,57 +0,0 @@
|
||||
--TEST--
|
||||
Directory streams compatibility with RecursiveDirectoryIterator
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$a = "rar://" . dirname(__FILE__) . '/dirs_and_extra_headers.rar#';
|
||||
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($a),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY);
|
||||
|
||||
$it->rewind();
|
||||
while($it->valid()) {
|
||||
if (!$it->isDot()) {
|
||||
echo 'SubPathName: ' . rawurldecode($it->getSubPathName()) . "\n";
|
||||
echo 'SubPath: ' . rawurldecode($it->getSubPath()) . "\n";
|
||||
echo 'Key: ' . $it->key() . "\n\n";
|
||||
}
|
||||
$it->next();
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
SubPathName: file1.txt
|
||||
SubPath:
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%sfile1.txt
|
||||
|
||||
SubPathName: file2_אּ.txt
|
||||
SubPath:
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%sfile2_%EF%AC%B0.txt
|
||||
|
||||
SubPathName: with_streams.txt
|
||||
SubPath:
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%swith_streams.txt
|
||||
|
||||
SubPathName: אּ%s%2Fempty%2E%sfile7.txt
|
||||
SubPath: אּ%s%2Fempty%2E
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%s%252Fempty%252E%sfile7.txt
|
||||
|
||||
SubPathName: אּ%sfile3.txt
|
||||
SubPath: אּ
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%sfile3.txt
|
||||
|
||||
SubPathName: אּ%sfile4_אּ.txt
|
||||
SubPath: אּ
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%sfile4_%EF%AC%B0.txt
|
||||
|
||||
SubPathName: אּ%sאּ_2%sfile5.txt
|
||||
SubPath: אּ%sאּ_2
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%s%EF%AC%B0_2%sfile5.txt
|
||||
|
||||
SubPathName: אּ%sאּ_2%sfile6_אּ.txt
|
||||
SubPath: אּ%sאּ_2
|
||||
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%s%EF%AC%B0_2%sfile6_%EF%AC%B0.txt
|
||||
|
||||
Done.
|
||||
@@ -1,58 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract() (file level password)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--CLEAN--
|
||||
@unlink(dirname(__FILE__).'/extract_temp');
|
||||
--FILE--
|
||||
<?php
|
||||
$dest = dirname(__FILE__).'/extract_temp';
|
||||
|
||||
echo "--> should fail (no password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
var_dump(count($entries));
|
||||
var_dump($entries[0]->extract(false, $dest));
|
||||
echo "\n";
|
||||
|
||||
echo "--> success (password is the same as the one given on rar_open):\n";
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar', 'samplepassword');
|
||||
$entries = rar_list($rar_file2);
|
||||
var_dump($entries[0]->extract(false, $dest));
|
||||
echo file_get_contents($dest);
|
||||
unlink($dest);
|
||||
echo "\n\n";
|
||||
|
||||
echo "--> should fail (password of 2nd file different from the one given on rar_open):\n";
|
||||
var_dump($entries[1]->extract(false, $dest));
|
||||
echo "\n\n";
|
||||
|
||||
echo "--> should give correct data (password of 2nd file is specified):\n";
|
||||
var_dump($entries[1]->extract(false, $dest, 'samplepassword2'));
|
||||
echo file_get_contents($dest);
|
||||
unlink($dest);
|
||||
echo "\n\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
--> should fail (no password):
|
||||
int(2)
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
--> success (password is the same as the one given on rar_open):
|
||||
bool(true)
|
||||
Encrypted file 1 contents.
|
||||
|
||||
--> should fail (password of 2nd file different from the one given on rar_open):
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
bool(false)
|
||||
|
||||
|
||||
--> should give correct data (password of 2nd file is specified):
|
||||
bool(true)
|
||||
Encrypted file 1 contents.
|
||||
|
||||
Done
|
||||
@@ -1,51 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract() process extended (Windows)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) die("skip");
|
||||
die("skip test is not working under run-tests");
|
||||
if (PHP_OS != 'WINNT') die("skip test for Windows NT");
|
||||
exec('cacls ' . escapeshellarg(dirname(__FILE__)), $perms);
|
||||
function concat($a,$b) { return $a.$b; }
|
||||
$perms = array_reduce($perms, 'concat');
|
||||
if (preg_match('/.* Everyone:\\(OI\\)\\(CI\\)F/i', $perms))
|
||||
die("skip directory has permissions that conflict with this test");
|
||||
?>
|
||||
--CLEAN--
|
||||
@rmdir(dirname(__FILE__).'/temp_directory');
|
||||
--FILE--
|
||||
<?php
|
||||
$fn1 = dirname(__FILE__) . '/dirs_and_extra_headers.rar';
|
||||
$dest = dirname(__FILE__).'/temp_directory';
|
||||
function concat($a,$b) { return $a.$b; }
|
||||
|
||||
@rmdir($dest);
|
||||
|
||||
echo "--> should have default permissions:\n";
|
||||
$rarF = RarArchive::open($fn1);
|
||||
$t = $rarF->getEntry('allow_everyone_ni');
|
||||
$t->extract(false, $dest, NULL);
|
||||
exec('cacls ' . escapeshellarg($dest), $perms);
|
||||
$perms = array_reduce($perms, 'concat');
|
||||
var_dump(preg_match('/.* Everyone:\\(OI\\)\\(CI\\)F/i', $perms));
|
||||
@rmdir($dest);
|
||||
echo "\n";
|
||||
|
||||
echo "--> should have permissions for everyone:\n";
|
||||
$rarF = RarArchive::open($fn1);
|
||||
$t = $rarF->getEntry('allow_everyone_ni');
|
||||
$t->extract(false, $dest, NULL, true);
|
||||
exec('cacls ' . escapeshellarg($dest), $perms);
|
||||
$perms = array_reduce($perms, 'concat');
|
||||
var_dump(preg_match('/.* Everyone:\\(OI\\)\\(CI\\)F/i', $perms));
|
||||
echo "\n";
|
||||
@rmdir($dest);
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
--> should have default permissions:
|
||||
int(0)
|
||||
|
||||
--> should have permissions for everyone:
|
||||
int(1)
|
||||
|
||||
Done
|
||||
@@ -1,12 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive direct instantiation does not crash
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
new RarArchive();
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Fatal error: Call to private RarArchive::__construct() from invalid context in %s on line %d
|
||||
@@ -1,12 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry direct instantiation does not crash
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) die("skip");
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
new RarEntry();
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Fatal error: Call to private RarEntry::__construct() from invalid context in %s on line %d
|
||||
@@ -1,17 +0,0 @@
|
||||
--TEST--
|
||||
URL stat PHP_STREAM_URL_STAT_QUIET does not leak memory
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = "rar://" .
|
||||
dirname(__FILE__) . '/dirlink_unix.rar' .
|
||||
"#non_existant_file";
|
||||
|
||||
var_dump(is_dir($file));
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
bool(false)
|
||||
Done.
|
||||
@@ -1,21 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getPosition() test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = RarArchive::open(dirname(__FILE__) . '/multi.part1.rar');
|
||||
|
||||
foreach ($file as $e) {
|
||||
echo $e->getPosition() . ". $e\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
0. RarEntry for file "file1.txt" (52b28202)
|
||||
1. RarEntry for file "file2.txt" (f2c79881)
|
||||
2. RarEntry for file "file3.txt" (bcbce32e)
|
||||
|
||||
Done.
|
||||
@@ -1,21 +0,0 @@
|
||||
--TEST--
|
||||
rar_list handles files with non-unique entry names
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = RarArchive::open(dirname(__FILE__) . '/repeated_name.rar');
|
||||
|
||||
$entries = rar_list($file);
|
||||
foreach ($entries as $e) {
|
||||
echo $e->getPosition() . ". $e\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
0. RarEntry for file "file.txt" (ae2a88a7)
|
||||
1. RarEntry for file "file.txt" (771df243)
|
||||
|
||||
Done.
|
||||
@@ -1,25 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream handles files with non-unique entry names
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = RarArchive::open(dirname(__FILE__) . '/repeated_name.rar');
|
||||
|
||||
foreach ($file as $e) {
|
||||
$stream = $e->getStream();
|
||||
if ($stream) {
|
||||
echo $e->getPosition() . ". $e\n";
|
||||
echo stream_get_contents($stream);
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
0. RarEntry for file "file.txt" (ae2a88a7)
|
||||
Content of first file.
|
||||
1. RarEntry for file "file.txt" (771df243)
|
||||
Content of second file.
|
||||
Done.
|
||||
@@ -1,33 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract handles files with non-unique entry names
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
$dest = dirname(__FILE__) . "temp_file";
|
||||
@unlink($dest);
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = RarArchive::open(dirname(__FILE__) . '/repeated_name.rar');
|
||||
$dest = dirname(__FILE__) . "temp_file";
|
||||
|
||||
foreach ($file as $e) {
|
||||
$res = $e->extract("", $dest);
|
||||
if ($res) {
|
||||
echo $e->getPosition() . ". $e\n";
|
||||
echo file_get_contents($dest);
|
||||
echo "\n";
|
||||
}
|
||||
else {
|
||||
die("failed extraction");
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
0. RarEntry for file "file.txt" (ae2a88a7)
|
||||
Content of first file.
|
||||
1. RarEntry for file "file.txt" (771df243)
|
||||
Content of second file.
|
||||
Done.
|
||||
@@ -1,52 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::getStream NULL can be given to indicate there's no password
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = RarArchive::open(dirname(__FILE__) . '/encrypted_only_files.rar');
|
||||
|
||||
foreach ($file as $e) {
|
||||
echo "* No password given:\n";
|
||||
$stream = $e->getStream();
|
||||
var_dump($stream);
|
||||
|
||||
echo "\n* NULL given (should have the same effect as no password):\n";
|
||||
$stream = $e->getStream(NULL);
|
||||
var_dump($stream);
|
||||
|
||||
echo "\n* empty string given as password (should have the same effect; "
|
||||
. "rar disallows empty passwords):\n";
|
||||
$stream = $e->getStream('');
|
||||
var_dump($stream);
|
||||
|
||||
echo "\n* non-empty password given; should give stream:\n";
|
||||
$stream = $e->getStream('bugabuga');
|
||||
var_dump($stream);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* No password given:
|
||||
|
||||
Warning: RarEntry::getStream(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* NULL given (should have the same effect as no password):
|
||||
|
||||
Warning: RarEntry::getStream(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* empty string given as password (should have the same effect; rar disallows empty passwords):
|
||||
|
||||
Warning: RarEntry::getStream(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* non-empty password given; should give stream:
|
||||
resource(%d) of type (stream)
|
||||
|
||||
Done.
|
||||
@@ -1,60 +0,0 @@
|
||||
--TEST--
|
||||
RarEntry::extract NULL can be given to indicate there's no password
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
$dest = dirname(__FILE__) . "temp_file";
|
||||
@unlink($dest);
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = RarArchive::open(dirname(__FILE__) . '/encrypted_only_files.rar');
|
||||
|
||||
$dest = dirname(__FILE__) . "temp_file";
|
||||
|
||||
foreach ($file as $e) {
|
||||
echo "* No password given:\n";
|
||||
$result = $e->extract('', $dest);
|
||||
var_dump($result);
|
||||
|
||||
echo "\n* NULL given (should have the same effect as no password):\n";
|
||||
$result = $e->extract('', $dest, NULL);
|
||||
var_dump($result);
|
||||
|
||||
echo "\n* empty string given as password (should have the same ".
|
||||
"effect as no password):\n";
|
||||
$result = $e->extract('', $dest, '');
|
||||
var_dump($result);
|
||||
|
||||
echo "\n* password given; a wrong one:\n";
|
||||
$result = $e->extract('', $dest, 'wrongpassword');
|
||||
var_dump($result);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* No password given:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* NULL given (should have the same effect as no password):
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* empty string given as password (should have the same effect as no password):
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* password given; a wrong one:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Done.
|
||||
@@ -1,42 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive::open NULL can be given to indicate there's no password
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$f = dirname(__FILE__) . '/encrypted_headers.rar';
|
||||
|
||||
echo "* No password given:\n";
|
||||
$file = RarArchive::open($f);
|
||||
rar_list($file);
|
||||
|
||||
echo "* NULL given:\n";
|
||||
$file = RarArchive::open($f, NULL);
|
||||
rar_list($file);
|
||||
|
||||
echo "* empty string given:\n";
|
||||
$file = RarArchive::open($f, '');
|
||||
rar_list($file);
|
||||
|
||||
echo "* wrong password given:\n";
|
||||
$file = RarArchive::open($f, "wrongpassword");
|
||||
rar_list($file);
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* No password given:
|
||||
|
||||
Warning: rar_list(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
* NULL given:
|
||||
|
||||
Warning: rar_list(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
* empty string given:
|
||||
|
||||
Warning: rar_list(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
* wrong password given:
|
||||
|
||||
Warning: rar_list(): ERAR_BAD_DATA in %s on line %d
|
||||
|
||||
Done.
|
||||
@@ -1,67 +0,0 @@
|
||||
--TEST--
|
||||
Traversal of volume with only an archive continue from last volume
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$f = dirname(__FILE__) . "/garbage.part03.rar";
|
||||
|
||||
echo "Traversal with rar_list:\n";
|
||||
$a = RarArchive::open($f);
|
||||
var_dump(rar_list($a));
|
||||
|
||||
echo "Traversal with rar_list (again with the same object):\n";
|
||||
var_dump(rar_list($a));
|
||||
|
||||
echo "\nTraversal with foreach:\n";
|
||||
$a = RarArchive::open($f);
|
||||
foreach ($a as $e) {
|
||||
die("should not get here");
|
||||
}
|
||||
echo "Success.\n";
|
||||
|
||||
echo "\nUsage of RarArchive::getEntry:\n";
|
||||
$a = RarArchive::open($f);
|
||||
var_dump($a->getEntry("garbage.txt"));
|
||||
|
||||
echo "\nUsage of directory stream:\n";
|
||||
$it = new DirectoryIterator("rar://" . rawurlencode($f));
|
||||
foreach ($it as $e) {
|
||||
die("should not get here");
|
||||
}
|
||||
echo "Success.\n";
|
||||
|
||||
echo "\nUsage of static url stat:\n";
|
||||
stat("rar://" . rawurlencode($f) . "#not_there");
|
||||
echo "Success.\n";
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Traversal with rar_list:
|
||||
array(0) {
|
||||
}
|
||||
Traversal with rar_list (again with the same object):
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Traversal with foreach:
|
||||
Success.
|
||||
|
||||
Usage of RarArchive::getEntry:
|
||||
|
||||
Warning: RarArchive::getEntry(): cannot find file "garbage.txt" in Rar archive "%sgarbage.part03.rar" in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Usage of directory stream:
|
||||
Success.
|
||||
|
||||
Usage of static url stat:
|
||||
|
||||
Warning: stat(): Found no entry not_there in archive %sgarbage.part03.rar in %s on line %d
|
||||
|
||||
Warning: stat(): stat failed for rar://%sgarbage.part03.rar#not_there in %s on line %d
|
||||
Success.
|
||||
|
||||
Done.
|
||||
@@ -1,65 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive count elements handler test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$f = dirname(__FILE__) . "/dirs_and_extra_headers.rar";
|
||||
$fempty = dirname(__FILE__) . "/garbage.part03.rar";
|
||||
|
||||
echo "* Normal test:\n";
|
||||
$a = RarArchive::open($f);
|
||||
echo "Count: " . count($a) . "\n";
|
||||
|
||||
echo "\n* Closed file test (1):\n";
|
||||
$a = RarArchive::open($f);
|
||||
$a->close();
|
||||
var_dump(count($a));
|
||||
|
||||
echo "\n* Closed file test (2):\n";
|
||||
$a = RarArchive::open($f);
|
||||
$a->getEntries();
|
||||
$a->close();
|
||||
var_dump(count($a));
|
||||
|
||||
echo "\n* Closed file test (3, exceptions):\n";
|
||||
$a = RarArchive::open($f);
|
||||
RarException::setUsingExceptions(true);
|
||||
$a->getEntries();
|
||||
$a->close();
|
||||
try {
|
||||
var_dump(count($a));
|
||||
} catch (RarException $e) {
|
||||
echo "OK, threw exception with message \"".$e->getMessage()."\"\n";
|
||||
}
|
||||
RarException::setUsingExceptions(false);
|
||||
|
||||
echo "\n* Empty file:\n";
|
||||
|
||||
$a = RarArchive::open($fempty);
|
||||
echo "Count: " . count($a) . "\n";
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* Normal test:
|
||||
Count: 13
|
||||
|
||||
* Closed file test (1):
|
||||
|
||||
Warning: count(): The archive is already closed in %s on line %d
|
||||
int(0)
|
||||
|
||||
* Closed file test (2):
|
||||
|
||||
Warning: count(): The archive is already closed in %s on line %d
|
||||
int(0)
|
||||
|
||||
* Closed file test (3, exceptions):
|
||||
OK, threw exception with message "The archive is already closed"
|
||||
|
||||
* Empty file:
|
||||
Count: 0
|
||||
|
||||
Done.
|
||||
109
tests/080.phpt
109
tests/080.phpt
@@ -1,109 +0,0 @@
|
||||
--TEST--
|
||||
File stream EOF behavior
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$a = RarArchive::open(dirname(__FILE__) . "/multi.part1.rar");
|
||||
$a2 = RarArchive::open(dirname(__FILE__) . "/4mb.rar");
|
||||
|
||||
function echoeof($stream) {
|
||||
echo feof($stream)?"At eof":"Not at eof";
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
echo "* First fread is given file size:\n";
|
||||
$stream = $a->getEntry("file1.txt")->getStream();
|
||||
echoeof($stream);
|
||||
var_dump(fread($stream, 18));
|
||||
echoeof($stream);
|
||||
var_dump(fread($stream, 1));
|
||||
echoeof($stream);
|
||||
|
||||
echo "\n* First fread is given size - 1:\n";
|
||||
$stream = $a->getEntry("file1.txt")->getStream();
|
||||
echoeof($stream);
|
||||
var_dump(fread($stream, 17));
|
||||
echoeof($stream);
|
||||
var_dump(fread($stream, 1));
|
||||
echoeof($stream);
|
||||
var_dump(fread($stream, 1));
|
||||
echoeof($stream);
|
||||
|
||||
echo "\n* First fread is given size + 1:\n";
|
||||
$stream = $a->getEntry("file1.txt")->getStream();
|
||||
echoeof($stream);
|
||||
var_dump(fread($stream, 19));
|
||||
echoeof($stream);
|
||||
|
||||
echo "\n* Read is aligned with dictionary, buffer and file size:\n";
|
||||
$stream = $a2->getEntry("4mb.txt")->getStream();
|
||||
echoeof($stream);
|
||||
var_dump(strlen(fread($stream, 4194304)));
|
||||
echoeof($stream);
|
||||
var_dump(strlen(fread($stream, 1)));
|
||||
echoeof($stream);
|
||||
|
||||
echo "\n* Read is dictionary, buffer and file size - 1:\n";
|
||||
$stream = $a2->getEntry("4mb.txt")->getStream();
|
||||
echoeof($stream);
|
||||
var_dump(strlen(fread($stream, 4194303)));
|
||||
echoeof($stream);
|
||||
var_dump(strlen(fread($stream, 1)));
|
||||
echoeof($stream);
|
||||
var_dump(strlen(fread($stream, 1)));
|
||||
echoeof($stream);
|
||||
|
||||
echo "\n* Read is dictionary, buffer and file size + 1:\n";
|
||||
$stream = $a2->getEntry("4mb.txt")->getStream();
|
||||
echoeof($stream);
|
||||
var_dump(strlen(fread($stream, 4194305)));
|
||||
echoeof($stream);
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* First fread is given file size:
|
||||
Not at eof
|
||||
string(18) "contents of file 1"
|
||||
Not at eof
|
||||
string(0) ""
|
||||
At eof
|
||||
|
||||
* First fread is given size - 1:
|
||||
Not at eof
|
||||
string(17) "contents of file "
|
||||
Not at eof
|
||||
string(1) "1"
|
||||
Not at eof
|
||||
string(0) ""
|
||||
At eof
|
||||
|
||||
* First fread is given size + 1:
|
||||
Not at eof
|
||||
string(18) "contents of file 1"
|
||||
At eof
|
||||
|
||||
* Read is aligned with dictionary, buffer and file size:
|
||||
Not at eof
|
||||
int(4194304)
|
||||
Not at eof
|
||||
int(0)
|
||||
At eof
|
||||
|
||||
* Read is dictionary, buffer and file size - 1:
|
||||
Not at eof
|
||||
int(4194303)
|
||||
Not at eof
|
||||
int(1)
|
||||
Not at eof
|
||||
int(0)
|
||||
At eof
|
||||
|
||||
* Read is dictionary, buffer and file size + 1:
|
||||
Not at eof
|
||||
int(4194304)
|
||||
At eof
|
||||
|
||||
Done.
|
||||
@@ -1,92 +0,0 @@
|
||||
--TEST--
|
||||
rar_list et al. give consistent results if called twice
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$f = dirname(__FILE__) . "/multi_broken.part1.rar";
|
||||
|
||||
echo "* rar_list():\n";
|
||||
$a = RarArchive::open($f);
|
||||
var_dump(rar_list($a));
|
||||
var_dump(rar_list($a));
|
||||
|
||||
echo "\n* rar_entry_get():\n";
|
||||
$a = RarArchive::open($f);
|
||||
var_dump($a->getEntry("file1.txt"));
|
||||
var_dump($a->getEntry("file1.txt"));
|
||||
|
||||
echo "\n* dimension access:\n";
|
||||
$a = RarArchive::open($f);
|
||||
var_dump($a[0]);
|
||||
var_dump($a[0]);
|
||||
|
||||
echo "\n* foreach access:\n";
|
||||
$a = RarArchive::open($f);
|
||||
foreach ($a as $e) { echo "shouldn't happen: $e\n"; };
|
||||
foreach ($a as $e) { echo "shouldn't happen: $e\n"; };
|
||||
|
||||
echo "\n* url stat:\n";
|
||||
var_dump(stat("rar://".rawurlencode($f)."#file1.txt"));
|
||||
var_dump(stat("rar://".rawurlencode($f)."#file1.txt"));
|
||||
//no need to test directory open, _rar_get_cachable_rararch handles it too
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* rar_list():
|
||||
|
||||
Warning: rar_list(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: rar_list(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: rar_list(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* rar_entry_get():
|
||||
|
||||
Warning: RarArchive::getEntry(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: RarArchive::getEntry(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Warning: RarArchive::getEntry(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
* dimension access:
|
||||
|
||||
Warning: main(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: main(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: main(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
NULL
|
||||
|
||||
* foreach access:
|
||||
|
||||
Warning: main(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: main(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: main(): ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
* url stat:
|
||||
|
||||
Warning: stat(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: stat(): Error reading entries of archive %smulti_broken.part1.rar: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: stat(): stat failed for rar://%smulti_broken.part1.rar#file1.txt in %s on line %s
|
||||
bool(false)
|
||||
|
||||
Warning: stat(): Volume %smulti_broken.part2.rar was not found in %s on line %d
|
||||
|
||||
Warning: stat(): Error reading entries of archive %smulti_broken.part1.rar: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: stat(): stat failed for rar://%smulti_broken.part1.rar#file1.txt in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Done.
|
||||
@@ -1,36 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive read_property handler basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
//see also test #81 for broken archives
|
||||
|
||||
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
|
||||
$f2 = dirname(__FILE__) . "/multi.part1.rar";
|
||||
|
||||
echo "* latest_winrar.rar:\n";
|
||||
$a = RarArchive::open($f1);
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
echo ($i + 1) . ". $a[$i]\n";
|
||||
}
|
||||
|
||||
echo "\n* multi.part1.rar:\n";
|
||||
$a = RarArchive::open($f2);
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
echo ($i + 1) . ". $a[$i]\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* latest_winrar.rar:
|
||||
1. RarEntry for file "1.txt" (a0de71c0)
|
||||
2. RarEntry for file "2.txt" (45a918de)
|
||||
|
||||
* multi.part1.rar:
|
||||
1. RarEntry for file "file1.txt" (52b28202)
|
||||
2. RarEntry for file "file2.txt" (f2c79881)
|
||||
|
||||
Done.
|
||||
@@ -1,26 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive read_property handler non-int valid dimensions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
|
||||
$a = RarArchive::open($f1);
|
||||
|
||||
echo "string (\"0\"). {$a['0']}\n";
|
||||
echo "string (\"1abc\"). {$a['1abc']}\n";
|
||||
echo "float (0.001). {$a[0.001]}\n";
|
||||
echo "string (\"0.001\"). {$a['0.001']}\n";
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
string ("0"). RarEntry for file "1.txt" (a0de71c0)
|
||||
|
||||
Notice: A non well formed numeric value encountered in %s on line %d
|
||||
string ("1abc"). RarEntry for file "2.txt" (45a918de)
|
||||
float (0.001). RarEntry for file "1.txt" (a0de71c0)
|
||||
string ("0.001"). RarEntry for file "1.txt" (a0de71c0)
|
||||
|
||||
Done.
|
||||
@@ -1,86 +0,0 @@
|
||||
--TEST--
|
||||
RarArchive read_property handler invalid dimensions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
//see also test #81 for broken archives
|
||||
|
||||
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
|
||||
$a = RarArchive::open($f1);
|
||||
|
||||
echo "* -1 (int):\n";
|
||||
echo $a[-1];
|
||||
|
||||
echo "\n* -1 (string):\n";
|
||||
echo $a["-1"];
|
||||
|
||||
echo "\n* -1 (double):\n";
|
||||
echo $a[(float) -1];
|
||||
|
||||
echo "\n* 100:\n";
|
||||
echo $a[100];
|
||||
|
||||
echo "\n* foo:\n";
|
||||
echo $a["foo"];
|
||||
|
||||
echo "\n* 18446744073709551616 (string, 2^64):\n";
|
||||
echo $a["18446744073709551616"];
|
||||
|
||||
echo "\n* -18446744073709551616 (string, -2^64):\n";
|
||||
echo $a["-18446744073709551616"];
|
||||
|
||||
echo "\n* 18446744073709551616 (float, 2^64):\n";
|
||||
echo $a[(float) 18446744073709551616];
|
||||
|
||||
echo "\n* array():\n";
|
||||
echo $a[array()];
|
||||
|
||||
echo "\n* new stdClass():\n";
|
||||
echo $a[new stdClass()];
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
* -1 (int):
|
||||
|
||||
Warning: main(): Dimension index must be non-negative, given -1 in %s on line %d
|
||||
|
||||
* -1 (string):
|
||||
|
||||
Warning: main(): Dimension index must be non-negative, given -1 in %s on line %d
|
||||
|
||||
* -1 (double):
|
||||
|
||||
Warning: main(): Dimension index must be non-negative, given -1 in %s on line %d
|
||||
|
||||
* 100:
|
||||
|
||||
Warning: main(): Dimension index exceeds or equals number of entries in RAR archive in %s on line %d
|
||||
|
||||
* foo:
|
||||
|
||||
Warning: main(): Attempt to use a non-numeric dimension to access a RarArchive object (invalid string) in %s on line %d
|
||||
|
||||
* 18446744073709551616 (string, 2^64):
|
||||
|
||||
Warning: main(): Dimension index is out of integer bounds in %s on line %d
|
||||
|
||||
* -18446744073709551616 (string, -2^64):
|
||||
|
||||
Warning: main(): Dimension index is out of integer bounds in %s on line %d
|
||||
|
||||
* 18446744073709551616 (float, 2^64):
|
||||
|
||||
Warning: main(): Dimension index is out of integer bounds in %s on line %d
|
||||
|
||||
* array():
|
||||
|
||||
Warning: main(): Attempt to use a non-numeric dimension to access a RarArchive object (invalid type) in %s on line %d
|
||||
|
||||
* new stdClass():
|
||||
|
||||
Warning: main(): Attempt to use an object with no get handler as a dimension to access a RarArchive object in %s on line %d
|
||||
|
||||
Done.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user