1 Commits

267 changed files with 12083 additions and 29392 deletions

43
.gitignore vendored
View File

@@ -1,43 +0,0 @@
*.o
*.lo
/tests/*.sh
/tests/*.exp
/tests/*.diff
/tests/*.log
/tests/*.php
/tests/*.out
/tests/*.mem
/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
/pecl-rar.*
/rar.la
*.autosave
/unrar/.libs

View File

@@ -1,33 +0,0 @@
language: c
dist: trusty
addons:
apt:
packages:
- valgrind
env:
#- PHP_VERSION=5.2.17 ZTS=yes MIRROR=http://museum.php.net/php5/
- PHP_VERSION=5.3.29 ZTS=yes
- PHP_VERSION=5.4.45 ZTS=yes
- PHP_VERSION=5.5.37 ZTS=yes
- PHP_VERSION=5.6.30 ZTS=yes RUN_TESTS_FLAGS=-m
- PHP_VERSION=5.6.30 ZTS=no
- PHP_VERSION=7.0.21 ZTS=yes COVERAGE=yes
- PHP_VERSION=7.1.7 ZTS=yes RUN_TESTS_FLAGS=-m
cache:
directories:
- $HOME/php_builds
before_install:
- source travis.sh
- maybe_install_php $PHP_VERSION $ZTS
install:
- build $PHP_VERSION $ZTS "$COVERAGE"
script:
- run_tests $PHP_VERSION $ZTS
after_success:
- 'test "$COVERAGE" != "yes" || bash <(curl -s https://codecov.io/bash)'

68
LICENSE
View File

@@ -1,68 +0,0 @@
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2010 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name "PHP" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact group@php.net.
4. Products derived from this software may not be called "PHP", nor
may "PHP" appear in their name, without prior written permission
from group@php.net. You may indicate that your software works in
conjunction with PHP by saying "Foo for PHP" instead of calling
it "PHP Foo" or "phpfoo"
5. The PHP Group may publish revised and/or new versions of the
license from time to time. Each version will be given a
distinguishing version number.
Once covered code has been published under a particular version
of the license, you may always continue to use it under the terms
of that version. You may also choose to use such covered code
under the terms of any subsequent version of the license
published by the PHP Group. No one other than the PHP Group has
the right to modify the terms applicable to covered code created
under this License.
6. Redistributions of any form whatsoever must retain the following
acknowledgment:
"This product includes PHP software, freely available from
<http://www.php.net/software/>".
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------
This software consists of voluntary contributions made by many
individuals on behalf of the PHP Group.
The PHP Group can be contacted via Email at group@php.net.
For more information on the PHP Group and the PHP project,
please see <http://www.php.net>.
PHP includes the Zend Engine, freely available at
<http://www.zend.com>.

15
README
View File

@@ -1,15 +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.
[![Build Status Appveyor](https://ci.appveyor.com/api/projects/status/cbgpepx6kyax2198/branch/master?svg=true)](https://ci.appveyor.com/project/cataphract/php-rar/branch/master)
[![Build Status Travis](https://travis-ci.org/cataphract/php-rar.svg?branch=master)](https://travis-ci.org/cataphract/php-rar)
[![codecov](https://codecov.io/gh/cataphract/php-rar/branch/master/graph/badge.svg)](https://codecov.io/gh/cataphract/php-rar)

View File

@@ -1,29 +0,0 @@
echo Running appveyor.bat
echo on
CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat"
IF NOT EXIST "C:\projects\php-sdk" (
wget -nv http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip
7z x -y php-sdk-binary-tools-20110915.zip -oC:\projects\php-sdk
)
IF NOT EXIST "C:\projects\php-src\Release_TS\php7ts.lib" (
git clone --depth=1 --branch=PHP-7.1 https://github.com/php/php-src C:\projects\php-src
wget -nv http://windows.php.net/downloads/php-sdk/deps-7.1-vc14-x86.7z
7z x -y deps-7.1-vc14-x86.7z -oC:\projects\php-src
CALL C:\projects\php-sdk\bin\phpsdk_setvars.bat
cd C:\projects\php-src
CALL buildconf.bat
CALL configure.bat --disable-all --enable-cli --with-config-file-scan-dir=C:\projects\extension\bin\modules.d --with-prefix=%APPVEYOR_BUILD_FOLDER%\bin --with-php-build=deps
nmake
) ELSE (
echo php7ts.lib already exists
cd C:\projects\php-src
CALL C:\projects\php-sdk\bin\phpsdk_setvars.bat
)
CALL buildconf.bat --force --add-modules-dir=%APPVEYOR_BUILD_FOLDER%\..
CALL configure.bat --disable-all --enable-cli --enable-rar=shared --with-config-file-scan-dir=C:\projects\extension\bin\modules.d --with-prefix=%APPVEYOR_BUILD_FOLDER%\bin --with-php-build=deps
nmake || exit /b
rmdir Release_TS\php-rar /S /Q
del /S /Q "Release_TS\*.sbr"

View File

@@ -1,26 +0,0 @@
# Based on igbinary's appveyor config.
version: '{branch}.{build}'
install:
- cmd: choco feature enable -n=allowGlobalConfirmation
- cmd: cinst wget
- cmd: mkdir %APPVEYOR_BUILD_FOLDER%\bin
build_script:
- cmd: "%APPVEYOR_BUILD_FOLDER%\\appveyor.bat"
test_script:
- cmd: cd C:\projects\php-src
- cmd: set NO_INTERACTION=1
- cmd: set REPORT_EXIT_STATUS=1
- cmd: set TZ=UTC
- cmd: 'nmake test TESTS="--show-diff --set-timeout 30 -d extension=C:\projects\php-src\Release_TS\php_rar.dll %APPVEYOR_BUILD_FOLDER%\tests"'
after_test:
# - cmd: dir /S C:\projects\php-src\Release_TS
- cmd: 'del C:\projects\php-src\Release_TS\php_rar.*'
cache:
- C:\ProgramData\chocolatey\lib -> appveyor.yml
- C:\projects\php-src
- C:\projects\php-sdk

View File

@@ -4,39 +4,28 @@ dnl config.m4 for extension rar
PHP_ARG_ENABLE(rar, whether to enable rar support,
[ --enable-rar Enable rar support])
unrar_sources="unrar/sha256.cpp unrar/qopen.cpp \
unrar/blake2s.cpp unrar/recvol.cpp \
unrar/headers.cpp unrar/match.cpp \
unrar/find.cpp \
unrar/resource.cpp \
unrar/pathfn.cpp \
unrar/dll.cpp unrar/threadpool.cpp unrar/volume.cpp \
unrar/unpack.cpp \
unrar/extract.cpp unrar/errhnd.cpp \
unrar/crc.cpp unrar/rijndael.cpp unrar/crypt.cpp \
unrar/rawread.cpp \
unrar/rs.cpp unrar/smallfn.cpp \
unrar/isnt.cpp unrar/rar.cpp unrar/consio.cpp \
unrar/scantree.cpp unrar/archive.cpp unrar/strfn.cpp \
unrar/strlist.cpp \
unrar/getbits.cpp unrar/hash.cpp \
unrar/filestr.cpp \
unrar/extinfo.cpp unrar/ui.cpp unrar/rarvm.cpp \
unrar/timefn.cpp unrar/sha1.cpp \
unrar/rdwrfn.cpp unrar/rs16.cpp unrar/cmddata.cpp \
unrar/extractchunk.cpp unrar/system.cpp \
unrar/unicode.cpp unrar/filcreat.cpp \
unrar/arcread.cpp unrar/filefn.cpp \
unrar/global.cpp unrar/list.cpp \
unrar/encname.cpp unrar/file.cpp \
unrar/secpassword.cpp unrar/options.cpp"
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"
if test "$PHP_RAR" != "no"; then
PHP_REQUIRE_CXX
AC_DEFINE(HAVE_RAR, 1, [Whether you have rar support])
PHP_SUBST(RAR_SHARED_LIBADD)
PHP_REQUIRE_CXX()
PHP_SUBST(RAR_SHARED_LIBADD)
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 -DSILENT -Wno-write-strings -Wall -I@ext_srcdir@/unrar)
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
PHP_NEW_EXTENSION(rar, rar.c rar_error.c rararch.c rarentry.c rar_stream.c $unrar_sources, $ext_shared,,-DRARDLL -DGUI -DSILENT -Wno-write-strings -I@ext_srcdir@/unrar)
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
fi

View File

@@ -4,34 +4,25 @@
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 /DSILENT /EHsc /D_WSTDIO_DEFINED");
EXTENSION("rar", "rar.c rar_error.c rararch.c rarentry.c rar_stream.c", PHP_RAR_SHARED, "/DRARDLL /DGUI /DSILENT /EHsc /D_WSTDIO_DEFINED");
ADD_SOURCES(configure_module_dirname + "/unrar",
"sha256.cpp qopen.cpp \
blake2s.cpp recvol.cpp \
headers.cpp match.cpp \
find.cpp \
resource.cpp \
pathfn.cpp \
dll.cpp threadpool.cpp volume.cpp \
unpack.cpp \
extract.cpp errhnd.cpp \
crc.cpp rijndael.cpp crypt.cpp \
rawread.cpp \
rs.cpp smallfn.cpp \
isnt.cpp rar.cpp consio.cpp \
scantree.cpp archive.cpp strfn.cpp \
strlist.cpp \
getbits.cpp hash.cpp \
filestr.cpp \
extinfo.cpp ui.cpp rarvm.cpp \
timefn.cpp sha1.cpp \
rdwrfn.cpp rs16.cpp cmddata.cpp \
extractchunk.cpp system.cpp \
unicode.cpp filcreat.cpp \
arcread.cpp filefn.cpp \
global.cpp list.cpp \
encname.cpp file.cpp \
secpassword.cpp options.cpp", "rar");
"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");
}

View File

@@ -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

View File

@@ -23,11 +23,11 @@ http://pear.php.net/dtd/package-2.0.xsd">
<active>no</active>
</developer>
<date>2013-10-11</date>
<date>2010-04-20</date>
<time>13:00:00</time>
<version>
<release>3.0.2</release>
<api>3.0.0</api>
<release>2.0.0</release>
<api>2.0.0</api>
</version>
<stability>
@@ -36,138 +36,77 @@ http://pear.php.net/dtd/package-2.0.xsd">
</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>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>
<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"/>
<file name="001.phpt" role="test" />
<file name="002.phpt" role="test" />
<file name="003.phpt" role="test" />
<file name="004.phpt" role="test" />
<file name="005.phpt" role="test" />
<file name="006.phpt" role="test" />
<file name="007.phpt" role="test" />
<file name="008.phpt" role="test" />
<file name="009.phpt" role="test" />
<file name="010.phpt" role="test" />
<file name="011.phpt" role="test" />
<file name="012.phpt" role="test" />
<file name="013.phpt" role="test" />
<file name="014.phpt" role="test" />
<file name="015.phpt" role="test" />
<file name="016.phpt" role="test" />
<file name="017.phpt" role="test" />
<file name="018.phpt" role="test" />
<file name="019.phpt" role="test" />
<file name="020.phpt" role="test" />
<file name="021.phpt" role="test" />
<file name="022.phpt" role="test" />
<file name="023.phpt" role="test" />
<file name="024.phpt" role="test" />
<file name="025.phpt" role="test" />
<file name="026.phpt" role="test" />
<file name="027.phpt" role="test" />
<file name="028.phpt" role="test" />
<file name="029.phpt" role="test" />
<file name="030.phpt" role="test" />
<file name="031.phpt" role="test" />
<file name="032.phpt" role="test" />
<file name="033.phpt" role="test" />
<file name="034.phpt" role="test" />
<file name="035.phpt" role="test" />
<file name="036.phpt" role="test" />
<file name="037.phpt" role="test" />
<file name="038.phpt" role="test" />
<file name="039.phpt" role="test" />
<file name="commented.rar" role="test" />
<file name="corrupted.rar" role="test" />
<file name="directories.rar" role="test" />
<file name="dirlink_unix.rar" role="test" />
<file name="encrypted_headers.rar" role="test" />
<file name="encrypted_only_files.rar" role="test" />
<file name="latest_winrar.rar" role="test" />
<file name="linux_rar.rar" role="test" />
<file name="multi_broken.part1.rar" role="test" />
<file name="multi.part1.rar" role="test" />
<file name="multi.part2.rar" role="test" />
<file name="multi.part3.rar" role="test" />
<file name="rar_notrar.rar" role="test" />
<file name="rar_unicode.rar" role="test" />
<file name="solid.rar" role="test" />
<file name="store_method.rar" role="test" />
</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" />
@@ -255,8 +194,6 @@ http://pear.php.net/dtd/package-2.0.xsd">
<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" />
@@ -290,16 +227,13 @@ http://pear.php.net/dtd/package-2.0.xsd">
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
<file name="CREDITS" role="doc" />
<file name="LICENSE" 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"/>
<file name="rar_error.c" role="src" />
</dir> <!-- / -->
</contents>
@@ -311,6 +245,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
<pearinstaller>
<min>1.4.0</min>
</pearinstaller>
<extension>
<name>spl</name>
</extension>
</required>
</dependencies>
@@ -319,46 +256,6 @@ http://pear.php.net/dtd/package-2.0.xsd">
<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>
@@ -369,7 +266,7 @@ For the other changes, see the changelog for version 2.0.0RC1.
<api>beta</api>
</stability>
<date>2010-01-17</date>
<license>PHP License and UnRar license</license>
<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.

250
php_rar.h
View File

@@ -27,31 +27,13 @@
/* $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
#include <php.h>
extern zend_module_entry rar_module_entry;
#define phpext_rar_ptr &rar_module_entry
#define PHP_RAR_VERSION "4.0.0"
#define PHP_RAR_VERSION "2.0.0-dev"
#ifdef PHP_WIN32
#define PHP_RAR_API __declspec(dllexport)
@@ -68,7 +50,6 @@ extern zend_module_entry rar_module_entry;
/* #include "unrar/rar.hpp */
/* only these includes are necessary anyway: */
#include "unrar/raros.hpp"
#include "unrar/rartypes.hpp"
/* no need to reinclude windows.h or new.h */
#define LEAN_RAR_INCLUDES
#include "unrar/os.hpp"
@@ -79,146 +60,23 @@ enum HOST_SYSTEM {
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
HOST_BEOS=5,HOST_MAX
};
enum FILE_SYSTEM_REDIRECT {
FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
FSREDIR_HARDLINK, FSREDIR_FILECOPY
};
/* maximum comment size if 64KB */
//maximum comment size if 64KB
#define RAR_MAX_COMMENT_SIZE 65536
/* PHP 7+ abstraction */
#if PHP_MAJOR_VERSION >= 7
typedef zend_object* rar_obj_ref;
#define rar_zval_add_ref(ppzv) zval_add_ref(*ppzv)
#define ZVAL_ALLOC_DUP(dst, src) \
do { \
dst = (zval*) emalloc(sizeof(zval)); \
ZVAL_DUP(dst, src); \
} while (0)
#define RAR_RETURN_STRINGL(s, l, duplicate) \
do { \
RETVAL_STRINGL(s, l); \
if (duplicate == 0) { \
efree(s); \
} \
return; \
} while (0)
#define RAR_ZVAL_STRING(z, s, duplicate) \
do { \
ZVAL_STRING(z, s); \
if (duplicate == 0) { \
efree(s); \
} \
} while (0)
typedef size_t zpp_s_size_t;
#define MAKE_STD_ZVAL(zv_p) \
do { \
(zv_p) = emalloc(sizeof(zval)); \
ZVAL_NULL(zv_p); \
} while (0)
#define INIT_ZVAL(zv) ZVAL_UNDEF(&zv)
#define ZEND_ACC_FINAL_CLASS ZEND_ACC_FINAL
#else /* PHP 5.x */
typedef zend_object_handle rar_obj_ref;
#define rar_zval_add_ref zval_add_ref
#define ZVAL_ALLOC_DUP(dst, src) \
do { \
zval *z_src = src; \
dst = z_src; \
zval_add_ref(&dst); \
SEPARATE_ZVAL(&dst); \
} while (0)
#define RAR_ZVAL_STRING ZVAL_STRING
#define RAR_RETURN_STRINGL(s, l, duplicate) RETURN_STRINGL(s, l, duplicate)
typedef int zpp_s_size_t;
#define zend_hash_str_del zend_hash_del
#endif
typedef struct _rar_cb_user_data {
char *password; /* can be NULL */
zval *callable; /* can be NULL */
} rar_cb_user_data;
typedef struct rar {
rar_obj_ref obj_ref;
struct _rar_entries *entries;
zend_object_handle id;
int entry_count; //>= number of files
struct RARHeaderDataEx **entries;
struct RAROpenArchiveDataEx *list_open_data;
struct RAROpenArchiveDataEx *extract_open_data;
/* archive handle opened with RAR_OM_LIST_INCSPLIT open mode */
//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;
char *password;
} rar_file_t;
/* Misc */
#if defined(ZTS) && PHP_MAJOR_VERSION < 7
# 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, zval * 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 */
//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) \
@@ -231,23 +89,6 @@ ZEND_EXTERN_MODULE_GLOBALS(rar);
{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
#endif
/* Other compatibility quirks */
/* PHP 5.3 doesn't have ZVAL_COPY_VALUE */
#if !defined(ZEND_COPY_VALUE) && PHP_MAJOR_VERSION == 5
#define ZVAL_COPY_VALUE(z, v) \
do { \
(z)->value = (v)->value; \
Z_TYPE_P(z) = Z_TYPE_P(v); \
} while (0)
#endif
#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);
@@ -259,32 +100,17 @@ 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 */
char *password, /* IN, can be null */
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;
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, ...);
@@ -292,47 +118,7 @@ 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);
@@ -342,25 +128,19 @@ 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);
void _rar_entry_to_zval(struct RARHeaderDataEx *entry, zval *object,
unsigned long packed_size 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;
char *utf_file_name,
char *password,
char *mode STREAMS_DC TSRMLS_DC);
#endif /* PHP_RAR_H */

