mirror of
https://github.com/php-win-ext/php-rar.git
synced 2026-03-24 04:52:07 +01:00
Compare commits
101 Commits
ext-v0.3.0
...
ext-v2.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7d4f10f7f | ||
|
|
0f76b938a4 | ||
|
|
670290aad1 | ||
|
|
82d3711a99 | ||
|
|
af49aafb1d | ||
|
|
7288320a37 | ||
|
|
fc23699737 | ||
|
|
fffcb9d508 | ||
|
|
79afa19815 | ||
|
|
02855820f7 | ||
|
|
5f7b823e40 | ||
|
|
59437d527f | ||
|
|
9be4e1e0e3 | ||
|
|
7089587b9e | ||
|
|
43dc0541aa | ||
|
|
36b2b5d2fc | ||
|
|
4e2dc20b2d | ||
|
|
61183fa339 | ||
|
|
7da530c6e3 | ||
|
|
b7794e851d | ||
|
|
444ee4b790 | ||
|
|
51b5b9b267 | ||
|
|
65758585af | ||
|
|
5966259561 | ||
|
|
67d29529f1 | ||
|
|
e09548cd2f | ||
|
|
6faef72502 | ||
|
|
c39465fa08 | ||
|
|
633a15f4b4 | ||
|
|
c4432e6c4b | ||
|
|
81934056d0 | ||
|
|
896a5d3a91 | ||
|
|
a153f2ba84 | ||
|
|
6c8276f3c8 | ||
|
|
380eb4fd06 | ||
|
|
c502332f09 | ||
|
|
e64419b1c3 | ||
|
|
a9d71e2adb | ||
|
|
c56f0c4ad9 | ||
|
|
6de793130a | ||
|
|
ba66f77e5f | ||
|
|
f93c189947 | ||
|
|
5ba817d02c | ||
|
|
3655bf9e21 | ||
|
|
3254b497a2 | ||
|
|
da1c055202 | ||
|
|
d3ffa6d3ba | ||
|
|
8d24ef1195 | ||
|
|
84d8d1c93f | ||
|
|
22be3d8ee9 | ||
|
|
397d6de791 | ||
|
|
6d00347ddd | ||
|
|
1401a0604c | ||
|
|
d033b8f836 | ||
|
|
b15940e101 | ||
|
|
829e402dbb | ||
|
|
48c55f71ea | ||
|
|
9876090ea6 | ||
|
|
3a71ec0c0f | ||
|
|
c52d6a92a6 | ||
|
|
8f65391767 | ||
|
|
3f841aca84 | ||
|
|
d39e216566 | ||
|
|
ed74b331d8 | ||
|
|
36e67a3493 | ||
|
|
d6673b97fd | ||
|
|
04ac7f6eba | ||
|
|
a4b1479338 | ||
|
|
d528906ec7 | ||
|
|
3c08bc522f | ||
|
|
dc4037e8ed | ||
|
|
b79060c741 | ||
|
|
2ea98f9c07 | ||
|
|
40b585bc2f | ||
|
|
62ebac8d88 | ||
|
|
cf7947cbbd | ||
|
|
f6900cb024 | ||
|
|
fa8c1c8aa8 | ||
|
|
4d7c5fc2c4 | ||
|
|
10d2444b31 | ||
|
|
63e0df6078 | ||
|
|
54ac112b0d | ||
|
|
9ec063426c | ||
|
|
1d4ad5767b | ||
|
|
0866f20178 | ||
|
|
5db1495374 | ||
|
|
75f63eae35 | ||
|
|
5f0d4b1516 | ||
|
|
7430bfae21 | ||
|
|
3010bc351e | ||
|
|
bfaaaa95fe | ||
|
|
379f5d1d43 | ||
|
|
f45fb54b0a | ||
|
|
e4d1885168 | ||
|
|
b5cecfd421 | ||
|
|
57f518d804 | ||
|
|
0ed5106066 | ||
|
|
473e865b38 | ||
|
|
b08d2ebc66 | ||
|
|
198fda108f | ||
|
|
a745071a2a |
30
config.m4
30
config.m4
@@ -5,20 +5,20 @@ PHP_ARG_ENABLE(rar, whether to enable rar support,
|
||||
[ --enable-rar Enable rar support])
|
||||
|
||||
unrar_sources="unrar/rar.cpp unrar/strlist.cpp unrar/strfn.cpp \
|
||||
unrar/pathfn.cpp unrar/int64.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/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
|
||||
@@ -26,6 +26,6 @@ if test "$PHP_RAR" != "no"; then
|
||||
PHP_SUBST(RAR_SHARED_LIBADD)
|
||||
PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", RAR_SHARED_LIBADD)
|
||||
|
||||
PHP_NEW_EXTENSION(rar, rar.cpp $unrar_sources, $ext_shared,,-DRARDLL -DGUI -DSILENT -I@ext_srcdir@/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
|
||||
|
||||
34
config.w32
34
config.w32
@@ -4,23 +4,23 @@
|
||||
ARG_ENABLE("rar", "Rar support", "no");
|
||||
|
||||
if (PHP_RAR != "no") {
|
||||
EXTENSION("rar", "rar.cpp", PHP_RAR_SHARED, "-DRARDLL -DGUI -DSILENT");
|
||||
ADD_SOURCES(configure_module_dirname + "/unrar", "rar.cpp \
|
||||
strlist.cpp strfn.cpp pathfn.cpp int64.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 list.cpp", "rar");
|
||||
|
||||
if (!PHP_RAR_SHARED) {
|
||||
ADD_DEF_FILE(configure_module_dirname + "\\unrar\\dll.def");
|
||||
}
|
||||
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",
|
||||
"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");
|
||||
}
|
||||
|
||||
548
package.xml
548
package.xml
@@ -1,186 +1,392 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<package>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.5.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
|
||||
http://pear.php.net/dtd/tasks-1.0.xsd
|
||||
http://pear.php.net/dtd/package-2.0
|
||||
http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<name>rar</name>
|
||||
<channel>pecl.php.net</channel>
|
||||
<summary>rar extension</summary>
|
||||
<description>
|
||||
Rar is a powerful and effective archiver, which was
|
||||
created by Eugene Roshal and became rather popular quite fast.
|
||||
This extension gives you possibility to read Rar archives.
|
||||
<description>PHP extension for reading RAR archives using bundled unRAR library.
|
||||
</description>
|
||||
<license>PHP License</license>
|
||||
<maintainers>
|
||||
<maintainer>
|
||||
<user>tony2001</user>
|
||||
<name>Antony Dovgal</name>
|
||||
<email>tony2001@phpclub.net</email>
|
||||
</maintainer>
|
||||
</maintainers>
|
||||
<release>
|
||||
<version>0.3.0</version>
|
||||
<date>2006-06-06</date>
|
||||
<state>beta</state>
|
||||
<notes>
|
||||
- Updated bundled unrar to version 3.6.2 (fixes compile errors with GCC4).
|
||||
- Several minor fixes.
|
||||
</notes>
|
||||
</release>
|
||||
|
||||
<lead>
|
||||
<name>Gustavo Lopes</name>
|
||||
<user>cataphract</user>
|
||||
<email>cataphract@php.net</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
|
||||
<developer>
|
||||
<name>Antony Dovgal</name>
|
||||
<user>tony2001</user>
|
||||
<email>tony@daylessday.org</email>
|
||||
<active>no</active>
|
||||
</developer>
|
||||
|
||||
<date>2010-04-20</date>
|
||||
<time>13:00:00</time>
|
||||
<version>
|
||||
<release>2.0.0</release>
|
||||
<api>2.0.0</api>
|
||||
</version>
|
||||
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<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 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="arccmt.cpp" role="src" />
|
||||
<file name="archive.cpp" role="src" />
|
||||
<file name="archive.hpp" role="src" />
|
||||
<file name="arcread.cpp" role="src" />
|
||||
<file name="array.hpp" role="src" />
|
||||
<file name="beosea.cpp" role="src" />
|
||||
<file name="cmddata.cpp" role="src" />
|
||||
<file name="cmddata.hpp" role="src" />
|
||||
<file name="coder.cpp" role="src" />
|
||||
<file name="coder.hpp" role="src" />
|
||||
<file name="compress.hpp" role="src" />
|
||||
<file name="consio.cpp" role="src" />
|
||||
<file name="consio.hpp" role="src" />
|
||||
<file name="crc.cpp" role="src" />
|
||||
<file name="crc.hpp" role="src" />
|
||||
<file name="crypt.cpp" role="src" />
|
||||
<file name="crypt.hpp" role="src" />
|
||||
<file name="dll.cpp" role="src" />
|
||||
<file name="dll.hpp" role="src" />
|
||||
<file name="encname.cpp" role="src" />
|
||||
<file name="encname.hpp" role="src" />
|
||||
<file name="errhnd.cpp" role="src" />
|
||||
<file name="errhnd.hpp" role="src" />
|
||||
<file name="extinfo.cpp" role="src" />
|
||||
<file name="extinfo.hpp" role="src" />
|
||||
<file name="extract.cpp" role="src" />
|
||||
<file name="extract.hpp" role="src" />
|
||||
<file name="extractchunk.cpp" role="src" />
|
||||
<file name="filcreat.cpp" role="src" />
|
||||
<file name="filcreat.hpp" role="src" />
|
||||
<file name="file.cpp" role="src" />
|
||||
<file name="file.hpp" role="src" />
|
||||
<file name="filefn.cpp" role="src" />
|
||||
<file name="filefn.hpp" role="src" />
|
||||
<file name="filestr.cpp" role="src" />
|
||||
<file name="filestr.hpp" role="src" />
|
||||
<file name="find.cpp" role="src" />
|
||||
<file name="find.hpp" role="src" />
|
||||
<file name="getbits.cpp" role="src" />
|
||||
<file name="getbits.hpp" role="src" />
|
||||
<file name="global.cpp" role="src" />
|
||||
<file name="global.hpp" role="src" />
|
||||
<file name="headers.hpp" role="src" />
|
||||
<file name="isnt.cpp" role="src" />
|
||||
<file name="isnt.hpp" role="src" />
|
||||
<file name="LICENSE.txt" role="doc" />
|
||||
<file name="list.cpp" role="src" />
|
||||
<file name="list.hpp" role="src" />
|
||||
<file name="loclang.hpp" role="src" />
|
||||
<file name="log.cpp" role="src" />
|
||||
<file name="log.hpp" role="src" />
|
||||
<file name="match.cpp" role="src" />
|
||||
<file name="match.hpp" role="src" />
|
||||
<file name="model.cpp" role="src" />
|
||||
<file name="model.hpp" role="src" />
|
||||
<file name="options.cpp" role="src" />
|
||||
<file name="options.hpp" role="src" />
|
||||
<file name="os.hpp" role="src" />
|
||||
<file name="os2ea.cpp" role="src" />
|
||||
<file name="pathfn.cpp" role="src" />
|
||||
<file name="pathfn.hpp" role="src" />
|
||||
<file name="rar.cpp" role="src" />
|
||||
<file name="rar.hpp" role="src" />
|
||||
<file name="rardefs.hpp" role="src" />
|
||||
<file name="rarlang.hpp" role="src" />
|
||||
<file name="raros.hpp" role="src" />
|
||||
<file name="rartypes.hpp" role="src" />
|
||||
<file name="rarvm.cpp" role="src" />
|
||||
<file name="rarvm.hpp" role="src" />
|
||||
<file name="rarvmtbl.cpp" role="src" />
|
||||
<file name="rawread.cpp" role="src" />
|
||||
<file name="rawread.hpp" role="src" />
|
||||
<file name="rdwrfn.cpp" role="src" />
|
||||
<file name="rdwrfn.hpp" role="src" />
|
||||
<file name="README.txt" role="doc" />
|
||||
<file name="recvol.cpp" role="src" />
|
||||
<file name="recvol.hpp" role="src" />
|
||||
<file name="resource.cpp" role="src" />
|
||||
<file name="resource.hpp" role="src" />
|
||||
<file name="rijndael.cpp" role="src" />
|
||||
<file name="rijndael.hpp" role="src" />
|
||||
<file name="rs.cpp" role="src" />
|
||||
<file name="rs.hpp" role="src" />
|
||||
<file name="savepos.cpp" role="src" />
|
||||
<file name="savepos.hpp" role="src" />
|
||||
<file name="scantree.cpp" role="src" />
|
||||
<file name="scantree.hpp" role="src" />
|
||||
<file name="sha1.cpp" role="src" />
|
||||
<file name="sha1.hpp" role="src" />
|
||||
<file name="smallfn.cpp" role="src" />
|
||||
<file name="smallfn.hpp" role="src" />
|
||||
<file name="strfn.cpp" role="src" />
|
||||
<file name="strfn.hpp" role="src" />
|
||||
<file name="strlist.cpp" role="src" />
|
||||
<file name="strlist.hpp" role="src" />
|
||||
<file name="suballoc.cpp" role="src" />
|
||||
<file name="suballoc.hpp" role="src" />
|
||||
<file name="system.cpp" role="src" />
|
||||
<file name="system.hpp" role="src" />
|
||||
<file name="timefn.cpp" role="src" />
|
||||
<file name="timefn.hpp" role="src" />
|
||||
<file name="ulinks.cpp" role="src" />
|
||||
<file name="ulinks.hpp" role="src" />
|
||||
<file name="unicode.cpp" role="src" />
|
||||
<file name="unicode.hpp" role="src" />
|
||||
<file name="unios2.cpp" role="src" />
|
||||
<file name="unpack.cpp" role="src" />
|
||||
<file name="unpack.hpp" role="src" />
|
||||
<file name="unpack15.cpp" role="src" />
|
||||
<file name="unpack20.cpp" role="src" />
|
||||
<file name="uowners.cpp" role="src" />
|
||||
<file name="version.hpp" role="src" />
|
||||
<file name="volume.cpp" role="src" />
|
||||
<file name="volume.hpp" role="src" />
|
||||
<file name="win32acl.cpp" role="src" />
|
||||
<file name="win32stm.cpp" role="src" />
|
||||
</dir> <!-- /unrar -->
|
||||
<file name="config.m4" role="src" />
|
||||
<file name="config.w32" role="src" />
|
||||
<file name="CREDITS" role="doc" />
|
||||
<file name="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" />
|
||||
</dir> <!-- / -->
|
||||
</contents>
|
||||
|
||||
<dependencies>
|
||||
<required>
|
||||
<php>
|
||||
<min>5.2.0</min>
|
||||
</php>
|
||||
<pearinstaller>
|
||||
<min>1.4.0</min>
|
||||
</pearinstaller>
|
||||
<extension>
|
||||
<name>spl</name>
|
||||
</extension>
|
||||
</required>
|
||||
</dependencies>
|
||||
|
||||
<providesextension>rar</providesextension>
|
||||
|
||||
<extsrcrelease />
|
||||
|
||||
<changelog>
|
||||
<release>
|
||||
<version>0.2</version>
|
||||
<date>2004-12-02</date>
|
||||
<state>beta</state>
|
||||
<notes>
|
||||
1) Added open_basedir and safe_mode checks.
|
||||
2) Fixed Win32 build issues (thanks to Edin).
|
||||
Currently only 5.x builds are available.
|
||||
3) Added OS constants.
|
||||
4) Fixed 0 bugs. There are no bugs, wee =)
|
||||
<version>
|
||||
<release>2.0.0RC1</release>
|
||||
<api>2.0.0RC1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2010-01-17</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>Changes in respect to release 1.0.0:
|
||||
PHP SUPPORT:
|
||||
- Support for PHP 4.3 dropped. PHP 5.2.x or 5.3.x is required.
|
||||
API BACKWARDS INCOMPATIBLE CHANGES:
|
||||
- Handles unicode filenames (uses UTF-8 external encoding). The file names inside the RAR archives are always returned in UTF-8. This will probably break your scripts.
|
||||
- Calling rar_close/RarArchive::close() invalidates RarEntry objects (actually, only extraction is forbidden, but don't rely on it).
|
||||
API backwards compatible changes:
|
||||
- Supports streaming from RAR archives. See RarEntry::getStream() method.
|
||||
- Added a bunch of constants to RarEntry.
|
||||
- Added RarEntry::__toString() method.
|
||||
- Added RarEntry::isDirectory() method.
|
||||
- Added RarEntry::isEncrypted() method.
|
||||
- Added OOP interface for rar_* functions with the RarArchive class.
|
||||
- Added rar_comment_get/RarArchive::getComment().
|
||||
- Added RarArchive::isSolid()/rar_solid_is().
|
||||
- Added RarArchive::__toString() method.
|
||||
- Added RarException class.
|
||||
- Exception throwing for expectable errors can be turned on by calling RarException::setUsingExceptions(). To check whether exception throwing is turned on, RarException::isUsingExceptions() can be used.
|
||||
Bug fixes:
|
||||
- Fixed by PECL bug #8821 (relative paths not working).
|
||||
- Fixed PECL bug #9470 (wrong CRC on multi-volume archives).
|
||||
- Fixed PECL bug #9649 (rar_close() not closing file descriptors if there were undestroyed RarEntry objects)
|
||||
- Fixed volumes opened with middle volumes showing files continued from previous volume with incorrect packed and unpacked sizes.
|
||||
- Fixed bug in UnRAR library that could cause a read out of buffer bounds on some corrupted RAR files.
|
||||
- Fixed RarEntry::getPackedSize() and RarEntry::getUnpackedSize() giving incorrect results for files > 2 GiB. Still, on platforms with 32-bit integers, MAX_INT will be returned for such files, othwerwise the correct value is given.
|
||||
Other changes:
|
||||
- Updated bundled UnRAR library to version 3.9.7 (RAR 3.9.1).
|
||||
- Changed bundled UnRAR library to allow partial file extraction.
|
||||
- All RarEntry properties are now private. This doesn't break the API because those properties were never part of the contract.
|
||||
- rar_open gives more detailed error messages on failure.
|
||||
- Extension now uses extended UnRAR library structures.
|
||||
- Added arginfo.
|
||||
- Added a bunch of tests.
|
||||
- A lot of refactoring and compilation as C, not C++.
|
||||
</notes>
|
||||
</release>
|
||||
|
||||
<release>
|
||||
<version>
|
||||
<release>1.0.0</release>
|
||||
<api>1.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<date>2008-02-26</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>- Upgraded bundled UnRar to version 3.7.8.
|
||||
- Updated source code to use new parameter parsing API.
|
||||
- Fixed PECL bug #9002 (rar_list invalidates rar resource)
|
||||
- Fixed PECL bug #11430 (rar_extract() doesn't close handles gracefully)
|
||||
- rar_open() now throws an error when failed to open the specified file.
|
||||
</notes>
|
||||
</release>
|
||||
|
||||
<release>
|
||||
<version>
|
||||
<release>0.3.1</release>
|
||||
<api>0.3.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2006-08-28</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>- Updated bundled unrar to version 3.6.8.
|
||||
- Fixed PHP4 compatibility.
|
||||
</notes>
|
||||
</release>
|
||||
|
||||
<release>
|
||||
<version>
|
||||
<release>0.3.0</release>
|
||||
<api>0.3.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2006-06-06</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>- Updated bundled unrar to version 3.6.2 (fixes compile errors with GCC4).
|
||||
- Several minor fixes.
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<version>0.1</version>
|
||||
<version>
|
||||
<release>0.2</release>
|
||||
<api>0.2</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>beta</release>
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2004-12-02</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>1) Added open_basedir and safe_mode checks.
|
||||
2) Fixed Win32 build issues (thanks to Edin).
|
||||
Currently only 5.x builds are available.
|
||||
3) Added OS constants.
|
||||
4) Fixed 0 bugs. There are no bugs, wee =)
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<version>
|
||||
<release>0.1</release>
|
||||
<api>0.1</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>alpha</release>
|
||||
<api>alpha</api>
|
||||
</stability>
|
||||
<date>2004-06-11</date>
|
||||
<state>alpha</state>
|
||||
<notes>
|
||||
1) Initial release
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>1) Initial release
|
||||
</notes>
|
||||
</release>
|
||||
</changelog>
|
||||
<filelist>
|
||||
<dir role="src" name="/">
|
||||
<file role="doc">CREDITS</file>
|
||||
<file role="doc">example.php</file>
|
||||
|
||||
<file role="src">config.m4</file>
|
||||
<file role="src">php_rar.h</file>
|
||||
<file role="src">rar.cpp</file>
|
||||
|
||||
<dir role="src" name="/unrar/">
|
||||
|
||||
<file role="doc">LICENSE.txt</file>
|
||||
<file role="doc">README.txt</file>
|
||||
|
||||
<file role="src">arccmt.cpp</file>
|
||||
<file role="src">archive.cpp</file>
|
||||
<file role="src">archive.hpp</file>
|
||||
<file role="src">arcread.cpp</file>
|
||||
<file role="src">array.hpp</file>
|
||||
<file role="src">beosea.cpp</file>
|
||||
<file role="src">cmddata.cpp</file>
|
||||
<file role="src">cmddata.hpp</file>
|
||||
<file role="src">coder.cpp</file>
|
||||
<file role="src">coder.hpp</file>
|
||||
<file role="src">compress.hpp</file>
|
||||
<file role="src">consio.cpp</file>
|
||||
<file role="src">consio.hpp</file>
|
||||
<file role="src">crc.cpp</file>
|
||||
<file role="src">crc.hpp</file>
|
||||
<file role="src">crypt.cpp</file>
|
||||
<file role="src">crypt.hpp</file>
|
||||
<file role="src">dll.cpp</file>
|
||||
<file role="src">dll.def</file>
|
||||
<file role="src">dll.hpp</file>
|
||||
<file role="src">encname.cpp</file>
|
||||
<file role="src">encname.hpp</file>
|
||||
<file role="src">errhnd.cpp</file>
|
||||
<file role="src">errhnd.hpp</file>
|
||||
<file role="src">extinfo.cpp</file>
|
||||
<file role="src">extinfo.hpp</file>
|
||||
<file role="src">extract.cpp</file>
|
||||
<file role="src">extract.hpp</file>
|
||||
<file role="src">filcreat.cpp</file>
|
||||
<file role="src">filcreat.hpp</file>
|
||||
<file role="src">file.cpp</file>
|
||||
<file role="src">filefn.cpp</file>
|
||||
<file role="src">filefn.hpp</file>
|
||||
<file role="src">file.hpp</file>
|
||||
<file role="src">filestr.cpp</file>
|
||||
<file role="src">filestr.hpp</file>
|
||||
<file role="src">find.cpp</file>
|
||||
<file role="src">find.hpp</file>
|
||||
<file role="src">getbits.cpp</file>
|
||||
<file role="src">getbits.hpp</file>
|
||||
<file role="src">global.cpp</file>
|
||||
<file role="src">global.hpp</file>
|
||||
<file role="src">headers.hpp</file>
|
||||
<file role="src">int64.cpp</file>
|
||||
<file role="src">int64.hpp</file>
|
||||
<file role="src">isnt.cpp</file>
|
||||
<file role="src">isnt.hpp</file>
|
||||
<file role="src">list.cpp</file>
|
||||
<file role="src">list.hpp</file>
|
||||
<file role="src">loclang.hpp</file>
|
||||
<file role="src">log.cpp</file>
|
||||
<file role="src">log.hpp</file>
|
||||
<file role="src">match.cpp</file>
|
||||
<file role="src">match.hpp</file>
|
||||
<file role="src">memfree.hpp</file>
|
||||
<file role="src">model.cpp</file>
|
||||
<file role="src">model.hpp</file>
|
||||
<file role="src">msc.dep</file>
|
||||
<file role="src">options.cpp</file>
|
||||
<file role="src">options.hpp</file>
|
||||
<file role="src">os2ea.cpp</file>
|
||||
<file role="src">os.hpp</file>
|
||||
<file role="src">pathfn.cpp</file>
|
||||
<file role="src">pathfn.hpp</file>
|
||||
<file role="src">rar.cpp</file>
|
||||
<file role="src">rardefs.hpp</file>
|
||||
<file role="src">rarfn.hpp</file>
|
||||
<file role="src">rar.hpp</file>
|
||||
<file role="src">rarlang.hpp</file>
|
||||
<file role="src">raros.hpp</file>
|
||||
<file role="src">rartypes.hpp</file>
|
||||
<file role="src">rarvm.cpp</file>
|
||||
<file role="src">rarvm.hpp</file>
|
||||
<file role="src">rarvmtbl.cpp</file>
|
||||
<file role="src">rawread.cpp</file>
|
||||
<file role="src">rawread.hpp</file>
|
||||
<file role="src">rdwrfn.cpp</file>
|
||||
<file role="src">rdwrfn.hpp</file>
|
||||
<file role="src">recvol.cpp</file>
|
||||
<file role="src">recvol.hpp</file>
|
||||
<file role="src">resource.cpp</file>
|
||||
<file role="src">resource.hpp</file>
|
||||
<file role="src">rijndael.cpp</file>
|
||||
<file role="src">rijndael.hpp</file>
|
||||
<file role="src">rs.cpp</file>
|
||||
<file role="src">rs.hpp</file>
|
||||
<file role="src">savepos.cpp</file>
|
||||
<file role="src">savepos.hpp</file>
|
||||
<file role="src">scantree.cpp</file>
|
||||
<file role="src">scantree.hpp</file>
|
||||
<file role="src">sha1.cpp</file>
|
||||
<file role="src">sha1.hpp</file>
|
||||
<file role="src">smallfn.cpp</file>
|
||||
<file role="src">smallfn.hpp</file>
|
||||
<file role="src">strfn.cpp</file>
|
||||
<file role="src">strfn.hpp</file>
|
||||
<file role="src">strlist.cpp</file>
|
||||
<file role="src">strlist.hpp</file>
|
||||
<file role="src">suballoc.cpp</file>
|
||||
<file role="src">suballoc.hpp</file>
|
||||
<file role="src">system.cpp</file>
|
||||
<file role="src">system.hpp</file>
|
||||
<file role="src">timefn.cpp</file>
|
||||
<file role="src">timefn.hpp</file>
|
||||
<file role="src">ulinks.cpp</file>
|
||||
<file role="src">ulinks.hpp</file>
|
||||
<file role="src">unicode.cpp</file>
|
||||
<file role="src">unicode.hpp</file>
|
||||
<file role="src">unpack15.cpp</file>
|
||||
<file role="src">unpack20.cpp</file>
|
||||
<file role="src">unpack.cpp</file>
|
||||
<file role="src">unpack.hpp</file>
|
||||
<file role="src">uowners.cpp</file>
|
||||
<file role="src">version.hpp</file>
|
||||
<file role="src">volume.cpp</file>
|
||||
<file role="src">volume.hpp</file>
|
||||
<file role="src">win32acl.cpp</file>
|
||||
<file role="src">win32stm.cpp</file>
|
||||
</dir>
|
||||
</dir>
|
||||
</filelist>
|
||||
</package>
|
||||
<!--
|
||||
vim:et:ts=1:sw=1
|
||||
|
||||
101
php_rar.h
101
php_rar.h
@@ -15,12 +15,13 @@
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| It's license states, that you MUST NOT use it's code to develop |
|
||||
| Its license states, that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony2001@phpclub.net> |
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
@@ -32,6 +33,8 @@
|
||||
extern zend_module_entry rar_module_entry;
|
||||
#define phpext_rar_ptr &rar_module_entry
|
||||
|
||||
#define PHP_RAR_VERSION "2.0.0-dev"
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define PHP_RAR_API __declspec(dllexport)
|
||||
#else
|
||||
@@ -42,26 +45,102 @@ extern zend_module_entry rar_module_entry;
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
/* causes linking errors (multiple definitions) in functions
|
||||
that were requested inlining but were not inlined by the compiler */
|
||||
/* #include "unrar/rar.hpp */
|
||||
/* only these includes are necessary anyway: */
|
||||
#include "unrar/raros.hpp"
|
||||
/* no need to reinclude windows.h or new.h */
|
||||
#define LEAN_RAR_INCLUDES
|
||||
#include "unrar/os.hpp"
|
||||
#include "unrar/dll.hpp"
|
||||
#include "unrar/version.hpp"
|
||||
/* These are in unrar/headers.hpp, but that header depends on several other */
|
||||
enum HOST_SYSTEM {
|
||||
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
|
||||
HOST_BEOS=5,HOST_MAX
|
||||
};
|
||||
|
||||
//maximum comment size if 64KB
|
||||
#define RAR_MAX_COMMENT_SIZE 65536
|
||||
|
||||
typedef struct rar {
|
||||
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
|
||||
void *arch_handle;
|
||||
char *password;
|
||||
} rar_file_t;
|
||||
|
||||
//PHP 5.2 compatibility
|
||||
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3
|
||||
# define ALLOC_PERMANENT_ZVAL(z) \
|
||||
(z) = (zval*) malloc(sizeof(zval));
|
||||
# define OPENBASEDIR_CHECKPATH(filename) \
|
||||
(PG(safe_mode) && \
|
||||
(!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) \
|
||||
|| php_check_open_basedir(filename TSRMLS_CC)
|
||||
# undef ZEND_BEGIN_ARG_INFO_EX
|
||||
# define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
|
||||
static const zend_arg_info name[] = { \
|
||||
{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
|
||||
#endif
|
||||
|
||||
/* rar.c */
|
||||
PHP_MINIT_FUNCTION(rar);
|
||||
PHP_MSHUTDOWN_FUNCTION(rar);
|
||||
PHP_RINIT_FUNCTION(rar);
|
||||
PHP_RSHUTDOWN_FUNCTION(rar);
|
||||
PHP_MINFO_FUNCTION(rar);
|
||||
|
||||
PHP_FUNCTION(rar_bogus_ctor);
|
||||
|
||||
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size);
|
||||
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size);
|
||||
int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
const char *const utf_file_name, /* IN */
|
||||
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 CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2);
|
||||
|
||||
/* rar_error.c */
|
||||
zend_class_entry *rarexception_ce_ptr;
|
||||
int _rar_handle_error(int errcode TSRMLS_DC);
|
||||
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC);
|
||||
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...);
|
||||
int _rar_using_exceptions(TSRMLS_D);
|
||||
const char * _rar_error_to_string(int errcode);
|
||||
void minit_rarerror(TSRMLS_D);
|
||||
|
||||
/* rararch.c */
|
||||
int _rar_get_file_resource(zval *zval_file, rar_file_t **rar_file TSRMLS_DC);
|
||||
int _rar_get_file_resource_ex(zval *zval_file, rar_file_t **rar_file, int silent TSRMLS_DC);
|
||||
void minit_rararch(TSRMLS_D);
|
||||
|
||||
PHP_FUNCTION(rar_open);
|
||||
PHP_FUNCTION(rar_list);
|
||||
PHP_FUNCTION(rar_entry_get);
|
||||
PHP_FUNCTION(rar_solid_is);
|
||||
PHP_FUNCTION(rar_comment_get);
|
||||
PHP_FUNCTION(rar_close);
|
||||
|
||||
typedef struct rar {
|
||||
int id;
|
||||
int entry_count;
|
||||
struct RARHeaderData **entries;
|
||||
struct RAROpenArchiveData *list_handle;
|
||||
struct RAROpenArchiveData *extract_handle;
|
||||
void *list_data;
|
||||
char *password;
|
||||
} rar_file_t;
|
||||
/* rarentry.c */
|
||||
extern zend_class_entry *rar_class_entry_ptr;
|
||||
void minit_rarentry(TSRMLS_D);
|
||||
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,
|
||||
char *utf_file_name,
|
||||
char *password,
|
||||
char *mode STREAMS_DC TSRMLS_DC);
|
||||
|
||||
#endif /* PHP_RAR_H */
|
||||
|
||||
|
||||
373
rar.c
Normal file
373
rar.c
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include <php.h>
|
||||
#include <php_ini.h>
|
||||
#include <zend_exceptions.h>
|
||||
#include <ext/standard/info.h>
|
||||
#include <ext/spl/spl_exceptions.h>
|
||||
|
||||
#if HAVE_RAR
|
||||
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Function prototypes for functions with internal linkage */
|
||||
static void _rar_fix_wide(wchar_t *str);
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Functions with external linkage */
|
||||
/* From unicode.cpp
|
||||
* I can't use that one directy because it takes a const wchar, not wchar_t.
|
||||
* And I shouldn't because it's not a public API.
|
||||
*/
|
||||
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size) /* {{{ */
|
||||
{
|
||||
long dsize= (long) dest_size;
|
||||
dsize--;
|
||||
while (*src != 0 && --dsize >= 0) {
|
||||
uint c =*(src++);
|
||||
if (c < 0x80)
|
||||
*(dest++) = c;
|
||||
else if (c < 0x800 && --dsize >= 0) {
|
||||
*(dest++) = (0xc0 | (c >> 6));
|
||||
*(dest++) = (0x80 | (c & 0x3f));
|
||||
}
|
||||
else if (c < 0x10000 && (dsize -= 2) >= 0) {
|
||||
*(dest++) = (0xe0 | (c >> 12));
|
||||
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
|
||||
*(dest++) = (0x80 | (c & 0x3f));
|
||||
}
|
||||
else if (c < 0x200000 && (dsize -= 3) >= 0) {
|
||||
*(dest++) = (0xf0 | (c >> 18));
|
||||
*(dest++) = (0x80 | ((c >> 12) & 0x3f));
|
||||
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
|
||||
*(dest++) = (0x80 | (c & 0x3f));
|
||||
}
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* idem */
|
||||
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size) /* {{{ */
|
||||
{
|
||||
long dsize = (long) dest_size;
|
||||
dsize--;
|
||||
while (*src != 0) {
|
||||
uint c = (unsigned char) *(src++),
|
||||
d;
|
||||
if (c < 0x80)
|
||||
d = c;
|
||||
else if ((c >> 5) == 6) {
|
||||
if ((*src & 0xc0) != 0x80)
|
||||
break;
|
||||
d=((c & 0x1f) << 6)|(*src & 0x3f);
|
||||
src++;
|
||||
}
|
||||
else if ((c>>4)==14) {
|
||||
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80)
|
||||
break;
|
||||
d = ((c & 0xf) << 12) | ((src[0] & 0x3f) << 6) | (src[1] & 0x3f);
|
||||
src += 2;
|
||||
}
|
||||
else if ((c>>3)==30) {
|
||||
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80)
|
||||
break;
|
||||
d = ((c & 7) << 18) | ((src[0] & 0x3f) << 12) | ((src[1] & 0x3f) << 6) | (src[2] & 0x3f);
|
||||
src += 3;
|
||||
}
|
||||
else
|
||||
break;
|
||||
if (--dsize < 0)
|
||||
break;
|
||||
if (d > 0xffff) {
|
||||
if (--dsize < 0 || d > 0x10ffff)
|
||||
break;
|
||||
*(dest++) = ((d - 0x10000) >> 10) + 0xd800;
|
||||
*(dest++) = (d & 0x3ff) + 0xdc00;
|
||||
}
|
||||
else
|
||||
*(dest++) = d;
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* 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 */
|
||||
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 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(utf_file_name != NULL);
|
||||
assert(arc_handle != NULL);
|
||||
assert(found != NULL);
|
||||
*found = FALSE;
|
||||
*arc_handle = NULL;
|
||||
used_header_data = header_data != NULL ?
|
||||
header_data :
|
||||
ecalloc(1, sizeof *used_header_data);
|
||||
|
||||
*arc_handle = RAROpenArchiveEx(open_data);
|
||||
if (*arc_handle == NULL) {
|
||||
retval = open_data->OpenResult;
|
||||
goto cleanup;
|
||||
}
|
||||
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) 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 (sizeof(wchar_t) > 2)
|
||||
_rar_fix_wide(used_header_data->FileNameW);
|
||||
|
||||
if (wcsncmp(used_header_data->FileNameW, file_name, NM) == 0) {
|
||||
*found = TRUE;
|
||||
goto cleanup;
|
||||
} else {
|
||||
process_result = RARProcessFile(*arc_handle, RAR_SKIP, NULL, NULL);
|
||||
}
|
||||
if (process_result != 0) {
|
||||
retval = process_result;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != 0 && result != 1) {
|
||||
//0 indicates success, 1 indicates normal end of file
|
||||
retval = result;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (header_data == NULL)
|
||||
efree(used_header_data);
|
||||
if (file_name != NULL)
|
||||
efree(file_name);
|
||||
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Only processes password callbacks */
|
||||
int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2) /* {{{ */
|
||||
{
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (msg == UCM_NEEDPASSWORD) {
|
||||
//user data is the password or null if none
|
||||
char *password = (char*) UserData;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
else if (msg == UCM_CHANGEVOLUME) {
|
||||
if (((int) P2) == RAR_VOL_ASK) {
|
||||
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(spl_ce_RuntimeException,
|
||||
"An object of this type cannot be created with the new operator.",
|
||||
0 TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Functions with internal linkage */
|
||||
static void _rar_fix_wide(wchar_t *str) /* {{{ */
|
||||
{
|
||||
wchar_t *write,
|
||||
*read;
|
||||
for (write = str, read = str; *read != L'\0'; read++) {
|
||||
if ((unsigned) *read <= 0x10ffff)
|
||||
*(write++) = *read;
|
||||
}
|
||||
*write = L'\0';
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
#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_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_void_archmeth, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, rarfile)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_entry_get, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, rarfile)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
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_close, arginfo_rar_void_archmeth)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MINIT_FUNCTION
|
||||
*/
|
||||
PHP_MINIT_FUNCTION(rar)
|
||||
{
|
||||
minit_rararch(TSRMLS_C);
|
||||
minit_rarentry(TSRMLS_C);
|
||||
minit_rarerror(TSRMLS_C);
|
||||
|
||||
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);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MINFO_FUNCTION
|
||||
*/
|
||||
PHP_MINFO_FUNCTION(rar)
|
||||
{
|
||||
char 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_row(2, "Revision", "$Revision$");
|
||||
|
||||
#if RARVER_BETA != 0
|
||||
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-%d-%d", RARVER_MAJOR, RARVER_MINOR,
|
||||
RARVER_PATCH, RARVER_YEAR, RARVER_MONTH, RARVER_DAY);
|
||||
#endif
|
||||
|
||||
php_info_print_table_row(2, "UnRAR version", version);
|
||||
php_info_print_table_end();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rar_module_entry
|
||||
*/
|
||||
zend_module_entry rar_module_entry = {
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
STANDARD_MODULE_HEADER,
|
||||
#endif
|
||||
"rar",
|
||||
rar_functions,
|
||||
PHP_MINIT(rar),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PHP_MINFO(rar),
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
PHP_RAR_VERSION,
|
||||
#endif
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
#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
|
||||
*/
|
||||
715
rar.cpp
715
rar.cpp
@@ -1,715 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| It's license states, that you MUST NOT use it's code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony2001@phpclub.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
}
|
||||
|
||||
#if HAVE_RAR
|
||||
|
||||
#include "php_rar.h"
|
||||
#include "unrar/rar.hpp"
|
||||
|
||||
static int le_rar_file;
|
||||
#define le_rar_file_name "Rar"
|
||||
static zend_class_entry *rar_class_entry_ptr;
|
||||
|
||||
/* {{{ internal functions protos */
|
||||
static void _rar_file_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
|
||||
static int _rar_list_files(rar_file_t * TSRMLS_DC);
|
||||
static int _rar_handle_error(int TSRMLS_DC);
|
||||
static void _rar_dos_date_to_text(int, char *);
|
||||
static void _rar_entry_to_zval(struct RARHeaderData *, zval * TSRMLS_DC);
|
||||
static zval **_rar_entry_get_property(zval *, char *, int TSRMLS_DC);
|
||||
/* }}} */
|
||||
|
||||
/* <internal> */
|
||||
|
||||
static void _rar_file_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
rar_file_t *rar = (rar_file_t *)rsrc->ptr;
|
||||
int i = 0;
|
||||
if (rar->list_data) {
|
||||
RARCloseArchive(rar->list_data);
|
||||
}
|
||||
if (rar->password) {
|
||||
efree(rar->password);
|
||||
}
|
||||
if (rar->entries && rar->entry_count) {
|
||||
for(i = 0; i < rar->entry_count; i++) {
|
||||
efree(rar->entries[i]);
|
||||
}
|
||||
efree(rar->entries);
|
||||
rar->entry_count = 0;
|
||||
}
|
||||
efree(rar->list_handle->ArcName);
|
||||
efree(rar->list_handle);
|
||||
efree(rar->extract_handle->ArcName);
|
||||
efree(rar->extract_handle);
|
||||
efree(rar);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_get_file_resource(zval **zval_file, rar_file_t **rar_file TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
*rar_file = (rar_file_t *) zend_fetch_resource(zval_file TSRMLS_CC, -1, le_rar_file_name, NULL, 1, le_rar_file);
|
||||
|
||||
if (*rar_file) {
|
||||
return 1;
|
||||
}
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find Rar file resource");
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int result = 0;
|
||||
while (result == 0) {
|
||||
struct RARHeaderData entry;
|
||||
result = RARReadHeader(rar->list_data, &entry);
|
||||
RARProcessFile(rar->list_data, RAR_OM_LIST, NULL, NULL);
|
||||
if (result == 0) {
|
||||
rar->entries = (struct RARHeaderData **)erealloc(rar->entries, sizeof(struct RARHeaderData *) * (rar->entry_count + 1));
|
||||
if (!rar->entries) {
|
||||
return FAILURE;
|
||||
}
|
||||
rar->entries[rar->entry_count] = (struct RARHeaderData *)emalloc(sizeof(struct RARHeaderData));
|
||||
memcpy(rar->entries[rar->entry_count], &entry, sizeof(struct RARHeaderData));
|
||||
rar->entry_count++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
switch (errcode) {
|
||||
case 0:
|
||||
/* no error */
|
||||
return SUCCESS;
|
||||
break;
|
||||
case ERAR_END_ARCHIVE:
|
||||
/* no error */
|
||||
return SUCCESS;
|
||||
break;
|
||||
case ERAR_NO_MEMORY:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_NO_MEMORY: not enough memory");
|
||||
break;
|
||||
case ERAR_BAD_DATA:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_DATA");
|
||||
break;
|
||||
case ERAR_BAD_ARCHIVE:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_ARCHIVE");
|
||||
break;
|
||||
case ERAR_UNKNOWN_FORMAT:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN_FORMAT");
|
||||
break;
|
||||
case ERAR_EOPEN:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EOPEN");
|
||||
break;
|
||||
case ERAR_ECREATE:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECREATE");
|
||||
break;
|
||||
case ERAR_ECLOSE:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECLOSE");
|
||||
break;
|
||||
case ERAR_EREAD:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EREAD");
|
||||
break;
|
||||
case ERAR_EWRITE:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EWRITE");
|
||||
break;
|
||||
case ERAR_SMALL_BUF:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_SMALL_BUF");
|
||||
break;
|
||||
case ERAR_UNKNOWN:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN: unknown RAR error");
|
||||
break;
|
||||
default:
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown RAR error");
|
||||
break;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
|
||||
{
|
||||
int second, minute, hour, day, month, year;
|
||||
/* following lines were taken from timefn.cpp */
|
||||
second = (dos_time & 0x1f)*2;
|
||||
minute = (dos_time>>5) & 0x3f;
|
||||
hour = (dos_time>>11) & 0x1f;
|
||||
day = (dos_time>>16) & 0x1f;
|
||||
month = (dos_time>>21) & 0x0f;
|
||||
year = (dos_time>>25)+1980;
|
||||
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void _rar_entry_to_zval(struct RARHeaderData *entry, zval *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char tmp_s [MAX_LENGTH_OF_LONG + 1];
|
||||
char time[50];
|
||||
|
||||
add_property_string(object, "name", entry->FileName, 1);
|
||||
add_property_long(object, "unpacked_size", entry->UnpSize);
|
||||
add_property_long(object, "packed_size", entry->PackSize);
|
||||
add_property_long(object, "host_os", entry->HostOS);
|
||||
|
||||
_rar_dos_date_to_text(entry->FileTime, time);
|
||||
add_property_string(object, "file_time", time, 1);
|
||||
|
||||
sprintf(tmp_s, "%lx", entry->FileCRC);
|
||||
add_property_string(object, "crc", tmp_s, 1);
|
||||
|
||||
add_property_long(object, "attr", entry->FileAttr);
|
||||
add_property_long(object, "version", entry->UnpVer);
|
||||
add_property_long(object, "method", entry->Method);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval **_rar_entry_get_property(zval *id, char *name, int namelen TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval **tmp;
|
||||
|
||||
if (zend_hash_find(Z_OBJPROP_P(id), name, namelen, (void **)&tmp) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find property %s", name);
|
||||
return NULL;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* </internal> */
|
||||
|
||||
#ifdef COMPILE_DL_RAR
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_GET_MODULE(rar)
|
||||
END_EXTERN_C()
|
||||
#endif
|
||||
|
||||
/* module functions */
|
||||
|
||||
/* {{{ proto rar_open(string filename [, string password])
|
||||
Open Rar archive and return resource */
|
||||
PHP_FUNCTION(rar_open)
|
||||
{
|
||||
zval **filename, **password;
|
||||
rar_file_t *rar = NULL;
|
||||
int ac = ZEND_NUM_ARGS(), result = 0;
|
||||
|
||||
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &filename, &password) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
convert_to_string_ex(filename);
|
||||
|
||||
if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
rar = (rar_file_t *) emalloc(sizeof(rar_file_t));
|
||||
rar->list_handle = (RAROpenArchiveData *) ecalloc(1, sizeof(RAROpenArchiveData));
|
||||
rar->list_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
|
||||
rar->list_handle->OpenMode = RAR_OM_LIST;
|
||||
rar->extract_handle = (RAROpenArchiveData *) ecalloc(1, sizeof(RAROpenArchiveData));
|
||||
rar->extract_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
|
||||
rar->extract_handle->OpenMode = RAR_OM_EXTRACT;
|
||||
rar->password = NULL;
|
||||
rar->entries = NULL;
|
||||
rar->entry_count = 0;
|
||||
|
||||
rar->list_data = RAROpenArchive(rar->list_handle);
|
||||
if (rar->list_data != NULL && rar->list_handle->OpenResult == 0) {
|
||||
if (ac == 2) {
|
||||
rar->password = estrndup(Z_STRVAL_PP(password), Z_STRLEN_PP(password));
|
||||
}
|
||||
rar->id = zend_list_insert(rar,le_rar_file);
|
||||
RETURN_RESOURCE(rar->id);
|
||||
}
|
||||
else {
|
||||
efree(rar->list_handle->ArcName);
|
||||
efree(rar->list_handle);
|
||||
efree(rar->extract_handle->ArcName);
|
||||
efree(rar->extract_handle);
|
||||
efree(rar);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto rar_list(resource rarfile)
|
||||
Return entries from the rar archive */
|
||||
PHP_FUNCTION(rar_list)
|
||||
{
|
||||
zval **file;
|
||||
rar_file_t *rar = NULL;
|
||||
int i = 0;
|
||||
int ac = ZEND_NUM_ARGS(), result = 0;
|
||||
|
||||
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (rar->entries == NULL) {
|
||||
result = _rar_list_files(rar TSRMLS_CC);
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
for (i = 0; i < rar->entry_count; i++) {
|
||||
zval *tmp;
|
||||
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
object_init_ex(tmp, rar_class_entry_ptr);
|
||||
|
||||
add_property_resource(tmp, "rarfile", rar->id);
|
||||
_rar_entry_to_zval(rar->entries[i], tmp TSRMLS_CC);
|
||||
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp, sizeof(zval*), NULL);
|
||||
}
|
||||
if (!return_value) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to list files from RAR archive");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto rar_entry_get(resource rarfile, string filename)
|
||||
Return entry from the rar archive */
|
||||
PHP_FUNCTION(rar_entry_get)
|
||||
{
|
||||
zval **file, **filename;
|
||||
rar_file_t *rar = NULL;
|
||||
int result = 0, i = 0;
|
||||
int ac = ZEND_NUM_ARGS();
|
||||
|
||||
if (ac < 2 || ac > 2 || zend_get_parameters_ex(ac, &file, &filename) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (rar->entries == NULL) {
|
||||
result = _rar_list_files(rar TSRMLS_CC);
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < rar->entry_count; i++){
|
||||
if (strcmp(rar->entries[i]->FileName, Z_STRVAL_PP(filename)) == 0) {
|
||||
object_init_ex(return_value, rar_class_entry_ptr);
|
||||
add_property_resource(return_value, "rarfile", rar->id);
|
||||
_rar_entry_to_zval(rar->entries[i], return_value TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!return_value) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find such file in RAR archive");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto rar_close(resource rarfile)
|
||||
Close Rar archive and free all resources */
|
||||
PHP_FUNCTION(rar_close)
|
||||
{
|
||||
zval **file;
|
||||
rar_file_t *rar = NULL;
|
||||
int file_counter = 0;
|
||||
int ac = ZEND_NUM_ARGS();
|
||||
|
||||
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
zend_list_delete(rar->id);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::extract(string path [, string filename ]);
|
||||
Extract file from the archive */
|
||||
PHP_METHOD(rarentry, extract)
|
||||
{
|
||||
zval **path, **filename, **tmp, **tmp_name;
|
||||
rar_file_t *rar = NULL;
|
||||
char *path_str = NULL, *extract_to_file = NULL;
|
||||
int ac = ZEND_NUM_ARGS(), resource_type = 0, result = 0, process_result = 0;
|
||||
zval *entry_obj = getThis();
|
||||
struct RARHeaderData entry;
|
||||
void *extract_data;
|
||||
|
||||
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &path, &filename) == FAILURE ) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "rarfile", sizeof("rarfile") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
rar = (rar_file_t *) zend_list_find(Z_LVAL_PP(tmp), &resource_type);
|
||||
|
||||
convert_to_string_ex(path);
|
||||
path_str = Z_STRVAL_PP(path);
|
||||
|
||||
if (Z_STRLEN_PP(path) && PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(path), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (Z_STRLEN_PP(path) && php_check_open_basedir(Z_STRVAL_PP(path) TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (ac == 2) {
|
||||
convert_to_string_ex(filename);
|
||||
extract_to_file = Z_STRVAL_PP(filename);
|
||||
|
||||
if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tmp_name = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (!rar || resource_type != le_rar_file) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Rar resource identifier not found");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
extract_data = RAROpenArchive(rar->extract_handle);
|
||||
|
||||
if (rar->extract_handle->OpenResult == 0 && extract_data != NULL) {
|
||||
if (rar->password) {
|
||||
RARSetPassword(extract_data, rar->password);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_rar_handle_error(rar->extract_handle->OpenResult TSRMLS_CC);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
while ((result = RARReadHeader(extract_data, &entry)) == 0) {
|
||||
if (strncmp(entry.FileName,Z_STRVAL_PP(tmp_name), sizeof(entry.FileName)) == 0) {
|
||||
process_result = RARProcessFile(extract_data, RAR_EXTRACT, path_str, extract_to_file);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
else {
|
||||
process_result = RARProcessFile(extract_data, RAR_SKIP, NULL, NULL);
|
||||
}
|
||||
if (_rar_handle_error(process_result TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't find file %s in archive %s", Z_STRVAL_PP(tmp_name), rar->extract_handle->ArcName);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getName();
|
||||
Return entry name */
|
||||
PHP_METHOD(rarentry, getName)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_string_ex(tmp);
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getUnpackedSize();
|
||||
Return unpacked size of the entry */
|
||||
PHP_METHOD(rarentry, getUnpackedSize)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "unpacked_size", sizeof("unpacked_size") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getPackedSize();
|
||||
Return packed size of the entry */
|
||||
PHP_METHOD(rarentry, getPackedSize)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "packed_size", sizeof("packed_size") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getHostOs();
|
||||
Return host OS of the entry */
|
||||
PHP_METHOD(rarentry, getHostOs)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "host_os", sizeof("host_os") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getFileTime();
|
||||
Return modification time of the entry */
|
||||
PHP_METHOD(rarentry, getFileTime)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "file_time", sizeof("file_time") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_string_ex(tmp);
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getCrc();
|
||||
Return CRC of the entry */
|
||||
PHP_METHOD(rarentry, getCrc)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "crc", sizeof("crc") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_string_ex(tmp);
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getAttr();
|
||||
Return attributes of the entry */
|
||||
PHP_METHOD(rarentry, getAttr)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "attr", sizeof("attr") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getVersion();
|
||||
Return version of the archiver, used to create this entry */
|
||||
PHP_METHOD(rarentry, getVersion)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "version", sizeof("version") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto RarEntry::getMethod();
|
||||
Return packing method */
|
||||
PHP_METHOD(rarentry, getMethod)
|
||||
{
|
||||
zval **tmp;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
if ((tmp = _rar_entry_get_property(entry_obj, "method", sizeof("method") TSRMLS_CC)) == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rar_functions[]
|
||||
*
|
||||
*/
|
||||
function_entry rar_functions[] = {
|
||||
PHP_FE(rar_open, NULL)
|
||||
PHP_FE(rar_list, NULL)
|
||||
PHP_FE(rar_entry_get, NULL)
|
||||
PHP_FE(rar_close, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static zend_function_entry php_rar_class_functions[] = {
|
||||
PHP_ME(rarentry, extract, NULL, 0)
|
||||
PHP_ME(rarentry, getName, NULL, 0)
|
||||
PHP_ME(rarentry, getUnpackedSize, NULL, 0)
|
||||
PHP_ME(rarentry, getPackedSize, NULL, 0)
|
||||
PHP_ME(rarentry, getHostOs, NULL, 0)
|
||||
PHP_ME(rarentry, getFileTime, NULL, 0)
|
||||
PHP_ME(rarentry, getCrc, NULL, 0)
|
||||
PHP_ME(rarentry, getAttr, NULL, 0)
|
||||
PHP_ME(rarentry, getVersion, NULL, 0)
|
||||
PHP_ME(rarentry, getMethod, NULL, 0)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MINIT_FUNCTION
|
||||
*/
|
||||
PHP_MINIT_FUNCTION(rar)
|
||||
{
|
||||
zend_class_entry rar_class_entry;
|
||||
INIT_CLASS_ENTRY(rar_class_entry, "RarEntry", php_rar_class_functions);
|
||||
rar_class_entry_ptr = zend_register_internal_class(&rar_class_entry TSRMLS_CC);
|
||||
|
||||
le_rar_file = zend_register_list_destructors_ex(_rar_file_list_dtor, NULL, le_rar_file_name, module_number);
|
||||
|
||||
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);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MINFO_FUNCTION
|
||||
*/
|
||||
PHP_MINFO_FUNCTION(rar)
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_header(2, "Rar support", "enabled");
|
||||
php_info_print_table_row(2, "Revision", "$Revision$");
|
||||
php_info_print_table_end();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rar_module_entry
|
||||
*/
|
||||
zend_module_entry rar_module_entry = {
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
STANDARD_MODULE_HEADER,
|
||||
#endif
|
||||
"rar",
|
||||
rar_functions,
|
||||
PHP_MINIT(rar),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PHP_MINFO(rar),
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
"0.1", /* Replace with version number for your extension */
|
||||
#endif
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
#endif /* HAVE_RAR */
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
233
rar_error.c
Normal file
233
rar_error.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <php.h>
|
||||
#include <zend_exceptions.h>
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Globals with external linkage */
|
||||
zend_class_entry *rarexception_ce_ptr;
|
||||
/* }}} */
|
||||
|
||||
/* Functions with external linkage {{{ */
|
||||
/* Functions with external linkage {{{ */
|
||||
int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return _rar_handle_error_ex("", errcode TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
const char *err = _rar_error_to_string(errcode);
|
||||
|
||||
if (err == NULL) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (_rar_using_exceptions(TSRMLS_C)) {
|
||||
zend_throw_exception_ex(rarexception_ce_ptr, errcode TSRMLS_CC,
|
||||
"unRAR internal error: %s%s", preamble, err);
|
||||
}
|
||||
else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s", preamble, err);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Errors not related to the unRAR library */
|
||||
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...) /* {{{ */
|
||||
{
|
||||
va_list arg;
|
||||
char *message;
|
||||
|
||||
#ifdef ZTS
|
||||
va_start(arg, TSRMLS_C);
|
||||
#else
|
||||
va_start(arg, format);
|
||||
#endif
|
||||
vspprintf(&message, 0, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (_rar_using_exceptions(TSRMLS_C))
|
||||
zend_throw_exception(rarexception_ce_ptr, message, -1L TSRMLS_CC);
|
||||
else
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
|
||||
efree(message);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int _rar_using_exceptions(TSRMLS_D)
|
||||
{
|
||||
zval *pval;
|
||||
pval = zend_read_static_property(rarexception_ce_ptr, "usingExceptions",
|
||||
sizeof("usingExceptions") -1, (zend_bool) 1 TSRMLS_CC);
|
||||
assert(Z_TYPE_P(pval) == IS_BOOL);
|
||||
|
||||
return Z_BVAL_P(pval);
|
||||
}
|
||||
|
||||
//returns a string or NULL if not an error
|
||||
const char * _rar_error_to_string(int errcode) /* {{{ */
|
||||
{
|
||||
const char *ret;
|
||||
switch (errcode) {
|
||||
case 0:
|
||||
/* no error */
|
||||
case 1:
|
||||
/* no error (comment completely read) */
|
||||
case ERAR_END_ARCHIVE:
|
||||
/* no error */
|
||||
ret = NULL;
|
||||
break;
|
||||
case ERAR_NO_MEMORY:
|
||||
ret = "ERAR_NO_MEMORY (not enough memory)";
|
||||
break;
|
||||
case ERAR_BAD_DATA:
|
||||
ret = "ERAR_BAD_DATA";
|
||||
break;
|
||||
case ERAR_BAD_ARCHIVE:
|
||||
ret = "ERAR_BAD_ARCHIVE";
|
||||
break;
|
||||
case ERAR_UNKNOWN_FORMAT:
|
||||
ret = "ERAR_UNKNOWN_FORMAT";
|
||||
break;
|
||||
case ERAR_EOPEN:
|
||||
ret = "ERAR_EOPEN (file open error)";
|
||||
break;
|
||||
case ERAR_ECREATE:
|
||||
ret = "ERAR_ECREATE";
|
||||
break;
|
||||
case ERAR_ECLOSE:
|
||||
ret = "ERAR_ECLOSE (error closing file)";
|
||||
break;
|
||||
case ERAR_EREAD:
|
||||
ret = "ERAR_EREAD";
|
||||
break;
|
||||
case ERAR_EWRITE:
|
||||
ret = "ERAR_EWRITE";
|
||||
break;
|
||||
case ERAR_SMALL_BUF:
|
||||
ret = "ERAR_SMALL_BUF";
|
||||
break;
|
||||
case ERAR_UNKNOWN:
|
||||
ret = "ERAR_UNKNOWN (unknown RAR error)";
|
||||
break;
|
||||
case ERAR_MISSING_PASSWORD:
|
||||
ret = "ERAR_MISSING_PASSWORD (password needed but not specified)";
|
||||
break;
|
||||
default:
|
||||
ret = "unknown RAR error (should not happen)";
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool RarException::setUsingExceptions(using_exceptions)
|
||||
Set whether exceptions are to be used */
|
||||
PHP_METHOD(rarexception, setUsingExceptions)
|
||||
{
|
||||
zend_bool argval;
|
||||
int result;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &argval) == FAILURE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = zend_update_static_property_bool(rarexception_ce_ptr,
|
||||
"usingExceptions", sizeof("usingExceptions") -1,
|
||||
(long) argval TSRMLS_CC);
|
||||
|
||||
if (result == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Could set error handling mode. This is a bug, please report it.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool RarException::isUsingExceptions()
|
||||
Return whether exceptions are being used */
|
||||
PHP_METHOD(rarexception, isUsingExceptions)
|
||||
{
|
||||
zval **pval;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//or zend_read_static_property, which calls zend_std_get... after chg scope
|
||||
pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
|
||||
sizeof("usingExceptions") -1, (zend_bool) 0 TSRMLS_CC);
|
||||
|
||||
//property always exists
|
||||
assert(pval != NULL);
|
||||
assert(Z_TYPE_PP(pval) == IS_BOOL);
|
||||
|
||||
RETURN_ZVAL(*pval, 0, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ arginfo */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarexception_sue, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, using_exceptions)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_rarexception_void, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
|
||||
static zend_function_entry php_rarexception_class_functions[] = {
|
||||
PHP_ME(rarexception, setUsingExceptions, arginfo_rarexception_sue, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
|
||||
PHP_ME(rarexception, isUsingExceptions, arginfo_rarexception_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
void minit_rarerror(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "RarException", php_rarexception_class_functions);
|
||||
rarexception_ce_ptr = zend_register_internal_class_ex(&ce,
|
||||
zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
|
||||
rarexception_ce_ptr->ce_flags |= ZEND_ACC_FINAL;
|
||||
zend_declare_property_bool(rarexception_ce_ptr, "usingExceptions",
|
||||
sizeof("usingExceptions") -1, 0L /* FALSE */,
|
||||
ZEND_ACC_PRIVATE | ZEND_ACC_STATIC TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
275
rar_stream.c
Normal file
275
rar_stream.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
|
||||
#if HAVE_RAR
|
||||
#ifdef ZEND_ENGINE_2
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include "php_rar.h"
|
||||
#include "unrar/rartypes.hpp"
|
||||
|
||||
#include "php_streams.h"
|
||||
/* will be needed to implement a wrapper
|
||||
* #include "ext/standard/file.h"
|
||||
* #include "ext/standard/php_string.h"
|
||||
* #include "fopen_wrappers.h"
|
||||
* #include "ext/standard/url.h"
|
||||
*/
|
||||
|
||||
typedef struct php_rar_stream_data_t {
|
||||
struct RAROpenArchiveDataEx open_data;
|
||||
struct RARHeaderDataEx header_data;
|
||||
HANDLE rar_handle;
|
||||
unsigned char *buffer;
|
||||
size_t buffer_size;
|
||||
size_t buffer_cont_size;
|
||||
size_t buffer_pos;
|
||||
uint64 cursor;
|
||||
int no_more_data;
|
||||
php_stream *stream;
|
||||
} php_rar_stream_data, *php_rar_stream_data_P;
|
||||
|
||||
#define STREAM_DATA_FROM_STREAM \
|
||||
php_rar_stream_data_P self = (php_rar_stream_data_P) stream->abstract;
|
||||
|
||||
/* {{{ php_rar_ops_read */
|
||||
static size_t php_rar_ops_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
||||
{
|
||||
int n = 0;
|
||||
STREAM_DATA_FROM_STREAM
|
||||
size_t left = count;
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
if (self->buffer != NULL && self->rar_handle != NULL) {
|
||||
while (left > 0) {
|
||||
size_t this_read_size;
|
||||
//if nothing in the buffer or buffer already read, fill buffer
|
||||
if (/*self->buffer_cont_size == 0 || > condition not necessary */
|
||||
self->buffer_pos == self->buffer_cont_size)
|
||||
{
|
||||
int res;
|
||||
self->buffer_pos = 0;
|
||||
self->buffer_cont_size = 0;
|
||||
/* Note: this condition is important, you cannot rely on
|
||||
* having a call to RARProcessFileChunk return no data and
|
||||
* break on the condition self->buffer_cont_size == 0 because
|
||||
* calling RARProcessFileChunk when there's no more data to
|
||||
* be read may cause an integer division by 0 in
|
||||
* RangeCoder::GetCurrentCount() */
|
||||
if (self->no_more_data)
|
||||
break;
|
||||
res = RARProcessFileChunk(self->rar_handle, self->buffer,
|
||||
self->buffer_size, &self->buffer_cont_size,
|
||||
&self->no_more_data);
|
||||
if (_rar_handle_error(res TSRMLS_CC) == FAILURE) {
|
||||
break; //finish in case of failure
|
||||
}
|
||||
assert(self->buffer_cont_size <= self->buffer_size);
|
||||
//we did not read anything. no need to continue
|
||||
if (self->buffer_cont_size == 0)
|
||||
break;
|
||||
}
|
||||
//if we get here we have data to be read in the buffer
|
||||
this_read_size = MIN(left,
|
||||
self->buffer_cont_size - self->buffer_pos);
|
||||
assert(this_read_size > 0);
|
||||
memcpy(&buf[count-left], &self->buffer[self->buffer_pos],
|
||||
this_read_size);
|
||||
left -= this_read_size;
|
||||
n += this_read_size;
|
||||
self->buffer_pos += this_read_size;
|
||||
assert(left >= 0);
|
||||
}
|
||||
|
||||
self->cursor += n;
|
||||
}
|
||||
|
||||
//no more data upstream and buffer already read
|
||||
if (self->no_more_data && self->buffer_pos == self->buffer_cont_size)
|
||||
stream->eof = 1;
|
||||
|
||||
if (!self->no_more_data && n == 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Extraction reported as unfinished but no data read. Please report"
|
||||
" this, as this is a bug.");
|
||||
stream->eof = 1;
|
||||
}
|
||||
|
||||
return n<1 ? 0 : n;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_rar_ops_write */
|
||||
static size_t php_rar_ops_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
|
||||
{
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Write operation not supported for RAR streams.");
|
||||
if (!stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_rar_ops_close */
|
||||
static int php_rar_ops_close(php_stream *stream, int close_handle TSRMLS_DC)
|
||||
{
|
||||
STREAM_DATA_FROM_STREAM
|
||||
|
||||
if (close_handle) {
|
||||
if (self->open_data.ArcName != NULL) {
|
||||
efree(self->open_data.ArcName);
|
||||
self->open_data.ArcName = NULL;
|
||||
}
|
||||
if (self->buffer != NULL) {
|
||||
efree(self->buffer);
|
||||
self->buffer = NULL;
|
||||
}
|
||||
if (self->rar_handle != NULL) {
|
||||
int res = RARCloseArchive(self->rar_handle);
|
||||
if (_rar_handle_error(res TSRMLS_CC) == FAILURE) {
|
||||
; //not much we can do...
|
||||
}
|
||||
self->rar_handle = NULL;
|
||||
}
|
||||
}
|
||||
efree(self);
|
||||
stream->abstract = NULL;
|
||||
return EOF;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_rar_ops_flush */
|
||||
static int php_rar_ops_flush(php_stream *stream TSRMLS_DC)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
php_stream_ops php_stream_rario_ops = {
|
||||
php_rar_ops_write, php_rar_ops_read,
|
||||
php_rar_ops_close, php_rar_ops_flush,
|
||||
"rar",
|
||||
NULL, /* seek */
|
||||
NULL, /* cast */
|
||||
NULL, /* stat */
|
||||
NULL /* set_option */
|
||||
};
|
||||
|
||||
/* {{{ php_stream_rar_open */
|
||||
php_stream *php_stream_rar_open(char *arc_name,
|
||||
char *utf_file_name,
|
||||
char *password,
|
||||
char *mode STREAMS_DC TSRMLS_DC)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_rar_stream_data_P self = NULL;
|
||||
int result,
|
||||
found;
|
||||
|
||||
if (strncmp(mode, "r", strlen("r")) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
self = ecalloc(1, sizeof *self);
|
||||
self->open_data.ArcName = estrdup(arc_name);
|
||||
self->open_data.OpenMode = RAR_OM_EXTRACT;
|
||||
|
||||
result = _rar_find_file(&self->open_data, utf_file_name, password,
|
||||
&self->rar_handle, &found, &self->header_data);
|
||||
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
_rar_handle_ext_error("Can't find file %s in archive %s" TSRMLS_CC,
|
||||
utf_file_name, arc_name);
|
||||
|
||||
{
|
||||
//no need to allocate a buffer bigger than the file uncomp size
|
||||
size_t buffer_size = (size_t)
|
||||
MIN((uint64) RAR_CHUNK_BUFFER_SIZE,
|
||||
INT32TO64(self->header_data.UnpSizeHigh,
|
||||
self->header_data.UnpSize));
|
||||
int process_result = RARProcessFileChunkInit(self->rar_handle);
|
||||
|
||||
if (_rar_handle_error(process_result TSRMLS_CC) == FAILURE) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
self->buffer = emalloc(buffer_size);
|
||||
self->buffer_size = buffer_size;
|
||||
stream = php_stream_alloc(&php_stream_rario_ops, self, NULL, mode);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (stream == NULL) { //failed
|
||||
if (self != NULL) {
|
||||
if (self->open_data.ArcName != NULL)
|
||||
efree(self->open_data.ArcName);
|
||||
if (self->buffer != NULL)
|
||||
efree(self->buffer);
|
||||
if (self->rar_handle != NULL)
|
||||
RARCloseArchive(self->rar_handle);
|
||||
efree(self);
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
/* }}} */
|
||||
#endif /* ZEND_ENGINE_2 */
|
||||
#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
|
||||
*/
|
||||
812
rararch.c
Normal file
812
rararch.c
Normal file
@@ -0,0 +1,812 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <php.h>
|
||||
#include <zend_interfaces.h>
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Type definitions reserved for this translation unit */
|
||||
typedef struct _ze_rararch_object {
|
||||
zend_object parent;
|
||||
rar_file_t *rar_file;
|
||||
} ze_rararch_object;
|
||||
|
||||
typedef struct _rararch_iterator {
|
||||
zend_object_iterator parent;
|
||||
int index; /* index in RARHeaderEx array */
|
||||
zval *value;
|
||||
} rararch_iterator;
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Globals with internal linkage */
|
||||
static zend_class_entry *rararch_ce_ptr;
|
||||
static zend_object_handlers rararch_object_handlers;
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Function prototypes for functions with internal linkage */
|
||||
static int _rar_list_files(rar_file_t * TSRMLS_DC);
|
||||
static int _rar_raw_entries_to_files(rar_file_t *rar,
|
||||
const wchar_t * const file, //can be NULL
|
||||
int *index,
|
||||
zval *target TSRMLS_DC);
|
||||
static zend_object_value rararch_ce_create_object(zend_class_entry *class_type TSRMLS_DC);
|
||||
static void rararch_ce_destroy_object(ze_rararch_object *object,
|
||||
zend_object_handle handle TSRMLS_DC);
|
||||
static void rararch_ce_free_object_storage(ze_rararch_object *object TSRMLS_DC);
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Function definitions with external linkage */
|
||||
int _rar_get_file_resource(zval *zval_file, rar_file_t **rar_file TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return _rar_get_file_resource_ex(zval_file, rar_file, FALSE TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Receives archive zval, returns object struct.
|
||||
* If silent is FALSE, it checks whether the archive is alredy closed, and if it
|
||||
* is, an exception/error is raised and 0 is returned
|
||||
*/
|
||||
int _rar_get_file_resource_ex(zval *zval_file, rar_file_t **rar_file, int silent TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
ze_rararch_object *zobj;
|
||||
zobj = zend_object_store_get_object(zval_file TSRMLS_CC);
|
||||
if (zobj == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Could not find object in the store. This is a bug, please report it.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*rar_file = zobj->rar_file;
|
||||
if ((*rar_file)->arch_handle == NULL && !silent) { //rar_close was called
|
||||
_rar_handle_ext_error("The archive is already closed." TSRMLS_CC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Helper functions and preprocessor definitions */
|
||||
static int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
int result = 0;
|
||||
int capacity = 0;
|
||||
while (result == 0) {
|
||||
struct RARHeaderDataEx entry;
|
||||
result = RARReadHeaderEx(rar->arch_handle, &entry);
|
||||
//value of 2nd argument is irrelevant in RAR_OM_LIST_[SPLIT] mode
|
||||
if (result == 0) {
|
||||
result = RARProcessFile(rar->arch_handle, RAR_SKIP, NULL, NULL);
|
||||
}
|
||||
if (result == 0) {
|
||||
assert(capacity >= rar->entry_count);
|
||||
if (capacity == rar->entry_count) { //0, 2, 6, 14, 30...
|
||||
capacity = (capacity + 1) * 2;
|
||||
rar->entries = erealloc(rar->entries,
|
||||
sizeof(*rar->entries) * capacity);
|
||||
if (!rar->entries)
|
||||
return FAILURE;
|
||||
}
|
||||
assert(capacity > rar->entry_count);
|
||||
rar->entries[rar->entry_count] = emalloc(sizeof(*rar->entries[0]));
|
||||
memcpy(rar->entries[rar->entry_count], &entry,
|
||||
sizeof *rar->entries[0]);
|
||||
rar->entry_count++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int _rar_raw_entries_to_files(rar_file_t *rar,
|
||||
const wchar_t * const file, //can be NULL
|
||||
int *index, //start index, can be NULL
|
||||
zval *target //array or initialized object zval
|
||||
TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
wchar_t last_name[1024] = {L'\0'};
|
||||
char strict_last_name[1024] = {'\0'};
|
||||
unsigned long packed_size = 0UL;
|
||||
struct RARHeaderDataEx *last_entry = NULL;
|
||||
int any_commit = FALSE;
|
||||
int first_file_check = (index == NULL) || (*index == 0);
|
||||
int target_is_obj = (file != NULL || index != NULL);
|
||||
int i;
|
||||
|
||||
assert(rar->entry_count == 0 || rar->entries != NULL);
|
||||
for (i = (index == NULL ? 0 : *index); i <= rar->entry_count; i++) {
|
||||
struct RARHeaderDataEx *entry;
|
||||
const wchar_t *current_name;
|
||||
const char *strict_current_name;
|
||||
int read_entry = (i != rar->entry_count); //whether we have a new entry this iteration
|
||||
int ended_file = FALSE; //whether we've seen a file and entries for the that file have ended
|
||||
int commit_file = FALSE; //whether we are creating a new zval
|
||||
int has_last_entry = (*strict_last_name != '\0'); //whether we had an entry last iteration
|
||||
|
||||
if (read_entry) {
|
||||
entry = rar->entries[i];
|
||||
current_name = entry->FileNameW;
|
||||
strict_current_name = entry->FileName;
|
||||
|
||||
/* If file is continued from previous volume, skip it, as otherwise
|
||||
* incorrect packed and unpacked sizes would be returned */
|
||||
if (first_file_check) {
|
||||
if (entry->Flags & 0x01)
|
||||
continue;
|
||||
else
|
||||
first_file_check = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* The wide file name may result from conversion from the
|
||||
* non-wide filename and this conversion may fail. In that
|
||||
* case, we can have entries of different files with the
|
||||
* the same wide file name. For this reason, we use the
|
||||
* non-wide file name to check if we have a new file and
|
||||
* don't trust the wide file name. */
|
||||
ended_file = has_last_entry && (!read_entry ||
|
||||
(strncmp(strict_last_name, strict_current_name, 1024) != 0));
|
||||
commit_file = ended_file && (index != NULL || file == NULL ||
|
||||
(file != NULL && wcsncmp(last_name, file, 1024) == 0));
|
||||
|
||||
if (commit_file) { //this entry corresponds to a new file
|
||||
zval *entry_obj,
|
||||
*rararch_obj;
|
||||
|
||||
/* guaranteed by commit_file = ended_file &&...
|
||||
* with ended_file = has_last_entry && ...
|
||||
* with has_last_entry = (last_name != NULL)
|
||||
* and last_entry is set when last_name is set */
|
||||
assert(last_entry != NULL);
|
||||
|
||||
any_commit = TRUE; //at least one commit done
|
||||
|
||||
//take care of last entry
|
||||
/* if target_is_obj, assume target is a zval that will hold the
|
||||
* entry, otherwise assume it is a numerical array */
|
||||
if (!target_is_obj) {
|
||||
MAKE_STD_ZVAL(entry_obj);
|
||||
}
|
||||
else
|
||||
entry_obj = target;
|
||||
|
||||
//create RarEntry object:
|
||||
object_init_ex(entry_obj, rar_class_entry_ptr);
|
||||
|
||||
//rararch property:
|
||||
MAKE_STD_ZVAL(rararch_obj);
|
||||
Z_TYPE_P(rararch_obj) = IS_OBJECT;
|
||||
Z_OBJ_HANDLE_P(rararch_obj) = rar->id;
|
||||
Z_OBJ_HT_P(rararch_obj) = &rararch_object_handlers;
|
||||
zend_update_property(rar_class_entry_ptr, entry_obj, "rarfile",
|
||||
sizeof("rararch") - 1, rararch_obj TSRMLS_CC);
|
||||
/* zend_update_property calls write_property handler, which
|
||||
* increments the refcount. We must decrease it here */
|
||||
zval_ptr_dtor(&rararch_obj); //restore refcount to 1
|
||||
/* to avoid destruction of the object due to refcount hitting
|
||||
* 0 when this new object zval we created is destroyed */
|
||||
zend_objects_store_add_ref_by_handle(rar->id TSRMLS_CC);
|
||||
|
||||
//remaining properties:
|
||||
_rar_entry_to_zval(last_entry, entry_obj, packed_size TSRMLS_CC);
|
||||
if (!target_is_obj) //target is an array, add to it
|
||||
add_next_index_zval(target, entry_obj);
|
||||
else
|
||||
break; //we're done
|
||||
}
|
||||
|
||||
if (ended_file) {
|
||||
packed_size = 0UL; //reset counter
|
||||
}
|
||||
|
||||
if (read_entry) { //sum packed size of current entry
|
||||
//we would exceed size of ulong. cap at ulong_max
|
||||
if (ULONG_MAX - packed_size < entry->PackSize)
|
||||
packed_size = ULONG_MAX;
|
||||
else {
|
||||
packed_size += entry->PackSize;
|
||||
if (entry->UnpSizeHigh != 0) {
|
||||
if (sizeof(unsigned long) >= 8) {
|
||||
packed_size += ((unsigned long) entry->UnpSizeHigh) << 32;
|
||||
}
|
||||
else {
|
||||
packed_size = ULONG_MAX; //cap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//prepare for next entry
|
||||
last_entry = entry;
|
||||
wcsncpy(last_name, current_name, 1024);
|
||||
strncpy(strict_last_name, strict_current_name, 1024);
|
||||
}
|
||||
}
|
||||
|
||||
if (index != NULL)
|
||||
*index = i;
|
||||
|
||||
return any_commit;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value rararch_ce_create_object(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object_value zov;
|
||||
ze_rararch_object *zobj;
|
||||
zval *tmp;
|
||||
|
||||
zobj = emalloc(sizeof *zobj);
|
||||
zend_object_std_init((zend_object*) zobj, class_type TSRMLS_CC);
|
||||
|
||||
zend_hash_copy(((zend_object*)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) rararch_ce_destroy_object,
|
||||
(zend_objects_free_object_storage_t) rararch_ce_free_object_storage,
|
||||
NULL TSRMLS_CC);
|
||||
zov.handlers = &rararch_object_handlers;
|
||||
return zov;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void rararch_ce_destroy_object(ze_rararch_object *object,
|
||||
zend_object_handle handle TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
rar_file_t *rar = object->rar_file;
|
||||
|
||||
//not really relevant, calls destr. zend func. ce->destructor if it exists
|
||||
zend_objects_destroy_object((zend_object*) object, handle TSRMLS_CC);
|
||||
|
||||
if (rar->arch_handle != NULL) {
|
||||
RARCloseArchive(rar->arch_handle);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void rararch_ce_free_object_storage(ze_rararch_object *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
rar_file_t *rar = object->rar_file;
|
||||
int i;
|
||||
|
||||
if (rar->password != NULL) {
|
||||
efree(rar->password);
|
||||
}
|
||||
if ((rar->entries != NULL) && (rar->entry_count > 0)) {
|
||||
for (i = 0; i < rar->entry_count; i++) {
|
||||
efree(rar->entries[i]);
|
||||
}
|
||||
efree(rar->entries);
|
||||
rar->entry_count = 0;
|
||||
}
|
||||
efree(rar->list_open_data->ArcName);
|
||||
efree(rar->list_open_data->CmtBuf);
|
||||
efree(rar->list_open_data);
|
||||
efree(rar->extract_open_data->ArcName);
|
||||
efree(rar->extract_open_data);
|
||||
efree(rar);
|
||||
|
||||
/* could call zend_objects_free_object_storage here (not before!), but
|
||||
* instead I'll mimic its behaviour */
|
||||
zend_object_std_dtor((zend_object*) object TSRMLS_CC);
|
||||
efree(object);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Missing function in VC6 */
|
||||
#if !HAVE_STRNLEN
|
||||
static size_t strnlen(const char *s, size_t maxlen) /* {{{ */
|
||||
{
|
||||
char *r = memchr(s, '\0', maxlen);
|
||||
return r ? r-s : maxlen;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
/* module functions */
|
||||
|
||||
/* {{{ proto RarArchive rar_open(string filename [, string password])
|
||||
Open RAR archive and return RarArchive object */
|
||||
PHP_FUNCTION(rar_open)
|
||||
{
|
||||
char *filename;
|
||||
char *password = NULL;
|
||||
char resolved_path[MAXPATHLEN];
|
||||
int filename_len;
|
||||
int password_len = 0;
|
||||
rar_file_t *rar = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename,
|
||||
&filename_len, &password, &password_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (OPENBASEDIR_CHECKPATH(filename)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
rar = emalloc(sizeof *rar);
|
||||
rar->list_open_data = ecalloc(1, sizeof *rar->list_open_data);
|
||||
rar->list_open_data->ArcName = estrndup(resolved_path,
|
||||
strnlen(resolved_path, MAXPATHLEN));
|
||||
rar->list_open_data->OpenMode = RAR_OM_LIST_INCSPLIT;
|
||||
rar->list_open_data->CmtBuf = ecalloc(RAR_MAX_COMMENT_SIZE, 1);
|
||||
rar->list_open_data->CmtBufSize = RAR_MAX_COMMENT_SIZE;
|
||||
rar->extract_open_data = ecalloc(1, sizeof *rar->extract_open_data);
|
||||
rar->extract_open_data->ArcName = estrndup(resolved_path,
|
||||
strnlen(resolved_path, MAXPATHLEN));
|
||||
rar->extract_open_data->OpenMode = RAR_OM_EXTRACT;
|
||||
rar->extract_open_data->CmtBuf = NULL; //not interested in it again
|
||||
rar->password = NULL;
|
||||
rar->entries = NULL;
|
||||
rar->entry_count = 0;
|
||||
|
||||
rar->arch_handle = RAROpenArchiveEx(rar->list_open_data);
|
||||
if (rar->arch_handle != NULL && rar->list_open_data->OpenResult == 0) {
|
||||
if (password_len > 0) {
|
||||
rar->password = estrndup(password, password_len);
|
||||
}
|
||||
//rar->id = ZEND_REGISTER_RESOURCE(return_value, rar, le_rar_file);
|
||||
object_init_ex(return_value, rararch_ce_ptr);
|
||||
{
|
||||
ze_rararch_object *zobj =
|
||||
zend_object_store_get_object(return_value TSRMLS_CC);
|
||||
zobj->rar_file = rar;
|
||||
}
|
||||
rar->id = Z_OBJ_HANDLE_P(return_value);
|
||||
} else {
|
||||
const char *err_str = _rar_error_to_string(rar->list_open_data->OpenResult);
|
||||
if (err_str == NULL)
|
||||
_rar_handle_ext_error("%s" TSRMLS_CC, "Archive opened failed "
|
||||
"(returned NULL handle), but did not return an error. "
|
||||
"Should not happen.");
|
||||
else {
|
||||
char *preamble;
|
||||
spprintf(&preamble, 0, "Failed to open %s: ", filename);
|
||||
_rar_handle_error_ex(preamble,
|
||||
rar->list_open_data->OpenResult TSRMLS_CC);
|
||||
efree(preamble);
|
||||
}
|
||||
efree(rar->list_open_data->ArcName);
|
||||
efree(rar->list_open_data->CmtBuf);
|
||||
efree(rar->list_open_data);
|
||||
efree(rar->extract_open_data->ArcName);
|
||||
efree(rar->extract_open_data);
|
||||
efree(rar);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
RARSetCallback(rar->arch_handle, _rar_unrar_callback, (LPARAM) rar->password);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array rar_list(RarArchive rarfile)
|
||||
Return entries from the rar archive */
|
||||
PHP_FUNCTION(rar_list)
|
||||
{
|
||||
zval *file = getThis();
|
||||
rar_file_t *rar = NULL;
|
||||
int result;
|
||||
|
||||
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
|
||||
&file, rararch_ce_ptr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (rar->entries == NULL) {
|
||||
result = _rar_list_files(rar TSRMLS_CC);
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
_rar_raw_entries_to_files(rar, NULL, NULL, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto object rar_entry_get(RarArchive rarfile, string filename)
|
||||
Return entry from the rar archive */
|
||||
PHP_FUNCTION(rar_entry_get)
|
||||
{
|
||||
zval *file = getThis();
|
||||
char *filename;
|
||||
rar_file_t *rar = NULL;
|
||||
int result;
|
||||
int found;
|
||||
int filename_len;
|
||||
wchar_t *filename_c = NULL;
|
||||
|
||||
if (file == NULL) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os",
|
||||
&file, rararch_ce_ptr, &filename, &filename_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
|
||||
&filename, &filename_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (rar->entries == NULL) {
|
||||
result = _rar_list_files(rar TSRMLS_CC);
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
filename_c = ecalloc(filename_len + 1, sizeof *filename_c);
|
||||
_rar_utf_to_wide(filename, filename_c, filename_len + 1);
|
||||
|
||||
found = _rar_raw_entries_to_files(rar, filename_c, NULL, return_value
|
||||
TSRMLS_CC);
|
||||
if (!found) {
|
||||
_rar_handle_ext_error(
|
||||
"cannot find file \"%s\" in Rar archive \"%s\"."
|
||||
TSRMLS_CC, filename, rar->list_open_data->ArcName);
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
|
||||
efree(filename_c);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string rar_solid_is(RarArchive rarfile)
|
||||
Return whether RAR archive is solid */
|
||||
PHP_FUNCTION(rar_solid_is)
|
||||
{
|
||||
zval *file = getThis();
|
||||
rar_file_t *rar = NULL;
|
||||
|
||||
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
|
||||
&file, rararch_ce_ptr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_BOOL((rar->list_open_data->Flags & 0x0008) != 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string rar_comment_get(RarArchive rarfile)
|
||||
Return comment of the rar archive */
|
||||
PHP_FUNCTION(rar_comment_get)
|
||||
{
|
||||
zval *file = getThis();
|
||||
rar_file_t *rar = NULL;
|
||||
unsigned cmt_state;
|
||||
|
||||
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
|
||||
&file, rararch_ce_ptr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
cmt_state = rar->list_open_data->CmtState;
|
||||
|
||||
if (_rar_handle_error(cmt_state TSRMLS_CC) == FAILURE)
|
||||
RETURN_FALSE;
|
||||
|
||||
if (cmt_state == 0) //comment not present
|
||||
RETURN_NULL(); //oddly, requires ()
|
||||
|
||||
if (cmt_state == 1) { //comment read completely
|
||||
//CmtSize - 1 because we don't need the null terminator
|
||||
RETURN_STRINGL(rar->list_open_data->CmtBuf,
|
||||
rar->list_open_data->CmtSize - 1, 1);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool rar_close(RarArchive rarfile)
|
||||
Close Rar archive and free all resources */
|
||||
PHP_FUNCTION(rar_close)
|
||||
{
|
||||
zval *file = getThis();
|
||||
rar_file_t *rar = NULL;
|
||||
|
||||
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
|
||||
&file, rararch_ce_ptr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
//zend_hash_index_del(&EG(regular_list), Z_RESVAL_P(file));
|
||||
/* When changed from resource to custom object, instead of fiddling
|
||||
* with the refcount to force object destruction, an indication that
|
||||
* the file is already closed is given by setting rar->arch_handle
|
||||
* to NULL. This is checked by _rar_get_file_resource. */
|
||||
RARCloseArchive(rar->arch_handle);
|
||||
rar->arch_handle = NULL;
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::__toString()
|
||||
Return string representation for entry */
|
||||
PHP_METHOD(rararch, __toString)
|
||||
{
|
||||
zval *arch_obj = getThis();
|
||||
rar_file_t *rar = NULL;
|
||||
const char format[] = "RAR Archive \"%s\"%s",
|
||||
closed[] = " (closed)";
|
||||
char *restring;
|
||||
int restring_len,
|
||||
is_closed;
|
||||
|
||||
if (!_rar_get_file_resource_ex(arch_obj, &rar, TRUE TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
is_closed = (rar->arch_handle == NULL);
|
||||
|
||||
//2 is size of %s, 1 is terminating 0
|
||||
restring_len = (sizeof(format) - 1) - 2 * 2 + 1;
|
||||
restring_len += strlen(rar->list_open_data->ArcName);
|
||||
if (is_closed)
|
||||
restring_len += sizeof(closed) - 1;
|
||||
|
||||
restring = emalloc(restring_len);
|
||||
snprintf(restring, restring_len, format, rar->list_open_data->ArcName,
|
||||
is_closed?closed:"");
|
||||
restring[restring_len - 1] = '\0'; //just to be safe
|
||||
|
||||
RETURN_STRING(restring, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ arginfo */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rararchive_open, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rararchive_getentry, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_rararchive_void, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
|
||||
static zend_function_entry php_rararch_class_functions[] = {
|
||||
PHP_ME_MAPPING(open, rar_open, arginfo_rararchive_open, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(getEntries, rar_list, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(getEntry, rar_entry_get, arginfo_rararchive_getentry, ZEND_ACC_PUBLIC)
|
||||
#ifdef RAR_ARCHIVE_LIST_ALIAS
|
||||
PHP_ME_MAPPING(list, rar_list, arginfo_rararchive_void, ZEND_ACC_PUBLIC | ZEND_ACC_DEPRECATED)
|
||||
#endif
|
||||
PHP_ME_MAPPING(isSolid, rar_solid_is, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(getComment, rar_comment_get, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(close, rar_close, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rararch, __toString, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(__construct, rar_bogus_ctor, arginfo_rararchive_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* {{{ Iteration. Very boring stuff indeed. */
|
||||
|
||||
/* {{{ Iteration Prototypes */
|
||||
static zend_object_iterator *rararch_it_get_iterator(zend_class_entry *ce,
|
||||
zval *object,
|
||||
int by_ref TSRMLS_DC);
|
||||
static void rararch_it_delete_cache(zend_object_iterator *iter TSRMLS_DC);
|
||||
static void rararch_it_dtor(zend_object_iterator *iter TSRMLS_DC);
|
||||
static void rararch_it_fetch(rararch_iterator *it TSRMLS_DC);
|
||||
static int rararch_it_valid(zend_object_iterator *iter TSRMLS_DC);
|
||||
static void rararch_it_current_data(zend_object_iterator *iter,
|
||||
zval ***data TSRMLS_DC);
|
||||
static void rararch_it_move_forward(zend_object_iterator *iter TSRMLS_DC);
|
||||
static void rararch_it_rewind(zend_object_iterator *iter TSRMLS_DC);
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_get_iterator */
|
||||
static zend_object_iterator *rararch_it_get_iterator(zend_class_entry *ce,
|
||||
zval *object,
|
||||
int by_ref TSRMLS_DC)
|
||||
{
|
||||
rararch_iterator *it;
|
||||
rar_file_t *rar;
|
||||
int res;
|
||||
|
||||
if (by_ref) {
|
||||
zend_error(E_ERROR,
|
||||
"An iterator cannot be used with foreach by reference");
|
||||
}
|
||||
|
||||
it = emalloc(sizeof *it);
|
||||
|
||||
res = _rar_get_file_resource_ex(object, &rar, 1 TSRMLS_CC);
|
||||
if (!res)
|
||||
zend_error(E_ERROR, "Cannot fetch RarArchive object");
|
||||
if (rar->arch_handle == NULL)
|
||||
zend_error(E_ERROR, "The archive is already closed, "
|
||||
"cannot give an iterator");
|
||||
if (rar->entries == NULL) {
|
||||
res = _rar_list_files(rar TSRMLS_CC);
|
||||
if (_rar_handle_error(res TSRMLS_CC) == FAILURE) {
|
||||
rar->entry_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
zval_add_ref(&object);
|
||||
it->parent.data = object;
|
||||
it->parent.funcs = ce->iterator_funcs.funcs;
|
||||
it->index = 0;
|
||||
it->value = NULL;
|
||||
return (zend_object_iterator*) it;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_invalidate_current */
|
||||
static void rararch_it_invalidate_current(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
rararch_iterator *it = (rararch_iterator *) iter;
|
||||
if (it->value != NULL) {
|
||||
zval_ptr_dtor(&it->value);
|
||||
it->value = NULL;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_dtor */
|
||||
static void rararch_it_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
rararch_iterator *it = (rararch_iterator *) iter;
|
||||
|
||||
rararch_it_invalidate_current((zend_object_iterator *) it TSRMLS_CC);
|
||||
|
||||
zval_ptr_dtor((zval**) &it->parent.data); /* decrease refcount on zval object */
|
||||
efree(it);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_fetch - populates it->current */
|
||||
static void rararch_it_fetch(rararch_iterator *it TSRMLS_DC)
|
||||
{
|
||||
rar_file_t *rar_file;
|
||||
int res;
|
||||
|
||||
assert(it->value == NULL);
|
||||
MAKE_STD_ZVAL(it->value);
|
||||
|
||||
res = _rar_get_file_resource_ex(it->parent.data, &rar_file, 1 TSRMLS_CC);
|
||||
if (!res)
|
||||
zend_error(E_ERROR, "Cannot fecth RarArchive object");
|
||||
|
||||
res = _rar_raw_entries_to_files(rar_file, NULL, &it->index, it->value
|
||||
TSRMLS_CC);
|
||||
if (!res)
|
||||
ZVAL_FALSE(it->value);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_valid */
|
||||
static int rararch_it_valid(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
zval *value = ((rararch_iterator *) iter)->value;
|
||||
assert(value != NULL);
|
||||
return (Z_TYPE_P(value) != IS_BOOL)?SUCCESS:FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_current_data */
|
||||
static void rararch_it_current_data(zend_object_iterator *iter,
|
||||
zval ***data TSRMLS_DC)
|
||||
{
|
||||
zval **value = &(((rararch_iterator *) iter)->value);
|
||||
assert(*value != NULL);
|
||||
*data = value;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_move_forward */
|
||||
static void rararch_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
rararch_iterator *it = (rararch_iterator *) iter;
|
||||
rararch_it_invalidate_current((zend_object_iterator *) it TSRMLS_CC);
|
||||
it->value = NULL;
|
||||
rararch_it_fetch(it TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ rararch_it_rewind */
|
||||
static void rararch_it_rewind(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
rararch_iterator *it = (rararch_iterator *) iter;
|
||||
rararch_it_invalidate_current((zend_object_iterator *) it TSRMLS_CC);
|
||||
it->index = 0;
|
||||
it->value = NULL;
|
||||
rararch_it_fetch(it TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* iterator handler table */
|
||||
static zend_object_iterator_funcs rararch_it_funcs = {
|
||||
rararch_it_dtor,
|
||||
rararch_it_valid,
|
||||
rararch_it_current_data,
|
||||
NULL,
|
||||
rararch_it_move_forward,
|
||||
rararch_it_rewind,
|
||||
rararch_it_invalidate_current
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
void minit_rararch(TSRMLS_D)
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
memcpy(&rararch_object_handlers, zend_get_std_object_handlers(),
|
||||
sizeof rararch_object_handlers);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "RarArchive", php_rararch_class_functions);
|
||||
rararch_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
|
||||
rararch_ce_ptr->ce_flags |= ZEND_ACC_FINAL_CLASS;
|
||||
rararch_ce_ptr->clone = NULL;
|
||||
rararch_ce_ptr->create_object = &rararch_ce_create_object;
|
||||
rararch_ce_ptr->get_iterator = rararch_it_get_iterator;
|
||||
rararch_ce_ptr->iterator_funcs.funcs = &rararch_it_funcs;
|
||||
zend_class_implements(rararch_ce_ptr TSRMLS_CC, 1, zend_ce_traversable);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
649
rarentry.c
Normal file
649
rarentry.c
Normal file
@@ -0,0 +1,649 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2009 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
| |
|
||||
| **** WARNING **** |
|
||||
| |
|
||||
| This module makes use of unRAR - free utility for RAR archives. |
|
||||
| Its license states that you MUST NOT use its code to develop |
|
||||
| a RAR (WinRAR) compatible archiver. |
|
||||
| Please, read unRAR license for full information. |
|
||||
| unRAR & RAR copyrights are owned by Eugene Roshal |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Antony Dovgal <tony@daylessday.org> |
|
||||
| Author: Gustavo Lopes <cataphract@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Globals with external linkage */
|
||||
zend_class_entry *rar_class_entry_ptr;
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Globals with internal linkage */
|
||||
static zend_object_handlers rarentry_object_handlers;
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Function prototypes for functions with internal linkage */
|
||||
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
|
||||
int name_length, char *doc_comment,
|
||||
int doc_comment_len TSRMLS_DC);
|
||||
static zval **_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC);
|
||||
static void _rar_dos_date_to_text(int dos_time, char *date_string);
|
||||
static zend_object_value rarentry_ce_create_object(zend_class_entry *class_type TSRMLS_DC);
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Functions with external linkage */
|
||||
/* should be passed the last entry that corresponds to a given file
|
||||
* only that one has the correct CRC. Still, it may have a wrong packedSize */
|
||||
void _rar_entry_to_zval(struct RARHeaderDataEx *entry, zval *object,
|
||||
unsigned long packed_size TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char tmp_s [MAX_LENGTH_OF_LONG + 1];
|
||||
char time[50];
|
||||
char *filename;
|
||||
long unp_size;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
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
|
||||
* zend_update_property_x updates the scope accordingly */
|
||||
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, "%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",
|
||||
sizeof("version") - 1, entry->UnpVer TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "method",
|
||||
sizeof("method") - 1, entry->Method TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "flags",
|
||||
sizeof("flags") - 1, entry->Flags TSRMLS_CC);
|
||||
|
||||
efree(filename);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Helper functions and preprocessor definitions */
|
||||
#define RAR_GET_PROPERTY(var, prop_name) \
|
||||
if (!entry_obj) { \
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "this method cannot be called statically"); \
|
||||
RETURN_FALSE; \
|
||||
} \
|
||||
if ((var = _rar_entry_get_property(entry_obj, prop_name, sizeof(prop_name) TSRMLS_CC)) == NULL) { \
|
||||
RETURN_FALSE; \
|
||||
}
|
||||
|
||||
#define REG_RAR_CLASS_CONST_LONG(const_name, value) \
|
||||
zend_declare_class_constant_long(rar_class_entry_ptr, const_name, \
|
||||
sizeof(const_name) - 1, (long) value TSRMLS_CC)
|
||||
|
||||
#define REG_RAR_PROPERTY(name, comment) \
|
||||
_rar_decl_priv_prop_null(rar_class_entry_ptr, name, sizeof(name) -1, \
|
||||
comment, sizeof(comment) - 1 TSRMLS_CC)
|
||||
|
||||
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
|
||||
int name_length, char *doc_comment,
|
||||
int doc_comment_len TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval *property;
|
||||
ALLOC_PERMANENT_ZVAL(property);
|
||||
INIT_ZVAL(*property);
|
||||
return zend_declare_property_ex(ce, name, name_length, property,
|
||||
ZEND_ACC_PRIVATE, doc_comment, doc_comment_len TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval **_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval **tmp;
|
||||
char *mangled_name;
|
||||
int mangled_name_len;
|
||||
|
||||
//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;
|
||||
}
|
||||
efree(mangled_name);
|
||||
return tmp;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
|
||||
{
|
||||
int second, minute, hour, day, month, year;
|
||||
/* following lines were taken from timefn.cpp */
|
||||
second = (dos_time & 0x1f)*2;
|
||||
minute = (dos_time>>5) & 0x3f;
|
||||
hour = (dos_time>>11) & 0x1f;
|
||||
day = (dos_time>>16) & 0x1f;
|
||||
month = (dos_time>>21) & 0x0f;
|
||||
year = (dos_time>>25)+1980;
|
||||
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_object_value rarentry_ce_create_object(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_object_value zov;
|
||||
zend_object *zobj;
|
||||
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 ]])
|
||||
Extract file from the archive */
|
||||
PHP_METHOD(rarentry, extract)
|
||||
{ //lots of variables, but no need to be intimidated
|
||||
char *dir,
|
||||
*filepath = NULL,
|
||||
*password = NULL;
|
||||
int dir_len,
|
||||
filepath_len = 0,
|
||||
password_len = 0;
|
||||
char *considered_path;
|
||||
char considered_path_res[MAXPATHLEN];
|
||||
int with_second_arg;
|
||||
|
||||
zval **tmp,
|
||||
**tmp_name;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
struct RARHeaderDataEx entry;
|
||||
HANDLE extract_handle = NULL;
|
||||
int result;
|
||||
int found;
|
||||
|
||||
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)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* Decide where to extract */
|
||||
with_second_arg = (filepath_len != 0);
|
||||
|
||||
//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
|
||||
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_name, "name");
|
||||
|
||||
if (password == NULL)
|
||||
password = rar->password; //use rar_open password by default
|
||||
|
||||
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;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
_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;
|
||||
}
|
||||
|
||||
/* Do extraction */
|
||||
if (!with_second_arg)
|
||||
result = RARProcessFile(extract_handle, RAR_EXTRACT,
|
||||
considered_path_res, NULL);
|
||||
else
|
||||
result = RARProcessFile(extract_handle, RAR_EXTRACT,
|
||||
NULL, considered_path_res);
|
||||
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
else {
|
||||
RETVAL_TRUE;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (extract_handle != NULL)
|
||||
RARCloseArchive(extract_handle);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::getName()
|
||||
Return entry name */
|
||||
PHP_METHOD(rarentry, getName)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "name");
|
||||
|
||||
convert_to_string_ex(tmp);
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getUnpackedSize()
|
||||
Return unpacked size of the entry */
|
||||
PHP_METHOD(rarentry, getUnpackedSize)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "unpacked_size");
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getPackedSize()
|
||||
Return packed size of the entry */
|
||||
PHP_METHOD(rarentry, getPackedSize)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "packed_size");
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getHostOs()
|
||||
Return host OS of the entry */
|
||||
PHP_METHOD(rarentry, getHostOs)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "host_os");
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::getFileTime()
|
||||
Return modification time of the entry */
|
||||
PHP_METHOD(rarentry, getFileTime)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "file_time");
|
||||
|
||||
convert_to_string_ex(tmp);
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::getCrc()
|
||||
Return CRC of the entry */
|
||||
PHP_METHOD(rarentry, getCrc)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "crc");
|
||||
|
||||
convert_to_string_ex(tmp);
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getAttr()
|
||||
Return attributes of the entry */
|
||||
PHP_METHOD(rarentry, getAttr)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "attr");
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getVersion()
|
||||
Return version of the archiver, used to create this entry */
|
||||
PHP_METHOD(rarentry, getVersion)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "version");
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::getMethod()
|
||||
Return packing method */
|
||||
PHP_METHOD(rarentry, getMethod)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "method");
|
||||
|
||||
convert_to_long_ex(tmp);
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto resource RarEntry::getStream([string password])
|
||||
Return stream for current entry */
|
||||
PHP_METHOD(rarentry, getStream)
|
||||
{
|
||||
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(name, "name");
|
||||
RAR_GET_PROPERTY(tmp, "rarfile");
|
||||
if (!_rar_get_file_resource(*tmp, &rar TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (password == NULL)
|
||||
password = rar->password; //use rar_open password by default
|
||||
|
||||
stream = php_stream_rar_open(rar->extract_open_data->ArcName,
|
||||
Z_STRVAL_PP(name), password, "r" STREAMS_CC TSRMLS_CC);
|
||||
|
||||
if (stream != NULL) {
|
||||
php_stream_to_zval(stream, return_value);
|
||||
}
|
||||
else
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::isDirectory()
|
||||
Return whether the entry represents a directory */
|
||||
PHP_METHOD(rarentry, isDirectory)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_dir;
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "flags");
|
||||
flags = Z_LVAL_PP(tmp);
|
||||
is_dir = ((flags & 0xE0) == 0xE0);
|
||||
|
||||
RETURN_BOOL(is_dir);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int RarEntry::isEncrypted()
|
||||
Return whether the entry is encrypted and needs a password */
|
||||
PHP_METHOD(rarentry, isEncrypted)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_encrypted;
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "flags");
|
||||
flags = Z_LVAL_PP(tmp);
|
||||
is_encrypted = (flags & 0x04);
|
||||
|
||||
RETURN_BOOL(is_encrypted);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::__toString()
|
||||
Return string representation for entry */
|
||||
PHP_METHOD(rarentry, __toString)
|
||||
{
|
||||
zval **flags_zval,
|
||||
**name_zval,
|
||||
**crc_zval;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_dir;
|
||||
char *name,
|
||||
*crc;
|
||||
char *restring;
|
||||
int restring_len;
|
||||
const char format[] = "RarEntry for %s \"%s\" (%s)";
|
||||
|
||||
RAR_GET_PROPERTY(flags_zval, "flags");
|
||||
flags = Z_LVAL_PP(flags_zval);
|
||||
is_dir = ((flags & 0xE0) == 0xE0);
|
||||
|
||||
RAR_GET_PROPERTY(name_zval, "name");
|
||||
name = Z_STRVAL_PP(name_zval);
|
||||
|
||||
RAR_GET_PROPERTY(crc_zval, "crc");
|
||||
crc = Z_STRVAL_PP(crc_zval);
|
||||
|
||||
//2 is size of %s, 8 is size of crc
|
||||
restring_len = (sizeof(format)-1) - 2 * 3 + (sizeof("directory")-1) +
|
||||
strlen(name) + 8 + 1;
|
||||
restring = emalloc(restring_len);
|
||||
snprintf(restring, restring_len, format, is_dir?"directory":"file",
|
||||
name, crc);
|
||||
restring[restring_len - 1] = '\0'; //just to be safe
|
||||
|
||||
RETURN_STRING(restring, 0);
|
||||
}
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ arginfo */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_extract, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, path)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_getstream, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, password)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_rar_void, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
|
||||
static zend_function_entry php_rar_class_functions[] = {
|
||||
PHP_ME(rarentry, extract, arginfo_rarentry_extract, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getName, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getUnpackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getPackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getHostOs, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getFileTime, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getCrc, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getAttr, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getVersion, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getMethod, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, getStream, arginfo_rarentry_getstream, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, isDirectory, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, isEncrypted, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(rarentry, __toString, arginfo_rar_void, ZEND_ACC_PUBLIC)
|
||||
PHP_ME_MAPPING(__construct, rar_bogus_ctor, arginfo_rar_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
void minit_rarentry(TSRMLS_D)
|
||||
{
|
||||
zend_class_entry ce;
|
||||
|
||||
memcpy(&rarentry_object_handlers, zend_get_std_object_handlers(),
|
||||
sizeof rarentry_object_handlers);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "RarEntry", php_rar_class_functions);
|
||||
rar_class_entry_ptr = zend_register_internal_class(&ce TSRMLS_CC);
|
||||
rar_class_entry_ptr->ce_flags |= ZEND_ACC_FINAL_CLASS;
|
||||
rar_class_entry_ptr->clone = NULL;
|
||||
//Custom creation currently not really needed, but you never know...
|
||||
rar_class_entry_ptr->create_object = &rarentry_ce_create_object;
|
||||
|
||||
REG_RAR_PROPERTY("rarfile", "Associated RAR archive");
|
||||
REG_RAR_PROPERTY("name", "File or directory name with path");
|
||||
REG_RAR_PROPERTY("unpacked_size", "Size of file when unpacked");
|
||||
REG_RAR_PROPERTY("packed_size", "Size of the packed file inside the archive");
|
||||
REG_RAR_PROPERTY("host_os", "OS used to pack the file");
|
||||
REG_RAR_PROPERTY("file_time", "Entry's time of last modification");
|
||||
REG_RAR_PROPERTY("crc", "CRC checksum for the unpacked file");
|
||||
REG_RAR_PROPERTY("attr", "OS-dependent file attributes");
|
||||
REG_RAR_PROPERTY("version", "RAR version needed to extract entry");
|
||||
REG_RAR_PROPERTY("method", "Identifier for packing method");
|
||||
REG_RAR_PROPERTY("flags", "Entry header flags");
|
||||
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_MSDOS", HOST_MSDOS);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_OS2", HOST_OS2);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_WIN32", HOST_WIN32);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_UNIX", HOST_UNIX);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_MACOS", HOST_MACOS);
|
||||
REG_RAR_CLASS_CONST_LONG("HOST_BEOS", HOST_BEOS);
|
||||
|
||||
//see WinNT.h
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_READONLY", 0x00001L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_HIDDEN", 0x00002L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SYSTEM", 0x00004L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DIRECTORY", 0x00010L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ARCHIVE", 0x00020L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DEVICE", 0x00040L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NORMAL", 0x00080L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_TEMPORARY", 0x00100L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SPARSE_FILE", 0x00200L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_REPARSE_POINT", 0x00400L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_COMPRESSED", 0x00800L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_OFFLINE", 0x01000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NOT_CONTENT_INDEXED", 0x02000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ENCRYPTED", 0x04000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_VIRTUAL", 0x10000L);
|
||||
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_EXECUTE", 0x00001L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_WRITE", 0x00002L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_READ", 0x00004L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_EXECUTE", 0x00008L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_WRITE", 0x00010L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_READ", 0x00020L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_EXECUTE", 0x00040L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_WRITE", 0x00080L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_READ", 0x00100L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_STICKY", 0x00200L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETGID", 0x00400L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETUID", 0x00800L);
|
||||
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FINAL_QUARTET", 0x0F000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FIFO", 0x01000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_CHAR_DEV", 0x02000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_DIRECTORY", 0x04000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_BLOCK_DEV", 0x06000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_REGULAR_FILE", 0x08000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SYM_LINK", 0x0A000L);
|
||||
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SOCKET", 0x0C000L);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -11,8 +11,17 @@ var_dump($rar_file1);
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
var_dump($rar_file2);
|
||||
|
||||
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
|
||||
var_dump($rar_file3);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
resource(%d) of type (Rar)
|
||||
resource(%d) of type (Rar)
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
object(RarArchive)#%d (%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
|
||||
|
||||
118
tests/002.phpt
118
tests/002.phpt
@@ -13,102 +13,124 @@ $rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$list2 = rar_list($rar_file2);
|
||||
var_dump($list2);
|
||||
|
||||
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
|
||||
$list3 = rar_list($rar_file3);
|
||||
var_dump($list3);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(RarEntry)#%d (10) {
|
||||
["rarfile"]=>
|
||||
resource(%d) of type (Rar)
|
||||
["name"]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%s (%s) {
|
||||
}
|
||||
["name%sprivate%s=>
|
||||
string(9) "plain.txt"
|
||||
["unpacked_size"]=>
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(15)
|
||||
["packed_size"]=>
|
||||
["packed_size%sprivate%s=>
|
||||
int(25)
|
||||
["host_os"]=>
|
||||
["host_os%sprivate%s=>
|
||||
int(3)
|
||||
["file_time"]=>
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 11:01:24"
|
||||
["crc"]=>
|
||||
["crc%sprivate%s=>
|
||||
string(8) "7728b6fe"
|
||||
["attr"]=>
|
||||
["attr%sprivate%s=>
|
||||
int(33188)
|
||||
["version"]=>
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method"]=>
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
}
|
||||
[1]=>
|
||||
object(RarEntry)#%d (10) {
|
||||
["rarfile"]=>
|
||||
resource(%d) of type (Rar)
|
||||
["name"]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (0) {
|
||||
}
|
||||
["name%sprivate%s=>
|
||||
string(30) "test file with whitespaces.txt"
|
||||
["unpacked_size"]=>
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(14)
|
||||
["packed_size"]=>
|
||||
["packed_size%sprivate%s=>
|
||||
int(20)
|
||||
["host_os"]=>
|
||||
["host_os%sprivate%s=>
|
||||
int(3)
|
||||
["file_time"]=>
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 11:01:32"
|
||||
["crc"]=>
|
||||
["crc%sprivate%s=>
|
||||
string(8) "21890dd9"
|
||||
["attr"]=>
|
||||
["attr%sprivate%s=>
|
||||
int(33188)
|
||||
["version"]=>
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method"]=>
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
}
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(RarEntry)#%d (10) {
|
||||
["rarfile"]=>
|
||||
resource(%d) of type (Rar)
|
||||
["name"]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["name%sprivate%s=>
|
||||
string(5) "1.txt"
|
||||
["unpacked_size"]=>
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size"]=>
|
||||
["packed_size%sprivate%s=>
|
||||
int(17)
|
||||
["host_os"]=>
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time"]=>
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:18"
|
||||
["crc"]=>
|
||||
["crc%sprivate%s=>
|
||||
string(8) "a0de71c0"
|
||||
["attr"]=>
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version"]=>
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method"]=>
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(36992)
|
||||
}
|
||||
[1]=>
|
||||
object(RarEntry)#%d (10) {
|
||||
["rarfile"]=>
|
||||
resource(%d) of type (Rar)
|
||||
["name"]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["name%sprivate%s=>
|
||||
string(5) "2.txt"
|
||||
["unpacked_size"]=>
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size"]=>
|
||||
["packed_size%sprivate%s=>
|
||||
int(16)
|
||||
["host_os"]=>
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time"]=>
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:26"
|
||||
["crc"]=>
|
||||
["crc%sprivate%s=>
|
||||
string(8) "45a918de"
|
||||
["attr"]=>
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version"]=>
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method"]=>
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
}
|
||||
}
|
||||
|
||||
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: rar_list() expects parameter 1 to be RarArchive, boolean given in %s on line %d
|
||||
NULL
|
||||
Done
|
||||
|
||||
@@ -13,52 +13,66 @@ $rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$entry2 = rar_entry_get($rar_file2, '2.txt');
|
||||
var_dump($entry2);
|
||||
|
||||
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
|
||||
$entry3 = rar_entry_get($rar_file3, '2.txt');
|
||||
var_dump($entry3);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
object(RarEntry)#%d (10) {
|
||||
["rarfile"]=>
|
||||
resource(%d) of type (Rar)
|
||||
["name"]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["name%sprivate%s=>
|
||||
string(30) "test file with whitespaces.txt"
|
||||
["unpacked_size"]=>
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(14)
|
||||
["packed_size"]=>
|
||||
["packed_size%sprivate%s=>
|
||||
int(20)
|
||||
["host_os"]=>
|
||||
["host_os%sprivate%s=>
|
||||
int(3)
|
||||
["file_time"]=>
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 11:01:32"
|
||||
["crc"]=>
|
||||
["crc%sprivate%s=>
|
||||
string(8) "21890dd9"
|
||||
["attr"]=>
|
||||
["attr%sprivate%s=>
|
||||
int(33188)
|
||||
["version"]=>
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method"]=>
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
}
|
||||
object(RarEntry)#%d (10) {
|
||||
["rarfile"]=>
|
||||
resource(%d) of type (Rar)
|
||||
["name"]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["name%sprivate%s=>
|
||||
string(5) "2.txt"
|
||||
["unpacked_size"]=>
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size"]=>
|
||||
["packed_size%sprivate%s=>
|
||||
int(16)
|
||||
["host_os"]=>
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time"]=>
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:26"
|
||||
["crc"]=>
|
||||
["crc%sprivate%s=>
|
||||
string(8) "45a918de"
|
||||
["attr"]=>
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version"]=>
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method"]=>
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
}
|
||||
|
||||
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
|
||||
Warning: rar_entry_get() expects parameter 1 to be RarArchive, boolean given in %s on line %d
|
||||
NULL
|
||||
Done
|
||||
|
||||
@@ -11,10 +11,12 @@ $entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
|
||||
$entry1->extract(dirname(__FILE__));
|
||||
$contents11 = file_get_contents(dirname(__FILE__).'/test file with whitespaces.txt');
|
||||
echo $contents11."\n";
|
||||
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
|
||||
|
||||
$entry1->extract(false,dirname(__FILE__).'/1.txt');
|
||||
$contents12 = file_get_contents(dirname(__FILE__).'/1.txt');
|
||||
echo $contents12."\n";
|
||||
@unlink(dirname(__FILE__).'/1.txt');
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$entry2 = rar_entry_get($rar_file2, '2.txt');
|
||||
@@ -22,19 +24,59 @@ $entry2 = rar_entry_get($rar_file2, '2.txt');
|
||||
$entry2->extract(dirname(__FILE__));
|
||||
$contents21 = file_get_contents(dirname(__FILE__).'/2.txt');
|
||||
echo $contents21."\n";
|
||||
@unlink(dirname(__FILE__).'/2.txt');
|
||||
|
||||
$entry2->extract(false,dirname(__FILE__).'/some.txt');
|
||||
$contents22 = file_get_contents(dirname(__FILE__).'/some.txt');
|
||||
echo $contents22."\n";
|
||||
|
||||
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
|
||||
@unlink(dirname(__FILE__).'/1.txt');
|
||||
@unlink(dirname(__FILE__).'/2.txt');
|
||||
@unlink(dirname(__FILE__).'/some.txt');
|
||||
|
||||
$entry2->extract(dirname(__FILE__));
|
||||
var_dump(file_get_contents(dirname(__FILE__).'/2.txt'));
|
||||
@unlink(dirname(__FILE__).'/2.txt');
|
||||
|
||||
$oldcwd = getcwd();
|
||||
chdir(dirname(__FILE__));
|
||||
|
||||
var_dump($entry2);
|
||||
var_dump($entry2->extract("",""));
|
||||
|
||||
@unlink('2.txt');
|
||||
|
||||
chdir($oldcwd);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
blah-blah-blah
|
||||
blah-blah-blah
|
||||
22222
|
||||
22222
|
||||
|
||||
string(5) "22222"
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#3 (0) {
|
||||
}
|
||||
["name%sprivate%s=>
|
||||
string(5) "2.txt"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(5)
|
||||
["packed_size%sprivate%s=>
|
||||
int(16)
|
||||
["host_os%sprivate%s=>
|
||||
int(2)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "2004-06-11 10:07:26"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "45a918de"
|
||||
["attr%sprivate%s=>
|
||||
int(32)
|
||||
["version%sprivate%s=>
|
||||
int(29)
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
}
|
||||
bool(true)
|
||||
Done
|
||||
|
||||
24
tests/005.phpt
Normal file
24
tests/005.phpt
Normal file
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
rar_comment_get() function
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/commented.rar');
|
||||
var_export(rar_comment_get($rar_file1));
|
||||
echo "\n";
|
||||
var_export(rar_comment_get($rar_file1));
|
||||
echo "\n";
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/linux_rar.rar');
|
||||
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.'
|
||||
NULL
|
||||
Done
|
||||
22
tests/006.phpt
Normal file
22
tests/006.phpt
Normal file
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
RarEntry::getCrc() method in multi-volume archives (PECL bug #9470)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
|
||||
$list = rar_list($rar_file1);
|
||||
echo $list[0]->getCrc()."\n";
|
||||
echo $list[1]->getCrc()."\n";
|
||||
echo $list[2]->getCrc()."\n";
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
52b28202
|
||||
f2c79881
|
||||
bcbce32e
|
||||
|
||||
Done
|
||||
18
tests/007.phpt
Normal file
18
tests/007.phpt
Normal file
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
rar_open() function with a non-RAR
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_notrar.rar');
|
||||
var_dump($rar_file1);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: rar_open(): Failed to open %s: ERAR_BAD_ARCHIVE in %s on line %d
|
||||
bool(false)
|
||||
|
||||
Done
|
||||
34
tests/008.phpt
Normal file
34
tests/008.phpt
Normal file
@@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
rar_entry_get() function
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
|
||||
$entry = rar_entry_get($rar_file1, "file1.txt");
|
||||
echo "$entry\n";
|
||||
$entry = rar_entry_get($rar_file1, "nonexistent_file.txt");
|
||||
var_dump($entry);
|
||||
echo "\n";
|
||||
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/nonexistent.rar');
|
||||
$entry = rar_entry_get($rar_file2, "file1.txt");
|
||||
var_dump($entry);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RarEntry for file "file1.txt" (52b28202)
|
||||
|
||||
Warning: rar_entry_get(): cannot find file "nonexistent_file.txt" in Rar archive "%s". in %s on line %d
|
||||
bool(false)
|
||||
|
||||
|
||||
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
Warning: rar_entry_get() expects parameter 1 to be RarArchive, boolean given in %s on line %d
|
||||
NULL
|
||||
|
||||
Done
|
||||
19
tests/009.phpt
Normal file
19
tests/009.phpt
Normal file
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
RarEntry::getName() function with unicode filenames
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
$name = reset($entries)->getName();
|
||||
var_dump($name);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(13) "file1À۞.txt"
|
||||
|
||||
Done
|
||||
32
tests/010.phpt
Normal file
32
tests/010.phpt
Normal file
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (good RAR file, one volume)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().":\n";
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 8192);
|
||||
}
|
||||
echo "\n\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
2 files:
|
||||
|
||||
1.txt:
|
||||
11111
|
||||
|
||||
2.txt:
|
||||
22222
|
||||
|
||||
Done
|
||||
38
tests/011.phpt
Normal file
38
tests/011.phpt
Normal file
@@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (good RAR file, several volumes)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
$a = "";
|
||||
while (!feof($stream)) {
|
||||
$a .= fread($stream, 8192);
|
||||
}
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
3 files:
|
||||
|
||||
file1.txt: 18 bytes, CRC 52B28202
|
||||
|
||||
file2.txt: 17704 bytes, CRC F2C79881
|
||||
|
||||
file3.txt: 18 bytes, CRC BCBCE32E
|
||||
|
||||
Done
|
||||
42
tests/012.phpt
Normal file
42
tests/012.phpt
Normal file
@@ -0,0 +1,42 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (bad RAR file)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files (will test only the first 4):\n\n";
|
||||
//var_dump($entries);
|
||||
$i = 0;
|
||||
foreach ($entries as $e) {
|
||||
if ($i++ >= 2)
|
||||
break;
|
||||
//$e->extract(false, dirname(__FILE__).'/temp.txt');
|
||||
//echo "now stream\n";
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
if ($stream === false) {
|
||||
echo "Could not get stream.\n\n";
|
||||
continue;
|
||||
}
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 8192);
|
||||
}
|
||||
fclose($stream);
|
||||
echo "\n";
|
||||
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
51 files (will test only the first 4):
|
||||
|
||||
test%s: The great battle of Gunprex versus Optiter!!!!!1
|
||||
Gunprex, Fire!
|
||||
So long, Optiter!
|
||||
|
||||
test%s: it,greIater!
|
||||
%s
|
||||
Done
|
||||
20
tests/013.phpt
Normal file
20
tests/013.phpt
Normal file
@@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
rar_entry_get() and RarEntry::getName() coherence
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
$name = reset($entries)->getName();
|
||||
$entryback = rar_entry_get($rar_file1, $name);
|
||||
echo "$entryback\n";
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RarEntry for file "file1À۞.txt" (52b28202)
|
||||
|
||||
Done
|
||||
26
tests/014.phpt
Normal file
26
tests/014.phpt
Normal file
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() on unicode entry
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entry = rar_entry_get($rar_file1, "file1À۞.txt");
|
||||
echo $entry."\n";
|
||||
echo "\n";
|
||||
$stream = $entry->getStream();
|
||||
if ($stream !== false)
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 8192);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RarEntry for file "file1À۞.txt" (52b28202)
|
||||
|
||||
contents of file 1
|
||||
Done
|
||||
30
tests/015.phpt
Normal file
30
tests/015.phpt
Normal file
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
rar_close() liberates resource (PECL bug #9649)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
copy(dirname(__FILE__).'/latest_winrar.rar', dirname(__FILE__).'/temp.rar');
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/temp.rar');
|
||||
echo $rar_file1."\n";
|
||||
$entries = rar_list($rar_file1);
|
||||
$entry1 = reset($entries);
|
||||
unset($entries);
|
||||
echo $entry1."\n";
|
||||
echo "\n";
|
||||
|
||||
rar_close($rar_file1);
|
||||
echo $rar_file1."\n";
|
||||
$entry1->extract(".");
|
||||
unlink(dirname(__FILE__).'/temp.rar');
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
RAR Archive "%s"
|
||||
RarEntry for file "1.txt" (a0de71c0)
|
||||
|
||||
RAR Archive "%s" (closed)
|
||||
|
||||
Warning: RarEntry::extract(): The archive is already closed. in %s on line %d
|
||||
Done
|
||||
50
tests/016.phpt
Normal file
50
tests/016.phpt
Normal file
@@ -0,0 +1,50 @@
|
||||
--TEST--
|
||||
RarEntry::extract() method (corrupt RAR file)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files (will test only the first 4):\n\n";
|
||||
//var_dump($entries);
|
||||
$i = 0;
|
||||
foreach ($entries as $e) {
|
||||
if ($i++ >= 4)
|
||||
break;
|
||||
echo "Extraction of file #$i:\n";
|
||||
$ret = $e->extract(false, dirname(__FILE__).'/temp.txt');
|
||||
if ($ret)
|
||||
echo "\tSUCCESS\n";
|
||||
else
|
||||
echo "\tFAILED\n";
|
||||
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
@unlink(dirname(__FILE__).'/temp.txt');
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
51 files (will test only the first 4):
|
||||
|
||||
Extraction of file #1:
|
||||
SUCCESS
|
||||
|
||||
Extraction of file #2:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
FAILED
|
||||
|
||||
Extraction of file #3:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
FAILED
|
||||
|
||||
Extraction of file #4:
|
||||
|
||||
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
|
||||
FAILED
|
||||
|
||||
Done
|
||||
22
tests/017.phpt
Normal file
22
tests/017.phpt
Normal file
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
RarEntry::extract() with unicode files
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
$e = reset($entries);
|
||||
|
||||
$e->extract(false, dirname(__FILE__).'/temp.txt');
|
||||
|
||||
echo file_get_contents(dirname(__FILE__).'/temp.txt');
|
||||
echo "\n";
|
||||
|
||||
@unlink(dirname(__FILE__).'/temp.txt');
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
contents of file 1
|
||||
Done
|
||||
24
tests/018.phpt
Normal file
24
tests/018.phpt
Normal file
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
rar_list()/rar_entry_get() with not first volume
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part2.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo "Number of entries: " . count($entries) . "\n";
|
||||
echo reset($entries)."\n";
|
||||
$e = rar_entry_get($rar_file1, "file2.txt");
|
||||
var_dump($e);
|
||||
$e = rar_entry_get($rar_file1, "file3.txt");
|
||||
echo $e."\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Number of entries: 1
|
||||
RarEntry for file "file3.txt" (bcbce32e)
|
||||
|
||||
Warning: rar_entry_get(): cannot find file "file2.txt" in Rar archive "%s. in %s on line %d
|
||||
bool(false)
|
||||
RarEntry for file "file3.txt" (bcbce32e)
|
||||
Done
|
||||
34
tests/019.phpt
Normal file
34
tests/019.phpt
Normal file
@@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (store method)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/store_method.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
$a = "";
|
||||
while (!feof($stream)) {
|
||||
$a .= fread($stream, 512);
|
||||
}
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
1 files:
|
||||
|
||||
tese.txt: 787 bytes, CRC 23B93A7A
|
||||
|
||||
Done
|
||||
36
tests/020.phpt
Normal file
36
tests/020.phpt
Normal file
@@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() function (solid archive)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/solid.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
echo count($entries)." files:\n\n";
|
||||
//var_dump($entries);
|
||||
function int32_to_hex($value) {
|
||||
$value &= 0xffffffff;
|
||||
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
|
||||
}
|
||||
foreach ($entries as $e) {
|
||||
$stream = $e->getStream();
|
||||
echo $e->getName().": ";
|
||||
$a = "";
|
||||
while (!feof($stream)) {
|
||||
$a .= fread($stream, 8192);
|
||||
}
|
||||
echo strlen($a)." bytes, CRC ";
|
||||
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
2 files:
|
||||
|
||||
tese.txt: 787 bytes, CRC 23B93A7A
|
||||
|
||||
unrardll.txt: 19192 bytes, CRC 2ED64B6E
|
||||
|
||||
Done
|
||||
19
tests/021.phpt
Normal file
19
tests/021.phpt
Normal file
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
RarEntry::isDirectory() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
|
||||
foreach ($entries as $e) {
|
||||
echo "{$e->getName()} is ". ($e->isDirectory()?"":"not ") . "a directory.\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
dirwithsth%cfileindir.txt is not a directory.
|
||||
dirwithsth is a directory.
|
||||
emptydir is a directory.
|
||||
Done
|
||||
40
tests/022.phpt
Normal file
40
tests/022.phpt
Normal file
@@ -0,0 +1,40 @@
|
||||
--TEST--
|
||||
RarEntry::extract() with directory
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
|
||||
$e = rar_entry_get($rar_file1, "emptydir");
|
||||
|
||||
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydir";
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
$extrres = $e->extract(dirname(__FILE__));
|
||||
var_dump($extrres);
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
@rmdir($dir);
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydircust";
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
$extrres = $e->extract(false, $dir);
|
||||
var_dump($extrres);
|
||||
$exists = is_dir($dir);
|
||||
var_dump($exists);
|
||||
@rmdir($dir);
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
|
||||
bool(false)
|
||||
bool(true)
|
||||
bool(true)
|
||||
Done
|
||||
21
tests/023.phpt
Normal file
21
tests/023.phpt
Normal file
@@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() with directory
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
|
||||
$e = rar_entry_get($rar_file1, "emptydir");
|
||||
$stream = $e->getStream();
|
||||
var_dump($stream);
|
||||
var_dump(feof($stream));
|
||||
var_dump(fread($stream, 200));
|
||||
var_dump(feof($stream));
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
resource(%d) of type (stream)
|
||||
bool(false)
|
||||
string(0) ""
|
||||
bool(true)
|
||||
Done
|
||||
46
tests/024.phpt
Normal file
46
tests/024.phpt
Normal file
@@ -0,0 +1,46 @@
|
||||
--TEST--
|
||||
rar_open()/RarEntry::getStream() (headers level password)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "--> should fail (no password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
|
||||
echo "\n--> should fail (wrong password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'wrongpassword');
|
||||
$entries = rar_list($rar_file1);
|
||||
|
||||
echo "\n--> should work:\n";
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
|
||||
$entries = rar_list($rar_file2);
|
||||
|
||||
echo "Found " . count($entries) . " files.\n";
|
||||
echo "Content of first one follows:\n";
|
||||
//reset($entries)->extract(false, "./temp.txt");
|
||||
$stream = reset($entries)->getStream();
|
||||
var_dump($stream);
|
||||
if ($stream !== FALSE) {
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 128);
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
--> should fail (no password):
|
||||
|
||||
Warning: rar_list(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
|
||||
--> should fail (wrong password):
|
||||
|
||||
Warning: rar_list(): ERAR_BAD_DATA in %s on line %d
|
||||
|
||||
--> should work:
|
||||
Found 2 files.
|
||||
Content of first one follows:
|
||||
resource(%d) of type (stream)
|
||||
Encrypted file 1 contents.
|
||||
Done
|
||||
26
tests/025.phpt
Normal file
26
tests/025.phpt
Normal file
@@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
rar_open()/RarEntry::extract() (headers level password)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
|
||||
$entries = rar_list($rar_file2);
|
||||
|
||||
echo "Found " . count($entries) . " files.\n";
|
||||
$tempfile = dirname(__FILE__).'/temp.txt';
|
||||
@unlink($tempfile);
|
||||
var_dump(reset($entries)->extract(false, $tempfile));
|
||||
echo "Content of first one follows:\n";
|
||||
echo file_get_contents($tempfile);
|
||||
$stream = reset($entries)->getStream();
|
||||
@unlink($tempfile);
|
||||
echo "\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Found 2 files.
|
||||
bool(true)
|
||||
Content of first one follows:
|
||||
Encrypted file 1 contents.
|
||||
Done
|
||||
45
tests/026.phpt
Normal file
45
tests/026.phpt
Normal file
@@ -0,0 +1,45 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() (file level password)
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "--> should fail (no password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
var_dump(count($entries));
|
||||
var_dump($entries[0]->getStream());
|
||||
echo "\n";
|
||||
|
||||
echo "--> success (password is the same as the one given on rar_open):\n";
|
||||
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar', 'samplepassword');
|
||||
$entries = rar_list($rar_file2);
|
||||
echo stream_get_contents($entries[0]->getStream());
|
||||
echo "\n\n";
|
||||
|
||||
echo "--> should give incorrect data (password of 2nd file different from the one given on rar_open):\n";
|
||||
echo rawurlencode(stream_get_contents($entries[1]->getStream()));
|
||||
echo "\n\n";
|
||||
|
||||
echo "--> should give correct data (password of 2nd file is specified):\n";
|
||||
echo stream_get_contents($entries[1]->getStream('samplepassword2'));
|
||||
echo "\n\n";
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
--> should fail (no password):
|
||||
int(2)
|
||||
|
||||
Warning: RarEntry::getStream(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
|
||||
bool(false)
|
||||
|
||||
--> success (password is the same as the one given on rar_open):
|
||||
Encrypted file 1 contents.
|
||||
|
||||
--> should give incorrect data (password of 2nd file different from the one given on rar_open):
|
||||
t%09%A6%2B%0D%1B%F6%815%5E%E7%EC%C0%0BF%5EH%3A%C0%0D%815%5E%E7%EC%C0
|
||||
|
||||
--> should give correct data (password of 2nd file is specified):
|
||||
Encrypted file 1 contents.
|
||||
|
||||
Done
|
||||
54
tests/027.phpt
Normal file
54
tests/027.phpt
Normal file
@@ -0,0 +1,54 @@
|
||||
--TEST--
|
||||
RarEntry::getStream() with Linux directories and links
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar = rar_open(dirname(__FILE__) . "/dirlink_unix.rar");
|
||||
|
||||
echo "\nDirectory\n";
|
||||
|
||||
$e = rar_entry_get($rar, "nopermdir");
|
||||
echo $e."\n";
|
||||
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n"; //no read/write/execute perms
|
||||
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n";
|
||||
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
|
||||
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
|
||||
$stream = $e->getStream();
|
||||
$cont = stream_get_contents($stream);
|
||||
echo "$cont (strlen() " . strlen($cont) . ")\n";
|
||||
|
||||
echo "\nLink\n";
|
||||
|
||||
$e = rar_entry_get($rar, "link");
|
||||
echo $e."\n";
|
||||
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n";
|
||||
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n"; //coincidence
|
||||
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
|
||||
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
|
||||
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
|
||||
$stream = $e->getStream();
|
||||
$cont = stream_get_contents($stream);
|
||||
echo "$cont (strlen() " . strlen($cont) . ")\n"; //varies on windows and linux
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
Directory
|
||||
RarEntry for directory "nopermdir" (0)
|
||||
perms: 0
|
||||
win directory bit:
|
||||
unix directory attr: 1
|
||||
unix symlink attr:
|
||||
(strlen() 0)
|
||||
|
||||
Link
|
||||
RarEntry for file "link" (43e55b49)
|
||||
perms: 777
|
||||
win directory bit: 1
|
||||
unix directory attr:
|
||||
unix symlink attr: 1
|
||||
%s
|
||||
Done
|
||||
14
tests/028.phpt
Normal file
14
tests/028.phpt
Normal file
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
RarArchive::open() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
|
||||
var_dump(get_class($arch));
|
||||
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
string(10) "RarArchive"
|
||||
Done
|
||||
21
tests/029.phpt
Normal file
21
tests/029.phpt
Normal file
@@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
RarArchive::getEntries() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
|
||||
foreach ($arch->getEntries() as $e) {
|
||||
echo $e . "\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
RarEntry for file "emptydir%clink" (36ac99f1)
|
||||
RarEntry for file "file" (b95e8411)
|
||||
RarEntry for file "link" (43e55b49)
|
||||
RarEntry for directory "emptydir" (0)
|
||||
RarEntry for directory "nopermdir" (0)
|
||||
RarEntry for directory "setuiddir" (0)
|
||||
RarEntry for directory "stickydir" (0)
|
||||
Done
|
||||
14
tests/030.phpt
Normal file
14
tests/030.phpt
Normal file
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
RarArchive::getEntry() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_arch = RarArchive::open(dirname(__FILE__) . '/solid.rar');
|
||||
$rar_entry = $rar_arch->getEntry('tese.txt');
|
||||
echo $rar_entry;
|
||||
echo "\n";
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
RarEntry for file "tese.txt" (23b93a7a)
|
||||
Done
|
||||
13
tests/031.phpt
Normal file
13
tests/031.phpt
Normal file
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
RarArchive::getComment() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rar_arch = RarArchive::open(dirname(__FILE__) . '/commented.rar');
|
||||
echo $rar_arch->getComment();
|
||||
echo "\n";
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
This is the comment of the file commented.rar.
|
||||
Done
|
||||
16
tests/032.phpt
Normal file
16
tests/032.phpt
Normal file
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
RarArchive traversal with multi-part archive
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$rarF = RarArchive::open(dirname(__FILE__) . '/multi.part1.rar');
|
||||
foreach ($rarF as $k => $rarE) {
|
||||
echo "$k. $rarE\n";
|
||||
}
|
||||
echo "Done\n";
|
||||
--EXPECTF--
|
||||
0. RarEntry for file "file1.txt" (52b28202)
|
||||
1. RarEntry for file "file2.txt" (f2c79881)
|
||||
2. RarEntry for file "file3.txt" (bcbce32e)
|
||||
Done
|
||||
15
tests/033.phpt
Normal file
15
tests/033.phpt
Normal file
@@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
rar_solid_is() basic test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arch1 = RarArchive::open(dirname(__FILE__) . "/store_method.rar");
|
||||
$arch2 = RarArchive::open(dirname(__FILE__) . "/solid.rar");
|
||||
echo "$arch1: " . ($arch1->isSolid()?'yes':'no') ."\n";
|
||||
echo "$arch2: " . (rar_solid_is($arch2)?'yes':'no') . "\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
RAR Archive "%sstore_method.rar": no
|
||||
RAR Archive "%ssolid.rar": yes
|
||||
Done.
|
||||
16
tests/034.phpt
Normal file
16
tests/034.phpt
Normal file
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
RarException::(set/is)UsingExceptions() test
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "Initial state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
|
||||
RarException::setUsingExceptions(true);
|
||||
echo "State change done.\n";
|
||||
echo "Final state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Initial state: no.
|
||||
State change done.
|
||||
Final state: yes.
|
||||
Done.
|
||||
19
tests/035.phpt
Normal file
19
tests/035.phpt
Normal file
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
rar_entry_get() non-existent file with exceptions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
RarException::setUsingExceptions(true);
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/latest_winrar.rar");
|
||||
try {
|
||||
$arch->getEntry('nonexistentfile.txt');
|
||||
} catch (RarException $re) {
|
||||
echo "Message: " . $re->getMessage()."\n";
|
||||
echo "Code: " . $re->getCode() ."\n";
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Message: cannot find file "nonexistentfile.txt" in Rar archive "%slatest_winrar.rar".
|
||||
Code: -1
|
||||
Done.
|
||||
18
tests/036.phpt
Normal file
18
tests/036.phpt
Normal file
@@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
rar_open() non-existent archive with exceptions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
RarException::setUsingExceptions(true);
|
||||
try {
|
||||
$arch = RarArchive::open(dirname(__FILE__) . "/nonexistentarchive.rar");
|
||||
} catch (RarException $re) {
|
||||
echo "Message: " . $re->getMessage()."\n";
|
||||
echo "Code: " . $re->getCode() ."\n";
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
Message: unRAR internal error: Failed to open %snonexistentarchive.rar: ERAR_EOPEN (file open error)
|
||||
Code: 15
|
||||
Done.
|
||||
24
tests/037.phpt
Normal file
24
tests/037.phpt
Normal file
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
RarEntry::getStream(), password not given, with exceptions
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
RarException::setUsingExceptions(true);
|
||||
echo "--> should fail (no password):\n";
|
||||
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
|
||||
$entries = rar_list($rar_file1);
|
||||
var_dump(count($entries));
|
||||
try {
|
||||
var_dump($entries[0]->getStream());
|
||||
} catch (RarException $re) {
|
||||
echo "Message: " . $re->getMessage()."\n";
|
||||
echo "Code: " . $re->getCode() ."\n";
|
||||
}
|
||||
echo "Done.\n";
|
||||
--EXPECTF--
|
||||
--> should fail (no password):
|
||||
int(2)
|
||||
Message: unRAR internal error: ERAR_MISSING_PASSWORD (password needed but not specified)
|
||||
Code: 22
|
||||
Done.
|
||||
15
tests/038.phpt
Normal file
15
tests/038.phpt
Normal file
@@ -0,0 +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: The archive is already closed, cannot give an iterator in %s on line %d
|
||||
15
tests/039.phpt
Normal file
15
tests/039.phpt
Normal file
@@ -0,0 +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.
|
||||
BIN
tests/commented.rar
Normal file
BIN
tests/commented.rar
Normal file
Binary file not shown.
BIN
tests/corrupted.rar
Normal file
BIN
tests/corrupted.rar
Normal file
Binary file not shown.
BIN
tests/directories.rar
Normal file
BIN
tests/directories.rar
Normal file
Binary file not shown.
BIN
tests/dirlink_unix.rar
Normal file
BIN
tests/dirlink_unix.rar
Normal file
Binary file not shown.
BIN
tests/encrypted_headers.rar
Normal file
BIN
tests/encrypted_headers.rar
Normal file
Binary file not shown.
BIN
tests/encrypted_only_files.rar
Normal file
BIN
tests/encrypted_only_files.rar
Normal file
Binary file not shown.
BIN
tests/multi.part1.rar
Normal file
BIN
tests/multi.part1.rar
Normal file
Binary file not shown.
BIN
tests/multi.part2.rar
Normal file
BIN
tests/multi.part2.rar
Normal file
Binary file not shown.
BIN
tests/multi.part3.rar
Normal file
BIN
tests/multi.part3.rar
Normal file
Binary file not shown.
BIN
tests/multi_broken.part1.rar
Normal file
BIN
tests/multi_broken.part1.rar
Normal file
Binary file not shown.
9
tests/rar_notrar.rar
Normal file
9
tests/rar_notrar.rar
Normal file
@@ -0,0 +1,9 @@
|
||||
6TGStcOyuEWU8uIuUALyOj7+iCAgQNcpGomfIg1QBpnXaiT93Ie8RbflCUO8u/1Z4hKNrieUqfoz
|
||||
R8hO/foBjEosLYUxjjMMqg7JYNd//Mp8UNqcI/0Ao8tXUfAdpKzNu2N3gYV99xRG3yUOWeAXI1Gx
|
||||
CaTj0uHuyzUQbskZdxInMqzajd9f9GVjpgrrz3sJNYMAT1qnFbCfXvRynv+Aby3TAiZKgnPVxuLs
|
||||
VpaieK8VmL0fNzIqoPSUqyMn+9t8fd/fuJmvkXSl/et7YSsE/4hmSGf1XPLw0khH7jmnyTMxh7BF
|
||||
VLjAt0bypII0tWZsQG7tHFtUb4UG2Np5Wt8ejCowkIHrBsUdZ4ALnySQmmqtakkqeFr73YPrhKGr
|
||||
y7ZeQb2sCAPv/NbDMj3q6JeeiIbBNx0OS2oIf1UVbU8fzvbDdZnd579K/b0YP3B7wKK5P54fd9eg
|
||||
kiapUkMAcFv7rSFBDGpszDhQFWpWJBY2OJCrAz0B+ZLymTYxiiirT4wTrTerAExTVHlHJF2r66m7
|
||||
VvXnJ+f6VnqIkSSFhAiHfT1ckCyGcTHBU7wy5ODDDsvUy7dZ2/eq1OhhnPS0lpvZLUiDtAAnBMcq
|
||||
axoA18HW9yccAh8BAnbQ/H7fIXqc4P3zA5CnxjAal25HE+3IVT4DCqOpT27aZvb/fJIkZDeXxwYv
|
||||
BIN
tests/rar_unicode.rar
Normal file
BIN
tests/rar_unicode.rar
Normal file
Binary file not shown.
BIN
tests/solid.rar
Normal file
BIN
tests/solid.rar
Normal file
Binary file not shown.
BIN
tests/store_method.rar
Normal file
BIN
tests/store_method.rar
Normal file
Binary file not shown.
@@ -1,41 +1,40 @@
|
||||
****** ***** ****** unRAR - free utility for RAR archives
|
||||
****** ***** ****** UnRAR - free utility for RAR archives
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
****** ******* ****** License for use and distribution of
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
** ** ** ** ** ** FREE portable version
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The source code of unRAR utility is freeware. This means:
|
||||
The source code of UnRAR utility is freeware. This means:
|
||||
|
||||
1. All copyrights to RAR and the utility unRAR are exclusively
|
||||
owned by the author - Eugene Roshal.
|
||||
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||
owned by the author - Alexander Roshal.
|
||||
|
||||
2. The unRAR sources may be used in any software to handle RAR
|
||||
2. The UnRAR sources may be used in any software to handle RAR
|
||||
archives without limitations free of charge, but cannot be used
|
||||
to re-create the RAR compression algorithm, which is proprietary.
|
||||
Distribution of modified unRAR sources in separate form or as a
|
||||
Distribution of modified UnRAR sources in separate form or as a
|
||||
part of other software is permitted, provided that it is clearly
|
||||
stated in the documentation and source comments that the code may
|
||||
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||
|
||||
3. The unRAR utility may be freely distributed. No person or company
|
||||
may charge a fee for the distribution of unRAR without written
|
||||
permission from the copyright holder.
|
||||
3. The UnRAR utility may be freely distributed. It is allowed
|
||||
to distribute UnRAR inside of other software packages.
|
||||
|
||||
4. THE RAR ARCHIVER AND THE UNRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||
4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
||||
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
||||
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
||||
OR MISUSING THIS SOFTWARE.
|
||||
|
||||
5. Installing and using the unRAR utility signifies acceptance of
|
||||
5. Installing and using the UnRAR utility signifies acceptance of
|
||||
these terms and conditions of the license.
|
||||
|
||||
6. If you don't agree with terms of the license you must remove
|
||||
unRAR files from your storage devices and cease to use the
|
||||
UnRAR files from your storage devices and cease to use the
|
||||
utility.
|
||||
|
||||
Thank you for your interest in RAR and unRAR.
|
||||
Thank you for your interest in RAR and UnRAR.
|
||||
|
||||
|
||||
Eugene Roshal
|
||||
Alexander L. Roshal
|
||||
@@ -15,20 +15,18 @@
|
||||
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
|
||||
in rartypes.hpp.
|
||||
|
||||
It is important to provide 1 byte alignment for structures
|
||||
in model.hpp. Now it contains '#pragma pack(1)' directive,
|
||||
but your compiler may require something else. Though Unrar
|
||||
should work with other model.hpp alignments, its memory
|
||||
requirements may increase significantly. Alignment in other
|
||||
modules is not important.
|
||||
if computer architecture does not allow not aligned data access,
|
||||
you need to undefine ALLOW_NOT_ALIGNED_INT and define
|
||||
STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory
|
||||
requirements.
|
||||
|
||||
If you use Borland C++ makefile (makefile.bcc), you need to define
|
||||
BASEPATHCC environment (or makefile) variable containing
|
||||
the path to Borland C++ installation.
|
||||
|
||||
Makefile.unix contains both Linux and IRIX compiler option sets.
|
||||
Linux is selected by default. If you need to compile Unrar for IRIX,
|
||||
just uncomment corresponding lines.
|
||||
Makefile.unix contains numerous compiler option sets.
|
||||
GCC Linux is selected by default. If you need to compile Unrar
|
||||
for other platforms, uncomment corresponding lines.
|
||||
|
||||
|
||||
2. Unrar binaries
|
||||
@@ -42,13 +40,14 @@
|
||||
|
||||
This source includes parts of code written by the following authors:
|
||||
|
||||
Dmitry Shkarin PPMII text compression
|
||||
Dmitry Shkarin PPMII v.H text compression
|
||||
Dmitry Subbotin Carryless rangecoder
|
||||
Szymon Stefanek AES encryption
|
||||
Brian Gladman AES encryption
|
||||
Steve Reid SHA-1 hash function
|
||||
Marcus Herbert makefile.unix file
|
||||
Tomasz Klim fixes for libunrar.so
|
||||
Robert Riebisch makefile.dj and patches for DJGPP
|
||||
|
||||
|
||||
4. Legal stuff
|
||||
|
||||
@@ -4,12 +4,13 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
return(false);
|
||||
SaveFilePos SavePos(*this);
|
||||
|
||||
ushort CmtLength;
|
||||
#ifndef SFX_MODULE
|
||||
ushort CmtLength;
|
||||
if (OldFormat)
|
||||
{
|
||||
Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET);
|
||||
CmtLength=GetByte()+(GetByte()<<8);
|
||||
CmtLength=GetByte();
|
||||
CmtLength+=(GetByte()<<8);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -46,9 +47,14 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
uint UnpCmtLength;
|
||||
if (OldFormat)
|
||||
{
|
||||
UnpCmtLength=GetByte()+(GetByte()<<8);
|
||||
#ifdef NOCRYPT
|
||||
return(false);
|
||||
#else
|
||||
UnpCmtLength=GetByte();
|
||||
UnpCmtLength+=(GetByte()<<8);
|
||||
CmtLength-=2;
|
||||
DataIO.SetCmt13Encryption();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
UnpCmtLength=CommHead.UnpSize;
|
||||
@@ -66,8 +72,8 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char *UnpData;
|
||||
uint UnpDataSize;
|
||||
byte *UnpData;
|
||||
size_t UnpDataSize;
|
||||
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
|
||||
CmtData->Alloc(UnpDataSize);
|
||||
memcpy(&((*CmtData)[0]),UnpData,UnpDataSize);
|
||||
@@ -90,8 +96,8 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE)
|
||||
if (CmtData->Size()>0)
|
||||
{
|
||||
int CmtSize=CmtData->Size();
|
||||
OemToCharBuff((char *)CmtData->Addr(),(char *)CmtData->Addr(),CmtSize);
|
||||
size_t CmtSize=CmtData->Size();
|
||||
OemToCharBuff((char *)CmtData->Addr(),(char *)CmtData->Addr(),(DWORD)CmtSize);
|
||||
|
||||
if (CmtDataW!=NULL)
|
||||
{
|
||||
@@ -107,19 +113,19 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
}
|
||||
|
||||
|
||||
int Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
size_t Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
{
|
||||
bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
|
||||
if (!ReadSubData(CmtData,NULL))
|
||||
return(0);
|
||||
int CmtSize=CmtData->Size();
|
||||
size_t CmtSize=CmtData->Size();
|
||||
if (Unicode)
|
||||
{
|
||||
CmtSize/=2;
|
||||
Array<wchar> DataW(CmtSize+1);
|
||||
RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
|
||||
DataW[CmtSize]=0;
|
||||
int DestSize=CmtSize*4;
|
||||
size_t DestSize=CmtSize*4;
|
||||
CmtData->Alloc(DestSize+1);
|
||||
WideToChar(DataW.Addr(),(char *)CmtData->Addr(),DestSize);
|
||||
(*CmtData)[DestSize]=0;
|
||||
@@ -152,7 +158,7 @@ void Archive::ViewComment()
|
||||
Array<byte> CmtBuf;
|
||||
if (GetComment(&CmtBuf,NULL))
|
||||
{
|
||||
int CmtSize=CmtBuf.Size();
|
||||
size_t CmtSize=CmtBuf.Size();
|
||||
char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize);
|
||||
if (ChPtr!=NULL)
|
||||
CmtSize=ChPtr-(char *)&CmtBuf[0];
|
||||
@@ -175,10 +181,10 @@ void Archive::ViewFileComment()
|
||||
Array<char> CmtBuf(MaxSize);
|
||||
SaveFilePos SavePos(*this);
|
||||
Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
|
||||
Int64 SaveCurBlockPos=CurBlockPos;
|
||||
Int64 SaveNextBlockPos=NextBlockPos;
|
||||
int64 SaveCurBlockPos=CurBlockPos;
|
||||
int64 SaveNextBlockPos=NextBlockPos;
|
||||
|
||||
int Size=ReadHeader();
|
||||
size_t Size=ReadHeader();
|
||||
|
||||
CurBlockPos=SaveCurBlockPos;
|
||||
NextBlockPos=SaveNextBlockPos;
|
||||
|
||||
@@ -57,7 +57,7 @@ void Archive::CheckArc(bool EnableBroken)
|
||||
if (!IsArchive(EnableBroken))
|
||||
{
|
||||
Log(FileName,St(MBadArc),FileName);
|
||||
ErrHandler.Exit(RAR_FATAL_ERROR);
|
||||
ErrHandler.Exit(FATAL_ERROR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -132,7 +132,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
else
|
||||
{
|
||||
Array<char> Buffer(MAXSFXSIZE);
|
||||
long CurPos=int64to32(Tell());
|
||||
long CurPos=(long)Tell();
|
||||
int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
|
||||
for (int I=0;I<ReadSize;I++)
|
||||
if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I]))
|
||||
@@ -186,7 +186,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
#else
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
Log(FileName,St(MUnknownMeth),FileName);
|
||||
Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
|
||||
@@ -197,13 +197,17 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
#ifdef RARDLL
|
||||
SilentOpen=true;
|
||||
#endif
|
||||
|
||||
//if not encrypted, we'll check it below
|
||||
NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0;
|
||||
|
||||
if (!SilentOpen || !Encrypted)
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
Int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||
|
||||
NotFirstVolume=false;
|
||||
while (ReadHeader())
|
||||
while (ReadHeader()!=0)
|
||||
{
|
||||
int HeaderType=GetHeaderType();
|
||||
if (HeaderType==NEWSUB_HEAD)
|
||||
@@ -226,6 +230,12 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
CurBlockPos=SaveCurBlockPos;
|
||||
NextBlockPos=SaveNextBlockPos;
|
||||
}
|
||||
if (!Volume || !NotFirstVolume)
|
||||
{
|
||||
strcpy(FirstVolumeName,FileName);
|
||||
strcpyw(FirstVolumeNameW,FileNameW);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,13 +10,11 @@ class Archive:public File
|
||||
private:
|
||||
bool IsSignature(byte *D);
|
||||
void UpdateLatestTime(FileHeader *CurBlock);
|
||||
void Protect(int RecSectors);
|
||||
void ConvertNameCase(char *Name);
|
||||
void ConvertNameCase(wchar *Name);
|
||||
void ConvertUnknownHeader();
|
||||
bool AddArcComment(char *NameToShow);
|
||||
int ReadOldHeader();
|
||||
void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array<byte> &TimeData);
|
||||
size_t ReadOldHeader();
|
||||
void UnexpEndArcMsg();
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
|
||||
CryptData HeadersCrypt;
|
||||
@@ -32,7 +30,7 @@ class Archive:public File
|
||||
OldMainHeader OldMhd;
|
||||
|
||||
int RecoverySectors;
|
||||
Int64 RecoveryPos;
|
||||
int64 RecoveryPos;
|
||||
|
||||
RarTime LatestTime;
|
||||
int LastReadBlock;
|
||||
@@ -42,13 +40,13 @@ class Archive:public File
|
||||
public:
|
||||
Archive(RAROptions *InitCmd=NULL);
|
||||
bool IsArchive(bool EnableBroken);
|
||||
int SearchBlock(int BlockType);
|
||||
int SearchSubBlock(const char *Type);
|
||||
size_t SearchBlock(int BlockType);
|
||||
size_t SearchSubBlock(const char *Type);
|
||||
int ReadBlock(int BlockType);
|
||||
void WriteBlock(int BlockType,BaseBlock *wb=NULL);
|
||||
int PrepareNamesToWrite(char *Name,wchar *NameW,char *DestName,byte *DestNameW);
|
||||
void SetLhdSize();
|
||||
int ReadHeader();
|
||||
size_t ReadHeader();
|
||||
void CheckArc(bool EnableBroken);
|
||||
void CheckOpen(char *Name,wchar *NameW=NULL);
|
||||
bool WCheckOpen(char *Name,wchar *NameW=NULL);
|
||||
@@ -72,12 +70,12 @@ class Archive:public File
|
||||
bool IsArcLabel();
|
||||
void ConvertAttributes();
|
||||
int GetRecoverySize(bool Required);
|
||||
void VolSubtractHeaderSize(int SubSize);
|
||||
void AddSubData(byte *SrcData,int DataSize,File *SrcFile,char *Name,bool AllowSplit);
|
||||
void VolSubtractHeaderSize(size_t SubSize);
|
||||
void AddSubData(byte *SrcData,size_t DataSize,File *SrcFile,const char *Name,bool AllowSplit);
|
||||
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
|
||||
int GetHeaderType() {return(CurHeaderType);};
|
||||
int ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW);
|
||||
void WriteCommentData(byte *Data,int DataSize,bool FileComment);
|
||||
size_t ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW);
|
||||
void WriteCommentData(byte *Data,size_t DataSize,bool FileComment);
|
||||
RAROptions* GetRAROptions() {return(Cmd);}
|
||||
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
|
||||
|
||||
@@ -96,8 +94,8 @@ class Archive:public File
|
||||
EAHeader EAHead;
|
||||
StreamHeader StreamHead;
|
||||
|
||||
Int64 CurBlockPos;
|
||||
Int64 NextBlockPos;
|
||||
int64 CurBlockPos;
|
||||
int64 NextBlockPos;
|
||||
|
||||
bool OldFormat;
|
||||
bool Solid;
|
||||
@@ -108,16 +106,16 @@ class Archive:public File
|
||||
bool NotFirstVolume;
|
||||
bool Protected;
|
||||
bool Encrypted;
|
||||
uint SFXSize;
|
||||
size_t SFXSize;
|
||||
bool BrokenFileHeader;
|
||||
|
||||
bool Splitting;
|
||||
|
||||
ushort HeaderCRC;
|
||||
|
||||
Int64 VolWrite;
|
||||
Int64 AddingFilesSize;
|
||||
uint AddingHeadersSize;
|
||||
int64 VolWrite;
|
||||
int64 AddingFilesSize;
|
||||
size_t AddingHeadersSize;
|
||||
|
||||
bool NewArchive;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
int Archive::SearchBlock(int BlockType)
|
||||
size_t Archive::SearchBlock(int BlockType)
|
||||
{
|
||||
int Size,Count=0;
|
||||
size_t Size,Count=0;
|
||||
while ((Size=ReadHeader())!=0 &&
|
||||
(BlockType==ENDARC_HEAD || GetHeaderType()!=ENDARC_HEAD))
|
||||
{
|
||||
@@ -16,9 +16,9 @@ int Archive::SearchBlock(int BlockType)
|
||||
}
|
||||
|
||||
|
||||
int Archive::SearchSubBlock(const char *Type)
|
||||
size_t Archive::SearchSubBlock(const char *Type)
|
||||
{
|
||||
int Size;
|
||||
size_t Size;
|
||||
while ((Size=ReadHeader())!=0 && GetHeaderType()!=ENDARC_HEAD)
|
||||
{
|
||||
if (GetHeaderType()==NEWSUB_HEAD && SubHead.CmpName(Type))
|
||||
@@ -29,7 +29,20 @@ int Archive::SearchSubBlock(const char *Type)
|
||||
}
|
||||
|
||||
|
||||
int Archive::ReadHeader()
|
||||
void Archive::UnexpEndArcMsg()
|
||||
{
|
||||
int64 ArcSize=FileLength();
|
||||
if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
|
||||
{
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MLogUnexpEOF));
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t Archive::ReadHeader()
|
||||
{
|
||||
CurBlockPos=Tell();
|
||||
|
||||
@@ -40,7 +53,7 @@ int Archive::ReadHeader()
|
||||
|
||||
RawRead Raw(this);
|
||||
|
||||
bool Decrypt=Encrypted && CurBlockPos>=SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;
|
||||
bool Decrypt=Encrypted && CurBlockPos>=(int64)SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;
|
||||
|
||||
if (Decrypt)
|
||||
{
|
||||
@@ -48,21 +61,25 @@ int Archive::ReadHeader()
|
||||
return(0);
|
||||
#else
|
||||
if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
|
||||
{
|
||||
UnexpEndArcMsg();
|
||||
return(0);
|
||||
}
|
||||
if (*Cmd->Password==0)
|
||||
#ifdef RARDLL
|
||||
if (Cmd->Callback==NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1)
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,sizeof(Cmd->Password))==-1)
|
||||
{
|
||||
Close();
|
||||
ErrHandler.Exit(RAR_USER_BREAK);
|
||||
//ErrHandler.Exit(USER_BREAK); original
|
||||
ErrHandler.Exit(NO_PASSWORD_ERROR);
|
||||
}
|
||||
|
||||
#else
|
||||
if (!GetPassword(PASSWORD_ARCHIVE,FileName,Cmd->Password,sizeof(Cmd->Password)))
|
||||
{
|
||||
Close();
|
||||
ErrHandler.Exit(RAR_USER_BREAK);
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
}
|
||||
#endif
|
||||
HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
|
||||
@@ -73,14 +90,7 @@ int Archive::ReadHeader()
|
||||
Raw.Read(SIZEOF_SHORTBLOCKHEAD);
|
||||
if (Raw.Size()==0)
|
||||
{
|
||||
Int64 ArcSize=FileLength();
|
||||
if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
|
||||
{
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MLogUnexpEOF));
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
}
|
||||
UnexpEndArcMsg();
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -96,7 +106,7 @@ int Archive::ReadHeader()
|
||||
Log(FileName,St(MLogFileHead),"???");
|
||||
#endif
|
||||
BrokenFileHeader=true;
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -150,28 +160,33 @@ int Archive::ReadHeader()
|
||||
hd->HighPackSize=hd->HighUnpSize=0;
|
||||
if (hd->UnpSize==0xffffffff)
|
||||
{
|
||||
hd->UnpSize=int64to32(INT64MAX);
|
||||
hd->HighUnpSize=int64to32(INT64MAX>>32);
|
||||
// UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
|
||||
// that we do not know the unpacked file size and must unpack it
|
||||
// until we find the end of file marker in compressed data.
|
||||
hd->UnpSize=(uint)(INT64NDF);
|
||||
hd->HighUnpSize=(uint)(INT64NDF>>32);
|
||||
}
|
||||
}
|
||||
hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize);
|
||||
hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize);
|
||||
hd->FullPackSize=INT32TO64(hd->HighPackSize,hd->PackSize);
|
||||
hd->FullUnpSize=INT32TO64(hd->HighUnpSize,hd->UnpSize);
|
||||
|
||||
char FileName[NM*4];
|
||||
int NameSize=Min(hd->NameSize,sizeof(FileName)-1);
|
||||
Raw.Get((byte *)FileName,NameSize);
|
||||
FileName[NameSize]=0;
|
||||
|
||||
strncpy(hd->FileName,FileName,sizeof(hd->FileName));
|
||||
hd->FileName[sizeof(hd->FileName)-1]=0;
|
||||
strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));
|
||||
|
||||
if (hd->HeadType==NEWSUB_HEAD)
|
||||
{
|
||||
// Let's calculate the size of optional data.
|
||||
int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
|
||||
if (hd->Flags & LHD_SALT)
|
||||
DataSize-=SALT_SIZE;
|
||||
if (DataSize>0)
|
||||
{
|
||||
// Here we read optional additional fields for subheaders.
|
||||
// They are stored after the file name and before salt.
|
||||
hd->SubData.Alloc(DataSize);
|
||||
Raw.Get(&hd->SubData[0],DataSize);
|
||||
if (hd->CmpName(SUBHEAD_TYPE_RR))
|
||||
@@ -187,7 +202,7 @@ int Archive::ReadHeader()
|
||||
if (hd->Flags & LHD_UNICODE)
|
||||
{
|
||||
EncodeFileName NameCoder;
|
||||
int Length=strlen(FileName);
|
||||
size_t Length=strlen(FileName);
|
||||
if (Length==hd->NameSize)
|
||||
{
|
||||
UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
|
||||
@@ -262,7 +277,7 @@ int Archive::ReadHeader()
|
||||
if (hd->HeadType==NEWSUB_HEAD)
|
||||
strcat(hd->FileName,"- ???");
|
||||
BrokenFileHeader=true;
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
#ifndef SHELL_EXT
|
||||
Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
|
||||
Alarm();
|
||||
@@ -371,8 +386,10 @@ int Archive::ReadHeader()
|
||||
bool Recovered=false;
|
||||
if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0)
|
||||
{
|
||||
// Last 7 bytes of recovered volume can contain zeroes, because
|
||||
// REV files store its own information (volume number, etc.) here.
|
||||
SaveFilePos SavePos(*this);
|
||||
Int64 Length=Tell();
|
||||
int64 Length=Tell();
|
||||
Seek(Length-7,SEEK_SET);
|
||||
Recovered=true;
|
||||
for (int J=0;J<7;J++)
|
||||
@@ -387,9 +404,9 @@ int Archive::ReadHeader()
|
||||
Close();
|
||||
|
||||
BrokenFileHeader=true;
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return(0);
|
||||
// ErrHandler.Exit(RAR_CRC_ERROR);
|
||||
// ErrHandler.Exit(CRC_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,7 +417,7 @@ int Archive::ReadHeader()
|
||||
Log(FileName,St(MLogFileHead),"???");
|
||||
#endif
|
||||
BrokenFileHeader=true;
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return(0);
|
||||
}
|
||||
return(Raw.Size());
|
||||
@@ -408,10 +425,10 @@ int Archive::ReadHeader()
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int Archive::ReadOldHeader()
|
||||
size_t Archive::ReadOldHeader()
|
||||
{
|
||||
RawRead Raw(this);
|
||||
if (CurBlockPos<=SFXSize)
|
||||
if (CurBlockPos<=(int64)SFXSize)
|
||||
{
|
||||
Raw.Read(SIZEOF_OLDMHD);
|
||||
Raw.Get(OldMhd.Mark,4);
|
||||
@@ -530,25 +547,46 @@ void Archive::ConvertAttributes()
|
||||
}
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
// umask defines which permission bits must not be set by default
|
||||
// when creating a file or directory.
|
||||
static mode_t mask = (mode_t) -1;
|
||||
|
||||
if (mask == (mode_t) -1)
|
||||
{
|
||||
// umask call returns the current umask value. Argument (022) is not
|
||||
// important here.
|
||||
mask = umask(022);
|
||||
|
||||
// Restore the original umask value, which was changed to 022 above.
|
||||
umask(mask);
|
||||
}
|
||||
|
||||
switch(NewLhd.HostOS)
|
||||
{
|
||||
case HOST_MSDOS:
|
||||
case HOST_OS2:
|
||||
case HOST_WIN32:
|
||||
if (NewLhd.FileAttr & 0x10)
|
||||
NewLhd.FileAttr=0x41ff & ~mask;
|
||||
else
|
||||
if (NewLhd.FileAttr & 1)
|
||||
NewLhd.FileAttr=0x8124 & ~mask;
|
||||
{
|
||||
// Mapping MSDOS, OS/2 and Windows file attributes to Unix.
|
||||
|
||||
if (NewLhd.FileAttr & 0x10) // FILE_ATTRIBUTE_DIRECTORY
|
||||
{
|
||||
// For directories we use 0777 mask.
|
||||
NewLhd.FileAttr=0777 & ~mask;
|
||||
}
|
||||
else
|
||||
NewLhd.FileAttr=0x81b6 & ~mask;
|
||||
if (NewLhd.FileAttr & 1) // FILE_ATTRIBUTE_READONLY
|
||||
{
|
||||
// For read only files we use 0444 mask with 'w' bits turned off.
|
||||
NewLhd.FileAttr=0444 & ~mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
// umask does not set +x for regular files, so we use 0666
|
||||
// instead of 0777 as for directories.
|
||||
NewLhd.FileAttr=0666 & ~mask;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOST_UNIX:
|
||||
case HOST_BEOS:
|
||||
@@ -583,10 +621,34 @@ void Archive::ConvertUnknownHeader()
|
||||
if ((byte)*s<32 || (byte)*s>127)
|
||||
*s='_';
|
||||
#endif
|
||||
|
||||
#if defined(_WIN_32) || defined(_EMX)
|
||||
// ':' in file names is allowed in Unix, but not in Windows.
|
||||
// Even worse, file data will be written to NTFS stream on NTFS,
|
||||
// so automatic name correction on file create error in extraction
|
||||
// routine does not work. In Windows and DOS versions we better
|
||||
// replace ':' now.
|
||||
if (*s==':')
|
||||
*s='_';
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
for (wchar *s=NewLhd.FileNameW;*s!=0;s++)
|
||||
{
|
||||
if (*s=='/' || *s=='\\')
|
||||
*s=CPATHDIVIDER;
|
||||
|
||||
#if defined(_WIN_32) || defined(_EMX)
|
||||
// ':' in file names is allowed in Unix, but not in Windows.
|
||||
// Even worse, file data will be written to NTFS stream on NTFS,
|
||||
// so automatic name correction on file create error in extraction
|
||||
// routine does not work. In Windows and DOS versions we better
|
||||
// replace ':' now.
|
||||
if (*s==':')
|
||||
*s='_';
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -598,7 +660,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MSubHeadCorrupt));
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return(false);
|
||||
}
|
||||
if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>/*PACK_VER*/36)
|
||||
@@ -631,7 +693,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
|
||||
SubDataIO.EnableShowProgress(false);
|
||||
SubDataIO.SetFiles(this,DestFile);
|
||||
SubDataIO.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER);
|
||||
SubDataIO.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER)!=0;
|
||||
SubDataIO.SetSubHeader(&SubHead,NULL);
|
||||
Unpack.SetDestSize(SubHead.UnpSize);
|
||||
if (SubHead.Method==0x30)
|
||||
@@ -644,7 +706,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MSubHeadDataCRC),SubHead.FileName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
if (UnpData!=NULL)
|
||||
UnpData->Reset();
|
||||
return(false);
|
||||
|
||||
@@ -7,17 +7,17 @@ template <class T> class Array
|
||||
{
|
||||
private:
|
||||
T *Buffer;
|
||||
int BufSize;
|
||||
int AllocSize;
|
||||
size_t BufSize;
|
||||
size_t AllocSize;
|
||||
public:
|
||||
Array();
|
||||
Array(int Size);
|
||||
Array(size_t Size);
|
||||
~Array();
|
||||
inline void CleanData();
|
||||
inline T& operator [](int Item);
|
||||
inline int Size();
|
||||
void Add(int Items);
|
||||
void Alloc(int Items);
|
||||
inline T& operator [](size_t Item);
|
||||
inline size_t Size();
|
||||
void Add(size_t Items);
|
||||
void Alloc(size_t Items);
|
||||
void Reset();
|
||||
void operator = (Array<T> &Src);
|
||||
void Push(T Item);
|
||||
@@ -38,7 +38,7 @@ template <class T> Array<T>::Array()
|
||||
}
|
||||
|
||||
|
||||
template <class T> Array<T>::Array(int Size)
|
||||
template <class T> Array<T>::Array(size_t Size)
|
||||
{
|
||||
Buffer=(T *)rarmalloc(sizeof(T)*Size);
|
||||
if (Buffer==NULL && Size!=0)
|
||||
@@ -55,25 +55,25 @@ template <class T> Array<T>::~Array()
|
||||
}
|
||||
|
||||
|
||||
template <class T> inline T& Array<T>::operator [](int Item)
|
||||
template <class T> inline T& Array<T>::operator [](size_t Item)
|
||||
{
|
||||
return(Buffer[Item]);
|
||||
}
|
||||
|
||||
|
||||
template <class T> inline int Array<T>::Size()
|
||||
template <class T> inline size_t Array<T>::Size()
|
||||
{
|
||||
return(BufSize);
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::Add(int Items)
|
||||
template <class T> void Array<T>::Add(size_t Items)
|
||||
{
|
||||
BufSize+=Items;
|
||||
if (BufSize>AllocSize)
|
||||
{
|
||||
int Suggested=AllocSize+AllocSize/4+32;
|
||||
int NewSize=Max(BufSize,Suggested);
|
||||
size_t Suggested=AllocSize+AllocSize/4+32;
|
||||
size_t NewSize=Max(BufSize,Suggested);
|
||||
|
||||
Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T));
|
||||
if (Buffer==NULL)
|
||||
@@ -83,7 +83,7 @@ template <class T> void Array<T>::Add(int Items)
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::Alloc(int Items)
|
||||
template <class T> void Array<T>::Alloc(size_t Items)
|
||||
{
|
||||
if (Items>AllocSize)
|
||||
Add(Items-BufSize);
|
||||
|
||||
@@ -5,7 +5,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return;
|
||||
}
|
||||
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
|
||||
@@ -29,14 +29,14 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return;
|
||||
}
|
||||
int fd = open(FileName,O_WRONLY);
|
||||
if (fd==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (NameSize>=sizeof(Name))
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
memcpy(Name,CurItem+10,NameSize);
|
||||
@@ -59,15 +59,13 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
AttrPos+=10+NameSize+Size;
|
||||
}
|
||||
close(fd);
|
||||
#ifndef GUI
|
||||
mprintf(St(MShowEA));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +79,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
|
||||
if (fd==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,7 +94,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
|
||||
if (NameSize>=sizeof(Name))
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
memcpy(Name,CurItem+10,NameSize);
|
||||
@@ -104,14 +102,12 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
|
||||
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
AttrPos+=10+NameSize+Size;
|
||||
}
|
||||
close(fd);
|
||||
#ifndef GUI
|
||||
mprintf(St(MShowEA));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ void CommandData::Init()
|
||||
*ArcNameW=0;
|
||||
FileLists=false;
|
||||
NoMoreSwitches=false;
|
||||
TimeConverted=false;
|
||||
|
||||
FileArgs=new StringList;
|
||||
ExclArgs=new StringList;
|
||||
@@ -51,14 +50,14 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
|
||||
if (Arg[1]=='-')
|
||||
NoMoreSwitches=true;
|
||||
else
|
||||
ProcessSwitch(&Arg[1]);
|
||||
ProcessSwitch(&Arg[1],(ArgW!=NULL && *ArgW!=0 ? &ArgW[1]:NULL));
|
||||
else
|
||||
if (*Command==0)
|
||||
{
|
||||
strncpy(Command,Arg,sizeof(Command));
|
||||
strncpyz(Command,Arg,ASIZE(Command));
|
||||
if (ArgW!=NULL)
|
||||
strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0]));
|
||||
if (toupper(*Command)=='S')
|
||||
if (etoupper(*Command)=='S')
|
||||
{
|
||||
const char *SFXName=Command[1] ? Command+1:DefSFXName;
|
||||
if (PointToName(SFXName)!=SFXName || FileExist(SFXName))
|
||||
@@ -67,7 +66,7 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
|
||||
GetConfigName(SFXName,SFXModule,true);
|
||||
}
|
||||
#ifndef GUI
|
||||
*Command=toupper(*Command);
|
||||
*Command=etoupper(*Command);
|
||||
if (*Command!='I' && *Command!='S')
|
||||
strupper(Command);
|
||||
#endif
|
||||
@@ -75,19 +74,23 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
|
||||
else
|
||||
if (*ArcName==0)
|
||||
{
|
||||
strncpy(ArcName,Arg,sizeof(ArcName));
|
||||
strncpyz(ArcName,Arg,ASIZE(ArcName));
|
||||
if (ArgW!=NULL)
|
||||
strncpyw(ArcNameW,ArgW,sizeof(ArcNameW)/sizeof(ArcNameW[0]));
|
||||
strncpyzw(ArcNameW,ArgW,ASIZE(ArcNameW));
|
||||
}
|
||||
else
|
||||
{
|
||||
int Length=strlen(Arg);
|
||||
char EndChar=Arg[Length-1];
|
||||
char CmdChar=toupper(*Command);
|
||||
size_t Length=strlen(Arg);
|
||||
char EndChar=Length==0 ? 0:Arg[Length-1];
|
||||
char CmdChar=etoupper(*Command);
|
||||
bool Add=strchr("AFUM",CmdChar)!=NULL;
|
||||
bool Extract=CmdChar=='X' || CmdChar=='E';
|
||||
if ((IsDriveDiv(EndChar) || IsPathDiv(EndChar)) && !Add)
|
||||
strcpy(ExtrPath,Arg);
|
||||
{
|
||||
strncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
||||
if (ArgW!=NULL)
|
||||
strncpyzw(ExtrPathW,ArgW,ASIZE(ExtrPathW));
|
||||
}
|
||||
else
|
||||
if ((Add || CmdChar=='T') && *Arg!='@')
|
||||
FileArgs->AddString(Arg);
|
||||
@@ -98,7 +101,18 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
|
||||
if (!Found && *Arg=='@' && !IsWildcard(Arg))
|
||||
{
|
||||
FileLists=true;
|
||||
ReadTextFile(Arg+1,FileArgs,false,true,true,true,true);
|
||||
|
||||
RAR_CHARSET Charset=FilelistCharset;
|
||||
|
||||
#if defined(_WIN_32) && !defined(GUI)
|
||||
// for compatibility reasons we use OEM encoding
|
||||
// in Win32 console version by default
|
||||
|
||||
if (Charset==RCH_DEFAULT)
|
||||
Charset=RCH_OEM;
|
||||
#endif
|
||||
|
||||
ReadTextFile(Arg+1,FileArgs,false,true,Charset,true,true,true);
|
||||
}
|
||||
else
|
||||
if (Found && FileData.IsDir && Extract && *ExtrPath==0)
|
||||
@@ -118,10 +132,10 @@ void CommandData::ParseDone()
|
||||
{
|
||||
if (FileArgs->ItemsCount()==0 && !FileLists)
|
||||
FileArgs->AddString(MASKALL);
|
||||
char CmdChar=toupper(*Command);
|
||||
bool Extract=CmdChar=='X' || CmdChar=='E';
|
||||
char CmdChar=etoupper(*Command);
|
||||
bool Extract=CmdChar=='X' || CmdChar=='E' || CmdChar=='P';
|
||||
if (Test && Extract)
|
||||
Test=false;
|
||||
Test=false; // Switch '-t' is senseless for 'X', 'E', 'P' commands.
|
||||
BareOutput=(CmdChar=='L' || CmdChar=='V') && Command[1]=='B';
|
||||
}
|
||||
|
||||
@@ -136,20 +150,35 @@ void CommandData::ParseEnvVar()
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SFX_MODULE)
|
||||
|
||||
// return 'false' if -cfg- is present and preprocess switches
|
||||
// which must be processed before the rest of command line
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
bool CommandData::IsConfigEnabled(int argc,char *argv[])
|
||||
{
|
||||
bool ConfigEnabled=true;
|
||||
for (int I=1;I<argc;I++)
|
||||
if (IsSwitch(*argv[I]))
|
||||
{
|
||||
if (stricomp(&argv[I][1],"-")==0)
|
||||
break;
|
||||
if (stricomp(&argv[I][1],"cfg-")==0)
|
||||
ConfigEnabled=false;
|
||||
#ifndef GUI
|
||||
if (strnicomp(&argv[I][1],"ilog",4)==0)
|
||||
{
|
||||
// ensure that correct log file name is already set
|
||||
// if we need to report an error when processing the command line
|
||||
ProcessSwitch(&argv[I][1]);
|
||||
InitLogOptions(LogName);
|
||||
}
|
||||
#endif
|
||||
if (strnicomp(&argv[I][1],"sc",2)==0)
|
||||
{
|
||||
// Process -sc before reading any file lists.
|
||||
ProcessSwitch(&argv[I][1]);
|
||||
}
|
||||
}
|
||||
return(ConfigEnabled);
|
||||
}
|
||||
@@ -165,7 +194,7 @@ void CommandData::ReadConfig(int argc,char *argv[])
|
||||
char *Str;
|
||||
while ((Str=List.GetString())!=NULL)
|
||||
{
|
||||
while (isspace(*Str))
|
||||
while (IsSpace(*Str))
|
||||
Str++;
|
||||
if (strnicomp(Str,"switches=",9)==0)
|
||||
ProcessSwitchesString(Str+9);
|
||||
@@ -198,15 +227,15 @@ void CommandData::ProcessSwitchesString(char *Str)
|
||||
|
||||
|
||||
#if !defined(SFX_MODULE)
|
||||
void CommandData::ProcessSwitch(char *Switch)
|
||||
void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
{
|
||||
|
||||
switch(toupper(Switch[0]))
|
||||
switch(etoupper(Switch[0]))
|
||||
{
|
||||
case 'I':
|
||||
if (strnicomp(&Switch[1],"LOG",3)==0)
|
||||
{
|
||||
strncpy(LogName,Switch[4] ? Switch+4:DefLogName,sizeof(LogName));
|
||||
strncpyz(LogName,Switch[4] ? Switch+4:DefLogName,ASIZE(LogName));
|
||||
break;
|
||||
}
|
||||
if (stricomp(&Switch[1],"SND")==0)
|
||||
@@ -221,7 +250,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
if (strnicomp(&Switch[1],"EML",3)==0)
|
||||
{
|
||||
strncpy(EmailTo,Switch[4] ? Switch+4:"@",sizeof(EmailTo));
|
||||
strncpyz(EmailTo,Switch[4] ? Switch+4:"@",ASIZE(EmailTo));
|
||||
EmailTo[sizeof(EmailTo)-1]=0;
|
||||
break;
|
||||
}
|
||||
@@ -230,10 +259,10 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
MsgStream=MSG_NULL;
|
||||
break;
|
||||
}
|
||||
if (toupper(Switch[1])=='D')
|
||||
if (etoupper(Switch[1])=='D')
|
||||
{
|
||||
for (int I=2;Switch[I]!=0;I++)
|
||||
switch(toupper(Switch[I]))
|
||||
switch(etoupper(Switch[I]))
|
||||
{
|
||||
case 'Q':
|
||||
MsgStream=MSG_ERRONLY;
|
||||
@@ -257,7 +286,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 'K':
|
||||
ArcTime=ARCTIME_KEEP;
|
||||
@@ -293,7 +322,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
Mode=(EXTTIME_MODE)(Switch[3]-'0');
|
||||
if (Switch[3]=='-')
|
||||
Mode=EXTTIME_NONE;
|
||||
switch(toupper(Switch[2]))
|
||||
switch(etoupper(Switch[2]))
|
||||
{
|
||||
case 'M':
|
||||
xmtime=Mode;
|
||||
@@ -323,7 +352,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 'C':
|
||||
ClearArc=true;
|
||||
@@ -337,9 +366,12 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
else
|
||||
{
|
||||
GenerateArcName=true;
|
||||
strncpy(GenerateMask,Switch+2,sizeof(GenerateMask));
|
||||
strncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
IgnoreGeneralAttr=true;
|
||||
break;
|
||||
case 'N': //reserved for archive name
|
||||
break;
|
||||
case 'O':
|
||||
@@ -347,15 +379,20 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
break;
|
||||
case 'P':
|
||||
strcpy(ArcPath,Switch+2);
|
||||
if (SwitchW!=NULL && *SwitchW!=0)
|
||||
strcpyw(ArcPathW,SwitchW+2);
|
||||
break;
|
||||
case 'S':
|
||||
SyncFiles=true;
|
||||
break;
|
||||
default:
|
||||
BadSwitch(Switch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
if (Switch[2]==0)
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 'S':
|
||||
DisableSortSolid=true;
|
||||
@@ -369,7 +406,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case '+':
|
||||
Overwrite=OVERWRITE_ALL;
|
||||
@@ -377,6 +414,9 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
case '-':
|
||||
Overwrite=OVERWRITE_NONE;
|
||||
break;
|
||||
case 0:
|
||||
Overwrite=OVERWRITE_FORCE_ASK;
|
||||
break;
|
||||
case 'R':
|
||||
Overwrite=OVERWRITE_AUTORENAME;
|
||||
break;
|
||||
@@ -402,13 +442,13 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 0:
|
||||
Recurse=RECURSE_ALWAYS;
|
||||
break;
|
||||
case '-':
|
||||
Recurse=0;
|
||||
Recurse=RECURSE_DISABLE;
|
||||
break;
|
||||
case '0':
|
||||
Recurse=RECURSE_WILDCARDS;
|
||||
@@ -436,15 +476,27 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
case 'X':
|
||||
if (Switch[1]!=0)
|
||||
{
|
||||
StringList *Args=toupper(Switch[0])=='N' ? InclArgs:ExclArgs;
|
||||
StringList *Args=etoupper(Switch[0])=='N' ? InclArgs:ExclArgs;
|
||||
if (Switch[1]=='@' && !IsWildcard(Switch))
|
||||
ReadTextFile(Switch+2,Args,false,true,true,true,true);
|
||||
{
|
||||
RAR_CHARSET Charset=FilelistCharset;
|
||||
|
||||
#if defined(_WIN_32) && !defined(GUI)
|
||||
// for compatibility reasons we use OEM encoding
|
||||
// in Win32 console version by default
|
||||
|
||||
if (Charset==RCH_DEFAULT)
|
||||
Charset=RCH_OEM;
|
||||
#endif
|
||||
|
||||
ReadTextFile(Switch+2,Args,false,true,Charset,true,true,true);
|
||||
}
|
||||
else
|
||||
Args->AddString(Switch+1);
|
||||
}
|
||||
break;
|
||||
case 'E':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 'P':
|
||||
switch(Switch[2])
|
||||
@@ -463,9 +515,6 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
ExclEmptyDir=true;
|
||||
break;
|
||||
case 'E':
|
||||
ProcessEA=false;
|
||||
break;
|
||||
@@ -490,14 +539,14 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
eprintf("\n");
|
||||
}
|
||||
else
|
||||
strncpy(Password,Switch+1,sizeof(Password));
|
||||
strncpyz(Password,Switch+1,ASIZE(Password));
|
||||
break;
|
||||
case 'H':
|
||||
if (toupper(Switch[1])=='P')
|
||||
if (etoupper(Switch[1])=='P')
|
||||
{
|
||||
EncryptHeaders=true;
|
||||
if (Switch[2]!=0)
|
||||
strncpy(Password,Switch+2,sizeof(Password));
|
||||
strncpyz(Password,Switch+2,ASIZE(Password));
|
||||
else
|
||||
if (*Password==0)
|
||||
{
|
||||
@@ -507,11 +556,10 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'Z':
|
||||
strncpy(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",sizeof(CommentFile)-1);
|
||||
CommentFile[sizeof(CommentFile)-1]=0;
|
||||
strncpyz(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",ASIZE(CommentFile));
|
||||
break;
|
||||
case 'M':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 'C':
|
||||
{
|
||||
@@ -525,19 +573,19 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
int Param1=0,Param2=0;
|
||||
FilterState State=FILTER_AUTO;
|
||||
FilterType Type=FILTER_NONE;
|
||||
if (isdigit(*Str))
|
||||
if (IsDigit(*Str))
|
||||
{
|
||||
Param1=atoi(Str);
|
||||
while (isdigit(*Str))
|
||||
while (IsDigit(*Str))
|
||||
Str++;
|
||||
}
|
||||
if (*Str==':' && isdigit(Str[1]))
|
||||
if (*Str==':' && IsDigit(Str[1]))
|
||||
{
|
||||
Param2=atoi(++Str);
|
||||
while (isdigit(*Str))
|
||||
while (IsDigit(*Str))
|
||||
Str++;
|
||||
}
|
||||
switch(toupper(*(Str++)))
|
||||
switch(etoupper(*(Str++)))
|
||||
{
|
||||
case 'T': Type=FILTER_PPM; break;
|
||||
case 'E': Type=FILTER_E8; break;
|
||||
@@ -560,7 +608,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
case 'D':
|
||||
{
|
||||
if ((WinSize=atoi(&Switch[2]))==0)
|
||||
WinSize=0x10000<<(toupper(Switch[2])-'A');
|
||||
WinSize=0x10000<<(etoupper(Switch[2])-'A');
|
||||
else
|
||||
WinSize*=1024;
|
||||
if (!CheckWinSize())
|
||||
@@ -597,8 +645,11 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
#ifdef PACK_SMP
|
||||
case 'T':
|
||||
Threads=atoi(Switch+2);
|
||||
if (Threads>MaxSearchThreads)
|
||||
if (Threads>16)
|
||||
BadSwitch(Switch);
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -609,7 +660,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
case 'D':
|
||||
@@ -623,7 +674,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
VolumePause=true;
|
||||
break;
|
||||
case 'E':
|
||||
if (toupper(Switch[2])=='R')
|
||||
if (etoupper(Switch[2])=='R')
|
||||
VersionControl=atoi(Switch+3)+1;
|
||||
break;
|
||||
case '-':
|
||||
@@ -631,16 +682,16 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Int64 NewVolSize=atoil(&Switch[1]);
|
||||
int64 NewVolSize=atoil(&Switch[1]);
|
||||
|
||||
if (NewVolSize==0)
|
||||
NewVolSize=INT64ERR;
|
||||
NewVolSize=INT64NDF; // Autodetecting volume size.
|
||||
else
|
||||
switch (Switch[strlen(Switch)-1])
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
switch(int64to32(NewVolSize))
|
||||
switch(NewVolSize)
|
||||
{
|
||||
case 360:
|
||||
NewVolSize=362496;
|
||||
@@ -692,30 +743,19 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
switch(toupper(Switch[1]))
|
||||
{
|
||||
case 0:
|
||||
FreshFiles=true;
|
||||
break;
|
||||
case 'C':
|
||||
if (toupper(Switch[2])=='U')
|
||||
{
|
||||
UnicodeComment=true;
|
||||
if (*CommentFile==0 || Switch[3]!=0)
|
||||
{
|
||||
strncpy(CommentFile,Switch[3]!=0 ? Switch+3:"stdin",sizeof(CommentFile)-1);
|
||||
CommentFile[sizeof(CommentFile)-1]=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (Switch[1]==0)
|
||||
FreshFiles=true;
|
||||
else
|
||||
BadSwitch(Switch);
|
||||
break;
|
||||
case 'U':
|
||||
if (Switch[1]==0)
|
||||
UpdateFiles=true;
|
||||
else
|
||||
BadSwitch(Switch);
|
||||
break;
|
||||
case 'W':
|
||||
strncpy(TempPath,&Switch[1],sizeof(TempPath)-1);
|
||||
strncpyz(TempPath,&Switch[1],ASIZE(TempPath));
|
||||
AddEndSlash(TempPath);
|
||||
break;
|
||||
case 'S':
|
||||
@@ -727,13 +767,13 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
else
|
||||
GetConfigName(SFXName,SFXModule,true);
|
||||
}
|
||||
if (isdigit(Switch[1]))
|
||||
if (IsDigit(Switch[1]))
|
||||
{
|
||||
Solid|=SOLID_COUNT;
|
||||
SolidCount=atoi(&Switch[1]);
|
||||
}
|
||||
else
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 0:
|
||||
Solid|=SOLID_NORMAL;
|
||||
@@ -751,18 +791,61 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
Solid|=SOLID_VOLUME_DEPENDENT;
|
||||
break;
|
||||
case 'L':
|
||||
if (isdigit(Switch[2]))
|
||||
if (IsDigit(Switch[2]))
|
||||
FileSizeLess=atoil(Switch+2);
|
||||
break;
|
||||
case 'M':
|
||||
if (isdigit(Switch[2]))
|
||||
if (IsDigit(Switch[2]))
|
||||
FileSizeMore=atoil(Switch+2);
|
||||
break;
|
||||
case 'C':
|
||||
{
|
||||
// Switch is already found bad, avoid reporting it several times.
|
||||
bool AlreadyBad=false;
|
||||
|
||||
RAR_CHARSET rch=RCH_DEFAULT;
|
||||
switch(etoupper(Switch[2]))
|
||||
{
|
||||
case 'A':
|
||||
rch=RCH_ANSI;
|
||||
break;
|
||||
case 'O':
|
||||
rch=RCH_OEM;
|
||||
break;
|
||||
case 'U':
|
||||
rch=RCH_UNICODE;
|
||||
break;
|
||||
default :
|
||||
BadSwitch(Switch);
|
||||
AlreadyBad=true;
|
||||
break;
|
||||
};
|
||||
if (!AlreadyBad)
|
||||
if (Switch[3]==0)
|
||||
CommentCharset=FilelistCharset=rch;
|
||||
else
|
||||
for (int I=3;Switch[I]!=0 && !AlreadyBad;I++)
|
||||
switch(etoupper(Switch[I]))
|
||||
{
|
||||
case 'C':
|
||||
CommentCharset=rch;
|
||||
break;
|
||||
case 'L':
|
||||
FilelistCharset=rch;
|
||||
break;
|
||||
default:
|
||||
BadSwitch(Switch);
|
||||
AlreadyBad=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if (Switch[2]==0)
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case '-':
|
||||
DisableComment=true;
|
||||
@@ -776,7 +859,7 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
}
|
||||
break;
|
||||
case 'K':
|
||||
switch(toupper(Switch[1]))
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 'B':
|
||||
KeepBroken=true;
|
||||
@@ -802,10 +885,8 @@ void CommandData::ProcessSwitch(char *Switch)
|
||||
#ifndef SFX_MODULE
|
||||
void CommandData::BadSwitch(char *Switch)
|
||||
{
|
||||
#ifndef GUI
|
||||
mprintf(St(MUnknownOption),Switch);
|
||||
#endif
|
||||
ErrHandler.Exit(RAR_USER_ERROR);
|
||||
ErrHandler.Exit(USER_ERROR);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -839,43 +920,41 @@ void CommandData::OutTitle()
|
||||
#endif
|
||||
|
||||
|
||||
inline bool CmpMSGID(MSGID i1,MSGID i2)
|
||||
{
|
||||
#ifdef MSGID_INT
|
||||
return(i1==i2);
|
||||
#else
|
||||
// If MSGID is const char*, we cannot compare pointers only.
|
||||
// Pointers to different instances of same strings can differ,
|
||||
// so we need to compare complete strings.
|
||||
return(strcmp(i1,i2)==0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CommandData::OutHelp()
|
||||
{
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
OutTitle();
|
||||
static MSGID Help[]={
|
||||
#ifdef SFX_MODULE
|
||||
// Console SFX switches definition.
|
||||
MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV
|
||||
#elif defined(UNRAR)
|
||||
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,MCHelpCmdP,
|
||||
MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,MCHelpSwAC,MCHelpSwAD,
|
||||
MCHelpSwAP,MCHelpSwAVm,MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
|
||||
// UnRAR switches definition.
|
||||
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
|
||||
MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,
|
||||
MCHelpSwm,MCHelpSwAC,MCHelpSwAD,MCHelpSwAI,MCHelpSwAP,
|
||||
MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
|
||||
MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
|
||||
MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,
|
||||
MCHelpSwOp,MCHelpSwOm,MCHelpSwOC,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
|
||||
MCHelpSwO,MCHelpSwOC,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
|
||||
MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSL,MCHelpSwSM,MCHelpSwTA,
|
||||
MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwVUnr,
|
||||
MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY
|
||||
#else
|
||||
MRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdA,MCHelpCmdC,MCHelpCmdCF,
|
||||
MCHelpCmdCH,MCHelpCmdCW,MCHelpCmdD,MCHelpCmdE,MCHelpCmdF,MCHelpCmdI,
|
||||
MCHelpCmdK,MCHelpCmdL,MCHelpCmdM,MCHelpCmdP,MCHelpCmdR,MCHelpCmdRC,
|
||||
MCHelpCmdRN,MCHelpCmdRR,MCHelpCmdRV,MCHelpCmdS,MCHelpCmdT,MCHelpCmdU,
|
||||
MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,
|
||||
MCHelpSwAO,MCHelpSwAP,MCHelpSwAS,MCHelpSwAV,MCHelpSwAVm,MCHelpSwCm,
|
||||
MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,MCHelpSwDF,MCHelpSwDH,MCHelpSwDS,
|
||||
MCHelpSwEa,MCHelpSwED,MCHelpSwEE,MCHelpSwEN,MCHelpSwEP,MCHelpSwEP1,
|
||||
MCHelpSwEP2,MCHelpSwEP3,MCHelpSwF,MCHelpSwFCU,MCHelpSwHP,MCHelpSwIDP,
|
||||
MCHelpSwIEML,MCHelpSwIERR,MCHelpSwILOG,MCHelpSwINUL,MCHelpSwIOFF,
|
||||
MCHelpSwISND,MCHelpSwK,MCHelpSwKB,MCHelpSwMn,MCHelpSwMC,MCHelpSwMD,
|
||||
MCHelpSwMS,MCHelpSwMT,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,MCHelpSwOp,
|
||||
MCHelpSwOm,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOS,MCHelpSwOW,
|
||||
MCHelpSwP,MCHelpSwPm,MCHelpSwR,MCHelpSwR0,MCHelpSwRI,MCHelpSwRR,
|
||||
MCHelpSwRV,MCHelpSwS,MCHelpSwSm,MCHelpSwSFX,MCHelpSwSI,MCHelpSwSL,
|
||||
MCHelpSwSM,MCHelpSwT,MCHelpSwTA,MCHelpSwTB,MCHelpSwTK,MCHelpSwTL,
|
||||
MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwV,MCHelpSwVn,
|
||||
MCHelpSwVD,MCHelpSwVER,MCHelpSwVN,MCHelpSwVP,MCHelpSwW,MCHelpSwX,
|
||||
MCHelpSwXa,MCHelpSwXal,MCHelpSwY,MCHelpSwZ
|
||||
// RAR switches definition.
|
||||
//removed in 3.9.7
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -888,12 +967,12 @@ void CommandData::OutHelp()
|
||||
#endif
|
||||
#ifndef _WIN_32
|
||||
static MSGID Win32Only[]={
|
||||
MCHelpSwIEML,MCHelpSwVD,MCHelpSwAC,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
|
||||
MCHelpSwEP2,MCHelpSwOC
|
||||
MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
|
||||
MCHelpSwEP2,MCHelpSwOC,MCHelpSwDR,MCHelpSwRI
|
||||
};
|
||||
bool Found=false;
|
||||
for (int J=0;J<sizeof(Win32Only)/sizeof(Win32Only[0]);J++)
|
||||
if (Help[I]==Win32Only[J])
|
||||
if (CmpMSGID(Help[I],Win32Only[J]))
|
||||
{
|
||||
Found=true;
|
||||
break;
|
||||
@@ -902,23 +981,23 @@ void CommandData::OutHelp()
|
||||
continue;
|
||||
#endif
|
||||
#if !defined(_UNIX) && !defined(_WIN_32)
|
||||
if (Help[I]==MCHelpSwOW)
|
||||
if (CmpMSGID(Help[I],MCHelpSwOW))
|
||||
continue;
|
||||
#endif
|
||||
#if !defined(_WIN_32) && !defined(_EMX)
|
||||
if (CmpMSGID(Help[I],MCHelpSwAC))
|
||||
continue;
|
||||
#endif
|
||||
#ifndef SAVE_LINKS
|
||||
if (Help[I]==MCHelpSwOL)
|
||||
continue;
|
||||
#endif
|
||||
#ifndef _WIN_32
|
||||
if (Help[I]==MCHelpSwRI)
|
||||
if (CmpMSGID(Help[I],MCHelpSwOL))
|
||||
continue;
|
||||
#endif
|
||||
#ifndef PACK_SMP
|
||||
if (Help[I]==MCHelpSwMT)
|
||||
if (CmpMSGID(Help[I],MCHelpSwMT))
|
||||
continue;
|
||||
#endif
|
||||
#ifndef _BEOS
|
||||
if (Help[I]==MCHelpSwEE)
|
||||
if (CmpMSGID(Help[I],MCHelpSwEE))
|
||||
{
|
||||
#if defined(_EMX) && !defined(_DJGPP)
|
||||
if (_osmode != OS2_MODE)
|
||||
@@ -932,7 +1011,7 @@ void CommandData::OutHelp()
|
||||
mprintf(St(Help[I]));
|
||||
}
|
||||
mprintf("\n");
|
||||
ErrHandler.Exit(RAR_USER_ERROR);
|
||||
ErrHandler.Exit(USER_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -960,13 +1039,16 @@ bool CommandData::ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullP
|
||||
}
|
||||
|
||||
|
||||
bool CommandData::ExclCheck(char *CheckName,bool CheckFullPath)
|
||||
// Return 'true' if we need to exclude the file from processing as result
|
||||
// of -x switch. If CheckInclList is true, we also check the file against
|
||||
// the include list created with -n switch.
|
||||
bool CommandData::ExclCheck(char *CheckName,bool CheckFullPath,bool CheckInclList)
|
||||
{
|
||||
if (ExclCheckArgs(ExclArgs,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
|
||||
return(true);
|
||||
if (InclArgs->ItemsCount()==0)
|
||||
if (!CheckInclList || InclArgs->ItemsCount()==0)
|
||||
return(false);
|
||||
if (ExclCheckArgs(InclArgs,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
|
||||
if (ExclCheckArgs(InclArgs,CheckName,false,MATCH_WILDSUBPATH))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
@@ -975,52 +1057,38 @@ bool CommandData::ExclCheck(char *CheckName,bool CheckFullPath)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
// Return 'true' if we need to exclude the file from processing.
|
||||
bool CommandData::TimeCheck(RarTime &ft)
|
||||
{
|
||||
if (FileTimeBefore.IsSet() && ft>=FileTimeBefore)
|
||||
return(true);
|
||||
if (FileTimeAfter.IsSet() && ft<=FileTimeAfter)
|
||||
return(true);
|
||||
/*
|
||||
if (FileTimeOlder!=0 || FileTimeNewer!=0)
|
||||
{
|
||||
if (!TimeConverted)
|
||||
{
|
||||
if (FileTimeOlder!=0)
|
||||
FileTimeOlder=SecondsToDosTime(FileTimeOlder);
|
||||
if (FileTimeNewer!=0)
|
||||
FileTimeNewer=SecondsToDosTime(FileTimeNewer);
|
||||
TimeConverted=true;
|
||||
}
|
||||
if (FileTimeOlder!=0 && ft>=FileTimeOlder)
|
||||
return(true);
|
||||
if (FileTimeNewer!=0 && ft<=FileTimeNewer)
|
||||
return(true);
|
||||
|
||||
}
|
||||
*/
|
||||
return(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
bool CommandData::SizeCheck(Int64 Size)
|
||||
// Return 'true' if we need to exclude the file from processing.
|
||||
bool CommandData::SizeCheck(int64 Size)
|
||||
{
|
||||
if (FileSizeLess!=INT64ERR && Size>=FileSizeLess)
|
||||
if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
|
||||
return(true);
|
||||
if (FileSizeMore!=INT64ERR && Size<=FileSizeMore)
|
||||
if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
|
||||
return(true);
|
||||
return(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType)
|
||||
{
|
||||
if (strlen(NewLhd.FileName)>=NM || strlenw(NewLhd.FileNameW)>=NM)
|
||||
return(0);
|
||||
if (ExclCheck(NewLhd.FileName,false))
|
||||
if (ExclCheck(NewLhd.FileName,false,true))
|
||||
return(0);
|
||||
#ifndef SFX_MODULE
|
||||
if (TimeCheck(NewLhd.mtime))
|
||||
@@ -1078,7 +1146,9 @@ int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType
|
||||
void CommandData::ProcessCommand()
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
if (Command[1] && strchr("FUADPXETK",*Command)!=NULL || *ArcName==0)
|
||||
|
||||
const char *SingleCharCommands="FUADPXETK";
|
||||
if (Command[1] && strchr(SingleCharCommands,*Command)!=NULL || *ArcName==0)
|
||||
OutHelp();
|
||||
|
||||
#ifdef _UNIX
|
||||
@@ -1156,13 +1226,13 @@ bool CommandData::IsSwitch(int Ch)
|
||||
#ifndef SFX_MODULE
|
||||
uint CommandData::GetExclAttr(char *Str)
|
||||
{
|
||||
if (isdigit(*Str))
|
||||
if (IsDigit(*Str))
|
||||
return(strtol(Str,NULL,0));
|
||||
else
|
||||
{
|
||||
uint Attr;
|
||||
for (Attr=0;*Str;Str++)
|
||||
switch(toupper(*Str))
|
||||
switch(etoupper(*Str))
|
||||
{
|
||||
#ifdef _UNIX
|
||||
case 'D':
|
||||
|
||||
@@ -7,14 +7,13 @@ class CommandData:public RAROptions
|
||||
{
|
||||
private:
|
||||
void ProcessSwitchesString(char *Str);
|
||||
void ProcessSwitch(char *Switch);
|
||||
void ProcessSwitch(char *Switch,wchar *SwitchW=NULL);
|
||||
void BadSwitch(char *Switch);
|
||||
bool ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode);
|
||||
uint GetExclAttr(char *Str);
|
||||
|
||||
bool FileLists;
|
||||
bool NoMoreSwitches;
|
||||
bool TimeConverted;
|
||||
bool BareOutput;
|
||||
public:
|
||||
CommandData();
|
||||
@@ -29,10 +28,11 @@ class CommandData:public RAROptions
|
||||
void OutTitle();
|
||||
void OutHelp();
|
||||
bool IsSwitch(int Ch);
|
||||
bool ExclCheck(char *CheckName,bool CheckFullPath);
|
||||
bool ExclCheck(char *CheckName,bool CheckFullPath,bool CheckInclList);
|
||||
bool StoreCheck(char *CheckName);
|
||||
bool TimeCheck(RarTime &ft);
|
||||
bool SizeCheck(Int64 Size);
|
||||
bool SizeCheck(int64 Size);
|
||||
bool AnyFiltersActive();
|
||||
int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH);
|
||||
void ProcessCommand();
|
||||
void AddArcName(char *Name,wchar *NameW);
|
||||
|
||||
@@ -17,9 +17,10 @@ void RangeCoder::InitDecoder(Unpack *UnpackRead)
|
||||
}
|
||||
|
||||
|
||||
// (int) cast before "low" added only to suppress compiler warnings.
|
||||
#define ARI_DEC_NORMALIZE(code,low,range,read) \
|
||||
{ \
|
||||
while ((low^(low+range))<TOP || range<BOT && ((range=-low&(BOT-1)),1)) \
|
||||
while ((low^(low+range))<TOP || range<BOT && ((range=-(int)low&(BOT-1)),1)) \
|
||||
{ \
|
||||
code=(code << 8) | read->GetChar(); \
|
||||
range <<= 8; \
|
||||
|
||||
@@ -29,7 +29,7 @@ enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
|
||||
|
||||
enum FilterType {
|
||||
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
|
||||
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
|
||||
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
|
||||
FILTER_ITANIUM, FILTER_E8E9V2
|
||||
};
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
#include "log.cpp"
|
||||
#endif
|
||||
|
||||
static int KbdAnsi(char *Addr,int Size);
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
|
||||
static uint GetKey();
|
||||
#endif
|
||||
|
||||
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
|
||||
@@ -121,45 +124,25 @@ void GetPasswordText(char *Str,int MaxLength)
|
||||
OemToChar(Str,Str);
|
||||
SetConsoleMode(hConIn,ConInMode);
|
||||
SetConsoleMode(hConOut,ConOutMode);
|
||||
#elif defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc)
|
||||
#elif defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
|
||||
fgets(Str,MaxLength-1,stdin);
|
||||
#else
|
||||
strncpy(Str,getpass(""),MaxLength-1);
|
||||
strncpyz(Str,getpass(""),MaxLength);
|
||||
#endif
|
||||
Str[MaxLength-1]=0;
|
||||
RemoveLF(Str);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
unsigned int GetKey()
|
||||
{
|
||||
#ifdef SILENT
|
||||
return(0);
|
||||
#else
|
||||
char Str[80];
|
||||
#ifdef __GNUC__
|
||||
fgets(Str,sizeof(Str),stdin);
|
||||
return(Str[0]);
|
||||
#else
|
||||
File SrcFile;
|
||||
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||
SrcFile.Read(Str,sizeof(Str));
|
||||
return(Str[0]);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength)
|
||||
{
|
||||
Alarm();
|
||||
while (true)
|
||||
{
|
||||
char PromptStr[256];
|
||||
char PromptStr[NM+256];
|
||||
#if defined(_EMX) || defined(_BEOS)
|
||||
strcpy(PromptStr,St(MAskPswEcho));
|
||||
#else
|
||||
@@ -168,7 +151,9 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
|
||||
if (Type!=PASSWORD_GLOBAL)
|
||||
{
|
||||
strcat(PromptStr,St(MFor));
|
||||
strcat(PromptStr,PointToName(FileName));
|
||||
char *NameOnly=PointToName(FileName);
|
||||
if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
|
||||
strcat(PromptStr,NameOnly);
|
||||
}
|
||||
eprintf("\n%s: ",PromptStr);
|
||||
GetPasswordText(Password,MaxLength);
|
||||
@@ -176,19 +161,12 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
|
||||
return(false);
|
||||
if (Type==PASSWORD_GLOBAL)
|
||||
{
|
||||
strcpy(PromptStr,St(MReAskPsw));
|
||||
eprintf(PromptStr);
|
||||
char CmpStr[256];
|
||||
GetPasswordText(CmpStr,sizeof(CmpStr));
|
||||
eprintf(St(MReAskPsw));
|
||||
char CmpStr[MAXPASSWORD];
|
||||
GetPasswordText(CmpStr,ASIZE(CmpStr));
|
||||
if (*CmpStr==0 || strcmp(Password,CmpStr)!=0)
|
||||
{
|
||||
strcpy(PromptStr,St(MNotMatchPsw));
|
||||
/*
|
||||
#ifdef _WIN_32
|
||||
CharToOem(PromptStr,PromptStr);
|
||||
#endif
|
||||
*/
|
||||
eprintf(PromptStr);
|
||||
eprintf(St(MNotMatchPsw));
|
||||
memset(Password,0,MaxLength);
|
||||
memset(CmpStr,0,sizeof(CmpStr));
|
||||
continue;
|
||||
@@ -202,6 +180,29 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
uint GetKey()
|
||||
{
|
||||
char Str[80];
|
||||
bool EndOfFile;
|
||||
#if defined(__GNUC__) || defined(sun)
|
||||
EndOfFile=(fgets(Str,sizeof(Str),stdin)==NULL);
|
||||
#else
|
||||
File SrcFile;
|
||||
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||
EndOfFile=(SrcFile.Read(Str,sizeof(Str))==0);
|
||||
#endif
|
||||
if (EndOfFile)
|
||||
{
|
||||
// Looks like stdin is a null device. We can enter to infinite loop
|
||||
// calling Ask(), so let's better exit.
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
}
|
||||
return(Str[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
int Ask(const char *AskStr)
|
||||
{
|
||||
@@ -212,7 +213,7 @@ int Ask(const char *AskStr)
|
||||
for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
|
||||
{
|
||||
char *CurItem=Item[NumItems];
|
||||
strncpy(CurItem,NextItem+1,sizeof(Item[0]));
|
||||
strncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
|
||||
char *EndItem=strchr(CurItem,'_');
|
||||
if (EndItem!=NULL)
|
||||
*EndItem=0;
|
||||
@@ -253,18 +254,18 @@ int Ask(const char *AskStr)
|
||||
#endif
|
||||
|
||||
|
||||
int KbdAnsi(char *Addr,int Size)
|
||||
int KbdAnsi(char *Addr,size_t Size)
|
||||
{
|
||||
int RetCode=0;
|
||||
#ifndef GUI
|
||||
for (int I=0;I<Size;I++)
|
||||
for (size_t I=0;I<Size;I++)
|
||||
if (Addr[I]==27 && Addr[I+1]=='[')
|
||||
{
|
||||
for (int J=I+2;J<Size;J++)
|
||||
for (size_t J=I+2;J<Size;J++)
|
||||
{
|
||||
if (Addr[J]=='\"')
|
||||
return(2);
|
||||
if (!isdigit(Addr[J]) && Addr[J]!=';')
|
||||
if (!IsDigit(Addr[J]) && Addr[J]!=';')
|
||||
break;
|
||||
}
|
||||
RetCode=1;
|
||||
@@ -274,16 +275,16 @@ int KbdAnsi(char *Addr,int Size)
|
||||
}
|
||||
|
||||
|
||||
void OutComment(char *Comment,int Size)
|
||||
void OutComment(char *Comment,size_t Size)
|
||||
{
|
||||
#ifndef GUI
|
||||
if (KbdAnsi(Comment,Size)==2)
|
||||
return;
|
||||
const int MaxOutSize=0x400;
|
||||
for (int I=0;I<Size;I+=MaxOutSize)
|
||||
const size_t MaxOutSize=0x400;
|
||||
for (size_t I=0;I<Size;I+=MaxOutSize)
|
||||
{
|
||||
char Msg[MaxOutSize+1];
|
||||
int CopySize=Min(MaxOutSize,Size-I);
|
||||
size_t CopySize=Min(MaxOutSize,Size-I);
|
||||
strncpy(Msg,Comment+I,CopySize);
|
||||
Msg[CopySize]=0;
|
||||
mprintf("%s",Msg);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef _RAR_CONSIO_
|
||||
#define _RAR_CONSIO_
|
||||
|
||||
enum {ALARM_SOUND,ERROR_SOUND,QUESTION_SOUND};
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
enum {SOUND_OK,SOUND_ALARM,SOUND_ERROR,SOUND_QUESTION};
|
||||
#endif
|
||||
|
||||
enum PASSWORD_TYPE {PASSWORD_GLOBAL,PASSWORD_FILE,PASSWORD_ARCHIVE};
|
||||
|
||||
@@ -12,13 +14,11 @@ void mprintf(const char *fmt,...);
|
||||
void eprintf(const char *fmt,...);
|
||||
void Alarm();
|
||||
void GetPasswordText(char *Str,int MaxLength);
|
||||
unsigned int GetKey();
|
||||
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength);
|
||||
int Ask(const char *AskStr);
|
||||
#endif
|
||||
|
||||
int KbdAnsi(char *Addr,int Size);
|
||||
void OutComment(char *Comment,int Size);
|
||||
void OutComment(char *Comment,size_t Size);
|
||||
|
||||
#ifdef SILENT
|
||||
#ifdef __GNUC__
|
||||
|
||||
@@ -14,11 +14,12 @@ void InitCRC()
|
||||
}
|
||||
|
||||
|
||||
uint CRC(uint StartCRC,const void *Addr,uint Size)
|
||||
uint CRC(uint StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
if (CRCTab[1]==0)
|
||||
InitCRC();
|
||||
byte *Data=(byte *)Addr;
|
||||
|
||||
#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
|
||||
while (Size>0 && ((long)Data & 7))
|
||||
{
|
||||
@@ -42,16 +43,17 @@ uint CRC(uint StartCRC,const void *Addr,uint Size)
|
||||
Size-=8;
|
||||
}
|
||||
#endif
|
||||
for (int I=0;I<Size;I++)
|
||||
|
||||
for (size_t I=0;I<Size;I++)
|
||||
StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
|
||||
return(StartCRC);
|
||||
}
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,uint Size)
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
byte *Data=(byte *)Addr;
|
||||
for (int I=0;I<Size;I++)
|
||||
for (size_t I=0;I<Size;I++)
|
||||
{
|
||||
StartCRC=(StartCRC+Data[I])&0xffff;
|
||||
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
extern uint CRCTab[256];
|
||||
|
||||
void InitCRC();
|
||||
uint CRC(uint StartCRC,const void *Addr,uint Size);
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,uint Size);
|
||||
uint CRC(uint StartCRC,const void *Addr,size_t Size);
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,7 +41,7 @@ static byte InitSubstTable[256]={
|
||||
|
||||
|
||||
|
||||
void CryptData::DecryptBlock(byte *Buf,int Size)
|
||||
void CryptData::DecryptBlock(byte *Buf,size_t Size)
|
||||
{
|
||||
rin.blockDecrypt(Buf,Size,Buf);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ void CryptData::Swap(byte *Ch1,byte *Ch2)
|
||||
#endif
|
||||
|
||||
|
||||
void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
|
||||
void CryptData::SetCryptKeys(const char *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
|
||||
{
|
||||
if (*Password==0)
|
||||
return;
|
||||
@@ -202,28 +202,28 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
|
||||
Key[3]=0xA4E7F123L;
|
||||
memset(Psw,0,sizeof(Psw));
|
||||
#if defined(_WIN_32) && !defined(GUI)
|
||||
CharToOemBuff(Password,(char*)Psw,strlen(Password));
|
||||
CharToOemBuff(Password,(char*)Psw,(DWORD)strlen(Password));
|
||||
#else
|
||||
strncpy((char *)Psw,Password,MAXPASSWORD-1);
|
||||
strncpyz((char *)Psw,Password,ASIZE(Psw));
|
||||
#endif
|
||||
int PswLength=strlen(Password);
|
||||
size_t PswLength=strlen(Password);
|
||||
memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
|
||||
for (int J=0;J<256;J++)
|
||||
for (int I=0;I<PswLength;I+=2)
|
||||
for (size_t I=0;I<PswLength;I+=2)
|
||||
{
|
||||
uint N1=(byte)CRCTab[(Psw[I]-J)&0xff];
|
||||
uint N2=(byte)CRCTab[(Psw[I+1]+J)&0xff];
|
||||
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
|
||||
Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]);
|
||||
}
|
||||
for (int I=0;I<PswLength;I+=16)
|
||||
for (size_t I=0;I<PswLength;I+=16)
|
||||
EncryptBlock20(&Psw[I]);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
bool Cached=false;
|
||||
for (int I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++)
|
||||
for (int I=0;I<ASIZE(Cache);I++)
|
||||
if (strcmp(Cache[I].Password,Password)==0 &&
|
||||
(Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
|
||||
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&
|
||||
@@ -242,7 +242,7 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
|
||||
PswW[MAXPASSWORD-1]=0;
|
||||
byte RawPsw[2*MAXPASSWORD+SALT_SIZE];
|
||||
WideToRaw(PswW,RawPsw);
|
||||
int RawLength=2*strlenw(PswW);
|
||||
size_t RawLength=2*strlenw(PswW);
|
||||
if (Salt!=NULL)
|
||||
{
|
||||
memcpy(RawPsw+RawLength,Salt,SALT_SIZE);
|
||||
@@ -287,7 +287,7 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void CryptData::SetOldKeys(char *Password)
|
||||
void CryptData::SetOldKeys(const char *Password)
|
||||
{
|
||||
uint PswCRC=CRC(0xffffffff,Password,strlen(Password));
|
||||
OldKey[0]=PswCRC&0xffff;
|
||||
|
||||
@@ -34,7 +34,7 @@ class CryptData
|
||||
void Crypt15(byte *Data,uint Count);
|
||||
void UpdKeys(byte *Buf);
|
||||
void Swap(byte *Ch1,byte *Ch2);
|
||||
void SetOldKeys(char *Password);
|
||||
void SetOldKeys(const char *Password);
|
||||
|
||||
Rijndael rin;
|
||||
|
||||
@@ -48,13 +48,13 @@ class CryptData
|
||||
static CryptKeyCacheItem Cache[4];
|
||||
static int CachePos;
|
||||
public:
|
||||
void SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
|
||||
void SetCryptKeys(const char *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
|
||||
void SetAV15Encryption();
|
||||
void SetCmt13Encryption();
|
||||
void EncryptBlock20(byte *Buf);
|
||||
void DecryptBlock20(byte *Buf);
|
||||
void EncryptBlock(byte *Buf,int Size);
|
||||
void DecryptBlock(byte *Buf,int Size);
|
||||
void EncryptBlock(byte *Buf,size_t Size);
|
||||
void DecryptBlock(byte *Buf,size_t Size);
|
||||
void Crypt(byte *Data,uint Count,int Method);
|
||||
static void SetSalt(byte *Salt,int SaltSize);
|
||||
};
|
||||
|
||||
154
unrar/dll.cpp
154
unrar/dll.cpp
@@ -53,14 +53,14 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
Data->Cmd.VersionControl=1;
|
||||
if (!Data->Arc.Open(r->ArcName,r->ArcNameW))
|
||||
{
|
||||
delete Data;
|
||||
r->OpenResult=ERAR_EOPEN;
|
||||
delete Data;
|
||||
return(NULL);
|
||||
}
|
||||
if (!Data->Arc.IsArchive(false))
|
||||
{
|
||||
delete Data;
|
||||
r->OpenResult=Data->Cmd.DllError!=0 ? Data->Cmd.DllError:ERAR_BAD_ARCHIVE;
|
||||
delete Data;
|
||||
return(NULL);
|
||||
}
|
||||
r->Flags=Data->Arc.NewMhd.Flags;
|
||||
@@ -68,9 +68,9 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
|
||||
{
|
||||
r->Flags|=2;
|
||||
int Size=CmtData.Size()+1;
|
||||
size_t Size=CmtData.Size()+1;
|
||||
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||
r->CmtSize=Min(Size,r->CmtBufSize);
|
||||
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
||||
if (Size<=r->CmtBufSize)
|
||||
r->CmtBuf[r->CmtSize-1]=0;
|
||||
@@ -104,12 +104,13 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
try
|
||||
{
|
||||
if ((Data->HeaderSize=Data->Arc.SearchBlock(FILE_HEAD))<=0)
|
||||
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
|
||||
{
|
||||
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
|
||||
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
|
||||
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
||||
{
|
||||
Data->Extract.SignatureFound=false;
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
return(RARReadHeader(hArcData,D));
|
||||
}
|
||||
@@ -125,8 +126,8 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
|
||||
else
|
||||
return(Code);
|
||||
}
|
||||
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
|
||||
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(D->FileName));
|
||||
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
|
||||
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
|
||||
D->Flags=Data->Arc.NewLhd.Flags;
|
||||
D->PackSize=Data->Arc.NewLhd.PackSize;
|
||||
D->UnpSize=Data->Arc.NewLhd.UnpSize;
|
||||
@@ -152,12 +153,13 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
try
|
||||
{
|
||||
if ((Data->HeaderSize=Data->Arc.SearchBlock(FILE_HEAD))<=0)
|
||||
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
|
||||
{
|
||||
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
|
||||
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
|
||||
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
||||
{
|
||||
Data->Extract.SignatureFound=false;
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
return(RARReadHeaderEx(hArcData,D));
|
||||
}
|
||||
@@ -173,23 +175,29 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||
else
|
||||
return(Code);
|
||||
}
|
||||
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
|
||||
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
|
||||
if (*Data->Arc.FileNameW)
|
||||
strncpyw(D->ArcNameW,Data->Arc.FileNameW,sizeof(D->ArcNameW));
|
||||
else
|
||||
CharToWide(Data->Arc.FileName,D->ArcNameW);
|
||||
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(D->FileName));
|
||||
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
|
||||
if (*Data->Arc.NewLhd.FileNameW)
|
||||
strncpyw(D->FileNameW,Data->Arc.NewLhd.FileNameW,sizeof(D->FileNameW));
|
||||
else
|
||||
{
|
||||
bool result;
|
||||
#ifdef _WIN_32
|
||||
char AnsiName[NM];
|
||||
OemToChar(Data->Arc.NewLhd.FileName,AnsiName);
|
||||
CharToWide(AnsiName,D->FileNameW);
|
||||
//The way to handle CharToWide failed calls differs to the method
|
||||
//unrar 3.9.7 introduced. 3.9.7 only returns an empty string, while I
|
||||
//call UtfToWide, which merely discarts invalid characters
|
||||
result = CharToWide(AnsiName,D->FileNameW);
|
||||
#else
|
||||
CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW);
|
||||
result = CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW);
|
||||
#endif
|
||||
if (!result)
|
||||
UtfToWide(Data->Arc.NewLhd.FileName, D->FileNameW, NM);
|
||||
}
|
||||
D->Flags=Data->Arc.NewLhd.Flags;
|
||||
D->PackSize=Data->Arc.NewLhd.PackSize;
|
||||
@@ -213,19 +221,38 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||
}
|
||||
|
||||
|
||||
int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
|
||||
int PASCAL ProcessFile(HANDLE hArcData, int Operation, char *DestPath,
|
||||
char *DestName, wchar *DestPathW, wchar *DestNameW,
|
||||
void *Buffer, size_t BufferSize, size_t *ReadSize,
|
||||
bool InitDataIO, int *finished)
|
||||
{
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
|
||||
/* if not extracting chunks, we want to init IO all the time
|
||||
* (that was the behaviour before adding RAR_EXTRACT_CHUNK, which thus
|
||||
* remains unaltered) */
|
||||
if (Operation != RAR_EXTRACT_CHUNK)
|
||||
InitDataIO = TRUE;
|
||||
|
||||
/* we must set these here because the function may return before executing the
|
||||
* code that updates the variables. */
|
||||
if (ReadSize != NULL)
|
||||
*ReadSize = 0;
|
||||
if (finished != NULL)
|
||||
*finished = TRUE;
|
||||
|
||||
try
|
||||
{
|
||||
Data->Cmd.DllError=0;
|
||||
if (Data->OpenMode==RAR_OM_LIST || Operation==RAR_SKIP && !Data->Arc.Solid)
|
||||
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
|
||||
Operation==RAR_SKIP && !Data->Arc.Solid)
|
||||
{
|
||||
if (/*Data->OpenMode==RAR_OM_LIST && */Data->Arc.Volume &&
|
||||
if (Data->Arc.Volume &&
|
||||
Data->Arc.GetHeaderType()==FILE_HEAD &&
|
||||
(Data->Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0)
|
||||
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
||||
{
|
||||
Data->Extract.SignatureFound=false;
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
return(0);
|
||||
}
|
||||
@@ -262,6 +289,9 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
||||
strncpyw(Data->Cmd.ExtrPathW,NullToEmpty(DestPathW),NM-2);
|
||||
AddEndSlash(Data->Cmd.ExtrPathW);
|
||||
strncpyw(Data->Cmd.DllDestNameW,NullToEmpty(DestNameW),NM-1);
|
||||
|
||||
if (*Data->Cmd.DllDestNameW!=0 && *Data->Cmd.DllDestName==0)
|
||||
WideToChar(Data->Cmd.DllDestNameW,Data->Cmd.DllDestName);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -271,15 +301,51 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
||||
|
||||
strcpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? "X":"T");
|
||||
Data->Cmd.Test=Operation!=RAR_EXTRACT;
|
||||
bool Repeat=false;
|
||||
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
|
||||
|
||||
while (Data->Arc.ReadHeader()!=0 && Data->Arc.GetHeaderType()==NEWSUB_HEAD)
|
||||
if (Operation == RAR_EXTRACT_CHUNK)
|
||||
{
|
||||
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
|
||||
Data->Arc.SeekToNext();
|
||||
//disabled completion percentage calculation/printing?
|
||||
Data->Cmd.DisablePercentage = true;
|
||||
//doesn't seem to be read except for inactive preproc. blocks anyway:
|
||||
Data->Cmd.DisableDone = true;
|
||||
Data->Extract.Buffer = Buffer;
|
||||
Data->Extract.BufferSize = BufferSize;
|
||||
}
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
|
||||
bool Repeat=false;
|
||||
if (Operation != RAR_EXTRACT_CHUNK)
|
||||
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,
|
||||
Data->HeaderSize,Repeat);
|
||||
else
|
||||
{
|
||||
if (InitDataIO) //chunk, init
|
||||
{
|
||||
bool res;
|
||||
res = Data->Extract.ExtractCurrentFileChunkInit(&Data->Cmd, Data->Arc,
|
||||
Data->HeaderSize, Repeat);
|
||||
if (!res && Data->Cmd.DllError == 0)
|
||||
Data->Cmd.DllError = ERAR_UNKNOWN;
|
||||
return Data->Cmd.DllError;
|
||||
}
|
||||
else //chunk, no init
|
||||
//returns always true
|
||||
//changes *ReadSize and *finished
|
||||
Data->Extract.ExtractCurrentFileChunk(&Data->Cmd, Data->Arc,
|
||||
ReadSize, finished);
|
||||
}
|
||||
|
||||
/* if extracting by chunks, do move to next block, not even if we've read
|
||||
* the whole file. The only purpose of this code seems to be applying
|
||||
* permissions and other metadata to files, so we're not interested if
|
||||
* extracting chunks */
|
||||
if (Operation != RAR_EXTRACT_CHUNK) {
|
||||
while (Data->Arc.ReadHeader()!=0 && Data->Arc.GetHeaderType()==NEWSUB_HEAD)
|
||||
{
|
||||
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
|
||||
Data->Arc.SeekToNext();
|
||||
}
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (int ErrCode)
|
||||
@@ -292,15 +358,32 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
||||
|
||||
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
|
||||
{
|
||||
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL));
|
||||
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL,NULL,0,
|
||||
NULL,false,NULL));
|
||||
}
|
||||
|
||||
|
||||
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
|
||||
{
|
||||
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName));
|
||||
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName,NULL,0,
|
||||
NULL,false,NULL));
|
||||
}
|
||||
|
||||
int PASCAL RARProcessFileChunkInit(HANDLE hArcData)
|
||||
{
|
||||
return ProcessFile(hArcData, RAR_EXTRACT_CHUNK, NULL, NULL, NULL, NULL,
|
||||
NULL, 0, NULL, true, NULL);
|
||||
}
|
||||
|
||||
int PASCAL RARProcessFileChunk(HANDLE hArcData,
|
||||
void *Buffer,
|
||||
size_t BufferSize,
|
||||
size_t *ReadSize,
|
||||
int *finished)
|
||||
{
|
||||
return ProcessFile(hArcData, RAR_EXTRACT_CHUNK, NULL, NULL, NULL, NULL,
|
||||
Buffer, BufferSize, ReadSize, false, finished);
|
||||
}
|
||||
|
||||
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
|
||||
{
|
||||
@@ -309,7 +392,7 @@ void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
|
||||
}
|
||||
|
||||
|
||||
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData)
|
||||
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
|
||||
{
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
Data->Cmd.Callback=Callback;
|
||||
@@ -323,12 +406,13 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro
|
||||
Data->Cmd.ProcessDataProc=ProcessDataProc;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NOCRYPT
|
||||
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
|
||||
{
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
strncpy(Data->Cmd.Password,Password,sizeof(Data->Cmd.Password));
|
||||
strncpyz(Data->Cmd.Password,Password,ASIZE(Data->Cmd.Password));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int PASCAL RARGetDllVersion()
|
||||
@@ -341,19 +425,21 @@ static int RarErrorToDll(int ErrCode)
|
||||
{
|
||||
switch(ErrCode)
|
||||
{
|
||||
case RAR_FATAL_ERROR:
|
||||
case FATAL_ERROR:
|
||||
return(ERAR_EREAD);
|
||||
case RAR_CRC_ERROR:
|
||||
case CRC_ERROR:
|
||||
return(ERAR_BAD_DATA);
|
||||
case RAR_WRITE_ERROR:
|
||||
case WRITE_ERROR:
|
||||
return(ERAR_EWRITE);
|
||||
case RAR_OPEN_ERROR:
|
||||
case OPEN_ERROR:
|
||||
return(ERAR_EOPEN);
|
||||
case RAR_CREATE_ERROR:
|
||||
case CREATE_ERROR:
|
||||
return(ERAR_ECREATE);
|
||||
case RAR_MEMORY_ERROR:
|
||||
case MEMORY_ERROR:
|
||||
return(ERAR_NO_MEMORY);
|
||||
case RAR_SUCCESS:
|
||||
case NO_PASSWORD_ERROR: //not in original
|
||||
return(ERAR_MISSING_PASSWORD);
|
||||
case SUCCESS:
|
||||
return(0);
|
||||
default:
|
||||
return(ERAR_UNKNOWN);
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
EXPORTS
|
||||
RAROpenArchive
|
||||
RAROpenArchiveEx
|
||||
RARCloseArchive
|
||||
RARReadHeader
|
||||
RARReadHeaderEx
|
||||
RARProcessFile
|
||||
RARSetCallback
|
||||
RARSetChangeVolProc
|
||||
RARSetProcessDataProc
|
||||
RARSetPassword
|
||||
RARGetDllVersion
|
||||
@@ -1,36 +1,44 @@
|
||||
#ifndef _UNRAR_DLL_
|
||||
#define _UNRAR_DLL_
|
||||
|
||||
#define ERAR_END_ARCHIVE 10
|
||||
#define ERAR_NO_MEMORY 11
|
||||
#define ERAR_BAD_DATA 12
|
||||
#define ERAR_BAD_ARCHIVE 13
|
||||
#define ERAR_UNKNOWN_FORMAT 14
|
||||
#define ERAR_EOPEN 15
|
||||
#define ERAR_ECREATE 16
|
||||
#define ERAR_ECLOSE 17
|
||||
#define ERAR_EREAD 18
|
||||
#define ERAR_EWRITE 19
|
||||
#define ERAR_SMALL_BUF 20
|
||||
#define ERAR_UNKNOWN 21
|
||||
#define ERAR_END_ARCHIVE 10
|
||||
#define ERAR_NO_MEMORY 11
|
||||
#define ERAR_BAD_DATA 12
|
||||
#define ERAR_BAD_ARCHIVE 13
|
||||
#define ERAR_UNKNOWN_FORMAT 14
|
||||
#define ERAR_EOPEN 15
|
||||
#define ERAR_ECREATE 16
|
||||
#define ERAR_ECLOSE 17
|
||||
#define ERAR_EREAD 18
|
||||
#define ERAR_EWRITE 19
|
||||
#define ERAR_SMALL_BUF 20
|
||||
#define ERAR_UNKNOWN 21
|
||||
#define ERAR_MISSING_PASSWORD 22
|
||||
|
||||
#define RAR_OM_LIST 0
|
||||
#define RAR_OM_EXTRACT 1
|
||||
#define RAR_OM_LIST 0
|
||||
#define RAR_OM_EXTRACT 1
|
||||
#define RAR_OM_LIST_INCSPLIT 2
|
||||
|
||||
#define RAR_SKIP 0
|
||||
#define RAR_TEST 1
|
||||
#define RAR_EXTRACT 2
|
||||
#define RAR_EXTRACT_CHUNK 3
|
||||
|
||||
#define RAR_VOL_ASK 0
|
||||
#define RAR_VOL_NOTIFY 1
|
||||
|
||||
#define RAR_DLL_VERSION 4
|
||||
|
||||
//Must be the same as MAXWINSIZE
|
||||
//not in original
|
||||
#define RAR_CHUNK_BUFFER_SIZE 0x400000
|
||||
|
||||
#ifdef _UNIX
|
||||
#define CALLBACK
|
||||
#define PASCAL
|
||||
#define LONG long
|
||||
#define HANDLE void *
|
||||
#define LPARAM long
|
||||
#define UINT unsigned int
|
||||
#endif
|
||||
|
||||
@@ -108,7 +116,7 @@ enum UNRARCALLBACK_MESSAGES {
|
||||
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD
|
||||
};
|
||||
|
||||
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LONG UserData,LONG P1,LONG P2);
|
||||
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
|
||||
|
||||
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
|
||||
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
|
||||
@@ -124,7 +132,9 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
|
||||
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
|
||||
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
|
||||
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName);
|
||||
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData);
|
||||
int PASCAL RARProcessFileChunkInit(HANDLE hArcData);
|
||||
int PASCAL RARProcessFileChunk(HANDLE hArcData, void *Buffer, size_t BufferSize, size_t *ReadSize, int *finished);
|
||||
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
|
||||
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
|
||||
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
|
||||
void PASCAL RARSetPassword(HANDLE hArcData,char *Password);
|
||||
|
||||
@@ -11,10 +11,10 @@ EncodeFileName::EncodeFileName()
|
||||
|
||||
|
||||
|
||||
void EncodeFileName::Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,
|
||||
int MaxDecSize)
|
||||
void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,
|
||||
size_t MaxDecSize)
|
||||
{
|
||||
int EncPos=0,DecPos=0;
|
||||
size_t EncPos=0,DecPos=0;
|
||||
byte HighByte=EncName[EncPos++];
|
||||
while (EncPos<EncSize && DecPos<MaxDecSize)
|
||||
{
|
||||
|
||||
@@ -8,13 +8,13 @@ class EncodeFileName
|
||||
|
||||
byte *EncName;
|
||||
byte Flags;
|
||||
int FlagBits;
|
||||
int FlagsPos;
|
||||
int DestSize;
|
||||
uint FlagBits;
|
||||
size_t FlagsPos;
|
||||
size_t DestSize;
|
||||
public:
|
||||
EncodeFileName();
|
||||
int Encode(char *Name,wchar *NameW,byte *EncName);
|
||||
void Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,int MaxDecSize);
|
||||
size_t Encode(char *Name,wchar *NameW,byte *EncName);
|
||||
void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,7 @@ ErrorHandler::ErrorHandler()
|
||||
|
||||
void ErrorHandler::Clean()
|
||||
{
|
||||
ExitCode=RAR_SUCCESS;
|
||||
ExitCode=SUCCESS;
|
||||
ErrCount=0;
|
||||
EnableBreak=true;
|
||||
Silent=false;
|
||||
@@ -22,7 +22,7 @@ void ErrorHandler::Clean()
|
||||
void ErrorHandler::MemoryError()
|
||||
{
|
||||
MemoryErrorMsg();
|
||||
Throw(RAR_MEMORY_ERROR);
|
||||
Throw(MEMORY_ERROR);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ void ErrorHandler::OpenError(const char *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
OpenErrorMsg(FileName);
|
||||
Throw(RAR_OPEN_ERROR);
|
||||
Throw(OPEN_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void ErrorHandler::CloseError(const char *FileName)
|
||||
}
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(RAR_FATAL_ERROR);
|
||||
Throw(FATAL_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -56,16 +56,17 @@ void ErrorHandler::ReadError(const char *FileName)
|
||||
ReadErrorMsg(NULL,FileName);
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(RAR_FATAL_ERROR);
|
||||
Throw(FATAL_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool ErrorHandler::AskRepeatRead(const char *FileName)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE) && !defined(GUI)
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE)
|
||||
if (!Silent)
|
||||
{
|
||||
SysErrMsg();
|
||||
mprintf("\n");
|
||||
Log(NULL,St(MErrRead),FileName);
|
||||
return(Ask(St(MRetryAbort))==1);
|
||||
@@ -81,7 +82,7 @@ void ErrorHandler::WriteError(const char *ArcName,const char *FileName)
|
||||
WriteErrorMsg(ArcName,FileName);
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(RAR_WRITE_ERROR);
|
||||
Throw(WRITE_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -94,19 +95,20 @@ void ErrorHandler::WriteErrorFAT(const char *FileName)
|
||||
ErrMsg(NULL,St(MNTFSRequired),FileName);
|
||||
#endif
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
|
||||
Throw(RAR_WRITE_ERROR);
|
||||
Throw(WRITE_ERROR);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool ErrorHandler::AskRepeatWrite(const char *FileName)
|
||||
bool ErrorHandler::AskRepeatWrite(const char *FileName,bool DiskFull)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(_WIN_CE) && !defined(GUI)
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
if (!Silent)
|
||||
{
|
||||
SysErrMsg();
|
||||
mprintf("\n");
|
||||
Log(NULL,St(MErrWrite),FileName);
|
||||
Log(NULL,St(DiskFull ? MNotEnoughDisk:MErrWrite),FileName);
|
||||
return(Ask(St(MRetryAbort))==1);
|
||||
}
|
||||
#endif
|
||||
@@ -124,7 +126,7 @@ void ErrorHandler::SeekError(const char *FileName)
|
||||
}
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(RAR_FATAL_ERROR);
|
||||
Throw(FATAL_ERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -173,19 +175,19 @@ void ErrorHandler::CreateErrorMsg(const char *ArcName,const char *FileName)
|
||||
#ifndef SILENT
|
||||
Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotCreate),FileName);
|
||||
Alarm();
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAXPATH)
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAX_PATH)
|
||||
if (GetLastError()==ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
int NameLength=strlen(FileName);
|
||||
size_t NameLength=strlen(FileName);
|
||||
if (!IsFullPath(FileName))
|
||||
{
|
||||
char CurDir[NM];
|
||||
GetCurrentDirectory(sizeof(CurDir),CurDir);
|
||||
NameLength+=strlen(CurDir)+1;
|
||||
}
|
||||
if (NameLength>MAXPATH)
|
||||
if (NameLength>MAX_PATH)
|
||||
{
|
||||
Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAXPATH);
|
||||
Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAX_PATH);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -247,14 +249,14 @@ void ErrorHandler::SetErrorCode(int Code)
|
||||
{
|
||||
switch(Code)
|
||||
{
|
||||
case RAR_WARNING:
|
||||
case RAR_USER_BREAK:
|
||||
if (ExitCode==RAR_SUCCESS)
|
||||
case WARNING:
|
||||
case USER_BREAK:
|
||||
if (ExitCode==SUCCESS)
|
||||
ExitCode=Code;
|
||||
break;
|
||||
case RAR_FATAL_ERROR:
|
||||
if (ExitCode==RAR_SUCCESS || ExitCode==RAR_WARNING)
|
||||
ExitCode=RAR_FATAL_ERROR;
|
||||
case FATAL_ERROR:
|
||||
if (ExitCode==SUCCESS || ExitCode==WARNING)
|
||||
ExitCode=FATAL_ERROR;
|
||||
break;
|
||||
default:
|
||||
ExitCode=Code;
|
||||
@@ -289,8 +291,9 @@ void _stdfunction ProcessSignal(int SigType)
|
||||
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE)
|
||||
ExtRes.UnloadDLL();
|
||||
#endif
|
||||
exit(RAR_USER_BREAK);
|
||||
#ifdef _WIN_32
|
||||
exit(USER_BREAK);
|
||||
#if defined(_WIN_32) && !defined(_MSC_VER)
|
||||
// never reached, just to avoid a compiler warning
|
||||
return(TRUE);
|
||||
#endif
|
||||
}
|
||||
@@ -314,7 +317,7 @@ void ErrorHandler::SetSignalHandlers(bool Enable)
|
||||
|
||||
void ErrorHandler::Throw(int Code)
|
||||
{
|
||||
if (Code==RAR_USER_BREAK && !EnableBreak)
|
||||
if (Code==USER_BREAK && !EnableBreak)
|
||||
return;
|
||||
ErrHandler.SetErrorCode(Code);
|
||||
#ifdef ALLOW_EXCEPTIONS
|
||||
|
||||
@@ -12,11 +12,13 @@
|
||||
#define rarrealloc realloc
|
||||
#define rarfree free
|
||||
#define rarstrdup strdup
|
||||
#define rarstrdupw strdupw
|
||||
|
||||
|
||||
|
||||
enum { RAR_SUCCESS,RAR_WARNING,RAR_FATAL_ERROR,RAR_CRC_ERROR,RAR_LOCK_ERROR,RAR_WRITE_ERROR,
|
||||
RAR_OPEN_ERROR,RAR_USER_ERROR,RAR_MEMORY_ERROR,RAR_CREATE_ERROR,RAR_USER_BREAK=255};
|
||||
//NO_PASSWORD_ERROR not in original. Maps to ERAR_MISSING_PASSWORD DLL error
|
||||
enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
|
||||
OPEN_ERROR,USER_ERROR,MEMORY_ERROR,CREATE_ERROR,NO_PASSWORD_ERROR,
|
||||
USER_BREAK=255};
|
||||
|
||||
class ErrorHandler
|
||||
{
|
||||
@@ -38,7 +40,7 @@ class ErrorHandler
|
||||
bool AskRepeatRead(const char *FileName);
|
||||
void WriteError(const char *ArcName,const char *FileName);
|
||||
void WriteErrorFAT(const char *FileName);
|
||||
bool AskRepeatWrite(const char *FileName);
|
||||
bool AskRepeatWrite(const char *FileName,bool DiskFull);
|
||||
void SeekError(const char *FileName);
|
||||
void GeneralErrMsg(const char *Msg);
|
||||
void MemoryErrorMsg();
|
||||
|
||||
@@ -4,6 +4,9 @@ CmdExtract::CmdExtract()
|
||||
{
|
||||
TotalFileCount=0;
|
||||
*Password=0;
|
||||
//next two lines added by me
|
||||
Buffer = NULL;
|
||||
BufferSize = 0;
|
||||
Unp=new Unpack(&DataIO);
|
||||
Unp->Init(NULL);
|
||||
}
|
||||
@@ -25,11 +28,24 @@ void CmdExtract::DoExtract(CommandData *Cmd)
|
||||
while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
|
||||
if (FindFile::FastFind(ArcName,ArcNameW,&FD))
|
||||
DataIO.TotalArcSize+=FD.Size;
|
||||
|
||||
Cmd->ArcNames->Rewind();
|
||||
while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
|
||||
{
|
||||
while (ExtractArchive(Cmd)==EXTRACT_ARC_REPEAT)
|
||||
;
|
||||
while (true)
|
||||
{
|
||||
char PrevCmdPassword[MAXPASSWORD];
|
||||
strcpy(PrevCmdPassword,Cmd->Password);
|
||||
|
||||
EXTRACT_ARC_CODE Code=ExtractArchive(Cmd);
|
||||
|
||||
// Restore Cmd->Password, which could be changed in IsArchive() call
|
||||
// for next header encrypted archive.
|
||||
strcpy(Cmd->Password,PrevCmdPassword);
|
||||
|
||||
if (Code!=EXTRACT_ARC_REPEAT)
|
||||
break;
|
||||
}
|
||||
if (FindFile::FastFind(ArcName,ArcNameW,&FD))
|
||||
DataIO.ProcessedArcSize+=FD.Size;
|
||||
}
|
||||
@@ -38,11 +54,9 @@ void CmdExtract::DoExtract(CommandData *Cmd)
|
||||
{
|
||||
if (!PasswordCancelled)
|
||||
{
|
||||
#ifndef GUI
|
||||
mprintf(St(MExtrNoFiles));
|
||||
#endif
|
||||
}
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
}
|
||||
#ifndef GUI
|
||||
else
|
||||
@@ -78,6 +92,8 @@ void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc)
|
||||
SignatureFound=false;
|
||||
AllMatchesExact=true;
|
||||
ReconstructDone=false;
|
||||
|
||||
StartTime.SetCurrentTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +102,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
|
||||
Archive Arc(Cmd);
|
||||
if (!Arc.WOpen(ArcName,ArcNameW))
|
||||
{
|
||||
ErrHandler.SetErrorCode(RAR_OPEN_ERROR);
|
||||
ErrHandler.SetErrorCode(OPEN_ERROR);
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
}
|
||||
|
||||
@@ -96,10 +112,11 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
|
||||
mprintf(St(MNotRAR),ArcName);
|
||||
#endif
|
||||
if (CmpExt(ArcName,"rar"))
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
}
|
||||
|
||||
// archive with corrupt encrypted header can be closed in IsArchive() call
|
||||
if (!Arc.IsOpened())
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
|
||||
@@ -107,13 +124,45 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
|
||||
if (Arc.Volume && Arc.NotFirstVolume)
|
||||
{
|
||||
char FirstVolName[NM];
|
||||
VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
|
||||
|
||||
VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING));
|
||||
// If several volume names from same volume set are specified
|
||||
// and current volume is not first in set and first volume is present
|
||||
// and specified too, let's skip the current volume.
|
||||
if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
|
||||
Cmd->ArcNames->Search(FirstVolName,NULL,false))
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
}
|
||||
#endif
|
||||
|
||||
int64 VolumeSetSize=0; // Total size of volumes after the current volume.
|
||||
|
||||
if (Arc.Volume)
|
||||
{
|
||||
// Calculate the total size of all accessible volumes.
|
||||
// This size is necessary to display the correct total progress indicator.
|
||||
|
||||
char NextName[NM];
|
||||
wchar NextNameW[NM];
|
||||
|
||||
strcpy(NextName,Arc.FileName);
|
||||
strcpyw(NextNameW,Arc.FileNameW);
|
||||
|
||||
while (true)
|
||||
{
|
||||
// First volume is already added to DataIO.TotalArcSize
|
||||
// in initial TotalArcSize calculation in DoExtract.
|
||||
// So we skip it and start from second volume.
|
||||
NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
|
||||
struct FindData FD;
|
||||
if (FindFile::FastFind(NextName,NextNameW,&FD))
|
||||
VolumeSetSize+=FD.Size;
|
||||
else
|
||||
break;
|
||||
}
|
||||
DataIO.TotalArcSize+=VolumeSetSize;
|
||||
}
|
||||
|
||||
ExtractArchiveInit(Cmd,Arc);
|
||||
|
||||
if (*Cmd->Command=='T' || *Cmd->Command=='I')
|
||||
@@ -131,34 +180,49 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
|
||||
|
||||
Arc.ViewComment();
|
||||
|
||||
// RAR can close a corrupt encrypted archive
|
||||
if (!Arc.IsOpened())
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
int Size=Arc.ReadHeader();
|
||||
size_t Size=Arc.ReadHeader();
|
||||
bool Repeat=false;
|
||||
if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
|
||||
if (Repeat)
|
||||
{
|
||||
// If we started extraction from not first volume and need to
|
||||
// restart it from first, we must correct DataIO.TotalArcSize
|
||||
// for correct total progress display. We subtract the size
|
||||
// of current volume and all volumes after it and add the size
|
||||
// of new (first) volume.
|
||||
struct FindData OldArc,NewArc;
|
||||
if (FindFile::FastFind(Arc.FileName,Arc.FileNameW,&OldArc) &&
|
||||
FindFile::FastFind(ArcName,ArcNameW,&NewArc))
|
||||
DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
|
||||
return(EXTRACT_ARC_REPEAT);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
}
|
||||
|
||||
|
||||
bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,bool &Repeat)
|
||||
bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
{
|
||||
char Command=*Cmd->Command;
|
||||
if (HeaderSize<=0)
|
||||
if (HeaderSize==0)
|
||||
if (DataIO.UnpVolume)
|
||||
{
|
||||
#ifdef NOVOLUME
|
||||
return(false);
|
||||
#else
|
||||
if (!MergeArchive(Arc,NULL,false,Command))
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return(false);
|
||||
}
|
||||
SignatureFound=false;
|
||||
@@ -188,9 +252,9 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
if (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)
|
||||
{
|
||||
#ifndef NOVOLUME
|
||||
if (!MergeArchive(Arc,NULL,false,Command))
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return(false);
|
||||
}
|
||||
SignatureFound=false;
|
||||
@@ -291,9 +355,18 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
|
||||
{
|
||||
char CurVolName[NM];
|
||||
/* Added the line below. The library was crashing without it, because
|
||||
* ArcName wouldn't be initialized. this code path is executed when
|
||||
* you open a volume, ask to unpack a file and that file doesn't start
|
||||
* in the opened volume. This function now changes this->ArcName into
|
||||
* the name of the first volume, sets the parameter Repeat to true and
|
||||
* returns false.
|
||||
* Possibly ArcName was supposed to be set from another method before.
|
||||
* Would need further investigation. */
|
||||
strncpy(ArcName, Arc.FileName, NM);
|
||||
strcpy(CurVolName,ArcName);
|
||||
|
||||
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING));
|
||||
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
|
||||
if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
||||
{
|
||||
*ArcNameW=0;
|
||||
@@ -316,7 +389,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
strcpy(ArcName,CurVolName);
|
||||
}
|
||||
#endif
|
||||
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER);
|
||||
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0;
|
||||
DataIO.NextVolumeMissing=false;
|
||||
|
||||
Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
|
||||
@@ -334,7 +407,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_BAD_DATA;
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(OPEN_ERROR);
|
||||
}
|
||||
ExactMatch=false;
|
||||
}
|
||||
@@ -344,16 +417,21 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
|
||||
if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
|
||||
{
|
||||
if (Arc.NewLhd.Flags & LHD_PASSWORD)
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
|
||||
#ifndef RARDLL
|
||||
if (*Password==0)
|
||||
#endif
|
||||
{
|
||||
#ifdef RARDLL
|
||||
if (*Cmd->Password==0)
|
||||
{
|
||||
if (Cmd->Callback==NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1)
|
||||
return(false);
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,sizeof(Cmd->Password))==-1)
|
||||
{
|
||||
Cmd->DllError = ERAR_MISSING_PASSWORD; //added by me
|
||||
return false;
|
||||
}
|
||||
}
|
||||
strcpy(Password,Cmd->Password);
|
||||
|
||||
#else
|
||||
@@ -372,7 +450,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll)))
|
||||
{
|
||||
case -1:
|
||||
ErrHandler.Exit(RAR_USER_BREAK);
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
case 2:
|
||||
if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password)))
|
||||
{
|
||||
@@ -397,7 +475,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
#ifndef SFX_MODULE
|
||||
if (Cmd->AppendArcNameToPath)
|
||||
{
|
||||
strcat(DestFileName,PointToName(Arc.FileName));
|
||||
strcat(DestFileName,PointToName(Arc.FirstVolumeName));
|
||||
SetExt(DestFileName,NULL);
|
||||
AddEndSlash(DestFileName);
|
||||
}
|
||||
@@ -407,7 +485,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
|
||||
bool EmptyName=false;
|
||||
#ifndef SFX_MODULE
|
||||
int Length=strlen(Cmd->ArcPath);
|
||||
size_t Length=strlen(Cmd->ArcPath);
|
||||
if (Length>1 && IsPathDiv(Cmd->ArcPath[Length-1]) &&
|
||||
strlen(ArcFileName)==Length-1)
|
||||
Length--;
|
||||
@@ -430,7 +508,10 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
else
|
||||
strcat(DestFileName,ExtrName);
|
||||
|
||||
if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2]))
|
||||
char DiskLetter=etoupper(DestFileName[0]);
|
||||
|
||||
if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2]) &&
|
||||
DiskLetter>='A' && DiskLetter<='Z')
|
||||
DestFileName[1]=':';
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
@@ -453,10 +534,10 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
if (Cmd->AppendArcNameToPath)
|
||||
{
|
||||
wchar FileNameW[NM];
|
||||
if (*Arc.FileNameW!=0)
|
||||
strcpyw(FileNameW,Arc.FileNameW);
|
||||
if (*Arc.FirstVolumeNameW!=0)
|
||||
strcpyw(FileNameW,Arc.FirstVolumeNameW);
|
||||
else
|
||||
CharToWide(Arc.FileName,FileNameW);
|
||||
CharToWide(Arc.FirstVolumeName,FileNameW);
|
||||
strcatw(DestFileNameW,PointToName(FileNameW));
|
||||
SetExt(DestFileNameW,NULL);
|
||||
AddEndSlash(DestFileNameW);
|
||||
@@ -467,7 +548,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
if (Length>0)
|
||||
{
|
||||
wchar ArcPathW[NM];
|
||||
CharToWide(Cmd->ArcPath,ArcPathW);
|
||||
GetWideName(Cmd->ArcPath,Cmd->ArcPathW,ArcPathW);
|
||||
Length=strlenw(ArcPathW);
|
||||
}
|
||||
ExtrNameW+=Length;
|
||||
@@ -489,31 +570,51 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
else
|
||||
*DestFileNameW=0;
|
||||
|
||||
ExtrFile=!SkipSolid && !EmptyName && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0/* && *ExtrName*/;
|
||||
ExtrFile=!SkipSolid && !EmptyName && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0;
|
||||
|
||||
if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X'))
|
||||
{
|
||||
struct FindData FD;
|
||||
if (FindFile::FastFind(DestFileName,DestNameW,&FD))
|
||||
{
|
||||
if (FD.mtime >= Arc.NewLhd.mtime)
|
||||
ExtrFile=false;
|
||||
{
|
||||
// If directory already exists and its modification time is newer
|
||||
// than start of extraction, it is likely it was created
|
||||
// when creating a path to one of already extracted items.
|
||||
// In such case we'll better update its time even if archived
|
||||
// directory is older.
|
||||
|
||||
if (!FD.IsDir || FD.mtime<StartTime)
|
||||
ExtrFile=false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (Cmd->FreshFiles)
|
||||
ExtrFile=false;
|
||||
}
|
||||
|
||||
// Skip encrypted file if no password is specified.
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && *Password==0)
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_MISSING_PASSWORD;
|
||||
#endif
|
||||
ExtrFile=false;
|
||||
}
|
||||
|
||||
#ifdef RARDLL
|
||||
if (*Cmd->DllDestName)
|
||||
{
|
||||
strncpy(DestFileName,Cmd->DllDestName,sizeof(DestFileName));
|
||||
strncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
|
||||
*DestFileNameW=0;
|
||||
if (Cmd->DllOpMode!=RAR_EXTRACT)
|
||||
ExtrFile=false;
|
||||
}
|
||||
if (*Cmd->DllDestNameW)
|
||||
{
|
||||
strncpyw(DestFileNameW,Cmd->DllDestNameW,sizeof(DestFileNameW)/sizeof(DestFileNameW[0]));
|
||||
strncpyzw(DestFileNameW,Cmd->DllDestNameW,ASIZE(DestFileNameW));
|
||||
DestNameW=DestFileNameW;
|
||||
if (Cmd->DllOpMode!=RAR_EXTRACT)
|
||||
ExtrFile=false;
|
||||
@@ -534,7 +635,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
#endif
|
||||
#endif
|
||||
ExtrFile=false;
|
||||
ErrHandler.SetErrorCode(RAR_WARNING);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
#endif
|
||||
@@ -563,7 +664,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
#endif
|
||||
return(true);
|
||||
}
|
||||
MKDIR_CODE MDCode=MakeDir(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
|
||||
MKDIR_CODE MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
|
||||
bool DirExist=false;
|
||||
if (MDCode!=MKDIR_SUCCESS)
|
||||
{
|
||||
@@ -575,7 +676,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
DirExist=false;
|
||||
}
|
||||
CreatePath(DestFileName,DestNameW,true);
|
||||
MDCode=MakeDir(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
|
||||
MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
|
||||
}
|
||||
if (MDCode==MKDIR_SUCCESS)
|
||||
{
|
||||
@@ -588,7 +689,8 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
else
|
||||
if (DirExist)
|
||||
{
|
||||
SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
|
||||
if (!Cmd->IgnoreGeneralAttr)
|
||||
SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
|
||||
PrevExtracted=true;
|
||||
}
|
||||
else
|
||||
@@ -598,16 +700,16 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_ECREATE;
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(RAR_CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
}
|
||||
if (PrevExtracted)
|
||||
{
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
|
||||
if (Cmd->SetCompressedAttr &&
|
||||
(Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
|
||||
SetFileCompression(DestFileName,DestFileNameW,true);
|
||||
SetFileCompression(DestFileName,DestNameW,true);
|
||||
#endif
|
||||
SetDirTime(DestFileName,
|
||||
SetDirTime(DestFileName,DestNameW,
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
|
||||
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
|
||||
@@ -631,7 +733,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
if (!UserReject)
|
||||
{
|
||||
ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
|
||||
ErrHandler.SetErrorCode(RAR_CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_ECREATE;
|
||||
#endif
|
||||
@@ -639,8 +741,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
{
|
||||
Log(Arc.FileName,St(MCorrectingName));
|
||||
char OrigName[sizeof(DestFileName)];
|
||||
strncpy(OrigName,DestFileName,sizeof(OrigName)-1);
|
||||
OrigName[sizeof(OrigName)-1]=0;
|
||||
strncpyz(OrigName,DestFileName,ASIZE(OrigName));
|
||||
|
||||
MakeNameUsable(DestFileName,true);
|
||||
CreatePath(DestFileName,NULL,true);
|
||||
@@ -664,6 +765,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
SkipSolid=true;
|
||||
TestMode=true;
|
||||
ExtrFile=true;
|
||||
|
||||
}
|
||||
if (ExtrFile)
|
||||
{
|
||||
@@ -736,7 +838,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
|
||||
else
|
||||
#endif
|
||||
Unp->DoUnpack(Arc.NewLhd.UnpVer,Arc.NewLhd.Flags & LHD_SOLID);
|
||||
Unp->DoUnpack(Arc.NewLhd.UnpVer,(Arc.NewLhd.Flags & LHD_SOLID)!=0);
|
||||
}
|
||||
|
||||
if (Arc.IsOpened())
|
||||
@@ -765,7 +867,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
Log(BadArcName,St(MCRCFailed),ArcFileName);
|
||||
}
|
||||
BrokenFile=true;
|
||||
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_BAD_DATA;
|
||||
#endif
|
||||
@@ -783,12 +885,16 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
#if defined(_WIN_32) || defined(_EMX)
|
||||
if (Cmd->ClearArc)
|
||||
Arc.NewLhd.FileAttr&=~FA_ARCH;
|
||||
/*
|
||||
else
|
||||
Arc.NewLhd.FileAttr|=FA_ARCH; //set archive bit for unpacked files (file is not backed up)
|
||||
*/
|
||||
#endif
|
||||
if (!BrokenFile || Cmd->KeepBroken)
|
||||
{
|
||||
if (BrokenFile)
|
||||
CurFile.Truncate();
|
||||
CurFile.SetOpenFileStat(
|
||||
CurFile.SetOpenFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
|
||||
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
|
||||
@@ -798,10 +904,11 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
(Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
|
||||
SetFileCompression(CurFile.FileName,CurFile.FileNameW,true);
|
||||
#endif
|
||||
CurFile.SetCloseFileStat(
|
||||
CurFile.SetCloseFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime,
|
||||
Arc.NewLhd.FileAttr);
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
|
||||
if (!Cmd->IgnoreGeneralAttr)
|
||||
SetFileAttr(CurFile.FileName,CurFile.FileNameW,Arc.NewLhd.FileAttr);
|
||||
PrevExtracted=true;
|
||||
}
|
||||
}
|
||||
@@ -820,16 +927,26 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
|
||||
return(true);
|
||||
}
|
||||
|
||||
//added by me
|
||||
#if !defined(MIN)
|
||||
#define MIN(a, b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize)
|
||||
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize)
|
||||
{
|
||||
Array<byte> Buffer(0x10000);
|
||||
while (1)
|
||||
{
|
||||
unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
|
||||
//uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
|
||||
/* With that original code, the whole file would necessarily be read on the
|
||||
* first call to this method */
|
||||
uint Code=DataIO.UnpRead(&Buffer[0], MIN(Buffer.Size(), (size_t) DestUnpSize));
|
||||
if (Code==0 || (int)Code==-1)
|
||||
break;
|
||||
Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
|
||||
//Code=Code<DestUnpSize ? Code:(uint)DestUnpSize;
|
||||
/* original code (basically Code = MIN(Code, (uint) DestUnpSize))
|
||||
* discards extra data.
|
||||
* It should not be necessary anymore (see change above) */
|
||||
DataIO.UnpWrite(&Buffer[0],Code);
|
||||
if (DestUnpSize>=0)
|
||||
DestUnpSize-=Code;
|
||||
|
||||
@@ -6,12 +6,15 @@ enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
|
||||
class CmdExtract
|
||||
{
|
||||
private:
|
||||
EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
|
||||
RarTime StartTime; // time when extraction started
|
||||
|
||||
ComprDataIO DataIO;
|
||||
Unpack *Unp;
|
||||
long TotalFileCount;
|
||||
unsigned long TotalFileCount;
|
||||
|
||||
long FileCount;
|
||||
long MatchedArgs;
|
||||
unsigned long FileCount;
|
||||
unsigned long MatchedArgs;
|
||||
bool FirstFile;
|
||||
bool AllMatchesExact;
|
||||
bool ReconstructDone;
|
||||
@@ -22,7 +25,6 @@ class CmdExtract
|
||||
char Password[MAXPASSWORD];
|
||||
bool PasswordAll;
|
||||
bool PrevExtracted;
|
||||
bool SignatureFound;
|
||||
char DestFileName[NM];
|
||||
wchar DestFileNameW[NM];
|
||||
bool PasswordCancelled;
|
||||
@@ -31,10 +33,18 @@ class CmdExtract
|
||||
~CmdExtract();
|
||||
void DoExtract(CommandData *Cmd);
|
||||
void ExtractArchiveInit(CommandData *Cmd,Archive &Arc);
|
||||
EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
|
||||
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,
|
||||
bool &Repeat);
|
||||
static void UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize);
|
||||
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,
|
||||
bool &Repeat);
|
||||
bool ExtractCurrentFileChunkInit(CommandData *Cmd, Archive &Arc,
|
||||
size_t HeaderSize, bool &Repeat);
|
||||
bool ExtractCurrentFileChunk(CommandData *Cmd, Archive &Arc,
|
||||
size_t *ReadSize, int *finished);
|
||||
static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize);
|
||||
|
||||
bool SignatureFound;
|
||||
//next two lines added by me
|
||||
void *Buffer;
|
||||
size_t BufferSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
155
unrar/extractchunk.cpp
Normal file
155
unrar/extractchunk.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
|
||||
Archive &Arc,
|
||||
size_t HeaderSize,
|
||||
bool &Repeat)
|
||||
{
|
||||
char Command = 'T';
|
||||
|
||||
Cmd->DllError=0;
|
||||
Repeat = false;
|
||||
|
||||
//turn on checks reserved for the first files extracted from an archive?
|
||||
FirstFile = true;
|
||||
|
||||
if (HeaderSize==0) {
|
||||
if (DataIO.UnpVolume)
|
||||
{
|
||||
#ifdef NOVOLUME
|
||||
return(false);
|
||||
#else
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command)) //command irrelevant
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return false;
|
||||
}
|
||||
SignatureFound=false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int HeadType=Arc.GetHeaderType();
|
||||
if (HeadType!=FILE_HEAD)
|
||||
return false;
|
||||
|
||||
DataIO.SetUnpackToMemory((byte*) this->Buffer, this->BufferSize);
|
||||
DataIO.SetSkipUnpCRC(true);
|
||||
DataIO.SetCurrentCommand(Command);
|
||||
//will still write to mem, as we've told it, but if I've screwed up the
|
||||
//there'll be no operations in the filesystem
|
||||
DataIO.SetTestMode(true);
|
||||
|
||||
if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
|
||||
{
|
||||
char CurVolName[NM];
|
||||
strncpy(ArcName, Arc.FileName, NM);
|
||||
strcpy(CurVolName, ArcName);
|
||||
|
||||
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
|
||||
if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
||||
{
|
||||
*ArcNameW=0;
|
||||
Repeat=true;
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
/* Actually known. The problem is that the file doesn't start on this volume. */
|
||||
Cmd->DllError = ERAR_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
strcpy(ArcName,CurVolName);
|
||||
}
|
||||
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0;
|
||||
DataIO.NextVolumeMissing=false;
|
||||
|
||||
Arc.Seek(Arc.NextBlockPos - Arc.NewLhd.FullPackSize, SEEK_SET);
|
||||
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
|
||||
{
|
||||
if (*Cmd->Password==0)
|
||||
if (Cmd->Callback==NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,
|
||||
(LPARAM)sizeof(Cmd->Password))==-1)
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
Cmd->DllError = ERAR_MISSING_PASSWORD;
|
||||
return false;
|
||||
}
|
||||
strcpy(Password,Cmd->Password);
|
||||
}
|
||||
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD) != 0) {
|
||||
if (*Cmd->Password == '\0') {
|
||||
if (Cmd->Callback == NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD, Cmd->UserData, (LPARAM) Cmd->Password,
|
||||
(LPARAM) sizeof(Cmd->Password)) == -1) {
|
||||
Cmd->DllError = ERAR_MISSING_PASSWORD;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
strncpy(Password, Cmd->Password, sizeof Password);
|
||||
}
|
||||
|
||||
if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsLink(Arc.NewLhd.FileAttr))
|
||||
return true;
|
||||
|
||||
if (Arc.IsArcDir())
|
||||
return true;
|
||||
|
||||
DataIO.CurUnpRead=0;
|
||||
DataIO.CurUnpWrite=0;
|
||||
DataIO.UnpFileCRC= Arc.OldFormat ? 0 : 0xffffffff;
|
||||
DataIO.PackedCRC= 0xffffffff;
|
||||
DataIO.SetEncryption(
|
||||
(Arc.NewLhd.Flags & LHD_PASSWORD) ? Arc.NewLhd.UnpVer : 0, Password,
|
||||
(Arc.NewLhd.Flags & LHD_SALT) ? Arc.NewLhd.Salt : NULL, false,
|
||||
Arc.NewLhd.UnpVer >= 36);
|
||||
DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
|
||||
DataIO.SetSkipUnpCRC(true);
|
||||
DataIO.SetFiles(&Arc, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CmdExtract::ExtractCurrentFileChunk(CommandData *Cmd, Archive &Arc,
|
||||
size_t *ReadSize,
|
||||
int *finished)
|
||||
{
|
||||
if (IsLink(Arc.NewLhd.FileAttr) || Arc.IsArcDir()) {
|
||||
*ReadSize = 0;
|
||||
*finished = TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
DataIO.SetUnpackToMemory((byte*) this->Buffer, this->BufferSize);
|
||||
|
||||
if (Arc.NewLhd.Method==0x30) {
|
||||
UnstoreFile(DataIO, this->BufferSize);
|
||||
/* not very sophisticated and may result in a subsequent
|
||||
* unnecessary call to this function (and probably will if
|
||||
* the buffer size is chosen so that it just fits for small
|
||||
* files) */
|
||||
*finished = (DataIO.GetUnpackToMemorySizeLeft() > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
|
||||
if (Arc.NewLhd.UnpVer<=15)
|
||||
Unp->DoUnpack(15,FileCount>1 && Arc.Solid, this->Buffer != NULL);
|
||||
else
|
||||
Unp->DoUnpack(Arc.NewLhd.UnpVer,
|
||||
(Arc.NewLhd.Flags & LHD_SOLID)!=0, this->Buffer != NULL);
|
||||
*finished = Unp->IsFileExtracted();
|
||||
}
|
||||
*ReadSize = this->BufferSize - DataIO.GetUnpackToMemorySizeLeft();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize,
|
||||
uint FileTime)
|
||||
{
|
||||
if (UserReject!=NULL)
|
||||
@@ -30,7 +30,7 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
#endif
|
||||
if (Cmd->AllYes || Mode==OVERWRITE_ALL)
|
||||
break;
|
||||
if (Mode==OVERWRITE_ASK)
|
||||
if (Mode==OVERWRITE_DEFAULT || Mode==OVERWRITE_FORCE_ASK)
|
||||
{
|
||||
eprintf(St(MFileExists),Name);
|
||||
int Choice=Ask(St(MYesNoAllRenQ));
|
||||
@@ -56,9 +56,7 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
}
|
||||
if (Choice==5)
|
||||
{
|
||||
#ifndef GUI
|
||||
mprintf(St(MAskNewName));
|
||||
#endif
|
||||
|
||||
char NewName[NM];
|
||||
#ifdef _WIN_32
|
||||
@@ -68,7 +66,13 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
NewName[Size]=0;
|
||||
OemToChar(NewName,NewName);
|
||||
#else
|
||||
fgets(NewName,sizeof(NewName),stdin);
|
||||
if (fgets(NewName,sizeof(NewName),stdin)==NULL)
|
||||
{
|
||||
// Process fgets failure as if user answered 'No'.
|
||||
if (UserReject!=NULL)
|
||||
*UserReject=true;
|
||||
return(false);
|
||||
}
|
||||
#endif
|
||||
RemoveLF(NewName);
|
||||
if (PointToName(NewName)==NewName)
|
||||
@@ -80,7 +84,7 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
continue;
|
||||
}
|
||||
if (Choice==6)
|
||||
ErrHandler.Exit(RAR_USER_BREAK);
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
}
|
||||
if (Mode==OVERWRITE_AUTORENAME)
|
||||
{
|
||||
@@ -90,7 +94,7 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
*NameW=0;
|
||||
}
|
||||
else
|
||||
Mode=OVERWRITE_ASK;
|
||||
Mode=OVERWRITE_DEFAULT;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +117,7 @@ bool GetAutoRenamedName(char *Name)
|
||||
Ext=Name+strlen(Name);
|
||||
for (int FileVer=1;;FileVer++)
|
||||
{
|
||||
sprintf(NewName,"%.*s(%d)%s",Ext-Name,Name,FileVer,Ext);
|
||||
sprintf(NewName,"%.*s(%d)%s",int(Ext-Name),Name,FileVer,Ext);
|
||||
if (!FileExist(NewName))
|
||||
{
|
||||
strcpy(Name,NewName);
|
||||
@@ -141,7 +145,7 @@ bool UpdateExistingShortName(char *Name,wchar *NameW)
|
||||
char NewName[NM];
|
||||
for (int I=0;I<10000;I+=123)
|
||||
{
|
||||
strncpy(NewName,Name,sizeof(NewName));
|
||||
strncpyz(NewName,Name,ASIZE(NewName));
|
||||
sprintf(PointToName(NewName),"rtmp%d",I);
|
||||
if (!FileExist(NewName))
|
||||
break;
|
||||
@@ -149,7 +153,7 @@ bool UpdateExistingShortName(char *Name,wchar *NameW)
|
||||
if (FileExist(NewName))
|
||||
return(false);
|
||||
char FullName[NM];
|
||||
strncpy(FullName,Name,sizeof(FullName));
|
||||
strncpyz(FullName,Name,ASIZE(FullName));
|
||||
strcpy(PointToName(FullName),PointToName(fd.Name));
|
||||
if (!MoveFile(FullName,NewName))
|
||||
return(false);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define _RAR_FILECREATE_
|
||||
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize=INT64ERR,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize=INT64NDF,
|
||||
uint FileTime=0);
|
||||
bool GetAutoRenamedName(char *Name);
|
||||
|
||||
|
||||
139
unrar/file.cpp
139
unrar/file.cpp
@@ -121,7 +121,7 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
|
||||
void File::TOpen(const char *Name,const wchar *NameW)
|
||||
{
|
||||
if (!WOpen(Name,NameW))
|
||||
ErrHandler.Exit(RAR_OPEN_ERROR);
|
||||
ErrHandler.Exit(OPEN_ERROR);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -135,14 +135,15 @@ bool File::WOpen(const char *Name,const wchar *NameW)
|
||||
}
|
||||
|
||||
|
||||
bool File::Create(const char *Name,const wchar *NameW)
|
||||
bool File::Create(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
DWORD ShareMode=(ShareRead || File::OpenShared) ? FILE_SHARE_READ:0;
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
|
||||
hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
|
||||
CREATE_ALWAYS,0,NULL);
|
||||
else
|
||||
hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
|
||||
hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
|
||||
CREATE_ALWAYS,0,NULL);
|
||||
#else
|
||||
hFile=fopen(Name,CREATEBINARY);
|
||||
@@ -176,19 +177,19 @@ void File::AddFileToList(FileHandle hFile)
|
||||
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
|
||||
void File::TCreate(const char *Name,const wchar *NameW)
|
||||
void File::TCreate(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
{
|
||||
if (!WCreate(Name,NameW))
|
||||
ErrHandler.Exit(RAR_FATAL_ERROR);
|
||||
if (!WCreate(Name,NameW,ShareRead))
|
||||
ErrHandler.Exit(FATAL_ERROR);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool File::WCreate(const char *Name,const wchar *NameW)
|
||||
bool File::WCreate(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
{
|
||||
if (Create(Name,NameW))
|
||||
if (Create(Name,NameW,ShareRead))
|
||||
return(true);
|
||||
ErrHandler.SetErrorCode(RAR_CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
ErrHandler.CreateErrorMsg(Name);
|
||||
return(false);
|
||||
}
|
||||
@@ -205,7 +206,7 @@ bool File::Close()
|
||||
if (!SkipClose)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
Success=CloseHandle(hFile);
|
||||
Success=CloseHandle(hFile)==TRUE;
|
||||
#else
|
||||
Success=fclose(hFile)!=EOF;
|
||||
#endif
|
||||
@@ -238,29 +239,37 @@ void File::Flush()
|
||||
|
||||
bool File::Delete()
|
||||
{
|
||||
if (HandleType!=FILE_HANDLENORMAL || !AllowDelete)
|
||||
if (HandleType!=FILE_HANDLENORMAL)
|
||||
return(false);
|
||||
if (hFile!=BAD_HANDLE)
|
||||
Close();
|
||||
if (!AllowDelete)
|
||||
return(false);
|
||||
return(DelFile(FileName,FileNameW));
|
||||
}
|
||||
|
||||
|
||||
bool File::Rename(const char *NewName)
|
||||
bool File::Rename(const char *NewName,const wchar *NewNameW)
|
||||
{
|
||||
// we do not need to rename if names are already same
|
||||
bool Success=strcmp(FileName,NewName)==0;
|
||||
if (Success && *FileNameW!=0 && *NullToEmpty(NewNameW)!=0)
|
||||
Success=strcmpw(FileNameW,NewNameW)==0;
|
||||
|
||||
if (!Success)
|
||||
Success=rename(FileName,NewName)==0;
|
||||
Success=RenameFile(FileName,FileNameW,NewName,NewNameW);
|
||||
|
||||
if (Success)
|
||||
{
|
||||
// renamed successfully, storing the new name
|
||||
strcpy(FileName,NewName);
|
||||
*FileNameW=0;
|
||||
strcpyw(FileNameW,NullToEmpty(NewNameW));
|
||||
}
|
||||
return(Success);
|
||||
}
|
||||
|
||||
|
||||
void File::Write(const void *Data,int Size)
|
||||
void File::Write(const void *Data,size_t Size)
|
||||
{
|
||||
if (Size==0)
|
||||
return;
|
||||
@@ -286,18 +295,22 @@ void File::Write(const void *Data,int Size)
|
||||
#endif
|
||||
while (1)
|
||||
{
|
||||
bool Success;
|
||||
bool Success=false;
|
||||
#ifdef _WIN_32
|
||||
DWORD Written;
|
||||
DWORD Written=0;
|
||||
if (HandleType!=FILE_HANDLENORMAL)
|
||||
{
|
||||
const int MaxSize=0x4000;
|
||||
for (int I=0;I<Size;I+=MaxSize)
|
||||
if (!(Success=WriteFile(hFile,(byte *)Data+I,Min(Size-I,MaxSize),&Written,NULL)))
|
||||
// writing to stdout can fail in old Windows if data block is too large
|
||||
const size_t MaxSize=0x4000;
|
||||
for (size_t I=0;I<Size;I+=MaxSize)
|
||||
{
|
||||
Success=WriteFile(hFile,(byte *)Data+I,(DWORD)Min(Size-I,MaxSize),&Written,NULL)==TRUE;
|
||||
if (!Success)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
Success=WriteFile(hFile,Data,Size,&Written,NULL);
|
||||
Success=WriteFile(hFile,Data,(DWORD)Size,&Written,NULL)==TRUE;
|
||||
#else
|
||||
int Written=fwrite(Data,1,Size,hFile);
|
||||
Success=Written==Size && !ferror(hFile);
|
||||
@@ -306,13 +319,13 @@ void File::Write(const void *Data,int Size)
|
||||
{
|
||||
#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(RARDLL)
|
||||
int ErrCode=GetLastError();
|
||||
Int64 FilePos=Tell();
|
||||
Int64 FreeSize=GetFreeDisk(FileName);
|
||||
int64 FilePos=Tell();
|
||||
uint64 FreeSize=GetFreeDisk(FileName);
|
||||
SetLastError(ErrCode);
|
||||
if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
|
||||
ErrHandler.WriteErrorFAT(FileName);
|
||||
#endif
|
||||
if (ErrHandler.AskRepeatWrite(FileName))
|
||||
if (ErrHandler.AskRepeatWrite(FileName,false))
|
||||
{
|
||||
#ifndef _WIN_32
|
||||
clearerr(hFile);
|
||||
@@ -329,9 +342,10 @@ void File::Write(const void *Data,int Size)
|
||||
}
|
||||
|
||||
|
||||
int File::Read(void *Data,int Size)
|
||||
int File::Read(void *Data,size_t Size)
|
||||
{
|
||||
Int64 FilePos;
|
||||
int64 FilePos=0; //initialized only to suppress some compilers warning
|
||||
|
||||
if (IgnoreReadErrors)
|
||||
FilePos=Tell();
|
||||
int ReadSize;
|
||||
@@ -345,10 +359,10 @@ int File::Read(void *Data,int Size)
|
||||
if (IgnoreReadErrors)
|
||||
{
|
||||
ReadSize=0;
|
||||
for (int I=0;I<Size;I+=512)
|
||||
for (size_t I=0;I<Size;I+=512)
|
||||
{
|
||||
Seek(FilePos+I,SEEK_SET);
|
||||
int SizeToRead=Min(Size-I,512);
|
||||
size_t SizeToRead=Min(Size-I,512);
|
||||
int ReadCode=DirectRead(Data,SizeToRead);
|
||||
ReadSize+=(ReadCode==-1) ? 512:ReadCode;
|
||||
}
|
||||
@@ -366,10 +380,11 @@ int File::Read(void *Data,int Size)
|
||||
}
|
||||
|
||||
|
||||
int File::DirectRead(void *Data,int Size)
|
||||
// Returns -1 in case of error.
|
||||
int File::DirectRead(void *Data,size_t Size)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
const int MaxDeviceRead=20000;
|
||||
const size_t MaxDeviceRead=20000;
|
||||
#endif
|
||||
#ifndef _WIN_CE
|
||||
if (HandleType==FILE_HANDLESTD)
|
||||
@@ -385,7 +400,7 @@ int File::DirectRead(void *Data,int Size)
|
||||
#endif
|
||||
#ifdef _WIN_32
|
||||
DWORD Read;
|
||||
if (!ReadFile(hFile,Data,Size,&Read,NULL))
|
||||
if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
|
||||
{
|
||||
if (IsDevice() && Size>MaxDeviceRead)
|
||||
return(DirectRead(Data,MaxDeviceRead));
|
||||
@@ -401,41 +416,41 @@ int File::DirectRead(void *Data,int Size)
|
||||
LastWrite=false;
|
||||
}
|
||||
clearerr(hFile);
|
||||
int ReadSize=fread(Data,1,Size,hFile);
|
||||
size_t ReadSize=fread(Data,1,Size,hFile);
|
||||
if (ferror(hFile))
|
||||
return(-1);
|
||||
return(ReadSize);
|
||||
return((int)ReadSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void File::Seek(Int64 Offset,int Method)
|
||||
void File::Seek(int64 Offset,int Method)
|
||||
{
|
||||
if (!RawSeek(Offset,Method) && AllowExceptions)
|
||||
ErrHandler.SeekError(FileName);
|
||||
}
|
||||
|
||||
|
||||
bool File::RawSeek(Int64 Offset,int Method)
|
||||
bool File::RawSeek(int64 Offset,int Method)
|
||||
{
|
||||
if (hFile==BAD_HANDLE)
|
||||
return(true);
|
||||
if (!is64plus(Offset) && Method!=SEEK_SET)
|
||||
if (Offset<0 && Method!=SEEK_SET)
|
||||
{
|
||||
Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
|
||||
Method=SEEK_SET;
|
||||
}
|
||||
#ifdef _WIN_32
|
||||
LONG HighDist=int64to32(Offset>>32);
|
||||
if (SetFilePointer(hFile,int64to32(Offset),&HighDist,Method)==0xffffffff &&
|
||||
LONG HighDist=(LONG)(Offset>>32);
|
||||
if (SetFilePointer(hFile,(LONG)Offset,&HighDist,Method)==0xffffffff &&
|
||||
GetLastError()!=NO_ERROR)
|
||||
return(false);
|
||||
#else
|
||||
LastWrite=false;
|
||||
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
|
||||
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
|
||||
if (fseeko(hFile,Offset,Method)!=0)
|
||||
#else
|
||||
if (fseek(hFile,(long)int64to32(Offset),Method)!=0)
|
||||
if (fseek(hFile,(long)Offset,Method)!=0)
|
||||
#endif
|
||||
return(false);
|
||||
#endif
|
||||
@@ -443,7 +458,7 @@ bool File::RawSeek(Int64 Offset,int Method)
|
||||
}
|
||||
|
||||
|
||||
Int64 File::Tell()
|
||||
int64 File::Tell()
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
LONG HighDist=0;
|
||||
@@ -453,7 +468,7 @@ Int64 File::Tell()
|
||||
ErrHandler.SeekError(FileName);
|
||||
else
|
||||
return(-1);
|
||||
return(int32to64(HighDist,LowDist));
|
||||
return(INT32TO64(HighDist,LowDist));
|
||||
#else
|
||||
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
|
||||
return(ftello(hFile));
|
||||
@@ -464,7 +479,7 @@ Int64 File::Tell()
|
||||
}
|
||||
|
||||
|
||||
void File::Prealloc(Int64 Size)
|
||||
void File::Prealloc(int64 Size)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
if (RawSeek(Size,SEEK_SET))
|
||||
@@ -493,7 +508,7 @@ void File::PutByte(byte Byte)
|
||||
bool File::Truncate()
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
return(SetEndOfFile(hFile));
|
||||
return(SetEndOfFile(hFile)==TRUE);
|
||||
#else
|
||||
return(false);
|
||||
#endif
|
||||
@@ -563,31 +578,7 @@ void File::GetOpenFileTime(RarTime *ft)
|
||||
}
|
||||
|
||||
|
||||
void File::SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
SetOpenFileTime(ftm,ftc,fta);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void File::SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
SetFileAttr(FileName,FileNameW,FileAttr);
|
||||
#endif
|
||||
#ifdef _EMX
|
||||
SetCloseFileTime(ftm,fta);
|
||||
SetFileAttr(FileName,FileNameW,FileAttr);
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
SetCloseFileTime(ftm,fta);
|
||||
chmod(FileName,(mode_t)FileAttr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Int64 File::FileLength()
|
||||
int64 File::FileLength()
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
Seek(0,SEEK_END);
|
||||
@@ -664,16 +655,16 @@ bool File::RemoveCreated()
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
long File::Copy(File &Dest,Int64 Length)
|
||||
int64 File::Copy(File &Dest,int64 Length)
|
||||
{
|
||||
Array<char> Buffer(0x10000);
|
||||
long CopySize=0;
|
||||
bool CopyAll=(Length==INT64ERR);
|
||||
int64 CopySize=0;
|
||||
bool CopyAll=(Length==INT64NDF);
|
||||
|
||||
while (CopyAll || Length>0)
|
||||
{
|
||||
Wait();
|
||||
int SizeToRead=(!CopyAll && Length<Buffer.Size()) ? int64to32(Length):Buffer.Size();
|
||||
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
|
||||
int ReadSize=Read(&Buffer[0],SizeToRead);
|
||||
if (ReadSize==0)
|
||||
break;
|
||||
|
||||
@@ -19,7 +19,7 @@ struct FileStat
|
||||
{
|
||||
uint FileAttr;
|
||||
uint FileTime;
|
||||
Int64 FileSize;
|
||||
int64 FileSize;
|
||||
bool IsDir;
|
||||
};
|
||||
|
||||
@@ -56,31 +56,29 @@ class File
|
||||
bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false);
|
||||
void TOpen(const char *Name,const wchar *NameW=NULL);
|
||||
bool WOpen(const char *Name,const wchar *NameW=NULL);
|
||||
bool Create(const char *Name,const wchar *NameW=NULL);
|
||||
void TCreate(const char *Name,const wchar *NameW=NULL);
|
||||
bool WCreate(const char *Name,const wchar *NameW=NULL);
|
||||
bool Create(const char *Name,const wchar *NameW=NULL,bool ShareRead=true);
|
||||
void TCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true);
|
||||
bool WCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true);
|
||||
bool Close();
|
||||
void Flush();
|
||||
bool Delete();
|
||||
bool Rename(const char *NewName);
|
||||
void Write(const void *Data,int Size);
|
||||
int Read(void *Data,int Size);
|
||||
int DirectRead(void *Data,int Size);
|
||||
void Seek(Int64 Offset,int Method);
|
||||
bool RawSeek(Int64 Offset,int Method);
|
||||
Int64 Tell();
|
||||
void Prealloc(Int64 Size);
|
||||
bool Rename(const char *NewName,const wchar *NewNameW=NULL);
|
||||
void Write(const void *Data,size_t Size);
|
||||
int Read(void *Data,size_t Size);
|
||||
int DirectRead(void *Data,size_t Size);
|
||||
void Seek(int64 Offset,int Method);
|
||||
bool RawSeek(int64 Offset,int Method);
|
||||
int64 Tell();
|
||||
void Prealloc(int64 Size);
|
||||
byte GetByte();
|
||||
void PutByte(byte Byte);
|
||||
bool Truncate();
|
||||
void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
|
||||
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
|
||||
static void SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta);
|
||||
void SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta);
|
||||
void SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr);
|
||||
void GetOpenFileTime(RarTime *ft);
|
||||
bool IsOpened() {return(hFile!=BAD_HANDLE);};
|
||||
Int64 FileLength();
|
||||
int64 FileLength();
|
||||
void SetHandleType(FILE_HANDLETYPE Type);
|
||||
FILE_HANDLETYPE GetHandleType() {return(HandleType);};
|
||||
bool IsDevice();
|
||||
@@ -89,7 +87,7 @@ class File
|
||||
FileHandle GetHandle() {return(hFile);};
|
||||
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;};
|
||||
char *GetName() {return(FileName);}
|
||||
long Copy(File &Dest,Int64 Length=INT64ERR);
|
||||
int64 Copy(File &Dest,int64 Length=INT64NDF);
|
||||
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
|
||||
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
|
||||
#ifdef _WIN_32
|
||||
|
||||
134
unrar/filefn.cpp
134
unrar/filefn.cpp
@@ -1,6 +1,6 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
|
||||
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
int Success;
|
||||
@@ -10,7 +10,8 @@ MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
|
||||
Success=CreateDirectory(Name,NULL);
|
||||
if (Success)
|
||||
{
|
||||
SetFileAttr(Name,NameW,Attr);
|
||||
if (SetAttr)
|
||||
SetFileAttr(Name,NameW,Attr);
|
||||
return(MKDIR_SUCCESS);
|
||||
}
|
||||
int ErrCode=GetLastError();
|
||||
@@ -25,15 +26,15 @@ MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
|
||||
if (__mkdir(Name)==0)
|
||||
#endif
|
||||
{
|
||||
SetFileAttr(Name,NameW,Attr);
|
||||
if (SetAttr)
|
||||
SetFileAttr(Name,NameW,Attr);
|
||||
return(MKDIR_SUCCESS);
|
||||
}
|
||||
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
int prevmask=umask(0);
|
||||
int ErrCode=Name==NULL ? -1:mkdir(Name,(mode_t)Attr);
|
||||
umask(prevmask);
|
||||
mode_t uattr=SetAttr ? (mode_t)Attr:0777;
|
||||
int ErrCode=Name==NULL ? -1:mkdir(Name,uattr);
|
||||
if (ErrCode==-1)
|
||||
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
|
||||
return(MKDIR_SUCCESS);
|
||||
@@ -41,9 +42,9 @@ MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
|
||||
}
|
||||
|
||||
|
||||
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
|
||||
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
#if defined(_WIN_32) || defined(_EMX)
|
||||
uint DirAttr=0;
|
||||
#else
|
||||
uint DirAttr=0777;
|
||||
@@ -54,6 +55,7 @@ void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
|
||||
bool Wide=false;
|
||||
#endif
|
||||
bool IgnoreAscii=false;
|
||||
bool Success=true;
|
||||
|
||||
const char *s=Path;
|
||||
for (int PosW=0;;PosW++)
|
||||
@@ -88,23 +90,27 @@ void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
|
||||
strncpy(DirName,Path,s-Path);
|
||||
DirName[s-Path]=0;
|
||||
}
|
||||
if (MakeDir(DirName,DirPtrW,DirAttr)==MKDIR_SUCCESS)
|
||||
if (MakeDir(DirName,DirPtrW,true,DirAttr)==MKDIR_SUCCESS)
|
||||
{
|
||||
#ifndef GUI
|
||||
mprintf(St(MCreatDir),DirName);
|
||||
mprintf(" %s",St(MOk));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
Success=false;
|
||||
}
|
||||
if (!IgnoreAscii)
|
||||
s=charnext(s);
|
||||
}
|
||||
if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
|
||||
MakeDir(Path,PathW,DirAttr);
|
||||
if (MakeDir(Path,PathW,true,DirAttr)!=MKDIR_SUCCESS)
|
||||
Success=false;
|
||||
return(Success);
|
||||
}
|
||||
|
||||
|
||||
void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
if (!WinNT())
|
||||
@@ -114,11 +120,14 @@ void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
bool sc=ftc!=NULL && ftc->IsSet();
|
||||
bool sa=fta!=NULL && fta->IsSet();
|
||||
|
||||
unsigned int DirAttr=GetFileAttr(Name);
|
||||
unsigned int DirAttr=GetFileAttr(Name,NameW);
|
||||
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0);
|
||||
if (ResetAttr)
|
||||
SetFileAttr(Name,NULL,0);
|
||||
HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
SetFileAttr(Name,NameW,0);
|
||||
|
||||
wchar DirNameW[NM];
|
||||
GetWideName(Name,NameW,DirNameW);
|
||||
HANDLE hFile=CreateFileW(DirNameW,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
@@ -132,7 +141,7 @@ void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
|
||||
CloseHandle(hFile);
|
||||
if (ResetAttr)
|
||||
SetFileAttr(Name,NULL,DirAttr);
|
||||
SetFileAttr(Name,NameW,DirAttr);
|
||||
#endif
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
File::SetCloseFileTimeByName(Name,ftm,fta);
|
||||
@@ -148,7 +157,7 @@ bool IsRemovable(const char *Name)
|
||||
int Type=GetDriveType(*Root ? Root:NULL);
|
||||
return(Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM);
|
||||
#elif defined(_EMX)
|
||||
char Drive=toupper(Name[0]);
|
||||
char Drive=etoupper(Name[0]);
|
||||
return((Drive=='A' || Drive=='B') && Name[1]==':');
|
||||
#else
|
||||
return(false);
|
||||
@@ -157,7 +166,7 @@ bool IsRemovable(const char *Name)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
Int64 GetFreeDisk(const char *Name)
|
||||
int64 GetFreeDisk(const char *Name)
|
||||
{
|
||||
#ifdef _WIN_32
|
||||
char Root[NM];
|
||||
@@ -176,55 +185,62 @@ Int64 GetFreeDisk(const char *Name)
|
||||
}
|
||||
if (pGetDiskFreeSpaceEx!=NULL)
|
||||
{
|
||||
GetFilePath(Name,Root);
|
||||
GetFilePath(Name,Root,ASIZE(Root));
|
||||
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
|
||||
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
|
||||
if (pGetDiskFreeSpaceEx(*Root ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
|
||||
uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
|
||||
return(int32to64(uiUserFree.u.HighPart,uiUserFree.u.LowPart));
|
||||
return(INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart));
|
||||
}
|
||||
|
||||
// We are here if we failed to load GetDiskFreeSpaceExA.
|
||||
DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters;
|
||||
if (!GetDiskFreeSpace(*Root ? Root:NULL,&SectorsPerCluster,&BytesPerSector,&FreeClusters,&TotalClusters))
|
||||
return(1457664);
|
||||
Int64 FreeSize=SectorsPerCluster*BytesPerSector;
|
||||
int64 FreeSize=SectorsPerCluster*BytesPerSector;
|
||||
FreeSize=FreeSize*FreeClusters;
|
||||
return(FreeSize);
|
||||
#elif defined(_BEOS)
|
||||
char Root[NM];
|
||||
GetFilePath(Name,Root);
|
||||
GetFilePath(Name,Root,ASIZE(Root));
|
||||
dev_t Dev=dev_for_path(*Root ? Root:".");
|
||||
if (Dev<0)
|
||||
return(1457664);
|
||||
fs_info Info;
|
||||
if (fs_stat_dev(Dev,&Info)!=0)
|
||||
return(1457664);
|
||||
Int64 FreeSize=Info.block_size;
|
||||
int64 FreeSize=Info.block_size;
|
||||
FreeSize=FreeSize*Info.free_blocks;
|
||||
return(FreeSize);
|
||||
#elif defined(_UNIX)
|
||||
return(1457664);
|
||||
#elif defined(_EMX)
|
||||
int Drive=(!isalpha(Name[0]) || Name[1]!=':') ? 0:toupper(Name[0])-'A'+1;
|
||||
int Drive=IsDiskLetter(Name) ? etoupper(Name[0])-'A'+1:0;
|
||||
#ifndef _DJGPP
|
||||
if (_osmode == OS2_MODE)
|
||||
{
|
||||
FSALLOCATE fsa;
|
||||
if (DosQueryFSInfo(Drive,1,&fsa,sizeof(fsa))!=0)
|
||||
return(1457664);
|
||||
Int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
|
||||
int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
|
||||
FreeSize=FreeSize*fsa.cUnitAvail;
|
||||
return(FreeSize);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
union REGS regs,outregs;
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.h.ah=0x36;
|
||||
regs.h.dl=Drive;
|
||||
#ifdef _DJGPP
|
||||
int86 (0x21,®s,&outregs);
|
||||
#else
|
||||
_int86 (0x21,®s,&outregs);
|
||||
#endif
|
||||
if (outregs.x.ax==0xffff)
|
||||
return(1457664);
|
||||
Int64 FreeSize=outregs.x.ax*outregs.x.cx;
|
||||
int64 FreeSize=outregs.x.ax*outregs.x.cx;
|
||||
FreeSize=FreeSize*outregs.x.bx;
|
||||
return(FreeSize);
|
||||
}
|
||||
@@ -300,8 +316,9 @@ bool IsLink(uint Attr)
|
||||
{
|
||||
#ifdef _UNIX
|
||||
return((Attr & 0xF000)==0xA000);
|
||||
#endif
|
||||
#else
|
||||
return(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -390,8 +407,10 @@ void ConvertNameToFull(const char *Src,char *Dest)
|
||||
strcpy(FullName,Src);
|
||||
else
|
||||
{
|
||||
getcwd(FullName,sizeof(FullName));
|
||||
AddEndSlash(FullName);
|
||||
if (getcwd(FullName,sizeof(FullName))==NULL)
|
||||
*FullName=0;
|
||||
else
|
||||
AddEndSlash(FullName);
|
||||
strcat(FullName,Src);
|
||||
}
|
||||
strcpy(Dest,FullName);
|
||||
@@ -443,13 +462,13 @@ void ConvertNameToFull(const wchar *Src,wchar *Dest)
|
||||
#ifndef SFX_MODULE
|
||||
char *MkTemp(char *Name)
|
||||
{
|
||||
int Length=strlen(Name);
|
||||
size_t Length=strlen(Name);
|
||||
if (Length<=6)
|
||||
return(NULL);
|
||||
int Random=clock();
|
||||
for (int Attempt=0;;Attempt++)
|
||||
{
|
||||
sprintf(Name+Length-6,"%06u",Random+Attempt);
|
||||
sprintf(Name+Length-6,"%06u",(Random+Attempt)%1000000);
|
||||
Name[Length-4]='.';
|
||||
if (!FileExist(Name))
|
||||
break;
|
||||
@@ -464,28 +483,53 @@ char *MkTemp(char *Name)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint CalcFileCRC(File *SrcFile,Int64 Size)
|
||||
uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)
|
||||
{
|
||||
SaveFilePos SavePos(*SrcFile);
|
||||
const int BufSize=0x10000;
|
||||
const size_t BufSize=0x10000;
|
||||
Array<byte> Data(BufSize);
|
||||
Int64 BlockCount=0;
|
||||
int64 BlockCount=0;
|
||||
uint DataCRC=0xffffffff;
|
||||
int ReadSize;
|
||||
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
int64 FileLength=SrcFile->FileLength();
|
||||
if (ShowMode!=CALCCRC_SHOWNONE)
|
||||
{
|
||||
mprintf(St(MCalcCRC));
|
||||
mprintf(" ");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SrcFile->Seek(0,SEEK_SET);
|
||||
while ((ReadSize=SrcFile->Read(&Data[0],int64to32(Size==INT64ERR ? Int64(BufSize):Min(Int64(BufSize),Size))))!=0)
|
||||
while (true)
|
||||
{
|
||||
size_t SizeToRead;
|
||||
if (Size==INT64NDF) // If we process the entire file.
|
||||
SizeToRead=BufSize; // Then always attempt to read the entire buffer.
|
||||
else
|
||||
SizeToRead=(size_t)Min((int64)BufSize,Size);
|
||||
int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
|
||||
if (ReadSize==0)
|
||||
break;
|
||||
|
||||
++BlockCount;
|
||||
if ((BlockCount & 15)==0)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
if (ShowMode==CALCCRC_SHOWALL)
|
||||
mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength));
|
||||
#endif
|
||||
Wait();
|
||||
}
|
||||
DataCRC=CRC(DataCRC,&Data[0],ReadSize);
|
||||
if (Size!=INT64ERR)
|
||||
if (Size!=INT64NDF)
|
||||
Size-=ReadSize;
|
||||
}
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
if (ShowMode==CALCCRC_SHOWALL)
|
||||
mprintf("\b\b\b\b ");
|
||||
#endif
|
||||
return(DataCRC^0xffffffff);
|
||||
}
|
||||
#endif
|
||||
@@ -509,19 +553,11 @@ bool DelFile(const char *Name,const wchar *NameW)
|
||||
}
|
||||
|
||||
|
||||
bool DelDir(const char *Name)
|
||||
{
|
||||
return(DelDir(Name,NULL));
|
||||
}
|
||||
|
||||
|
||||
bool DelDir(const char *Name,const wchar *NameW)
|
||||
{
|
||||
return(rmdir(Name)==0);
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE)
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
|
||||
bool SetFileCompression(char *Name,wchar *NameW,bool State)
|
||||
{
|
||||
wchar FileNameW[NM];
|
||||
@@ -539,3 +575,11 @@ bool SetFileCompression(char *Name,wchar *NameW,bool State)
|
||||
return(RetCode!=0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
|
||||
|
||||
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr);
|
||||
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
|
||||
void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
|
||||
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr);
|
||||
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
|
||||
void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta);
|
||||
bool IsRemovable(const char *Name);
|
||||
Int64 GetFreeDisk(const char *Name);
|
||||
int64 GetFreeDisk(const char *Name);
|
||||
bool FileExist(const char *Name,const wchar *NameW=NULL);
|
||||
bool WildFileExist(const char *Name,const wchar *NameW=NULL);
|
||||
bool IsDir(uint Attr);
|
||||
@@ -25,7 +25,9 @@ void ConvertNameToFull(const wchar *Src,wchar *Dest);
|
||||
char* MkTemp(char *Name);
|
||||
|
||||
|
||||
uint CalcFileCRC(File *SrcFile,Int64 Size=INT64ERR);
|
||||
enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL};
|
||||
uint CalcFileCRC(File *SrcFile,int64 Size=INT64NDF,CALCCRC_SHOWMODE ShowMode=CALCCRC_SHOWNONE);
|
||||
|
||||
bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW);
|
||||
bool DelFile(const char *Name);
|
||||
bool DelFile(const char *Name,const wchar *NameW);
|
||||
@@ -36,4 +38,7 @@ bool DelDir(const char *Name,const wchar *NameW);
|
||||
bool SetFileCompression(char *Name,wchar *NameW,bool State);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
static bool IsUnicode(byte *Data,int Size);
|
||||
|
||||
bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
|
||||
bool ConvertToAnsi,bool Unquote,bool SkipComments)
|
||||
bool ReadTextFile(const char *Name,StringList *List,bool Config,
|
||||
bool AbortOnError,RAR_CHARSET SrcCharset,bool Unquote,
|
||||
bool SkipComments,bool ExpandEnvStr)
|
||||
{
|
||||
char FileName[NM];
|
||||
if (Config)
|
||||
@@ -19,7 +20,7 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
|
||||
if (!OpenCode)
|
||||
{
|
||||
if (AbortOnError)
|
||||
ErrHandler.Exit(RAR_OPEN_ERROR);
|
||||
ErrHandler.Exit(OPEN_ERROR);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
@@ -37,9 +38,19 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
|
||||
|
||||
memset(&Data[DataSize],0,5);
|
||||
|
||||
if (IsUnicode((byte *)&Data[0],DataSize))
|
||||
if (SrcCharset==RCH_UNICODE ||
|
||||
SrcCharset==RCH_DEFAULT && IsUnicode((byte *)&Data[0],DataSize))
|
||||
{
|
||||
wchar *CurStr=(wchar *)&Data[2];
|
||||
// Unicode in native system format, can be more than 2 bytes per character.
|
||||
Array<wchar> DataW(Data.Size()/2+1);
|
||||
for (size_t I=2;I<Data.Size()-1;I+=2)
|
||||
{
|
||||
// Need to convert Data to (byte) first to prevent the sign extension
|
||||
// to higher bytes.
|
||||
DataW[(I-2)/2]=(wchar)((byte)Data[I])+(wchar)((byte)Data[I+1])*256;
|
||||
}
|
||||
|
||||
wchar *CurStr=&DataW[0];
|
||||
Array<char> AnsiName;
|
||||
|
||||
while (*CurStr!=0)
|
||||
@@ -63,8 +74,11 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
|
||||
}
|
||||
if (*CurStr)
|
||||
{
|
||||
int Length=strlenw(CurStr);
|
||||
int AddSize=4*(Length-AnsiName.Size()+1);
|
||||
// Length and AddSize must be defined as signed, because AddSize
|
||||
// can be negative.
|
||||
int Length=(int)strlenw(CurStr);
|
||||
int AddSize=4*(Length-(int)AnsiName.Size()+1);
|
||||
|
||||
if (AddSize>0)
|
||||
AnsiName.Add(AddSize);
|
||||
if (Unquote && *CurStr=='\"' && CurStr[Length-1]=='\"')
|
||||
@@ -73,7 +87,28 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
|
||||
CurStr++;
|
||||
}
|
||||
WideToChar(CurStr,&AnsiName[0],AnsiName.Size());
|
||||
List->AddString(&AnsiName[0],CurStr);
|
||||
|
||||
bool Expanded=false;
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE)
|
||||
if (ExpandEnvStr && *CurStr=='%')
|
||||
{
|
||||
// expanding environment variables in Windows version
|
||||
|
||||
char ExpName[NM];
|
||||
wchar ExpNameW[NM];
|
||||
*ExpNameW=0;
|
||||
int ret,retw=1;
|
||||
ret=ExpandEnvironmentStrings(&AnsiName[0],ExpName,ASIZE(ExpName));
|
||||
if (ret!=0 && WinNT())
|
||||
retw=ExpandEnvironmentStringsW(CurStr,ExpNameW,ASIZE(ExpNameW));
|
||||
Expanded=ret!=0 && ret<ASIZE(ExpName) &&
|
||||
retw!=0 && retw<ASIZE(ExpNameW);
|
||||
if (Expanded)
|
||||
List->AddString(ExpName,ExpNameW);
|
||||
}
|
||||
#endif
|
||||
if (!Expanded)
|
||||
List->AddString(&AnsiName[0],CurStr);
|
||||
}
|
||||
CurStr=NextStr+1;
|
||||
while (*CurStr=='\r' || *CurStr=='\n')
|
||||
@@ -106,7 +141,7 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
|
||||
{
|
||||
if (Unquote && *CurStr=='\"')
|
||||
{
|
||||
int Length=strlen(CurStr);
|
||||
size_t Length=strlen(CurStr);
|
||||
if (CurStr[Length-1]=='\"')
|
||||
{
|
||||
CurStr[Length-1]=0;
|
||||
@@ -114,10 +149,25 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
|
||||
}
|
||||
}
|
||||
#if defined(_WIN_32)
|
||||
if (ConvertToAnsi)
|
||||
if (SrcCharset==RCH_OEM)
|
||||
OemToChar(CurStr,CurStr);
|
||||
#endif
|
||||
List->AddString(CurStr);
|
||||
|
||||
bool Expanded=false;
|
||||
#if defined(_WIN_32) && !defined(_WIN_CE)
|
||||
if (ExpandEnvStr && *CurStr=='%')
|
||||
{
|
||||
// expanding environment variables in Windows version
|
||||
|
||||
char ExpName[NM];
|
||||
int ret=ExpandEnvironmentStrings(CurStr,ExpName,ASIZE(ExpName));
|
||||
Expanded=ret!=0 && ret<ASIZE(ExpName);
|
||||
if (Expanded)
|
||||
List->AddString(ExpName);
|
||||
}
|
||||
#endif
|
||||
if (!Expanded)
|
||||
List->AddString(CurStr);
|
||||
}
|
||||
CurStr=NextStr+1;
|
||||
while (*CurStr=='\r' || *CurStr=='\n')
|
||||
@@ -133,7 +183,7 @@ bool IsUnicode(byte *Data,int Size)
|
||||
if (Size<4 || Data[0]!=0xff || Data[1]!=0xfe)
|
||||
return(false);
|
||||
for (int I=2;I<Size;I++)
|
||||
if (Data[I]<32)
|
||||
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
|
||||
return(true);
|
||||
return(false);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user