602
rar.c
View File

@@ -35,9 +35,6 @@
extern "C" {
#endif
#define _GNU_SOURCE
#include <string.h>
#ifdef PHP_WIN32
# include <math.h>
#endif
@@ -55,26 +52,10 @@ extern "C" {
#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);
static void _rar_fix_wide(wchar_t *str);
/* }}} */
/* {{{ 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.
@@ -86,18 +67,18 @@ void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size) /* {{{ *
while (*src != 0 && --dsize >= 0) {
uint c =*(src++);
if (c < 0x80)
*(dest++) = (char) c;
*(dest++) = c;
else if (c < 0x800 && --dsize >= 0) {
*(dest++) = (char) (0xc0 | (c >> 6));
*(dest++) = (0xc0 | (c >> 6));
*(dest++) = (0x80 | (c & 0x3f));
}
else if (c < 0x10000 && (dsize -= 2) >= 0) {
*(dest++) = (char) (0xe0 | (c >> 12));
*(dest++) = (0xe0 | (c >> 12));
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
*(dest++) = (0x80 | (c & 0x3f));
*(dest++) = (0x80 | (c & 0x3f));
}
else if (c < 0x200000 && (dsize -= 3) >= 0) {
*(dest++) = (char) (0xf0 | (c >> 18));
*(dest++) = (0xf0 | (c >> 18));
*(dest++) = (0x80 | ((c >> 12) & 0x3f));
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
*(dest++) = (0x80 | (c & 0x3f));
@@ -142,87 +123,34 @@ void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size) /* {{{ *
if (d > 0xffff) {
if (--dsize < 0 || d > 0x10ffff)
break;
*(dest++) = (wchar_t) (((d - 0x10000) >> 10) + 0xd800);
*(dest++) = ((d - 0x10000) >> 10) + 0xd800;
*(dest++) = (d & 0x3ff) + 0xdc00;
}
else
*(dest++) = (wchar_t) d;
*(dest++) = 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) {
#if PHP_MAJOR_VERSION < 7
zval_ptr_dtor(&udata->callable);
#else
zval_ptr_dtor(udata->callable);
efree(udata->callable);
#endif
}
udata->password = NULL;
udata->callable = NULL;
}
/* }}} */
/* WARNING: It's the caller who must close the archive. */
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 */
char *password, /* IN, can be null */
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;
wchar_t *file_name = NULL;
int utf_file_name_len;
struct RARHeaderDataEx *used_header_data;
int retval = 0; /* success in rar parlance */
assert(open_data != NULL);
assert(file_name != NULL);
assert(utf_file_name != NULL);
assert(arc_handle != NULL);
assert(found != NULL);
*found = FALSE;
@@ -236,12 +164,15 @@ int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
retval = open_data->OpenResult;
goto cleanup;
}
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) cb_udata);
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) password);
utf_file_name_len = strlen(utf_file_name);
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);
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
#if WCHAR_MAX > 0xffff
_rar_fix_wide(used_header_data->FileNameW, NM);
#endif
if (sizeof(wchar_t) > 2)
_rar_fix_wide(used_header_data->FileNameW);
if (wcsncmp(used_header_data->FileNameW, file_name, NM) == 0) {
*found = TRUE;
@@ -256,7 +187,7 @@ int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
}
if (result != 0 && result != 1) {
/* 0 indicates success, 1 indicates normal end of file */
//0 indicates success, 1 indicates normal end of file
retval = result;
goto cleanup;
}
@@ -264,545 +195,144 @@ int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
cleanup:
if (header_data == NULL)
efree(used_header_data);
if (file_name != NULL)
efree(file_name);
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 & RHDF_SPLITBEFORE) ||
(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. */
/* Only processes password callbacks */
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;
//user data is the password or null if none
char *password = (char*) UserData;
if (password == NULL || password[0] == '\0') {
if (password == NULL) {
/*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';
strncpy((char*) P1, password, (size_t) P2);
}
}
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;
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Volume %s was not found.", (char*) P1);
/* this means a volume is missing. return -1 to abort */
return -1;
}
}
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,
zend_throw_exception(spl_ce_RuntimeException,
"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);
RAR_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) /* {{{ */
static void _rar_fix_wide(wchar_t *str) /* {{{ */
{
wchar_t *write,
*read,
*max_fin;
max_fin = str + max_size;
for (write = str, read = str; *read != L'\0' && read != max_fin; read++) {
*read;
for (write = str, read = str; *read != L'\0'; 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) /* {{{ */
{
#if PHP_MAJOR_VERSION < 7
zval *failed_vol,
*retval_ptr = NULL,
**params;
#else
zval failed_vol,
retval,
*params,
*const retval_ptr = &retval;
#endif
int ret = -1;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(failed_vol);
RAR_ZVAL_STRING(failed_vol, dst_buffer, 1);
params = &failed_vol;
fci->retval_ptr_ptr = &retval_ptr;
fci->params = &params;
#else
ZVAL_STRING(&failed_vol, dst_buffer);
ZVAL_NULL(&retval);
params = &failed_vol;
fci->retval = &retval;
fci->params = params;
#endif
fci->param_count = 1;
#if PHP_MAJOR_VERSION < 7
if (zend_call_function(fci, cache TSRMLS_CC) != SUCCESS ||
fci->retval_ptr_ptr == NULL ||
*fci->retval_ptr_ptr == NULL) {
#else
if (zend_call_function(fci, cache TSRMLS_CC) != SUCCESS || EG(exception)) {
#endif
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Failure to call volume find callback");
goto cleanup;
}
#if PHP_MAJOR_VERSION < 7
assert(*fci->retval_ptr_ptr == retval_ptr);
#else
assert(fci->retval == &retval);
#endif
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:
#if PHP_MAJOR_VERSION < 7
zval_ptr_dtor(&failed_vol);
if (retval_ptr != NULL) {
zval_ptr_dtor(&retval_ptr);
}
#else
zval_ptr_dtor(&failed_vol);
zval_ptr_dtor(&retval);
#endif
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
BEGIN_EXTERN_C()
ZEND_GET_MODULE(rar)
END_EXTERN_C()
#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)
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_close, arginfo_rar_void_archmeth)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ Globals' related activities */
ZEND_DECLARE_MODULE_GLOBALS(rar);
#if PHP_MAJOR_VERSION < 7
static int _rar_array_apply_remove_first(void *pDest TSRMLS_DC)
#else
static int _rar_array_apply_remove_first(zval *pDest TSRMLS_DC)
#endif
{
return (ZEND_HASH_APPLY_STOP | ZEND_HASH_APPLY_REMOVE);
}
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);
}
rar_zval_add_ref(&zv);
#if PHP_MAJOR_VERSION < 7
assert(Z_REFCOUNT_P(zv) > 1);
SEPARATE_ZVAL(&zv); /* ensure we store a heap allocated copy */
zend_hash_update(cc->data, key, key_len, &zv, sizeof(zv), NULL);
#else
zend_hash_str_update(cc->data, key, key_len, zv);
#endif
}
static zval *_rar_contents_cache_get(const char *key,
uint key_len,
zval *rv TSRMLS_DC)
{
rar_contents_cache *cc = &RAR_G(contents_cache);
zval *element = NULL;
#if PHP_MAJOR_VERSION < 7
zval **element_p = NULL;
zend_hash_find(cc->data, key, key_len, (void **) &element_p);
if (element_p) {
element = *element_p;
}
#else
element = zend_hash_str_find(cc->data, key, key_len);
#endif
if (element != NULL) {
cc->hits++;
INIT_ZVAL(*rv);
ZVAL_COPY_VALUE(rv, element);
zval_copy_ctor(rv);
return rv;
}
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)
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(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)
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(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);
php_info_print_table_header(2, "Rar support", "enabled");
php_info_print_table_row(2, "Rar EXT version", PHP_RAR_VERSION);
php_info_print_table_row(2, "Revision", "$Revision$");
#if RARVER_BETA != 0
sprintf(version,"%d.%02d beta%d patch%d %d-%02d-%02d", RARVER_MAJOR,
sprintf(version,"%d.%02d beta%d patch%d %d-%d-%d", 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,
sprintf(version,"%d.%02d patch%d %d-%d-%d", 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();
}
/* }}} */
@@ -810,22 +340,20 @@ ZEND_MODULE_INFO_D(rar)
/* {{{ rar_module_entry
*/
zend_module_entry rar_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"rar",
rar_functions,
ZEND_MODULE_STARTUP_N(rar),
/* ZEND_MODULE_SHUTDOWN_N(rar), */
PHP_MINIT(rar),
NULL,
/* ZEND_MODULE_ACTIVATE_N(rar), */
NULL,
ZEND_MODULE_DEACTIVATE_N(rar),
ZEND_MODULE_INFO_N(rar),
NULL,
PHP_MINFO(rar),
#if ZEND_MODULE_API_NO >= 20010901
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
STANDARD_MODULE_PROPERTIES
};
/* }}} */

View File

@@ -52,11 +52,11 @@ int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
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);
}
@@ -70,7 +70,7 @@ void _rar_handle_ext_error(const char *format TSRMLS_DC, ...) /* {{{ */
va_list arg;
char *message;
#if defined(ZTS) && PHP_MAJOR_VERSION < 7
#ifdef ZTS
va_start(arg, TSRMLS_C);
#else
va_start(arg, format);
@@ -91,16 +91,12 @@ 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);
#if PHP_MAJOR_VERSION < 7
assert(Z_TYPE_P(pval) == IS_BOOL);
assert(Z_TYPE_P(pval) == IS_BOOL);
return Z_BVAL_P(pval);
#else
assert(Z_TYPE_P(pval) == IS_TRUE || Z_TYPE_P(pval) == IS_FALSE);
return Z_TYPE_P(pval) == IS_TRUE;
#endif
}
/* returns a string or NULL if not an error */
//returns a string or NULL if not an error
const char * _rar_error_to_string(int errcode) /* {{{ */
{
const char *ret;
@@ -175,8 +171,7 @@ PHP_METHOD(rarexception, setUsingExceptions)
if (result == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not set error handling mode. "
"This is a bug, please report it.");
"Could set error handling mode. This is a bug, please report it.");
return;
}
}
@@ -186,39 +181,21 @@ PHP_METHOD(rarexception, setUsingExceptions)
Return whether exceptions are being used */
PHP_METHOD(rarexception, isUsingExceptions)
{
#if PHP_MAJOR_VERSION < 7
zval **pval;
#else
zval *pval;
#endif
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
//or zend_read_static_property, which calls zend_std_get... after chg scope
pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, (zend_bool) 0 TSRMLS_CC);
#elif PHP_MAJOR_VERSION < 7
pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, (zend_bool) 0, NULL TSRMLS_CC);
#else
zend_string *prop_name =
zend_string_init("usingExceptions", sizeof("usingExceptions") - 1, 0);
pval = zend_std_get_static_property(rarexception_ce_ptr, prop_name,
(zend_bool) 0);
zend_string_release(prop_name);
#endif
/* property always exists */
//property always exists
assert(pval != NULL);
#if PHP_MAJOR_VERSION < 7
assert(Z_TYPE_PP(pval) == IS_BOOL);
assert(Z_TYPE_PP(pval) == IS_BOOL);
RETURN_ZVAL(*pval, 0, 0);
#else
assert(Z_TYPE_P(pval) == IS_TRUE || Z_TYPE_P(pval) == IS_FALSE);
RETURN_ZVAL(pval, 0, 0);
#endif
}
/* }}} */
@@ -242,13 +219,8 @@ void minit_rarerror(TSRMLS_D) /* {{{ */
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "RarException", php_rarexception_class_functions);
#if PHP_MAJOR_VERSION < 7
rarexception_ce_ptr = zend_register_internal_class_ex(&ce,
zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
#else
rarexception_ce_ptr = zend_register_internal_class_ex(&ce,
zend_exception_get_default(TSRMLS_C));
#endif
rarexception_ce_ptr->ce_flags |= ZEND_ACC_FINAL;
zend_declare_property_bool(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, 0L /* FALSE */,

View File

@@ -1,625 +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);
#if PHP_MAJOR_VERSION >= 7
static void _rar_nav_swap_entries(void *op1, void *op2);
#endif
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]);
#if PHP_MAJOR_VERSION < 7
zend_qsort(rar->entries->entries_array_s, rar->entries->num_entries,
sizeof *rar->entries->entries_array_s, _rar_nav_compare_entries
TSRMLS_CC);
#else
zend_qsort(rar->entries->entries_array_s, rar->entries->num_entries,
sizeof *rar->entries->entries_array_s, _rar_nav_compare_entries,
_rar_nav_swap_entries);
#endif
}
}
/* }}} */
/* {{{ _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)
{
if (state) {
/* may not have been initialized due to error conditions
* in rararch_it_get_iterator that jumped out of the function */
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 = {0};
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 & RHDF_SPLITBEFORE)
continue;
else
first_file_check = FALSE;
}
/* reset packed size if not split before */
if ((entry.Flags & RHDF_SPLITBEFORE) == 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 & RHDF_SPLITAFTER) /* 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] == SPATHDIVIDER[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] == SPATHDIVIDER[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] == SPATHDIVIDER[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*/);
}
/* }}} */
#if PHP_MAJOR_VERSION >= 7
static void _rar_nav_swap_entries(void *op1, void *op2) /* {{{ */
{
/* just swaps two pointer values */
struct _rar_unique_entry **a = op1,
**b = op2,
*tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
/* }}} */
#endif
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] != SPATHDIVIDER[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, SPATHDIVIDER[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
*/

File diff suppressed because it is too large Load Diff

1139
rararch.c

File diff suppressed because it is too large Load Diff

View File

@@ -31,96 +31,76 @@
extern "C" {
#endif
#define _GNU_SOURCE
#include <string.h>
#include <php.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 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 */
/* parent is zval to RarArchive object. The object (not the zval, in PHP 5.x)
* will have its refcount increased */
void _rar_entry_to_zval(zval *parent,
struct RARHeaderDataEx *entry,
unsigned long packed_size,
size_t position,
zval *object TSRMLS_DC) /* {{{ */
void _rar_entry_to_zval(struct RARHeaderDataEx *entry, zval *object,
unsigned long packed_size 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 */
zval *parent_copy = parent;
#if PHP_MAJOR_VERSION < 7
/* allocate zval on the heap */
zval_addref_p(parent_copy);
SEPARATE_ZVAL(&parent_copy);
/* set refcount to 0; zend_update_property will increase it */
Z_DELREF_P(parent_copy);
#endif
long unp_size;
object_init_ex(object, rar_class_entry_ptr);
zend_update_property(rar_class_entry_ptr, object, "rarfile",
sizeof("rararch") - 1, parent_copy TSRMLS_CC);
if (sizeof(long) >= 8)
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;
}
#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) * 4;
filename = (char*) emalloc(filename_size);
/* 2 instead of sizeof(wchar_t) would suffice, I think. I doubt
* _rar_wide_to_utf handles characters not in UCS-2. But better be safe */
filename = (char*) emalloc(sizeof(entry->FileNameW) * sizeof(wchar_t));
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);
_rar_wide_to_utf(entry->FileNameW, filename,
sizeof(entry->FileNameW) * sizeof(wchar_t));
/* 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
* properties from here with add_property_x
* 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_string(rar_class_entry_ptr, object, "name",
sizeof("name") - 1, filename 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);
sprintf(tmp_s, "%lx", 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",
@@ -130,28 +110,6 @@ void _rar_entry_to_zval(zval *parent,
zend_update_property_long(rar_class_entry_ptr, object, "flags",
sizeof("flags") - 1, entry->Flags TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "redir_type",
sizeof("redir_type") - 1, entry->RedirType TSRMLS_CC);
if (entry->RedirName) {
char *redir_target = NULL;
size_t redir_target_size;
zend_update_property_long(rar_class_entry_ptr, object,
"redir_to_directory", sizeof("redir_to_directory") - 1,
!!entry->DirTarget TSRMLS_CC);
redir_target_size = entry->RedirNameSize * 4;
redir_target = emalloc(redir_target_size);
assert(redir_target_size > 0);
_rar_wide_to_utf(entry->RedirName, redir_target, redir_target_size);
zend_update_property_string(rar_class_entry_ptr, object, "redir_target",
sizeof("redir_target") - 1, redir_target TSRMLS_CC);
efree(redir_target);
}
efree(filename);
}
/* }}} */
@@ -163,8 +121,7 @@ void _rar_entry_to_zval(zval *parent,
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) { \
if ((var = _rar_entry_get_property(entry_obj, prop_name, sizeof(prop_name) TSRMLS_CC)) == NULL) { \
RETURN_FALSE; \
}
@@ -180,56 +137,35 @@ 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) /* {{{ */
{
#if PHP_MAJOR_VERSION < 7
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);
#else
zval property;
zend_string *name_str,
*doc_str;
int ret;
ZVAL_NULL(&property);
name_str = zend_string_init(name, (size_t) name_length, 1);
doc_str = zend_string_init(doc_comment, (size_t) doc_comment_len, 1);
ret = zend_declare_property_ex(ce, name_str, &property, ZEND_ACC_PRIVATE,
doc_str);
zend_string_release(name_str);
zend_string_release(doc_str);
return ret;
#endif
}
/* }}} */
static zval *_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
static zval **_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
{
zval *tmp;
#if PHP_MAJOR_VERSION >= 7
zval zv;
#endif
#if PHP_VERSION_ID < 70100
zend_class_entry *orig_scope = EG(scope);
zval **tmp;
char *mangled_name;
int mangled_name_len;
EG(scope) = rar_class_entry_ptr;
#endif
#if PHP_MAJOR_VERSION < 7
tmp = zend_read_property(Z_OBJCE_P(entry_obj), entry_obj, name, namelen, 1 TSRMLS_CC);
#else
tmp = zend_read_property(Z_OBJCE_P(entry_obj), entry_obj, name, namelen, 1, &zv);
#endif
if (tmp == NULL) {
//perhaps cleaner alternative: use Z_OBJ_HANDLER_P(entry_obj, read_property)
//another way to avoid mem allocation would be to get the mangled name from
//ce->properties_info.name (properties_info hash table indexes by unmangled name)
//see also zend_read_property
zend_mangle_property_name(&mangled_name, &mangled_name_len, "RarEntry",
sizeof("RarEntry") - 1, name, namelen, 0);
if (zend_hash_find(Z_OBJPROP_P(entry_obj), mangled_name, mangled_name_len,
(void**) &tmp) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Bug: unable to find property '%s'. Please report.", name);
efree(mangled_name);
return NULL;
}
#if PHP_VERSION_ID < 70100
EG(scope) = orig_scope;
#endif
efree(mangled_name);
return tmp;
}
/* }}} */
@@ -247,83 +183,90 @@ static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
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;
zval *tmp;
zobj = emalloc(sizeof *zobj);
zend_object_std_init(zobj, class_type TSRMLS_CC);
zend_hash_copy(zobj->properties, &(class_type->default_properties),
(copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
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]])
/* {{{ proto bool RarEntry::extract(string dir [, string filepath [, string password ]])
Extract file from the archive */
PHP_METHOD(rarentry, extract)
{ /* lots of variables, but no need to be intimidated */
{ //lots of variables, but no need to be intimidated
char *dir,
*filepath = NULL,
*password = NULL;
zpp_s_size_t dir_len,
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;
zval **tmp,
**tmp_name;
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 ) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &dir, &dir_len,
&filepath, &filepath_len, &password, &password_len) == FAILURE ) {
return;
}
RAR_GET_PROPERTY(tmp, "rarfile");
if (_rar_get_file_resource(tmp, &rar TSRMLS_CC) == FAILURE) {
if (!_rar_get_file_resource(*tmp, &rar TSRMLS_CC)) {
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 */
//the arguments are mutually exclusive. If the second is specified, must ignore the first
if (!with_second_arg) {
if (dir_len == 0) /* both params empty */
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");
RAR_GET_PROPERTY(tmp_name, "name");
/* 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);
if (password == NULL)
password = rar->password; //use rar_open password by default
result = _rar_find_file_p(rar->extract_open_data,
(size_t) Z_LVAL_P(tmp_position), &cb_udata, &extract_handle, &found,
&entry);
result = _rar_find_file(rar->extract_open_data, Z_STRVAL_PP(tmp_name),
password, &extract_handle, &found, &entry);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
@@ -331,20 +274,13 @@ PHP_METHOD(rarentry, extract)
}
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);
_rar_handle_ext_error("Can't find file %s in archive %s" TSRMLS_CC,
Z_STRVAL_PP(tmp_name),
rar->list_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,
@@ -359,40 +295,24 @@ PHP_METHOD(rarentry, extract)
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 **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "name");
RAR_RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
@@ -400,14 +320,13 @@ PHP_METHOD(rarentry, getName)
Return unpacked size of the entry */
PHP_METHOD(rarentry, getUnpackedSize)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "unpacked_size");
RETURN_LONG(Z_LVAL_P(tmp));
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
@@ -415,14 +334,13 @@ PHP_METHOD(rarentry, getUnpackedSize)
Return packed size of the entry */
PHP_METHOD(rarentry, getPackedSize)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "packed_size");
RETURN_LONG(Z_LVAL_P(tmp));
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
@@ -430,31 +348,27 @@ PHP_METHOD(rarentry, getPackedSize)
Return host OS of the entry */
PHP_METHOD(rarentry, getHostOs)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "host_os");
RETURN_LONG(Z_LVAL_P(tmp));
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto string RarEntry::getFileTime()
Return modification time of the entry.
Due to the way the unrar library returns this time, this is in the
system's timezone. */
Return modification time of the entry */
PHP_METHOD(rarentry, getFileTime)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "file_time");
RAR_RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
@@ -462,14 +376,13 @@ PHP_METHOD(rarentry, getFileTime)
Return CRC of the entry */
PHP_METHOD(rarentry, getCrc)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "crc");
RAR_RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
@@ -477,14 +390,13 @@ PHP_METHOD(rarentry, getCrc)
Return attributes of the entry */
PHP_METHOD(rarentry, getAttr)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "attr");
RETURN_LONG(Z_LVAL_P(tmp));
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
@@ -492,14 +404,13 @@ PHP_METHOD(rarentry, getAttr)
Return version of the archiver, used to create this entry */
PHP_METHOD(rarentry, getVersion)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "version");
RETURN_LONG(Z_LVAL_P(tmp));
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
@@ -507,51 +418,44 @@ PHP_METHOD(rarentry, getVersion)
Return packing method */
PHP_METHOD(rarentry, getMethod)
{
zval *tmp;
zval **tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "method");
RETURN_LONG(Z_LVAL_P(tmp));
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto resource RarEntry::getStream([string password = NULL])
/* {{{ proto resource RarEntry::getStream([string password])
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;
zpp_s_size_t password_len; /* ignored */
rar_cb_user_data cb_udata = {NULL};
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!",
zval **tmp, **name;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
php_stream *stream = NULL;
char *password = NULL;
int password_len; //ignored
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
&password, &password_len) == FAILURE ) {
return;
}
RAR_GET_PROPERTY(position, "position");
RAR_GET_PROPERTY(name, "name");
RAR_GET_PROPERTY(tmp, "rarfile");
if (_rar_get_file_resource(tmp, &rar TSRMLS_CC) == FAILURE) {
if (!_rar_get_file_resource(*tmp, &rar TSRMLS_CC)) {
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;
if (password == NULL)
password = rar->password; //use rar_open password by default
/* 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);
Z_STRVAL_PP(name), password, "r" STREAMS_CC TSRMLS_CC);
if (stream != NULL) {
php_stream_to_zval(stream, return_value);
}
@@ -564,17 +468,15 @@ PHP_METHOD(rarentry, getStream)
Return whether the entry represents a directory */
PHP_METHOD(rarentry, isDirectory)
{
zval *tmp;
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 & RHDF_DIRECTORY) != 0;
flags = Z_LVAL_PP(tmp);
is_dir = ((flags & 0xE0) == 0xE0);
RETURN_BOOL(is_dir);
}
/* }}} */
@@ -583,112 +485,54 @@ PHP_METHOD(rarentry, isDirectory)
Return whether the entry is encrypted and needs a password */
PHP_METHOD(rarentry, isEncrypted)
{
zval *tmp;
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 & RHDF_ENCRYPTED) != 0;
flags = Z_LVAL_PP(tmp);
is_encrypted = (flags & 0x04);
RETURN_BOOL(is_encrypted);
}
/* }}} */
/* {{{ proto int RarEntry::getRedirType()
Returns the redirection type, or NULL if there's none */
PHP_METHOD(rarentry, getRedirType)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "redir_type");
if (Z_TYPE_P(tmp) != IS_LONG) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad redir type stored");
RETURN_FALSE;
}
if (Z_LVAL_P(tmp) == FSREDIR_NONE) {
RETURN_NULL();
}
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto bool RarEntry::isRedirectToDirectory()
Returns true if there is redirection and the target is a directory,
null if there is no redirection, false otherwise */
PHP_METHOD(rarentry, isRedirectToDirectory)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "redir_to_directory");
RETURN_ZVAL(tmp, 1, 0);
}
/* }}} */
/* {{{ proto bool RarEntry::getRedirTarget()
Returns the redirection target, encoded as UTF-8, or NULL */
PHP_METHOD(rarentry, getRedirTarget)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "redir_target");
RETURN_ZVAL(tmp, 1, 0);
}
/* }}} */
/* {{{ proto string RarEntry::__toString()
Return string representation for entry */
PHP_METHOD(rarentry, __toString)
{
zval *flags_zval,
*name_zval,
*crc_zval;
zval **flags_zval,
**name_zval,
**crc_zval;
zval *entry_obj = getThis();
long flags;
int is_dir;
char *name,
*crc;
char *restring;
int restring_size;
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 & RHDF_DIRECTORY;
flags = Z_LVAL_PP(flags_zval);
is_dir = ((flags & 0xE0) == 0xE0);
RAR_GET_PROPERTY(name_zval, "name");
name = Z_STRVAL_P(name_zval);
name = Z_STRVAL_PP(name_zval);
RAR_GET_PROPERTY(crc_zval, "crc");
crc = Z_STRVAL_P(crc_zval);
crc = Z_STRVAL_PP(crc_zval);
/* 2 is size of %s, 8 is size of crc */
restring_size = (sizeof(format)-1) - 2 * 3 + (sizeof("directory")-1) +
//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_size);
snprintf(restring, restring_size, format, is_dir?"directory":"file",
restring = emalloc(restring_len);
snprintf(restring, restring_len, format, is_dir?"directory":"file",
name, crc);
restring[restring_size - 1] = '\0'; /* just to be safe */
RAR_RETURN_STRINGL(restring, strlen(restring), 0);
restring[restring_len - 1] = '\0'; //just to be safe
RETURN_STRING(restring, 0);
}
/* }}} */
/* }}} */
@@ -698,7 +542,6 @@ 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)
@@ -711,7 +554,6 @@ 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)
@@ -724,9 +566,6 @@ static zend_function_entry php_rar_class_functions[] = {
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, getRedirType, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, isRedirectToDirectory, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getRedirTarget, 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}
@@ -736,13 +575,17 @@ 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");
@@ -753,10 +596,7 @@ void minit_rarentry(TSRMLS_D)
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_PROPERTY("redir_type", "The type of redirection or NULL");
REG_RAR_PROPERTY("redir_to_directory", "Whether the redirection target is a directory");
REG_RAR_PROPERTY("redir_target", "Target of the redirectory");
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);
@@ -764,13 +604,7 @@ void minit_rarentry(TSRMLS_D)
REG_RAR_CLASS_CONST_LONG("HOST_MACOS", HOST_MACOS);
REG_RAR_CLASS_CONST_LONG("HOST_BEOS", HOST_BEOS);
REG_RAR_CLASS_CONST_LONG("FSREDIR_UNIXSYMLINK", FSREDIR_UNIXSYMLINK);
REG_RAR_CLASS_CONST_LONG("FSREDIR_WINSYMLINK", FSREDIR_WINSYMLINK);
REG_RAR_CLASS_CONST_LONG("FSREDIR_JUNCTION", FSREDIR_JUNCTION);
REG_RAR_CLASS_CONST_LONG("FSREDIR_HARDLINK", FSREDIR_HARDLINK);
REG_RAR_CLASS_CONST_LONG("FSREDIR_FILECOPY", FSREDIR_FILECOPY);
/* see WinNT.h */
//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);

View File

@@ -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.

View File

@@ -22,6 +22,6 @@ 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
Warning: rar_open(): Failed to open %s/no_such_file.rar: ERAR_EOPEN (file open error) in %s on line %d
bool(false)
Done

View File

@@ -24,10 +24,8 @@ array(2) {
[0]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
object(RarArchive)#%s (%s) {
}
["position%sprivate%s=>
int(0)
["name%sprivate%s=>
string(9) "plain.txt"
["unpacked_size%sprivate%s=>
@@ -47,21 +45,13 @@ array(2) {
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
int(32800)
}
[1]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
object(RarArchive)#%d (0) {
}
["position%sprivate%s=>
int(1)
["name%sprivate%s=>
string(30) "test file with whitespaces.txt"
["unpacked_size%sprivate%s=>
@@ -81,13 +71,7 @@ array(2) {
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
int(32800)
}
}
array(2) {
@@ -96,8 +80,6 @@ array(2) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(0)
["name%sprivate%s=>
string(5) "1.txt"
["unpacked_size%sprivate%s=>
@@ -117,21 +99,13 @@ array(2) {
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
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=>
@@ -151,13 +125,7 @@ array(2) {
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(16)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
int(37008)
}
}

View File

@@ -24,8 +24,6 @@ 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=>
@@ -45,20 +43,12 @@ object(RarEntry)#%d (%d) {
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate%s=>
int(0)
["redir_to_directory%sprivate%s=>
NULL
["redir_target%sprivate%s=>
NULL
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=>
@@ -78,13 +68,7 @@ object(RarEntry)#%d (%d) {
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(16)
["redir_type%sprivate%s=>
int(0)
["redir_to_directory%sprivate%s=>
NULL
["redir_target%sprivate%s=>
NULL
int(37008)
}
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d

View File

@@ -55,10 +55,8 @@ blah-blah-blah
string(5) "22222"
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
object(RarArchive)#3 (0) {
}
["position%sprivate%s=>
int(1)
["name%sprivate%s=>
string(5) "2.txt"
["unpacked_size%sprivate%s=>
@@ -78,13 +76,7 @@ object(RarEntry)#%d (%d) {
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(16)
["redir_type%sprivate%s=>
int(0)
["redir_to_directory%sprivate%s=>
NULL
["redir_target%sprivate%s=>
NULL
int(37008)
}
bool(true)
Done

View File

@@ -10,27 +10,15 @@ 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

View File

@@ -22,7 +22,7 @@ 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
Warning: rar_entry_get(): cannot find file "nonexistent_file.txt" in Rar archive "%s". in %s on line %d
bool(false)

View File

@@ -15,10 +15,6 @@ function int32_to_hex($value) {
}
foreach ($entries as $e) {
$stream = $e->getStream();
if ($stream === false) {
die("Failed to get stream.\n");
break;
}
echo $e->getName().": ";
$a = "";
while (!feof($stream)) {

View File

@@ -20,7 +20,7 @@ foreach ($entries as $e) {
echo "Could not get stream.\n\n";
continue;
}
while (!feof($stream) && $i != 2) {
while (!feof($stream)) {
echo fread($stream, 8192);
}
fclose($stream);
@@ -37,5 +37,6 @@ test%s: The great battle of Gunprex versus Optiter!!!!!1
Gunprex, Fire!
So long, Optiter!
test%s
test%s: it,greIater!
%s
Done

View File

@@ -26,5 +26,5 @@ RarEntry for file "1.txt" (a0de71c0)
RAR Archive "%s" (closed)
Warning: RarEntry::extract(): The archive is already closed in %s on line %d
Warning: RarEntry::extract(): The archive is already closed. in %s on line %d
Done

View File

@@ -18,7 +18,7 @@ echo "Done\n";
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
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

View File

@@ -25,10 +25,6 @@ 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):
@@ -46,7 +42,4 @@ 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

View File

@@ -8,17 +8,8 @@ $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.

View File

@@ -14,6 +14,6 @@ try {
}
echo "Done.\n";
--EXPECTF--
Message: cannot find file "nonexistentfile.txt" in Rar archive "%slatest_winrar.rar"
Message: cannot find file "nonexistentfile.txt" in Rar archive "%slatest_winrar.rar".
Code: -1
Done.

View File

@@ -1,15 +1,15 @@
--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
--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: The archive is already closed, cannot give an iterator in %s on line %d

View File

@@ -1,15 +1,15 @@
--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.
--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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,90 +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, 'strpos');
$rar->getEntries();
echo "\nGiven callback that takes another kind of arguments:\n";
$rar = RarArchive::open($fn, null, 'array_keys');
$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: strpos() 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: array_keys() expects parameter 1 to be array, string given 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.

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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 > 2048))
die("skip test is for systems where MAXPATHLEN > 2048");
$rp = dirname(__FILE__) . "/" . str_repeat("a", 2048);
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", 2048); }
$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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,40 +0,0 @@
--TEST--
RAR file stream stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=Asia/Tokyo
--FILE--
<?php
umask(0);
$stream = fopen("rar://" .
dirname(__FILE__) . '/latest_winrar.rar' .
"#1.txt", "r");
$r = array_slice(fstat($stream), 13);
if (PHP_OS == 'WINNT') {
// we don't return the correct value on windows
$r['mtime'] = 1086948439;
}
print_r($r);
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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,70 +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';
$r = array_slice(fstat(opendir($u)), 13);
if (PHP_OS == 'WINNT') {
// we don't give the correct values on windows
$r['atime'] = 1272938643;
$r['mtime'] = 1272938643;
$r['ctime'] = 1272813170;
}
print_r($r);
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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -1,14 +0,0 @@
--TEST--
RarArchive direct instantiation does not crash (PHP 5.x)
--SKIPIF--
<?php
if (!extension_loaded("rar")) die("skip");
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID >= 70000) die("skip for PHP 5.x");
--FILE--
<?php
new RarArchive();
echo "Done\n";
--EXPECTF--
Fatal error: Call to private RarArchive::__construct() from invalid context in %s on line %d

View File

@@ -1,13 +0,0 @@
--TEST--
RarEntry direct instantiation does not crash (PHP 5.x)
--SKIPIF--
<?php if(!extension_loaded("rar")) die("skip");
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID >= 70000) die("skip for PHP 5.x");
--FILE--
<?php
new RarEntry();
echo "Done\n";
--EXPECTF--
Fatal error: Call to private RarEntry::__construct() from invalid context in %s on line %d

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,20 +0,0 @@
--TEST--
RarArchive has_property handler is given a closed archive
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
$a->close();
var_dump(isset($a[0]));
echo "\n";
echo "Done.\n";
--EXPECTF--
Warning: main(): The archive is already closed in %s on line %d
bool(false)
Done.

View File

@@ -1,16 +0,0 @@
--TEST--
RarArchive write_property gives a fatal error
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
$a[0] = "jjj";
echo "\n";
echo "Done.\n";
--EXPECTF--
Fatal error: main(): A RarArchive object is not writable in %s on line %d

View File

@@ -1,21 +0,0 @@
--TEST--
RarArchive read_property gives a fatal error on a write context
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
unset($a[0]["jj"]);
//or
//$a[0] *= 6;
//$a[0]["jj"] = "bar";
//$h = &$a[0];
echo "\n";
echo "Done.\n";
--EXPECTF--
Fatal error: main(): A RarArchive object is not modifiable in %s on line %d

View File

@@ -1,16 +0,0 @@
--TEST--
RarArchive write_property gives a fatal error
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
$a[0] = "hhh";
echo "\n";
echo "Done.\n";
--EXPECTF--
Fatal error: main(): A RarArchive object is not writable in %s on line %d

View File

@@ -1,16 +0,0 @@
--TEST--
RarArchive unset_property gives a fatal error
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
unset($a[0]);
echo "\n";
echo "Done.\n";
--EXPECTF--
Fatal error: main(): A RarArchive object is not writable in %s on line %d

View File

@@ -1,30 +0,0 @@
--TEST--
RarArchive has_property gives a fatal error
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
var_dump(isset($a[0]));
var_dump(!empty($a[0]));
var_dump(isset($a[2]));
var_dump(!empty($a[2]));
var_dump(isset($a["jsdf"]));
var_dump(!empty($a["jlkjlk"]));
echo "\n";
echo "Done.\n";
--EXPECTF--
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
Done.

View File

@@ -1,78 +0,0 @@
--TEST--
RarArchive::isBroken/rar_broken_is test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f = dirname(__FILE__) . "/latest_winrar.rar";
$b = dirname(__FILE__) . "/multi_broken.part1.rar";
echo "\n* unbroken file; bad arguments\n";
$a = RarArchive::open($f);
var_dump($a->isBroken("jjj"));
var_dump(rar_broken_is($a, "jjj"));
echo "\n* unbroken file; as first call\n";
var_dump($a->isBroken());
echo "\n* unbroken file; as second call\n";
$a = RarArchive::open($f);
$a->getEntries();
var_dump($a->isBroken());
echo "\n* broken file; as first call; don't allow broken\n";
$a = RarArchive::open($b);
var_dump($a->isBroken());
echo "\n* broken file; as first call; don't allow broken; kill warning\n";
function retnull() { return null; }
$a = RarArchive::open($b, null, 'retnull');
var_dump($a->isBroken());
echo "\n* broken file; as first call; don't allow broken; kill warning; non OOP\n";
$a = RarArchive::open($b, null, 'retnull');
var_dump(rar_broken_is($a));
echo "\n* broken file; as second call; don't allow broken\n";
$a = RarArchive::open($b);
$a->getEntries();
var_dump($a->isBroken());
echo "\n";
echo "Done.\n";
--EXPECTF--
* unbroken file; bad arguments
Warning: RarArchive::isBroken() expects exactly 0 parameters, 1 given in %s on line %d
NULL
Warning: rar_broken_is() expects exactly 1 parameter, 2 given in %s on line %d
NULL
* unbroken file; as first call
bool(false)
* unbroken file; as second call
bool(false)
* broken file; as first call; don't allow broken
Warning: RarArchive::isBroken(): Volume %smulti_broken.part2.rar was not found in %s on line %d
bool(true)
* broken file; as first call; don't allow broken; kill warning
bool(true)
* broken file; as first call; don't allow broken; kill warning; non OOP
bool(true)
* broken file; as second call; don't allow broken
Warning: RarArchive::getEntries(): Volume %smulti_broken.part2.rar was not found in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
bool(true)
Done.

View File

@@ -1,76 +0,0 @@
--TEST--
RarArchive::setAllowBroken has the desired effect
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
function retnull() { return null; }
$b = dirname(__FILE__) . "/multi_broken.part1.rar";
echo "* broken file; bad arguments\n";
$a = RarArchive::open($b, null, 'retnull');
$a->setAllowBroken();
rar_allow_broken_set($a);
echo "\n* broken file; do not allow broken (default)\n";
$a = RarArchive::open($b, null, 'retnull');
var_dump($a->getEntries());
var_dump(count($a));
echo "\n* broken file; do not allow broken (explicit)\n";
$a = RarArchive::open($b, null, 'retnull');
$a->setAllowBroken(false);
var_dump($a->getEntries());
var_dump(count($a));
echo "\n* broken file; allow broken\n";
$a = RarArchive::open($b, null, 'retnull');
$a->setAllowBroken(true);
foreach ($a->getEntries() as $e) {
echo "$e\n";
}
var_dump(count($a));
echo "\n* broken file; allow broken; non OOP\n";
$a = RarArchive::open($b, null, 'retnull');
rar_allow_broken_set($a, true);
foreach ($a->getEntries() as $e) {
echo "$e\n";
}
var_dump(count($a));
echo "\n";
echo "Done.\n";
--EXPECTF--
* broken file; bad arguments
Warning: RarArchive::setAllowBroken() expects exactly 1 parameter, 0 given in %s on line %d
Warning: rar_allow_broken_set() expects exactly 2 parameters, 1 given in %s on line %d
* broken file; do not allow broken (default)
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
bool(false)
Warning: count(): ERAR_EOPEN (file open error) in %s on line %d
int(0)
* broken file; do not allow broken (explicit)
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
bool(false)
Warning: count(): ERAR_EOPEN (file open error) in %s on line %d
int(0)
* broken file; allow broken
RarEntry for file "file1.txt" (52b28202)
int(1)
* broken file; allow broken; non OOP
RarEntry for file "file1.txt" (52b28202)
int(1)
Done.

View File

@@ -1,18 +0,0 @@
--TEST--
Traversal of RarArchive with foreach by reference gives error
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
foreach ($a as &$v) {
die("shouldn't have gotten here");
}
echo "\n";
echo "Done.\n";
--EXPECTF--
Fatal error: main(): An iterator cannot be used with foreach by reference in %s on line %d

View File

@@ -1,28 +0,0 @@
--TEST--
rar_close is called twice
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f1 = dirname(__FILE__) . "/latest_winrar.rar";
$a = RarArchive::open($f1);
echo $a."\n";
$a->close();
echo $a."\n";
$a->close();
echo $a."\n";
echo "\n";
echo "Done.\n";
--EXPECTF--
RAR Archive "%slatest_winrar.rar"
RAR Archive "%slatest_winrar.rar" (closed)
Warning: RarArchive::close(): The archive is already closed in %s on line %d
RAR Archive "%slatest_winrar.rar" (closed)
Done.

View File

@@ -1,118 +0,0 @@
--TEST--
Wrapper cache exaustion test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$f = array();
$f[] = dirname(__FILE__) . "/latest_winrar.rar";
$f[] = dirname(__FILE__) . "/directories.rar";
$f[] = dirname(__FILE__) . "/dirs_and_extra_headers.rar";
$f[] = dirname(__FILE__) . "/encrypted_only_files.rar";
$f[] = dirname(__FILE__) . "/linux_rar.rar";
$f_l = dirname(__FILE__) . "/rar_unicode.rar";
function printstats() {
echo "Stats: ".rar_wrapper_cache_stats()."\n";
}
echo "* Invalid call to rar_wrapper_cache_stats():\n";
var_dump(rar_wrapper_cache_stats("sfddf"));
echo "\n* Initial stats:\n";
printstats();
echo "\n* Fill cache:\n";
foreach ($f as $n) {
var_export(file_exists("rar://" . rawurlencode($n)));
echo "\n";
}
printstats();
clearstatcache();
echo "\n* Hit cache:\n";
foreach ($f as $n) {
var_export(file_exists("rar://" . rawurlencode($n)));
echo "\n";
}
printstats();
clearstatcache();
echo "\n* Evict first file:\n";
var_export(file_exists("rar://" . rawurlencode($f_l))); //0 out
echo "\n";
printstats();
clearstatcache();
echo "\n* One hit, one miss:\n";
var_export(file_exists("rar://" . rawurlencode($f[1]))); //hit
echo "\n";
var_export(file_exists("rar://" . rawurlencode($f[0]))); //miss, 1 out
echo "\n";
printstats();
clearstatcache();
echo "\n* Miss on last evicted:\n";
var_export(file_exists("rar://" . rawurlencode($f[1]))); //miss, 2 out
echo "\n";
printstats();
clearstatcache();
echo "\n* Hit on three last added :\n";
var_export(file_exists("rar://" . rawurlencode($f_l)));
echo "\n";
var_export(file_exists("rar://" . rawurlencode($f[0])));
echo "\n";
var_export(file_exists("rar://" . rawurlencode($f[1])));
echo "\n";
printstats();
clearstatcache();
echo "\n";
echo "Done.\n";
--EXPECTF--
* Invalid call to rar_wrapper_cache_stats():
Warning: rar_wrapper_cache_stats() expects exactly 0 parameters, 1 given in %s on line %d
NULL
* Initial stats:
Stats: 0/0 (hits/misses)
* Fill cache:
true
true
true
true
true
Stats: 0/5 (hits/misses)
* Hit cache:
true
true
true
true
true
Stats: 5/5 (hits/misses)
* Evict first file:
true
Stats: 5/6 (hits/misses)
* One hit, one miss:
true
true
Stats: 6/7 (hits/misses)
* Miss on last evicted:
true
Stats: 6/8 (hits/misses)
* Hit on three last added :
true
true
true
Stats: 9/8 (hits/misses)
Done.

View File

@@ -1,43 +0,0 @@
--TEST--
Module info test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
ob_start();
phpinfo(INFO_MODULES);
$phpinfo = ob_get_contents();
ob_end_clean();
$phpinfo = preg_replace('/\r\n?/', "\n", $phpinfo); //normalize line endings
$phpinfo = explode("\n", $phpinfo);
$found = false;
$empty = 0;
foreach ($phpinfo as $line) {
if (!$found) {
if ($line == "rar") {
$found = true;
}
}
else {
if (empty($line)) {
$empty++;
}
elseif ($empty == 1) {
echo $line."\n";
}
}
}
echo "\n";
echo "Done.\n";
--EXPECTF--
RAR support => enabled
RAR EXT version => %d.%d.%s
UnRAR version => %d.%d%spatch%d %d-%d-%d
UnRAR API version => %d extension %d
Done.

View File

@@ -1,31 +0,0 @@
--TEST--
PECL bug #18449 (Extraction of uncompressed and encrypted files fails)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--CLEAN--
<?php
@unlink(dirname(__FILE__) . '/base.css');
@unlink(dirname(__FILE__) . '/reset.css');
--FILE--
<?php
$rar_archives = array(
dirname(__FILE__) . '/secret-crypted-none.rar',
dirname(__FILE__) . '/secret-none.rar',
);
foreach ($rar_archives as $rar_archive) {
echo basename($rar_archive), "\n";
$rar = rar_open($rar_archive, 'secret');
foreach ($rar as $rar_file) {
$rar_file->extract(dirname(__FILE__));
}
@unlink(dirname(__FILE__) . '/base.css');
@unlink(dirname(__FILE__) . '/reset.css');
rar_close($rar);
}
echo "\nDone.\n";
--EXPECTF--
secret-crypted-none.rar
secret-none.rar
Done.

View File

@@ -1,22 +0,0 @@
--TEST--
PECL bug #18449 (Extraction of uncompressed and encrypted files fails; stream variant)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--CLEAN--
<?php
@unlink(dirname(__FILE__) . '/base.css');
@unlink(dirname(__FILE__) . '/reset.css');
--FILE--
<?php
$rar = rar_open(dirname(__FILE__) . '/secret-none.rar', 'secret');
foreach ($rar as $rar_file) {
var_dump(strlen(stream_get_contents($rar_file->getStream())));
}
echo "\nDone.\n";
--EXPECTF--
int(2279)
int(1316)
Done.

View File

@@ -1,29 +0,0 @@
--TEST--
Bug #59939: Streaming empty file from archive issues a warning
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar = RarArchive::open(dirname(__FILE__) . '/empty_file.rar');
if ($rar === false) die("could not open RAR file");
$rar_file = $rar->getEntry('empty_file');
if ($rar_file === false) die("could not find entry");
$stream = $rar_file->getStream();
if ($stream === false) die("could not open stream");
var_dump(feof($stream),
fread($stream, 1024*1024),
feof($stream));
echo "\n";
echo "Done.\n";
?>
--EXPECT--
bool(false)
string(0) ""
bool(true)
Done.

View File

@@ -1,37 +0,0 @@
--TEST--
fopen modes 'r' and 'rb' are the only allowed
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$file = 'rar://' . rawurlencode(dirname(__FILE__) . '/linux_rar.rar')
. '#/plain.txt';
echo "Testing 'r'\n";
$fd = fopen($file, 'r');
if ($fd) echo "opened\n\n";
echo "Testing 'rb'\n";
$fd = fopen($file, 'rb');
if ($fd) echo "opened\n\n";
echo "Testing 'r+'\n";
$fd = fopen($file, 'r+');
if ($fd) echo "opened\n\n";
echo "\n";
echo "Done.\n";
?>
--EXPECTF--
Testing 'r'
opened
Testing 'rb'
opened
Testing 'r+'
Warning: fopen(%s): failed to open stream: Only the "r" and "rb" open modes are permitted, given r+ in %s on line %d
Done.

View File

@@ -1,54 +0,0 @@
--TEST--
Supports version 5 RAR files
--SKIPIF--
<?php if(!extension_loaded("rar")) die("skip");
if (isset($_ENV['APPVEYOR'])) die("skip failing on appveyor");
--FILE--
<?php
RarException::setUsingExceptions(true);
$file = dirname(__FILE__) . '/rar5_multi.part1.rar';
$rar = RarArchive::open($file);
$entry = $rar->getEntry('usr' . DIRECTORY_SEPARATOR . 'bin' .
DIRECTORY_SEPARATOR . 'text2image');
var_dump($entry);
$stream = $entry->getStream('passw0rd');
$contents = stream_get_contents($stream);
echo "(unpacked) MD5: ", md5($contents), "\n";
echo "Done.\n";
?>
--EXPECTF--
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(0)
["name%sprivate%s=>
string(18) "usr%sbin%stext2image"
["unpacked_size%sprivate%s=>
int(147528)
["packed_size%sprivate%s=>
int(57104)
["host_os%sprivate%s=>
int(3)
["file_time%sprivate%s=>
string(19) "%s"
["crc%sprivate%s=>
string(8) "83c9a6b7"
["attr%sprivate%s=>
int(33261)
["version%sprivate%s=>
int(200)
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(5)
["redir_type%sprivate%s=>
int(0)
["redir_to_directory%sprivate%s=>
NULL
["redir_target%sprivate%s=>
NULL
}
(unpacked) MD5: c07ce36ec260848f47fe8ac1408f938f
Done.

View File

@@ -1,17 +0,0 @@
--TEST--
RarArchive direct instantiation does not crash (PHP 7)
--SKIPIF--
<?php
if (!extension_loaded("rar")) die("skip");
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 70000) die("skip for PHP >= 7");
--FILE--
<?php
new RarArchive();
echo "Done\n";
--EXPECTF--
Fatal error: Uncaught Error: Call to private RarArchive::__construct() from invalid context in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View File

@@ -1,16 +0,0 @@
--TEST--
RarEntry direct instantiation does not crash (PHP 7)
--SKIPIF--
<?php if(!extension_loaded("rar")) die("skip");
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 70000) die("skip for PHP >= 7");
--FILE--
<?php
new RarEntry();
echo "Done\n";
--EXPECTF--
Fatal error: Uncaught Error: Call to private RarEntry::__construct() from invalid context in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View File

@@ -1,19 +0,0 @@
--TEST--
Clone of RarArchive is forbidden (PHP 7)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip";
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 70000) die("skip for PHP >= 7");
--FILE--
<?php
RarException::setUsingExceptions(true);
$file = dirname(__FILE__) . '/rar5_multi.part1.rar';
$rar = RarArchive::open($file);
$rar2 = clone $rar;
$rar2->getEntries();
echo "Never reached.\n";
?>
--EXPECTF--
Fatal error: Uncaught Error: Trying to clone an uncloneable object of class RarArchive in %s:5
Stack trace:
#0 {main}
thrown in %s on line %d

View File

@@ -1,16 +0,0 @@
--TEST--
Clone of RarArchive is forbidden (PHP 5.x)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip";
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID >= 70000) die("skip for PHP 5.x");
--FILE--
<?php
RarException::setUsingExceptions(true);
$file = dirname(__FILE__) . '/rar5_multi.part1.rar';
$rar = RarArchive::open($file);
$rar2 = clone $rar;
$rar2->getEntries();
echo "Never reached.\n";
?>
--EXPECTF--
Fatal error: Trying to clone an uncloneable object of class RarArchive in %s on line %d

View File

@@ -1,19 +0,0 @@
--TEST--
Stat times don't depend on timezone (cf. 056.phpt)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=UTC
--FILE--
<?php
umask(0);
$stream = fopen("rar://" .
dirname(__FILE__) . '/latest_winrar.rar' .
"#1.txt", "r");
$fs = fstat($stream);
echo $fs['mtime'], "\n";
echo "Done.\n";
--EXPECTF--
1086948439
Done.

Some files were not shown because too many files have changed in this diff Show More