mirror of
https://github.com/php-win-ext/php-rar.git
synced 2026-03-24 13:02:06 +01:00
Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bb74bf820 | ||
|
|
1a2f9f5104 | ||
|
|
0fd6896a25 | ||
|
|
d2a8a89e64 | ||
|
|
d95d7a794f | ||
|
|
9129dab024 | ||
|
|
897139b2ce | ||
|
|
2a29f7e763 | ||
|
|
3a830bc07c | ||
|
|
119722d581 | ||
|
|
4f821913ad | ||
|
|
6939711766 | ||
|
|
c499b4d2d2 | ||
|
|
a191673249 | ||
|
|
c6f8765250 | ||
|
|
5402805db0 | ||
|
|
e6e481cfb2 | ||
|
|
a3c0236a7d | ||
|
|
f8ee7cc273 | ||
|
|
e699b159cf | ||
|
|
41875e7bd6 | ||
|
|
3a2688b3eb | ||
|
|
524d195253 | ||
|
|
e1609b9dfd | ||
|
|
4f804014ca | ||
|
|
abe9816391 | ||
|
|
5876366b26 | ||
|
|
c1e389af0d | ||
|
|
73972e070d | ||
|
|
74aed951bb | ||
|
|
26929db6a9 | ||
|
|
4fb28f3858 | ||
|
|
4e04320979 | ||
|
|
b72aaff789 | ||
|
|
3b2d2eb296 | ||
|
|
166fe908ad | ||
|
|
0265686bbd | ||
|
|
f650a6e340 | ||
|
|
a20ca1559c | ||
|
|
2ab141deed | ||
|
|
498cad468e | ||
|
|
65d5132550 | ||
|
|
358432a7eb | ||
|
|
bbeab2dc4e | ||
|
|
5f81d8688f | ||
|
|
d6dfd5054c | ||
|
|
5d1e369c38 | ||
|
|
2f36bd7cac | ||
|
|
34859cf5b4 | ||
|
|
99cb19e838 | ||
|
|
f19f569f44 | ||
|
|
762b1ae3b0 | ||
|
|
fe2d2f46e4 | ||
|
|
6391dc21ca | ||
|
|
98bcf3697a | ||
|
|
4cda46d212 | ||
|
|
b2bc8dc586 | ||
|
|
96eec2b31c | ||
|
|
d5f04a3a88 | ||
|
|
13cb064031 | ||
|
|
a238d20430 | ||
|
|
66e2666696 | ||
|
|
55a328ff22 | ||
|
|
e632e338ef | ||
|
|
2ea5d74e6d | ||
|
|
5840034b59 | ||
|
|
d72ef1dbce | ||
|
|
e2db202b89 | ||
|
|
1cf4e2c02c | ||
|
|
ee28abf175 | ||
|
|
ece47716ab | ||
|
|
388707153c | ||
|
|
60cf649b85 | ||
|
|
113935cbc5 | ||
|
|
881989bbac | ||
|
|
b1c3582301 | ||
|
|
1cfe9592c0 | ||
|
|
c92f03f1e2 | ||
|
|
430a8ba763 | ||
|
|
e2c046d88d | ||
|
|
63d3b18405 | ||
|
|
6963ed8f43 | ||
|
|
0a57b9b313 | ||
|
|
3b9dd4dd6e | ||
|
|
28e2572026 | ||
|
|
21cba90843 | ||
|
|
0473c464e1 | ||
|
|
9cd367de03 | ||
|
|
0ef63a5fbb | ||
|
|
75486ffa92 | ||
|
|
7d8ada6e1e | ||
|
|
02e98e3188 | ||
|
|
18a025c38d | ||
|
|
3bd27b4b36 | ||
|
|
5bb815b5db | ||
|
|
e06c6250d0 | ||
|
|
1e542a4db3 | ||
|
|
6907905144 | ||
|
|
f8cb60259d | ||
|
|
1e2e912de2 | ||
|
|
479c373f4d | ||
|
|
6c1dd8a81f | ||
|
|
b451c7c79b | ||
|
|
c915d361f4 | ||
|
|
15aa6f20d6 | ||
|
|
561966f23b | ||
|
|
80986445f5 | ||
|
|
446a2e8492 | ||
|
|
12719dce2c | ||
|
|
75c4bbc240 | ||
|
|
951ccf9767 | ||
|
|
2538d242ee | ||
|
|
e91808a5eb | ||
|
|
a9631cfddd | ||
|
|
89c4cbe487 | ||
|
|
876cb51c4c | ||
|
|
ad8e1e2a2b | ||
|
|
825de01ac1 | ||
|
|
7a8b0a7f59 | ||
|
|
35f7e43f2f | ||
|
|
3a535eba4e | ||
|
|
a16b24d665 | ||
|
|
9bd14a69e8 | ||
|
|
c093245020 | ||
|
|
f5ca2159f0 | ||
|
|
b8102334c6 | ||
|
|
eaffae90c0 | ||
|
|
2e18f53535 | ||
|
|
fff0c56e2e | ||
|
|
59a53d18ed | ||
|
|
e1490118df | ||
|
|
7bacdf6736 | ||
|
|
00a58e1934 | ||
|
|
55dd7388ab | ||
|
|
a18c3b7fdc | ||
|
|
c3cf0e0dd4 |
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
*.o
|
||||
*.lo
|
||||
/tests/*.sh
|
||||
/tests/*.exp
|
||||
/tests/*.diff
|
||||
/tests/*.log
|
||||
/tests/*.php
|
||||
/tests/*.out
|
||||
/tests/*.mem
|
||||
/run-tests.php
|
||||
/modules
|
||||
/missing
|
||||
/.deps
|
||||
/.libs
|
||||
/Makefile
|
||||
/Makefile.fragments
|
||||
/Makefile.global
|
||||
/Makefile.objects
|
||||
/acinclude.m4
|
||||
/aclocal.m4
|
||||
/autom4te.cache
|
||||
/build
|
||||
/config.guess
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.nice
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/configure.in
|
||||
/install-sh
|
||||
/intl.la
|
||||
/libtool
|
||||
/mkinstalldirs
|
||||
/ltmain.sh
|
||||
/.cproject
|
||||
/.project
|
||||
/.settings
|
||||
/pecl-rar.*
|
||||
/rar.la
|
||||
*.autosave
|
||||
23
.travis.yml
Normal file
23
.travis.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
language: c
|
||||
dist: trusty
|
||||
|
||||
env:
|
||||
#- PHP_VERSION=5.2.17 ZTS=yes MIRROR=http://museum.php.net/php5/
|
||||
- PHP_VERSION=5.3.29 ZTS=yes
|
||||
- PHP_VERSION=5.4.45 ZTS=yes
|
||||
- PHP_VERSION=5.5.37 ZTS=yes
|
||||
- PHP_VERSION=5.6.30 ZTS=yes
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/php_builds
|
||||
|
||||
before_install:
|
||||
- source travis.sh
|
||||
- maybe_install_php $PHP_VERSION $ZTS
|
||||
|
||||
install:
|
||||
- build $PHP_VERSION $ZTS
|
||||
|
||||
script:
|
||||
- run_tests $PHP_VERSION $ZTS
|
||||
68
LICENSE
Normal file
68
LICENSE
Normal file
@@ -0,0 +1,68 @@
|
||||
--------------------------------------------------------------------
|
||||
The PHP License, version 3.01
|
||||
Copyright (c) 1999 - 2010 The PHP Group. All rights reserved.
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, is permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
3. The name "PHP" must not be used to endorse or promote products
|
||||
derived from this software without prior written permission. For
|
||||
written permission, please contact group@php.net.
|
||||
|
||||
4. Products derived from this software may not be called "PHP", nor
|
||||
may "PHP" appear in their name, without prior written permission
|
||||
from group@php.net. You may indicate that your software works in
|
||||
conjunction with PHP by saying "Foo for PHP" instead of calling
|
||||
it "PHP Foo" or "phpfoo"
|
||||
|
||||
5. The PHP Group may publish revised and/or new versions of the
|
||||
license from time to time. Each version will be given a
|
||||
distinguishing version number.
|
||||
Once covered code has been published under a particular version
|
||||
of the license, you may always continue to use it under the terms
|
||||
of that version. You may also choose to use such covered code
|
||||
under the terms of any subsequent version of the license
|
||||
published by the PHP Group. No one other than the PHP Group has
|
||||
the right to modify the terms applicable to covered code created
|
||||
under this License.
|
||||
|
||||
6. Redistributions of any form whatsoever must retain the following
|
||||
acknowledgment:
|
||||
"This product includes PHP software, freely available from
|
||||
<http://www.php.net/software/>".
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
|
||||
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
|
||||
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals on behalf of the PHP Group.
|
||||
|
||||
The PHP Group can be contacted via Email at group@php.net.
|
||||
|
||||
For more information on the PHP Group and the PHP project,
|
||||
please see <http://www.php.net>.
|
||||
|
||||
PHP includes the Zend Engine, freely available at
|
||||
<http://www.zend.com>.
|
||||
49
config.m4
49
config.m4
@@ -4,28 +4,39 @@ dnl config.m4 for extension rar
|
||||
PHP_ARG_ENABLE(rar, whether to enable rar support,
|
||||
[ --enable-rar Enable rar support])
|
||||
|
||||
unrar_sources="unrar/rar.cpp unrar/strlist.cpp unrar/strfn.cpp \
|
||||
unrar/pathfn.cpp unrar/smallfn.cpp unrar/savepos.cpp \
|
||||
unrar/global.cpp unrar/file.cpp unrar/filefn.cpp \
|
||||
unrar/filcreat.cpp unrar/archive.cpp unrar/arcread.cpp \
|
||||
unrar/unicode.cpp unrar/system.cpp unrar/isnt.cpp \
|
||||
unrar/crypt.cpp unrar/crc.cpp unrar/rawread.cpp \
|
||||
unrar/encname.cpp unrar/resource.cpp unrar/match.cpp \
|
||||
unrar/timefn.cpp unrar/rdwrfn.cpp unrar/consio.cpp \
|
||||
unrar/options.cpp unrar/ulinks.cpp unrar/errhnd.cpp \
|
||||
unrar/rarvm.cpp unrar/rijndael.cpp unrar/getbits.cpp \
|
||||
unrar/sha1.cpp unrar/extinfo.cpp unrar/extract.cpp \
|
||||
unrar/volume.cpp unrar/find.cpp \
|
||||
unrar/unpack.cpp unrar/cmddata.cpp unrar/dll.cpp \
|
||||
unrar/filestr.cpp unrar/recvol.cpp unrar/rs.cpp \
|
||||
unrar/scantree.cpp unrar/log.cpp unrar/extractchunk.cpp"
|
||||
unrar_sources="unrar/sha256.cpp unrar/qopen.cpp \
|
||||
unrar/blake2s.cpp unrar/recvol.cpp \
|
||||
unrar/headers.cpp unrar/match.cpp \
|
||||
unrar/find.cpp \
|
||||
unrar/resource.cpp \
|
||||
unrar/pathfn.cpp \
|
||||
unrar/dll.cpp unrar/threadpool.cpp unrar/volume.cpp \
|
||||
unrar/unpack.cpp \
|
||||
unrar/extract.cpp unrar/errhnd.cpp \
|
||||
unrar/crc.cpp unrar/rijndael.cpp unrar/crypt.cpp \
|
||||
unrar/rawread.cpp \
|
||||
unrar/rs.cpp unrar/smallfn.cpp \
|
||||
unrar/isnt.cpp unrar/rar.cpp unrar/consio.cpp \
|
||||
unrar/scantree.cpp unrar/archive.cpp unrar/strfn.cpp \
|
||||
unrar/strlist.cpp \
|
||||
unrar/getbits.cpp unrar/hash.cpp \
|
||||
unrar/filestr.cpp \
|
||||
unrar/extinfo.cpp unrar/ui.cpp unrar/rarvm.cpp \
|
||||
unrar/timefn.cpp unrar/sha1.cpp \
|
||||
unrar/rdwrfn.cpp unrar/rs16.cpp unrar/cmddata.cpp \
|
||||
unrar/extractchunk.cpp unrar/system.cpp \
|
||||
unrar/unicode.cpp unrar/filcreat.cpp \
|
||||
unrar/arcread.cpp unrar/filefn.cpp \
|
||||
unrar/global.cpp unrar/list.cpp \
|
||||
unrar/encname.cpp unrar/file.cpp \
|
||||
unrar/secpassword.cpp unrar/options.cpp"
|
||||
|
||||
if test "$PHP_RAR" != "no"; then
|
||||
PHP_REQUIRE_CXX
|
||||
AC_DEFINE(HAVE_RAR, 1, [Whether you have rar support])
|
||||
PHP_SUBST(RAR_SHARED_LIBADD)
|
||||
PHP_SUBST(RAR_SHARED_LIBADD)
|
||||
PHP_REQUIRE_CXX()
|
||||
PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", RAR_SHARED_LIBADD)
|
||||
|
||||
PHP_NEW_EXTENSION(rar, rar.c rar_error.c rararch.c rarentry.c rar_stream.c rar_navigation.c $unrar_sources, $ext_shared,,-DRARDLL -DGUI -DSILENT -Wno-write-strings -I@ext_srcdir@/unrar)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
|
||||
PHP_NEW_EXTENSION(rar, rar.c rar_error.c rararch.c rarentry.c rar_stream.c rar_navigation.c $unrar_sources, $ext_shared,,-DRARDLL -DSILENT -Wno-write-strings -Wall -I@ext_srcdir@/unrar)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
|
||||
fi
|
||||
|
||||
@@ -20,7 +20,8 @@ if (PHP_RAR != "no") {
|
||||
volume.cpp find.cpp \
|
||||
unpack.cpp cmddata.cpp dll.cpp \
|
||||
filestr.cpp recvol.cpp rs.cpp \
|
||||
scantree.cpp extractchunk.cpp log.cpp", "rar");
|
||||
scantree.cpp extractchunk.cpp log.cpp \
|
||||
secpassword.cpp ", "rar");
|
||||
|
||||
AC_DEFINE("HAVE_RAR", 1, "Rar support");
|
||||
}
|
||||
|
||||
52
package.xml
52
package.xml
@@ -23,10 +23,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<active>no</active>
|
||||
</developer>
|
||||
|
||||
<date>2011-06-12</date>
|
||||
<time>05:00:00</time>
|
||||
<date>2013-10-11</date>
|
||||
<time>13:00:00</time>
|
||||
<version>
|
||||
<release>3.0.0</release>
|
||||
<release>3.0.2</release>
|
||||
<api>3.0.0</api>
|
||||
</version>
|
||||
|
||||
@@ -36,24 +36,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
</stability>
|
||||
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<notes>Changes in this version:
|
||||
- Updated to unrar 4.0.7 (corresponds to WinRAR 4.0.0 stable).
|
||||
- Support for PHP 5.4.
|
||||
- Added url wrapper rar://.
|
||||
- Added volume find callback to RarArchive::open/rar_open.
|
||||
- Added support for stat, both static and to opened streams.
|
||||
- Added rar_allow_broken_set/RarArchive::setAllowBroken and rar_broken_is/
|
||||
RarArchive::isBroken, which control/query the behavior with archives with
|
||||
missing volumes.
|
||||
- Added option to RarEntry::extract() to allow from extraction of ACL (windows)
|
||||
/owner (unix)/extended attributes (os/2).
|
||||
- Added support for RAR archives that have several entries with the same name.
|
||||
- Implemented count elements handler for RarArchive.
|
||||
- Implemented dimensions handlers for RarArchive.
|
||||
- Fixed packed sizes which were using high bits from unpacked sizes.
|
||||
- Fixed PECL bug #20498 (RarEntry::extract not really accepting a password).
|
||||
- Fixed PECL bug #18449 (Extraction of uncompressed and encrypted files fails).
|
||||
- Many more tests.
|
||||
<notes>- Fixed build with PHP 5.5.
|
||||
- Upgraded bundled unrar to version 4.2.4.
|
||||
</notes>
|
||||
<contents>
|
||||
<dir name="/">
|
||||
@@ -157,11 +141,13 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<file role="test" name="096.phpt"/>
|
||||
<file role="test" name="097.phpt"/>
|
||||
<file role="test" name="098.phpt"/>
|
||||
<file role="test" name="099.phpt"/>
|
||||
<file role="test" name="commented.rar"/>
|
||||
<file role="test" name="corrupted.rar"/>
|
||||
<file role="test" name="directories.rar"/>
|
||||
<file role="test" name="dirlink_unix.rar"/>
|
||||
<file role="test" name="dirs_and_extra_headers.rar"/>
|
||||
<file role="test" name="empty_file.rar"/>
|
||||
<file role="test" name="encrypted_headers.rar"/>
|
||||
<file role="test" name="encrypted_only_files.rar"/>
|
||||
<file role="test" name="garbage.part03.rar"/>
|
||||
@@ -181,6 +167,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<file role="test" name="store_method.rar"/>
|
||||
</dir> <!-- /tests -->
|
||||
<dir name="unrar">
|
||||
<file name="acknow.txt" role="doc" />
|
||||
<file name="arccmt.cpp" role="src" />
|
||||
<file name="archive.cpp" role="src" />
|
||||
<file name="archive.hpp" role="src" />
|
||||
@@ -268,6 +255,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<file name="savepos.hpp" role="src" />
|
||||
<file name="scantree.cpp" role="src" />
|
||||
<file name="scantree.hpp" role="src" />
|
||||
<file name="secpassword.cpp" role="src" />
|
||||
<file name="secpassword.hpp" role="src" />
|
||||
<file name="sha1.cpp" role="src" />
|
||||
<file name="sha1.hpp" role="src" />
|
||||
<file name="smallfn.cpp" role="src" />
|
||||
@@ -301,6 +290,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<file name="config.m4" role="src" />
|
||||
<file name="config.w32" role="src" />
|
||||
<file name="CREDITS" role="doc" />
|
||||
<file name="LICENSE" role="doc" />
|
||||
<file name="README" role="doc" />
|
||||
<file name="example.php" role="doc" />
|
||||
<file name="php_rar.h" role="src" />
|
||||
@@ -329,6 +319,24 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<extsrcrelease />
|
||||
|
||||
<changelog>
|
||||
<release>
|
||||
<version>
|
||||
<release>3.0.1</release>
|
||||
<api>3.0.0</api>
|
||||
</version>
|
||||
<stability>
|
||||
<release>stable</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
<date>2012-07-29</date>
|
||||
<notes>Changes in this version:
|
||||
- Merge changes made to unrar up to version 4.2.2.
|
||||
- Fix leak in PHP >= 5.3.11, = 5.4.0 and compile error in master.
|
||||
- Fix some tests failing if TZ != Europe/Lisbon.
|
||||
- Fix bad pointer in an error message.
|
||||
- Added test for bug #59939 (can't reproduce).
|
||||
</notes>
|
||||
</release>
|
||||
<release>
|
||||
<version>
|
||||
<release>2.0.0</release>
|
||||
@@ -361,7 +369,7 @@ For the other changes, see the changelog for version 2.0.0RC1.
|
||||
<api>beta</api>
|
||||
</stability>
|
||||
<date>2010-01-17</date>
|
||||
<license uri="http://www.php.net/license">PHP License</license>
|
||||
<license>PHP License and UnRar 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.
|
||||
|
||||
10
php_rar.h
10
php_rar.h
@@ -49,8 +49,7 @@
|
||||
extern zend_module_entry rar_module_entry;
|
||||
#define phpext_rar_ptr &rar_module_entry
|
||||
|
||||
#define PHP_RAR_VERSION "3.0.0"
|
||||
#define PHP_RAR_REVISION "$Revision$"
|
||||
#define PHP_RAR_VERSION "4.0.0"
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define PHP_RAR_API __declspec(dllexport)
|
||||
@@ -67,6 +66,7 @@ extern zend_module_entry rar_module_entry;
|
||||
/* #include "unrar/rar.hpp */
|
||||
/* only these includes are necessary anyway: */
|
||||
#include "unrar/raros.hpp"
|
||||
#include "unrar/rartypes.hpp"
|
||||
/* no need to reinclude windows.h or new.h */
|
||||
#define LEAN_RAR_INCLUDES
|
||||
#include "unrar/os.hpp"
|
||||
@@ -77,8 +77,6 @@ enum HOST_SYSTEM {
|
||||
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
|
||||
HOST_BEOS=5,HOST_MAX
|
||||
};
|
||||
#define LHD_WINDOWMASK 0x00e0U
|
||||
#define LHD_DIRECTORY 0x00e0U
|
||||
|
||||
/* maximum comment size if 64KB */
|
||||
#define RAR_MAX_COMMENT_SIZE 65536
|
||||
@@ -288,8 +286,8 @@ void _rar_entry_to_zval(zval *parent,
|
||||
/* rar_stream.c */
|
||||
php_stream *php_stream_rar_open(char *arc_name,
|
||||
size_t position,
|
||||
rar_cb_user_data *cb_udata_ptr, /* will be copied */
|
||||
char *mode STREAMS_DC TSRMLS_DC);
|
||||
rar_cb_user_data *cb_udata_ptr /* will be copied */
|
||||
STREAMS_DC TSRMLS_DC);
|
||||
extern php_stream_wrapper php_stream_rar_wrapper;
|
||||
|
||||
#endif /* PHP_RAR_H */
|
||||
|
||||
24
rar.c
24
rar.c
@@ -155,11 +155,11 @@ void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size) /* {{{ *
|
||||
void _rar_destroy_userdata(rar_cb_user_data *udata) /* {{{ */
|
||||
{
|
||||
assert(udata != NULL);
|
||||
|
||||
|
||||
if (udata->password != NULL) {
|
||||
efree(udata->password);
|
||||
}
|
||||
|
||||
|
||||
if (udata->callable != NULL)
|
||||
zval_ptr_dtor(&udata->callable);
|
||||
|
||||
@@ -180,7 +180,7 @@ int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
size_t utf_file_name_len = strlen(utf_file_name);
|
||||
int ret;
|
||||
|
||||
file_name = ecalloc(utf_file_name_len + 1, sizeof *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);
|
||||
ret = _rar_find_file_w(open_data, file_name, cb_udata, arc_handle, found,
|
||||
header_data);
|
||||
@@ -231,7 +231,7 @@ int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
goto cleanup;
|
||||
}
|
||||
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) cb_udata);
|
||||
|
||||
|
||||
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
|
||||
#if WCHAR_MAX > 0xffff
|
||||
_rar_fix_wide(used_header_data->FileNameW, NM);
|
||||
@@ -292,10 +292,11 @@ int _rar_find_file_p(struct RAROpenArchiveDataEx *open_data, /* IN */
|
||||
goto cleanup;
|
||||
}
|
||||
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) cb_udata);
|
||||
|
||||
|
||||
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
|
||||
/* skip entries that were split before with incrementing current pos */
|
||||
if ((used_header_data->Flags & 0x01U) || (curpos++ != position)) {
|
||||
if ((used_header_data->Flags & RHDF_SPLITBEFORE) ||
|
||||
(curpos++ != position)) {
|
||||
process_result = RARProcessFile(*arc_handle, RAR_SKIP, NULL, NULL);
|
||||
} else {
|
||||
*found = TRUE;
|
||||
@@ -321,7 +322,7 @@ cleanup:
|
||||
}
|
||||
|
||||
/* An unRAR callback.
|
||||
* Processes requests for passwords and missing volumes
|
||||
* Processes requests for passwords and missing volumes
|
||||
* If there is (userland) volume find callback specified, try to use that
|
||||
* callback to retrieve the name of the missing volume. Otherwise, or if
|
||||
* the volume find callback returns null, cancel the operation. */
|
||||
@@ -329,7 +330,7 @@ int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2
|
||||
{
|
||||
rar_cb_user_data *userdata = (rar_cb_user_data*) UserData;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
|
||||
if (msg == UCM_NEEDPASSWORD) {
|
||||
/* user data is the password or null if none */
|
||||
char *password = userdata->password;
|
||||
@@ -451,7 +452,7 @@ static int _rar_unrar_volume_user_callback(char* dst_buffer,
|
||||
fci->retval_ptr_ptr = &retval_ptr;
|
||||
fci->params = ¶ms;
|
||||
fci->param_count = 1;
|
||||
|
||||
|
||||
if (zend_call_function(fci, cache TSRMLS_CC) != SUCCESS ||
|
||||
fci->retval_ptr_ptr == NULL ||
|
||||
*fci->retval_ptr_ptr == NULL) {
|
||||
@@ -459,7 +460,7 @@ static int _rar_unrar_volume_user_callback(char* dst_buffer,
|
||||
"Failure to call volume find callback");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
assert(*fci->retval_ptr_ptr == retval_ptr);
|
||||
if (Z_TYPE_P(retval_ptr) == IS_NULL) {
|
||||
/* let return -1 */
|
||||
@@ -698,7 +699,7 @@ ZEND_MODULE_STARTUP_D(rar)
|
||||
ZEND_MODULE_GLOBALS_DTOR_N(rar)); */
|
||||
|
||||
php_register_url_stream_wrapper("rar", &php_stream_rar_wrapper TSRMLS_CC);
|
||||
|
||||
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_MSDOS", HOST_MSDOS, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_OS2", HOST_OS2, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("RAR_HOST_WIN32", HOST_WIN32, CONST_CS | CONST_PERSISTENT);
|
||||
@@ -732,7 +733,6 @@ ZEND_MODULE_INFO_D(rar)
|
||||
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", PHP_RAR_REVISION);
|
||||
|
||||
#if RARVER_BETA != 0
|
||||
sprintf(version,"%d.%02d beta%d patch%d %d-%02d-%02d", RARVER_MAJOR,
|
||||
|
||||
12
rar_error.c
12
rar_error.c
@@ -52,11 +52,11 @@ int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
|
||||
if (err == NULL) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
if (_rar_using_exceptions(TSRMLS_C)) {
|
||||
zend_throw_exception_ex(rarexception_ce_ptr, errcode TSRMLS_CC,
|
||||
"unRAR internal error: %s%s", preamble, err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s", preamble, err);
|
||||
}
|
||||
@@ -91,7 +91,7 @@ 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);
|
||||
assert(Z_TYPE_P(pval) == IS_BOOL);
|
||||
|
||||
return Z_BVAL_P(pval);
|
||||
}
|
||||
@@ -187,7 +187,7 @@ PHP_METHOD(rarexception, isUsingExceptions)
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* or zend_read_static_property, which calls zend_std_get... after chg scope */
|
||||
#if PHP_VERSION_ID < 50399
|
||||
pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
|
||||
@@ -198,8 +198,8 @@ PHP_METHOD(rarexception, isUsingExceptions)
|
||||
#endif
|
||||
/* property always exists */
|
||||
assert(pval != NULL);
|
||||
assert(Z_TYPE_PP(pval) == IS_BOOL);
|
||||
|
||||
assert(Z_TYPE_PP(pval) == IS_BOOL);
|
||||
|
||||
RETURN_ZVAL(*pval, 0, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
1194
rar_navigation.c
1194
rar_navigation.c
File diff suppressed because it is too large
Load Diff
134
rar_stream.c
134
rar_stream.c
@@ -34,7 +34,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include <php.h>
|
||||
|
||||
#if HAVE_RAR
|
||||
|
||||
@@ -43,9 +43,10 @@ extern "C" {
|
||||
#include "php_rar.h"
|
||||
#include "unrar/rartypes.hpp"
|
||||
|
||||
#include "php_streams.h"
|
||||
#include "ext/standard/url.h"
|
||||
#include "ext/standard/php_string.h"
|
||||
#include <php_streams.h>
|
||||
#include <ext/standard/url.h>
|
||||
#include <ext/standard/php_string.h>
|
||||
#include <ext/standard/file.h>
|
||||
|
||||
typedef struct php_rar_stream_data_t {
|
||||
struct RAROpenArchiveDataEx open_data;
|
||||
@@ -79,7 +80,7 @@ typedef struct php_rar_dir_stream_data_t {
|
||||
#define STREAM_DIR_DATA_FROM_STREAM \
|
||||
php_rar_dir_stream_data_P self = (php_rar_dir_stream_data_P) stream->abstract;
|
||||
|
||||
/* len can be -1 (calculate) */
|
||||
/* len can be -1 (calculate) */
|
||||
static char *_rar_wide_to_utf_with_alloc(const wchar_t *wide, int len)
|
||||
{
|
||||
size_t size;
|
||||
@@ -263,49 +264,38 @@ static mode_t _rar_convert_file_attrs(unsigned os_attrs,
|
||||
/* leave as is */
|
||||
ret = (mode_t) (os_attrs & 0xffff);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
if ((flags & LHD_WINDOWMASK) == LHD_DIRECTORY)
|
||||
if (flags & RHDF_DIRECTORY)
|
||||
ret = S_IFDIR;
|
||||
else
|
||||
ret = S_IFREG;
|
||||
|
||||
ret |= 0777;
|
||||
ret &= ~mask;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* If from is not set, sets to to default and returns SUCCESS.
|
||||
* If from is set, converts it to a time_t. In case of failure returns FAILURE.
|
||||
* In case of success, copies the result to to and returns SUCCESS. */
|
||||
static int _rar_time_convert(RARTime *from, time_t *to) /* {{{ */
|
||||
static void _rar_time_convert(unsigned low, unsigned high, time_t *to) /* {{{ */
|
||||
{
|
||||
time_t default_ = (time_t) 0;
|
||||
time_t retval;
|
||||
struct tm time_s = {0};
|
||||
|
||||
if (from->Year == 0U) {
|
||||
if (high == 0U && low == 0U) {
|
||||
*to = default_;
|
||||
return SUCCESS;
|
||||
return;
|
||||
}
|
||||
|
||||
time_s.tm_sec = from->Second;
|
||||
time_s.tm_min = from->Minute;
|
||||
time_s.tm_hour = from->Hour;
|
||||
time_s.tm_mday = from->Day;
|
||||
time_s.tm_mon = from->Month - 1; /* starts at 0 in time_t */
|
||||
time_s.tm_year = from->Year - 1900;
|
||||
/* 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970. */
|
||||
uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000);
|
||||
|
||||
if ((retval = mktime(&time_s)) == -1)
|
||||
return FAILURE;
|
||||
else {
|
||||
*to = retval;
|
||||
return SUCCESS;
|
||||
}
|
||||
/* value is in 10^-7 seconds since 01-01-1601 */
|
||||
/* convert to nanoseconds, shift to 01-01-1970 and convert to seconds */
|
||||
*to = (time_t) ((INT32TO64(high, low) * 100 - ushift) / 1000000000);
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -339,10 +329,11 @@ static int _rar_stat_from_header(struct RARHeaderDataEx *header,
|
||||
}
|
||||
|
||||
|
||||
_rar_time_convert(&header->atime, &ssb->sb.st_atime);
|
||||
_rar_time_convert(&header->ctime, &ssb->sb.st_ctime);
|
||||
_rar_time_convert(header->AtimeLow, header->AtimeHigh, &ssb->sb.st_atime);
|
||||
_rar_time_convert(header->CtimeLow, header->CtimeHigh, &ssb->sb.st_ctime);
|
||||
|
||||
if (header->mtime.Year == 0) { /* high precision mod time undefined */
|
||||
if (header->MtimeLow == 0 && header->MtimeHigh == 0) {
|
||||
/* high precision mod time undefined */
|
||||
struct tm time_s = {0};
|
||||
time_t time;
|
||||
unsigned dos_time = header->FileTime;
|
||||
@@ -357,8 +348,10 @@ static int _rar_stat_from_header(struct RARHeaderDataEx *header,
|
||||
return FAILURE;
|
||||
ssb->sb.st_mtime = time;
|
||||
}
|
||||
else
|
||||
_rar_time_convert(&header->mtime, &ssb->sb.st_mtime);
|
||||
else {
|
||||
_rar_time_convert(header->MtimeLow, header->MtimeHigh,
|
||||
&ssb->sb.st_mtime);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ST_BLKSIZE
|
||||
ssb->sb.st_blksize = 0;
|
||||
@@ -430,7 +423,7 @@ static size_t php_rar_dir_ops_read(php_stream *stream, char *buf, size_t count T
|
||||
strlcpy(entry.d_name, encoded_name, sizeof entry.d_name);
|
||||
efree(encoded_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
self->cur_offset++;
|
||||
|
||||
@@ -443,7 +436,7 @@ static size_t php_rar_dir_ops_read(php_stream *stream, char *buf, size_t count T
|
||||
static int php_rar_dir_ops_close(php_stream *stream, int close_handle TSRMLS_DC)
|
||||
{
|
||||
STREAM_DIR_DATA_FROM_STREAM
|
||||
|
||||
|
||||
zval_ptr_dtor(&self->rar_obj);
|
||||
efree(self->directory);
|
||||
efree(self->state);
|
||||
@@ -451,7 +444,7 @@ static int php_rar_dir_ops_close(php_stream *stream, int close_handle TSRMLS_DC)
|
||||
stream->abstract = NULL;
|
||||
|
||||
/* 0 because that's what php_plain_files_dirstream_close returns... */
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -503,19 +496,14 @@ static php_stream_ops php_stream_rar_dirio_ops = {
|
||||
* was already done in RarArchive::open */
|
||||
php_stream *php_stream_rar_open(char *arc_name,
|
||||
size_t position,
|
||||
rar_cb_user_data *cb_udata_ptr, /* will be copied */
|
||||
char *mode STREAMS_DC TSRMLS_DC)
|
||||
rar_cb_user_data *cb_udata_ptr /* will be copied */
|
||||
STREAMS_DC TSRMLS_DC)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
php_rar_stream_data_P self = NULL;
|
||||
int result,
|
||||
found;
|
||||
|
||||
/* mode must be exactly "r" */
|
||||
if (strncmp(mode, "r", sizeof("r")) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
self = ecalloc(1, sizeof *self);
|
||||
self->open_data.ArcName = estrdup(arc_name);
|
||||
self->open_data.OpenMode = RAR_OM_EXTRACT;
|
||||
@@ -526,7 +514,7 @@ php_stream *php_stream_rar_open(char *arc_name,
|
||||
self->cb_userdata.callable = cb_udata_ptr->callable;
|
||||
zval_add_ref(&self->cb_userdata.callable);
|
||||
}
|
||||
|
||||
|
||||
result = _rar_find_file_p(&self->open_data, position, &self->cb_userdata,
|
||||
&self->rar_handle, &found, &self->header_data);
|
||||
|
||||
@@ -551,7 +539,7 @@ php_stream *php_stream_rar_open(char *arc_name,
|
||||
|
||||
self->buffer = emalloc(buffer_size);
|
||||
self->buffer_size = buffer_size;
|
||||
stream = php_stream_alloc(&php_stream_rario_ops, self, NULL, mode);
|
||||
stream = php_stream_alloc(&php_stream_rario_ops, self, NULL, "rb");
|
||||
stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
|
||||
}
|
||||
|
||||
@@ -591,7 +579,7 @@ static char *zend_resolve_path(const char *filename,
|
||||
}
|
||||
|
||||
/* do not use the include path in these circumstances */
|
||||
if ((*filename == '.' && (IS_SLASH(filename[1]) ||
|
||||
if ((*filename == '.' && (IS_SLASH(filename[1]) ||
|
||||
((filename[1] == '.') && IS_SLASH(filename[2])))) ||
|
||||
IS_ABSOLUTE_PATH(filename, filename_length) ||
|
||||
path == NULL || path[0] == '\0') {
|
||||
@@ -728,7 +716,7 @@ static int _rar_get_archive_and_fragment(php_stream_wrapper *wrapper,
|
||||
"<urlencoded entry name>]]\"");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
tmp_arch_len = (tmp_fragment != NULL)?
|
||||
(tmp_fragment - filename) : (strlen(filename));
|
||||
tmp_archive = emalloc(tmp_arch_len + 1);
|
||||
@@ -754,7 +742,7 @@ static int _rar_get_archive_and_fragment(php_stream_wrapper *wrapper,
|
||||
if ((*archive = expand_filepath(tmp_archive, NULL TSRMLS_CC))
|
||||
== NULL) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
|
||||
"Could not expand the path %s", archive);
|
||||
"Could not expand the path %s", tmp_archive);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
@@ -802,7 +790,7 @@ static int _rar_get_archive_and_fragment(php_stream_wrapper *wrapper,
|
||||
wchar_t *ptr;
|
||||
for (ptr = *fragment; *ptr != L'\0'; ptr++) {
|
||||
if (*ptr == L'\\' || *ptr == L'/')
|
||||
*ptr = PATHDIVIDERW[0];
|
||||
*ptr = SPATHDIVIDER[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,10 +830,10 @@ static php_stream *php_stream_rar_opener(php_stream_wrapper *wrapper,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mode must be exactly "r" */
|
||||
if (strncmp(mode, "r", sizeof("r")) != 0) {
|
||||
/* mode must be "r" or "rb", which, for BC reasons, are treated identically */
|
||||
if (mode[0] != 'r' || (mode[1] != '\0' && mode[1] != 'b') || strlen(mode) > 2) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
|
||||
"Only the \"r\" open mode is permitted, given %s", mode);
|
||||
"Only the \"r\" and \"rb\" open modes are permitted, given %s", mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -870,7 +858,7 @@ static php_stream *php_stream_rar_opener(php_stream_wrapper *wrapper,
|
||||
zval_add_ref(&self->cb_userdata.callable);
|
||||
SEPARATE_ZVAL(&self->cb_userdata.callable);
|
||||
}
|
||||
|
||||
|
||||
rar_result = _rar_find_file_w(&self->open_data, fragment,
|
||||
&self->cb_userdata, &self->rar_handle, &file_found,
|
||||
&self->header_data);
|
||||
@@ -888,7 +876,7 @@ static php_stream *php_stream_rar_opener(php_stream_wrapper *wrapper,
|
||||
efree(mb_fragment);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
/* once found, the password that matters is the file level password.
|
||||
* we will NOT default on the open password if no file level password is
|
||||
* given, but an open password is. This behaviour is differs from that of
|
||||
@@ -985,7 +973,7 @@ static int _rar_get_cachable_rararch(php_stream_wrapper *wrapper,
|
||||
ret = FAILURE;
|
||||
|
||||
assert(rar_obj != NULL);
|
||||
|
||||
|
||||
_rar_arch_cache_get_key(arch_path, open_passwd, volume_cb, &cache_key,
|
||||
&cache_key_len);
|
||||
*rar_obj = RAR_G(contents_cache).get(cache_key, cache_key_len TSRMLS_CC);
|
||||
@@ -1056,7 +1044,9 @@ cleanup:
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _rar_stream_tidy_wrapper_error_log */
|
||||
/* {{{ _rar_stream_tidy_wrapper_error_log
|
||||
* These two different versions are because of PHP commit 7166298 */
|
||||
#if PHP_VERSION_ID <= 50310 || PHP_VERSION_ID == 50400
|
||||
/* copied from main/streams/streams.c because it's an internal function */
|
||||
static void _rar_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC)
|
||||
{
|
||||
@@ -1074,6 +1064,14 @@ static void _rar_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRML
|
||||
wrapper->err_count = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void _rar_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC)
|
||||
{
|
||||
if (wrapper && FG(wrapper_errors)) {
|
||||
zend_hash_del(FG(wrapper_errors), (const char*)&wrapper, sizeof wrapper);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_stream_rar_stater */
|
||||
@@ -1107,7 +1105,7 @@ static int php_stream_rar_stater(php_stream_wrapper *wrapper,
|
||||
NULL, &volume_cb TSRMLS_CC);
|
||||
}
|
||||
/* end preliminaries }}} */
|
||||
|
||||
|
||||
if (_rar_get_cachable_rararch(wrapper, options, open_path, open_passwd,
|
||||
volume_cb, &rararch, &rar TSRMLS_CC) == FAILURE)
|
||||
goto cleanup;
|
||||
@@ -1157,7 +1155,7 @@ cleanup:
|
||||
*/
|
||||
if (flags & PHP_STREAM_URL_STAT_QUIET)
|
||||
_rar_stream_tidy_wrapper_error_log(wrapper TSRMLS_CC);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1189,10 +1187,10 @@ static php_stream *php_stream_rar_dir_opener(php_stream_wrapper *wrapper,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mode must be exactly "r" */
|
||||
if (strncmp(mode, "r", sizeof("r")) != 0) {
|
||||
/* mode must be "r" or "rb", which, for BC reasons, are treated identically */
|
||||
if (mode[0] != 'r' || (mode[1] != '\0' && mode[1] != 'b') || strlen(mode) > 2) {
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
|
||||
"Only the \"r\" open mode is permitted, given %s", mode);
|
||||
"Only the \"r\" and \"rb\" open modes are permitted, given %s", mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1216,16 +1214,16 @@ static php_stream *php_stream_rar_dir_opener(php_stream_wrapper *wrapper,
|
||||
fragment_len = wcslen(fragment);
|
||||
self->directory = ecalloc(fragment_len + 1, sizeof *self->directory);
|
||||
wmemcpy(self->directory, fragment, fragment_len + 1);
|
||||
|
||||
|
||||
/* Remove the ending in the path separator */
|
||||
if (fragment_len > 0 &&
|
||||
self->directory[fragment_len - 1] == PATHDIVIDERW[0]) {
|
||||
self->directory[fragment_len - 1] == SPATHDIVIDER[0]) {
|
||||
self->directory[fragment_len - 1] = L'\0';
|
||||
self->dir_size = fragment_len;
|
||||
}
|
||||
else
|
||||
self->dir_size = fragment_len + 1;
|
||||
|
||||
|
||||
_rar_entry_search_start(rar, RAR_SEARCH_DIRECTORY | RAR_SEARCH_NAME,
|
||||
&self->state TSRMLS_CC);
|
||||
if (self->dir_size != 1) { /* skip if asked for root */
|
||||
@@ -1233,10 +1231,10 @@ static php_stream *php_stream_rar_dir_opener(php_stream_wrapper *wrapper,
|
||||
* to the archive, which I'll assume occurs in all good archives */
|
||||
_rar_entry_search_advance(
|
||||
self->state, self->directory, self->dir_size, 0);
|
||||
if (!self->state->found || ((self->state->header->Flags &
|
||||
LHD_WINDOWMASK) != LHD_DIRECTORY)) {
|
||||
if (!self->state->found || !(self->state->header->Flags &
|
||||
RHDF_DIRECTORY)) {
|
||||
const char *message;
|
||||
char *mb_entry = _rar_wide_to_utf_with_alloc(self->directory,
|
||||
char *mb_entry = _rar_wide_to_utf_with_alloc(self->directory,
|
||||
(size_t) self->dir_size - 1);
|
||||
|
||||
if (!self->state->found)
|
||||
|
||||
70
rararch.c
70
rararch.c
@@ -73,8 +73,6 @@ static zend_object_handlers rararch_object_handlers;
|
||||
|
||||
/* {{{ Function prototypes for functions with internal linkage */
|
||||
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);
|
||||
/* }}} */
|
||||
|
||||
@@ -130,7 +128,7 @@ int _rar_create_rararch_obj(const char* resolved_path,
|
||||
zval_add_ref(&rar->cb_userdata.callable);
|
||||
SEPARATE_ZVAL(&rar->cb_userdata.callable);
|
||||
}
|
||||
|
||||
|
||||
object_init_ex(object, rararch_ce_ptr);
|
||||
zobj = zend_object_store_get_object(object TSRMLS_CC);
|
||||
zobj->rar_file = rar;
|
||||
@@ -138,11 +136,11 @@ int _rar_create_rararch_obj(const char* resolved_path,
|
||||
|
||||
RARSetCallback(rar->arch_handle, _rar_unrar_callback,
|
||||
(LPARAM) &rar->cb_userdata);
|
||||
|
||||
|
||||
return SUCCESS;
|
||||
} else {
|
||||
*err_code = rar->list_open_data->OpenResult;
|
||||
|
||||
|
||||
efree(rar->list_open_data->ArcName);
|
||||
efree(rar->list_open_data->CmtBuf);
|
||||
efree(rar->list_open_data);
|
||||
@@ -157,7 +155,7 @@ int _rar_create_rararch_obj(const char* resolved_path,
|
||||
void _rar_close_file_resource(rar_file_t *rar) /* {{{ */
|
||||
{
|
||||
assert(rar->arch_handle != NULL);
|
||||
|
||||
|
||||
/* 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
|
||||
@@ -249,7 +247,7 @@ static zend_object_value rararch_ce_create_object(zend_class_entry *class_type T
|
||||
object_properties_init((zend_object*)zobj, class_type);
|
||||
#endif
|
||||
zov.handle = zend_objects_store_put(zobj,
|
||||
(zend_objects_store_dtor_t) rararch_ce_destroy_object,
|
||||
(zend_objects_store_dtor_t) zend_objects_destroy_object,
|
||||
(zend_objects_free_object_storage_t) rararch_ce_free_object_storage,
|
||||
NULL TSRMLS_CC);
|
||||
zov.handlers = &rararch_object_handlers;
|
||||
@@ -257,30 +255,16 @@ static zend_object_value rararch_ce_create_object(zend_class_entry *class_type T
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void rararch_ce_destroy_object(ze_rararch_object *object,
|
||||
zend_object_handle handle TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
rar_file_t *rar = object->rar_file;
|
||||
|
||||
/* can safely assume rar != NULL here. This function is not called
|
||||
* if object construction fails */
|
||||
assert(rar != NULL);
|
||||
|
||||
/* 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;
|
||||
|
||||
/* may be NULL if the user did new RarArchive() */
|
||||
if (rar != NULL) {
|
||||
if (rar->arch_handle != NULL) {
|
||||
RARCloseArchive(rar->arch_handle);
|
||||
}
|
||||
|
||||
_rar_destroy_userdata(&rar->cb_userdata);
|
||||
|
||||
_rar_delete_entries(rar TSRMLS_CC);
|
||||
@@ -292,7 +276,7 @@ static void rararch_ce_free_object_storage(ze_rararch_object *object TSRMLS_DC)
|
||||
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);
|
||||
@@ -310,7 +294,7 @@ static int rararch_handlers_preamble(zval *object, rar_file_t **rar TSRMLS_DC) /
|
||||
if (_rar_get_file_resource(object, rar TSRMLS_CC) == FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
return _rar_handle_error(_rar_list_files(*rar TSRMLS_CC) TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -374,7 +358,7 @@ static int rararch_dimensions_preamble(rar_file_t *rar,
|
||||
"an integer (get handler returned another object)");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
ret = rararch_dimensions_preamble(rar, newoffset, index, quiet
|
||||
TSRMLS_CC);
|
||||
FREE_ZVAL(newoffset);
|
||||
@@ -411,11 +395,11 @@ static int rararch_dimensions_preamble(rar_file_t *rar,
|
||||
/* }}} */
|
||||
|
||||
/* {{{ RarArchive count_elements handler */
|
||||
static int rararch_count_elements(zval *object, long *count TSRMLS_DC)
|
||||
static int rararch_count_elements(zval *object, long *count TSRMLS_DC)
|
||||
{
|
||||
rar_file_t *rar = NULL;
|
||||
size_t entry_count;
|
||||
|
||||
|
||||
if (rararch_handlers_preamble(object, &rar TSRMLS_CC) == FAILURE) {
|
||||
*count = 0L;
|
||||
return SUCCESS; /* intentional */
|
||||
@@ -540,7 +524,7 @@ PHP_FUNCTION(rar_open)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_rar_create_rararch_obj(resolved_path, password, callable,
|
||||
return_value, &err_code TSRMLS_CC) == FAILURE) {
|
||||
const char *err_str = _rar_error_to_string(err_code);
|
||||
@@ -575,9 +559,9 @@ PHP_FUNCTION(rar_list)
|
||||
|
||||
if (_rar_handle_error(_rar_list_files(rar TSRMLS_CC) TSRMLS_CC) == FAILURE)
|
||||
RETURN_FALSE;
|
||||
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
|
||||
_rar_raw_entries_to_array(rar, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -611,7 +595,7 @@ PHP_FUNCTION(rar_entry_get)
|
||||
if (_rar_handle_error(_rar_list_files(rar TSRMLS_CC) TSRMLS_CC) == FAILURE)
|
||||
RETURN_FALSE;
|
||||
|
||||
filename_c = ecalloc(filename_len + 1, sizeof *filename_c);
|
||||
filename_c = ecalloc(filename_len + 1, sizeof *filename_c);
|
||||
_rar_utf_to_wide(filename, filename_c, filename_len + 1);
|
||||
|
||||
_rar_entry_search_start(rar, RAR_SEARCH_NAME, &sstate TSRMLS_CC);
|
||||
@@ -624,7 +608,7 @@ PHP_FUNCTION(rar_entry_get)
|
||||
_rar_handle_ext_error(
|
||||
"cannot find file \"%s\" in Rar archive \"%s\""
|
||||
TSRMLS_CC, filename, rar->list_open_data->ArcName);
|
||||
RETVAL_FALSE;
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
_rar_entry_search_end(sstate);
|
||||
|
||||
@@ -662,7 +646,7 @@ PHP_FUNCTION(rar_comment_get)
|
||||
if (_rar_get_file_resource(file, &rar TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
cmt_state = rar->list_open_data->CmtState;
|
||||
|
||||
if (_rar_handle_error(cmt_state TSRMLS_CC) == FAILURE)
|
||||
@@ -699,7 +683,7 @@ PHP_FUNCTION(rar_broken_is)
|
||||
result = _rar_list_files(rar TSRMLS_CC);
|
||||
rar->allow_broken = orig_allow_broken;
|
||||
|
||||
RETURN_BOOL(_rar_error_to_string(result) != NULL);
|
||||
RETURN_BOOL(_rar_error_to_string(result) != NULL);
|
||||
}
|
||||
|
||||
/* {{{ proto bool rar_allow_broken_set(RarArchive rarfile, bool allow_broken)
|
||||
@@ -760,7 +744,7 @@ PHP_METHOD(rararch, __toString)
|
||||
char *restring;
|
||||
size_t restring_size;
|
||||
int is_closed;
|
||||
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
if (_rar_get_file_resource_ex(arch_obj, &rar, TRUE TSRMLS_CC) == FAILURE) {
|
||||
@@ -779,7 +763,7 @@ PHP_METHOD(rararch, __toString)
|
||||
snprintf(restring, restring_size, format, rar->list_open_data->ArcName,
|
||||
is_closed?closed:"");
|
||||
restring[restring_size - 1] = '\0'; /* just to be safe */
|
||||
|
||||
|
||||
RETURN_STRINGL(restring, (int) restring_size - 1, 0);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -859,7 +843,7 @@ static zend_object_iterator *rararch_it_get_iterator(zend_class_entry *ce,
|
||||
if (rar->arch_handle == NULL)
|
||||
php_error_docref(NULL TSRMLS_CC, E_ERROR,
|
||||
"The archive is already closed, cannot give an iterator");
|
||||
res = _rar_list_files(rar TSRMLS_CC);
|
||||
res = _rar_list_files(rar TSRMLS_CC);
|
||||
if (_rar_handle_error(res TSRMLS_CC) == FAILURE) {
|
||||
/* if it failed, do not expose the possibly incomplete entry list */
|
||||
it->empty_iterator = 1;
|
||||
@@ -891,11 +875,11 @@ static void rararch_it_invalidate_current(zend_object_iterator *iter TSRMLS_DC)
|
||||
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 */
|
||||
|
||||
|
||||
_rar_entry_search_end(it->state);
|
||||
efree(it);
|
||||
}
|
||||
|
||||
186
rarentry.c
186
rarentry.c
@@ -34,7 +34,7 @@ extern "C" {
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
|
||||
#include "php.h"
|
||||
#include <php.h>
|
||||
#include "php_rar.h"
|
||||
|
||||
/* {{{ Globals with external linkage */
|
||||
@@ -49,7 +49,7 @@ static zend_object_handlers rarentry_object_handlers;
|
||||
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
|
||||
int name_length, char *doc_comment,
|
||||
int doc_comment_len TSRMLS_DC);
|
||||
static zval **_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC);
|
||||
static zval *_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC);
|
||||
static void _rar_dos_date_to_text(int dos_time, char *date_string);
|
||||
static zend_object_value rarentry_ce_create_object(zend_class_entry *class_type TSRMLS_DC);
|
||||
/* }}} */
|
||||
@@ -106,15 +106,15 @@ void _rar_entry_to_zval(zval *parent, /* zval to RarArchive object, will have it
|
||||
sizeof("packed_size") - 1, packed_size TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "host_os",
|
||||
sizeof("host_os") - 1, entry->HostOS TSRMLS_CC);
|
||||
|
||||
|
||||
_rar_dos_date_to_text(entry->FileTime, time);
|
||||
zend_update_property_string(rar_class_entry_ptr, object, "file_time",
|
||||
sizeof("file_time") - 1, time TSRMLS_CC);
|
||||
|
||||
|
||||
sprintf(tmp_s, "%x", entry->FileCRC);
|
||||
zend_update_property_string(rar_class_entry_ptr, object, "crc",
|
||||
sizeof("crc") - 1, tmp_s TSRMLS_CC);
|
||||
|
||||
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "attr",
|
||||
sizeof("attr") - 1, entry->FileAttr TSRMLS_CC);
|
||||
zend_update_property_long(rar_class_entry_ptr, object, "version",
|
||||
@@ -160,28 +160,14 @@ static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval **_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
|
||||
static zval *_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval **tmp;
|
||||
zval member;
|
||||
zval *tmp;
|
||||
zend_class_entry *orig_scope = EG(scope);
|
||||
|
||||
EG(scope) = rar_class_entry_ptr;
|
||||
|
||||
INIT_ZVAL(member);
|
||||
Z_TYPE(member) = IS_STRING;
|
||||
Z_STRVAL(member) = name;
|
||||
Z_STRLEN(member) = namelen;
|
||||
|
||||
/* probably should be replaced by zend_read_property */
|
||||
|
||||
#if PHP_VERSION_ID < 50399
|
||||
tmp = Z_OBJ_HANDLER_P(entry_obj, get_property_ptr_ptr)(entry_obj, &member
|
||||
TSRMLS_CC);
|
||||
#else
|
||||
tmp = Z_OBJ_HANDLER_P(entry_obj, get_property_ptr_ptr)(entry_obj, &member,
|
||||
NULL TSRMLS_CC);
|
||||
#endif
|
||||
tmp = zend_read_property(Z_OBJCE_P(entry_obj), entry_obj, name, namelen, 1 TSRMLS_CC);
|
||||
if (tmp == NULL) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Bug: unable to find property '%s'. Please report.", name);
|
||||
@@ -248,8 +234,8 @@ PHP_METHOD(rarentry, extract)
|
||||
int with_second_arg;
|
||||
zend_bool process_ed = 0;
|
||||
|
||||
zval **tmp,
|
||||
**tmp_position;
|
||||
zval *tmp,
|
||||
*tmp_position;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
struct RARHeaderDataEx entry;
|
||||
@@ -259,7 +245,7 @@ PHP_METHOD(rarentry, extract)
|
||||
/* gotta have a new copy (shallow is enough) because we may want to use a
|
||||
* password that's different from the one stored in the rar_file_t object*/
|
||||
rar_cb_user_data cb_udata = {NULL};
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss!b", &dir,
|
||||
&dir_len, &filepath, &filepath_len, &password, &password_len,
|
||||
&process_ed) == FAILURE ) {
|
||||
@@ -267,7 +253,7 @@ PHP_METHOD(rarentry, extract)
|
||||
}
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "rarfile");
|
||||
if (_rar_get_file_resource(*tmp, &rar TSRMLS_CC) == FAILURE) {
|
||||
if (_rar_get_file_resource(tmp, &rar TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -284,14 +270,14 @@ PHP_METHOD(rarentry, extract)
|
||||
else {
|
||||
considered_path = filepath;
|
||||
}
|
||||
|
||||
|
||||
if (OPENBASEDIR_CHECKPATH(considered_path)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (!expand_filepath(considered_path, considered_path_res TSRMLS_CC)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Find file inside archive */
|
||||
RAR_GET_PROPERTY(tmp_position, "position");
|
||||
|
||||
@@ -304,7 +290,7 @@ PHP_METHOD(rarentry, extract)
|
||||
memcpy(&cb_udata, &rar->cb_userdata, sizeof cb_udata);
|
||||
|
||||
result = _rar_find_file_p(rar->extract_open_data,
|
||||
(size_t) Z_LVAL_PP(tmp_position), &cb_udata, &extract_handle, &found,
|
||||
(size_t) Z_LVAL_P(tmp_position), &cb_udata, &extract_handle, &found,
|
||||
&entry);
|
||||
|
||||
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
|
||||
@@ -314,7 +300,7 @@ PHP_METHOD(rarentry, extract)
|
||||
|
||||
if (!found) {
|
||||
_rar_handle_ext_error("Can't find file with index %d in archive %s"
|
||||
TSRMLS_CC, Z_LVAL_PP(tmp_position),
|
||||
TSRMLS_CC, Z_LVAL_P(tmp_position),
|
||||
rar->extract_open_data->ArcName);
|
||||
RETVAL_FALSE;
|
||||
goto cleanup;
|
||||
@@ -341,7 +327,7 @@ PHP_METHOD(rarentry, extract)
|
||||
else {
|
||||
RETVAL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
if (extract_handle != NULL)
|
||||
RARCloseArchive(extract_handle);
|
||||
@@ -352,14 +338,14 @@ cleanup:
|
||||
Return position for the entry */
|
||||
PHP_METHOD(rarentry, getPosition)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "position");
|
||||
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -367,14 +353,14 @@ PHP_METHOD(rarentry, getPosition)
|
||||
Return entry name */
|
||||
PHP_METHOD(rarentry, getName)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "name");
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -382,14 +368,14 @@ PHP_METHOD(rarentry, getName)
|
||||
Return unpacked size of the entry */
|
||||
PHP_METHOD(rarentry, getUnpackedSize)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "unpacked_size");
|
||||
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -397,14 +383,14 @@ PHP_METHOD(rarentry, getUnpackedSize)
|
||||
Return packed size of the entry */
|
||||
PHP_METHOD(rarentry, getPackedSize)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "packed_size");
|
||||
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -412,29 +398,31 @@ PHP_METHOD(rarentry, getPackedSize)
|
||||
Return host OS of the entry */
|
||||
PHP_METHOD(rarentry, getHostOs)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "host_os");
|
||||
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string RarEntry::getFileTime()
|
||||
Return modification time of the entry */
|
||||
Return modification time of the entry.
|
||||
Due to the way the unrar library returns this time, this is in the
|
||||
system's timezone. */
|
||||
PHP_METHOD(rarentry, getFileTime)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "file_time");
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -442,14 +430,14 @@ PHP_METHOD(rarentry, getFileTime)
|
||||
Return CRC of the entry */
|
||||
PHP_METHOD(rarentry, getCrc)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "crc");
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -457,14 +445,14 @@ PHP_METHOD(rarentry, getCrc)
|
||||
Return attributes of the entry */
|
||||
PHP_METHOD(rarentry, getAttr)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "attr");
|
||||
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -472,14 +460,14 @@ PHP_METHOD(rarentry, getAttr)
|
||||
Return version of the archiver, used to create this entry */
|
||||
PHP_METHOD(rarentry, getVersion)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "version");
|
||||
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -487,14 +475,14 @@ PHP_METHOD(rarentry, getVersion)
|
||||
Return packing method */
|
||||
PHP_METHOD(rarentry, getMethod)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "method");
|
||||
|
||||
RETURN_LONG(Z_LVAL_PP(tmp));
|
||||
|
||||
RETURN_LONG(Z_LVAL_P(tmp));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -502,8 +490,8 @@ PHP_METHOD(rarentry, getMethod)
|
||||
Return stream for current entry */
|
||||
PHP_METHOD(rarentry, getStream)
|
||||
{
|
||||
zval **tmp,
|
||||
**position;
|
||||
zval *tmp,
|
||||
*position;
|
||||
rar_file_t *rar = NULL;
|
||||
zval *entry_obj = getThis();
|
||||
php_stream *stream = NULL;
|
||||
@@ -511,7 +499,7 @@ PHP_METHOD(rarentry, getStream)
|
||||
int password_len; /* ignored */
|
||||
rar_cb_user_data cb_udata = {NULL};
|
||||
|
||||
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!",
|
||||
&password, &password_len) == FAILURE ) {
|
||||
return;
|
||||
@@ -519,7 +507,7 @@ PHP_METHOD(rarentry, getStream)
|
||||
|
||||
RAR_GET_PROPERTY(position, "position");
|
||||
RAR_GET_PROPERTY(tmp, "rarfile");
|
||||
if (_rar_get_file_resource(*tmp, &rar TSRMLS_CC) == FAILURE) {
|
||||
if (_rar_get_file_resource(tmp, &rar TSRMLS_CC) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -530,8 +518,8 @@ PHP_METHOD(rarentry, getStream)
|
||||
|
||||
/* doesn't matter that cb_udata is stack allocated, it will be copied */
|
||||
stream = php_stream_rar_open(rar->extract_open_data->ArcName,
|
||||
Z_LVAL_PP(position), &cb_udata, "r" STREAMS_CC TSRMLS_CC);
|
||||
|
||||
Z_LVAL_P(position), &cb_udata STREAMS_CC TSRMLS_CC);
|
||||
|
||||
if (stream != NULL) {
|
||||
php_stream_to_zval(stream, return_value);
|
||||
}
|
||||
@@ -544,17 +532,17 @@ PHP_METHOD(rarentry, getStream)
|
||||
Return whether the entry represents a directory */
|
||||
PHP_METHOD(rarentry, isDirectory)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_dir;
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "flags");
|
||||
flags = Z_LVAL_PP(tmp);
|
||||
is_dir = ((flags & LHD_WINDOWMASK) == LHD_DIRECTORY);
|
||||
|
||||
flags = Z_LVAL_P(tmp);
|
||||
is_dir = (flags & RHDF_DIRECTORY) != 0;
|
||||
|
||||
RETURN_BOOL(is_dir);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -563,17 +551,17 @@ PHP_METHOD(rarentry, isDirectory)
|
||||
Return whether the entry is encrypted and needs a password */
|
||||
PHP_METHOD(rarentry, isEncrypted)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_encrypted;
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "flags");
|
||||
flags = Z_LVAL_PP(tmp);
|
||||
is_encrypted = (flags & 0x04);
|
||||
|
||||
flags = Z_LVAL_P(tmp);
|
||||
is_encrypted = (flags & RHDF_ENCRYPTED) != 0;
|
||||
|
||||
RETURN_BOOL(is_encrypted);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -582,9 +570,9 @@ PHP_METHOD(rarentry, isEncrypted)
|
||||
Return string representation for entry */
|
||||
PHP_METHOD(rarentry, __toString)
|
||||
{
|
||||
zval **flags_zval,
|
||||
**name_zval,
|
||||
**crc_zval;
|
||||
zval *flags_zval,
|
||||
*name_zval,
|
||||
*crc_zval;
|
||||
zval *entry_obj = getThis();
|
||||
long flags;
|
||||
int is_dir;
|
||||
@@ -595,16 +583,16 @@ PHP_METHOD(rarentry, __toString)
|
||||
const char format[] = "RarEntry for %s \"%s\" (%s)";
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(flags_zval, "flags");
|
||||
flags = Z_LVAL_PP(flags_zval);
|
||||
is_dir = ((flags & 0xE0) == 0xE0);
|
||||
flags = Z_LVAL_P(flags_zval);
|
||||
is_dir = flags & RHDF_DIRECTORY;
|
||||
|
||||
RAR_GET_PROPERTY(name_zval, "name");
|
||||
name = Z_STRVAL_PP(name_zval);
|
||||
name = Z_STRVAL_P(name_zval);
|
||||
|
||||
RAR_GET_PROPERTY(crc_zval, "crc");
|
||||
crc = Z_STRVAL_PP(crc_zval);
|
||||
crc = Z_STRVAL_P(crc_zval);
|
||||
|
||||
/* 2 is size of %s, 8 is size of crc */
|
||||
restring_len = (sizeof(format)-1) - 2 * 3 + (sizeof("directory")-1) +
|
||||
@@ -613,7 +601,7 @@ PHP_METHOD(rarentry, __toString)
|
||||
snprintf(restring, restring_len, format, is_dir?"directory":"file",
|
||||
name, crc);
|
||||
restring[restring_len - 1] = '\0'; /* just to be safe */
|
||||
|
||||
|
||||
RETURN_STRING(restring, 0);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -681,7 +669,7 @@ void minit_rarentry(TSRMLS_D)
|
||||
REG_RAR_PROPERTY("version", "RAR version needed to extract entry");
|
||||
REG_RAR_PROPERTY("method", "Identifier for packing method");
|
||||
REG_RAR_PROPERTY("flags", "Entry header flags");
|
||||
|
||||
|
||||
REG_RAR_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);
|
||||
|
||||
@@ -24,7 +24,7 @@ array(2) {
|
||||
[0]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%s (%s) {
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(0)
|
||||
@@ -47,12 +47,12 @@ array(2) {
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
int(0)
|
||||
}
|
||||
[1]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (0) {
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(1)
|
||||
@@ -75,7 +75,7 @@ array(2) {
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
int(0)
|
||||
}
|
||||
}
|
||||
array(2) {
|
||||
@@ -105,7 +105,7 @@ array(2) {
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(36992)
|
||||
int(0)
|
||||
}
|
||||
[1]=>
|
||||
object(RarEntry)#%d (%d) {
|
||||
@@ -133,7 +133,7 @@ array(2) {
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
int(16)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ object(RarEntry)#%d (%d) {
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(32800)
|
||||
int(0)
|
||||
}
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
@@ -72,7 +72,7 @@ object(RarEntry)#%d (%d) {
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
int(16)
|
||||
}
|
||||
|
||||
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
|
||||
|
||||
@@ -55,7 +55,7 @@ blah-blah-blah
|
||||
string(5) "22222"
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#3 (0) {
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(1)
|
||||
@@ -78,7 +78,7 @@ object(RarEntry)#%d (%d) {
|
||||
["method%sprivate%s=>
|
||||
int(53)
|
||||
["flags%sprivate%s=>
|
||||
int(37008)
|
||||
int(16)
|
||||
}
|
||||
bool(true)
|
||||
Done
|
||||
|
||||
@@ -33,9 +33,9 @@ echo "Done\n";
|
||||
--EXPECTF--
|
||||
51 files (will test only the first 4):
|
||||
|
||||
: The great battle of Gunprex versus Optiter!!!!!1
|
||||
test/C:5B': The great battle of Gunprex versus Optiter!!!!!1
|
||||
Gunprex, Fire!
|
||||
So long, Optiter!
|
||||
|
||||
:
|
||||
test/Sbv=Ð:
|
||||
Done
|
||||
|
||||
@@ -5,9 +5,9 @@ RarArchive::open() volume callback long return (case MAXPATHLEN > NM)
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
if (!defined("PHP_MAXPATHLEN"))
|
||||
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
|
||||
if (!(PHP_MAXPATHLEN > 1024))
|
||||
die("skip test is for systems where MAXPATHLEN > 1024");
|
||||
$rp = dirname(__FILE__) . "/" . str_repeat("a", 1024);
|
||||
if (!(PHP_MAXPATHLEN > 2048))
|
||||
die("skip test is for systems where MAXPATHLEN > 2048");
|
||||
$rp = dirname(__FILE__) . "/" . str_repeat("a", 2048);
|
||||
if (strlen(dirname(__FILE__) > PHP_MAXPATHLEN - 1))
|
||||
die("skip current directory is too deep.");
|
||||
--FILE--
|
||||
@@ -17,8 +17,8 @@ if (!defined("PHP_MAXPATHLEN"))
|
||||
|
||||
chdir(dirname(__FILE__));
|
||||
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
|
||||
|
||||
function testA($vol) { if ($vol[0] != 'a') return str_repeat("a", 1024); }
|
||||
|
||||
function testA($vol) { if ($vol[0] != 'a') return str_repeat("a", 2048); }
|
||||
$rar = RarArchive::open($fn, null, 'testA');
|
||||
$rar->getEntries();
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ RAR file stream stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--ENV--
|
||||
TZ=Europe/Lisbon
|
||||
--FILE--
|
||||
<?php
|
||||
umask(0);
|
||||
@@ -24,7 +26,7 @@ Array
|
||||
[rdev] => 0
|
||||
[size] => 5
|
||||
[atime] => 0
|
||||
[mtime] => 1086948439
|
||||
[mtime] => 1086944839
|
||||
[ctime] => 0
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
|
||||
@@ -3,6 +3,8 @@ url stat test
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--ENV--
|
||||
TZ=Europe/Lisbon
|
||||
--FILE--
|
||||
<?php
|
||||
umask(0);
|
||||
|
||||
@@ -3,6 +3,8 @@ RAR directory stream stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--ENV--
|
||||
TZ=Europe/Lisbon
|
||||
--FILE--
|
||||
<?php
|
||||
umask(0);
|
||||
@@ -52,9 +54,9 @@ Array
|
||||
[gid] => 0
|
||||
[rdev] => 0
|
||||
[size] => 0
|
||||
[atime] => 1272938643
|
||||
[mtime] => 1272938643
|
||||
[ctime] => 1272813170
|
||||
[atime] => 1272935043
|
||||
[mtime] => 1272935043
|
||||
[ctime] => 1272809570
|
||||
[blksize] => %s
|
||||
[blocks] => %s
|
||||
)
|
||||
|
||||
@@ -37,7 +37,6 @@ echo "Done.\n";
|
||||
--EXPECTF--
|
||||
RAR support => enabled
|
||||
RAR EXT version => %d.%d.%s
|
||||
Revision => %s
|
||||
UnRAR version => %d.%d%spatch%d %d-%d-%d
|
||||
UnRAR API version => %d extension %d
|
||||
|
||||
|
||||
29
tests/099.phpt
Normal file
29
tests/099.phpt
Normal file
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Bug #59939: Streaming empty file from archive issues a warning
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$rar = RarArchive::open(dirname(__FILE__) . '/empty_file.rar');
|
||||
if ($rar === false) die("could not open RAR file");
|
||||
|
||||
$rar_file = $rar->getEntry('empty_file');
|
||||
if ($rar_file === false) die("could not find entry");
|
||||
|
||||
$stream = $rar_file->getStream();
|
||||
if ($stream === false) die("could not open stream");
|
||||
|
||||
var_dump(feof($stream),
|
||||
fread($stream, 1024*1024),
|
||||
feof($stream));
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(false)
|
||||
string(0) ""
|
||||
bool(true)
|
||||
|
||||
Done.
|
||||
37
tests/100.phpt
Normal file
37
tests/100.phpt
Normal file
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
fopen modes 'r' and 'rb' are the only allowed
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$file = 'rar://' . rawurlencode(dirname(__FILE__) . '/linux_rar.rar')
|
||||
. '#/plain.txt';
|
||||
|
||||
echo "Testing 'r'\n";
|
||||
$fd = fopen($file, 'r');
|
||||
if ($fd) echo "opened\n\n";
|
||||
|
||||
echo "Testing 'rb'\n";
|
||||
$fd = fopen($file, 'rb');
|
||||
if ($fd) echo "opened\n\n";
|
||||
|
||||
echo "Testing 'r+'\n";
|
||||
$fd = fopen($file, 'r+');
|
||||
if ($fd) echo "opened\n\n";
|
||||
|
||||
echo "\n";
|
||||
echo "Done.\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Testing 'r'
|
||||
opened
|
||||
|
||||
Testing 'rb'
|
||||
opened
|
||||
|
||||
Testing 'r+'
|
||||
|
||||
Warning: fopen(%s): failed to open stream: Only the "r" and "rb" open modes are permitted, given r+ in %s on line %d
|
||||
|
||||
Done.
|
||||
46
tests/101.phpt
Normal file
46
tests/101.phpt
Normal file
@@ -0,0 +1,46 @@
|
||||
--TEST--
|
||||
Supports version 5 RAR files
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("rar")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
RarException::setUsingExceptions(true);
|
||||
$file = dirname(__FILE__) . '/rar5_multi.part1.rar';
|
||||
$rar = RarArchive::open($file);
|
||||
$entry = $rar->getEntry('usr/bin/text2image');
|
||||
var_dump($entry);
|
||||
$stream = $entry->getStream('passw0rd');
|
||||
$contents = stream_get_contents($stream);
|
||||
echo "(unpacked) MD5: ", md5($contents), "\n";
|
||||
echo "Done.\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
object(RarEntry)#%d (%d) {
|
||||
["rarfile%sprivate%s=>
|
||||
object(RarArchive)#%d (%d) {
|
||||
}
|
||||
["position%sprivate%s=>
|
||||
int(0)
|
||||
["name%sprivate%s=>
|
||||
string(18) "usr/bin/text2image"
|
||||
["unpacked_size%sprivate%s=>
|
||||
int(147528)
|
||||
["packed_size%sprivate%s=>
|
||||
int(57104)
|
||||
["host_os%sprivate%s=>
|
||||
int(3)
|
||||
["file_time%sprivate%s=>
|
||||
string(19) "%s"
|
||||
["crc%sprivate%s=>
|
||||
string(8) "83c9a6b7"
|
||||
["attr%sprivate%s=>
|
||||
int(33261)
|
||||
["version%sprivate%s=>
|
||||
int(200)
|
||||
["method%sprivate%s=>
|
||||
int(51)
|
||||
["flags%sprivate%s=>
|
||||
int(5)
|
||||
}
|
||||
(unpacked) MD5: c07ce36ec260848f47fe8ac1408f938f
|
||||
Done.
|
||||
BIN
tests/empty_file.rar
Normal file
BIN
tests/empty_file.rar
Normal file
Binary file not shown.
BIN
tests/rar5_multi.part1.rar
Normal file
BIN
tests/rar5_multi.part1.rar
Normal file
Binary file not shown.
BIN
tests/rar5_multi.part2.rar
Normal file
BIN
tests/rar5_multi.part2.rar
Normal file
Binary file not shown.
75
travis.sh
Executable file
75
travis.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
BUILDS_DIR=$HOME/php_builds
|
||||
MIRROR=${MIRROR:-http://us1.php.net/distributions}
|
||||
JOBS=3
|
||||
|
||||
function prefix {
|
||||
local readonly version=$1 zts=$2
|
||||
local zts_suffix=''
|
||||
if [[ $zts = 'yes' ]]; then
|
||||
zts_suffix='-zts'
|
||||
fi
|
||||
|
||||
echo "$BUILDS_DIR/${version}$zts_suffix"
|
||||
}
|
||||
|
||||
function install_php {
|
||||
local readonly version=$1 zts=$2
|
||||
local readonly url="$MIRROR/php-$version.tar.gz" \
|
||||
extract_dir="/tmp/php-$version" prefix=$(prefix $version $zts)
|
||||
local extra_flags=''
|
||||
|
||||
mkdir -p "$extract_dir"
|
||||
wget -O - "$url" | tar -C "$extract_dir" --strip-components=1 -xzf -
|
||||
|
||||
pushd "$extract_dir"
|
||||
if [[ $zts = 'yes' ]]; then
|
||||
extra_flags="$extra_flags --enable-maintainer-zts"
|
||||
fi
|
||||
./configure --prefix="$prefix" --disable-all --enable-cli \
|
||||
$extra_flags
|
||||
make -j $JOBS install
|
||||
popd
|
||||
}
|
||||
|
||||
function build_ext {
|
||||
local readonly prefix=$1
|
||||
"$prefix"/bin/phpize
|
||||
./configure --with-php-config="$prefix/bin/php-config"
|
||||
make -j $JOBS
|
||||
}
|
||||
|
||||
function do_tests {
|
||||
local readonly prefix=$1
|
||||
TEST_PHP_EXECUTABLE="$prefix/bin/php" REPORT_EXIT_STATUS=1 \
|
||||
"$prefix/bin/php" "$prefix"/lib/php/build/run-tests.php \
|
||||
-q -d extension=modules/rar.so --set-timeout 300 --show-diff \
|
||||
$RUN_TESTS_FLAGS tests
|
||||
}
|
||||
|
||||
# public functions below
|
||||
|
||||
function maybe_install_php {
|
||||
set -e
|
||||
set -o pipefail
|
||||
local readonly version=$1 zts=$2
|
||||
local readonly prefix=$(prefix $version $zts)
|
||||
if [[ ! -d $prefix ]]; then
|
||||
install_php $version $zts
|
||||
fi
|
||||
}
|
||||
|
||||
function build {
|
||||
set -e
|
||||
set -o pipefail
|
||||
if [[ ! -f modules/rar.so ]]; then
|
||||
build_ext "$(prefix $1 $2)"
|
||||
fi
|
||||
}
|
||||
|
||||
function run_tests {
|
||||
set -e
|
||||
set -o pipefail
|
||||
do_tests "$(prefix $1 $2)"
|
||||
}
|
||||
@@ -10,13 +10,15 @@
|
||||
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
|
||||
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
|
||||
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.
|
||||
2. UnRAR source code may be used in any software to handle
|
||||
RAR archives without limitations free of charge, but cannot be
|
||||
used to develop RAR (WinRAR) compatible archiver and to
|
||||
re-create RAR compression algorithm, which is proprietary.
|
||||
Distribution of modified UnRAR source code in separate form
|
||||
or as a part of other software is permitted, provided that
|
||||
full text of this paragraph, starting from "UnRAR source code"
|
||||
words, is included in license, or in documentation if license
|
||||
is not available, and in source code comments of resulting package.
|
||||
|
||||
3. The UnRAR utility may be freely distributed. It is allowed
|
||||
to distribute UnRAR inside of other software packages.
|
||||
@@ -37,4 +39,4 @@
|
||||
Thank you for your interest in RAR and UnRAR.
|
||||
|
||||
|
||||
Alexander L. Roshal
|
||||
Alexander L. Roshal
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
|
||||
1. General
|
||||
|
||||
This package includes freeware Unrar C++ source and a few makefiles
|
||||
(makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source
|
||||
is subset of RAR and generated from RAR source automatically,
|
||||
This package includes freeware Unrar C++ source and makefile for
|
||||
several Unix compilers.
|
||||
|
||||
Unrar source is subset of RAR and generated from RAR source automatically,
|
||||
by a small program removing blocks like '#ifndef UNRAR ... #endif'.
|
||||
Such method is not perfect and you may find some RAR related
|
||||
stuff unnecessary in Unrar, especially in header files.
|
||||
Such method is not perfect and you may find some RAR related stuff
|
||||
unnecessary in Unrar, especially in header files.
|
||||
|
||||
If you wish to port Unrar to a new platform, you may need to edit
|
||||
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
|
||||
@@ -17,16 +18,7 @@
|
||||
|
||||
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 numerous compiler option sets.
|
||||
GCC Linux is selected by default. If you need to compile Unrar
|
||||
for other platforms, uncomment corresponding lines.
|
||||
STRICT_ALIGNMENT_REQUIRED in os.h.
|
||||
|
||||
|
||||
2. Unrar binaries
|
||||
@@ -38,16 +30,8 @@
|
||||
|
||||
3. Acknowledgements
|
||||
|
||||
This source includes parts of code written by the following authors:
|
||||
|
||||
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
|
||||
This source includes parts of code written by other authors.
|
||||
Please see acknow.txt file for details.
|
||||
|
||||
|
||||
4. Legal stuff
|
||||
|
||||
279
unrar/UnRAR.vcxproj
Normal file
279
unrar/UnRAR.vcxproj
Normal file
@@ -0,0 +1,279 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{95CC809B-03FC-4EDB-BB20-FD07A698C05F}</ProjectGuid>
|
||||
<RootNamespace>UnRAR</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>build\unrar32\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>build\unrar64\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>build\unrar32\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>build\unrar64\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration />
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>false</StringPooling>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration />
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="archive.cpp" />
|
||||
<ClCompile Include="arcread.cpp" />
|
||||
<ClCompile Include="blake2s.cpp" />
|
||||
<ClCompile Include="cmddata.cpp" />
|
||||
<ClCompile Include="consio.cpp" />
|
||||
<ClCompile Include="crc.cpp" />
|
||||
<ClCompile Include="crypt.cpp" />
|
||||
<ClCompile Include="encname.cpp" />
|
||||
<ClCompile Include="errhnd.cpp" />
|
||||
<ClCompile Include="extinfo.cpp" />
|
||||
<ClCompile Include="extract.cpp" />
|
||||
<ClCompile Include="filcreat.cpp" />
|
||||
<ClCompile Include="file.cpp" />
|
||||
<ClCompile Include="filefn.cpp" />
|
||||
<ClCompile Include="filestr.cpp" />
|
||||
<ClCompile Include="find.cpp" />
|
||||
<ClCompile Include="getbits.cpp" />
|
||||
<ClCompile Include="global.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hash.cpp" />
|
||||
<ClCompile Include="headers.cpp" />
|
||||
<ClCompile Include="isnt.cpp" />
|
||||
<ClCompile Include="list.cpp" />
|
||||
<ClCompile Include="match.cpp" />
|
||||
<ClCompile Include="options.cpp" />
|
||||
<ClCompile Include="pathfn.cpp" />
|
||||
<ClCompile Include="qopen.cpp" />
|
||||
<ClCompile Include="rar.cpp" />
|
||||
<ClCompile Include="rarpch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rarvm.cpp" />
|
||||
<ClCompile Include="rawread.cpp" />
|
||||
<ClCompile Include="rdwrfn.cpp" />
|
||||
<ClCompile Include="recvol.cpp" />
|
||||
<ClCompile Include="resource.cpp" />
|
||||
<ClCompile Include="rijndael.cpp" />
|
||||
<ClCompile Include="rs.cpp" />
|
||||
<ClCompile Include="rs16.cpp" />
|
||||
<ClCompile Include="scantree.cpp" />
|
||||
<ClCompile Include="secpassword.cpp" />
|
||||
<ClCompile Include="sha1.cpp" />
|
||||
<ClCompile Include="sha256.cpp" />
|
||||
<ClCompile Include="smallfn.cpp" />
|
||||
<ClCompile Include="strfn.cpp" />
|
||||
<ClCompile Include="strlist.cpp" />
|
||||
<ClCompile Include="system.cpp" />
|
||||
<ClCompile Include="threadpool.cpp" />
|
||||
<ClCompile Include="timefn.cpp" />
|
||||
<ClCompile Include="ui.cpp" />
|
||||
<ClCompile Include="unicode.cpp" />
|
||||
<ClCompile Include="unpack.cpp" />
|
||||
<ClCompile Include="volume.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
876
unrar/UnRARDll.vcproj
Normal file
876
unrar/UnRARDll.vcproj
Normal file
@@ -0,0 +1,876 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="UnRAR"
|
||||
ProjectGUID="{E815C46C-36C4-499F-BBC2-E772C6B17971}"
|
||||
RootNamespace="UnRAR"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="build\unrardll32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
StructMemberAlignment="3"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="build\unrardll64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
StructMemberAlignment="3"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar64.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="build\unrardll32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
FloatingPointModel="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/SAFESEH"
|
||||
OutputFile="$(OutDir)\unrar.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="build\unrardll64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT"
|
||||
StringPooling="false"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar64.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="release_nocrypt|Win32"
|
||||
OutputDirectory="build\unrardll32\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll32\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT;RAR_NOCRYPT"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
FloatingPointModel="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="0"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/SAFESEH"
|
||||
OutputFile="$(OutDir)\unrar_nocrypt.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll_nocrypt.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="release_nocrypt|x64"
|
||||
OutputDirectory="build\unrardll64\$(ConfigurationName)"
|
||||
IntermediateDirectory="build\unrardll64\$(ConfigurationName)\obj"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/MP"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="0"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="RARDLL;UNRAR;SILENT;RAR_NOCRYPT"
|
||||
StringPooling="false"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
StructMemberAlignment="3"
|
||||
BufferSecurityCheck="true"
|
||||
EnableFunctionLevelLinking="true"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderThrough="rar.hpp"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
CallingConvention="2"
|
||||
DisableSpecificWarnings="4007;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\unrar64_nocrypt.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="true"
|
||||
ModuleDefinitionFile="dll_nocrypt.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="archive.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="arcread.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="blake2s.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="cmddata.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="consio.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="crc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="crypt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="dll.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="encname.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="errhnd.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extinfo.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="extract.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filcreat.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="file.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filefn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="filestr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="find.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="getbits.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="global.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="hash.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="headers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="isnt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="match.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="options.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="pathfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="qopen.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rar.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rarpch.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="release_nocrypt|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rarvm.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rawread.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rdwrfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rijndael.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rs.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rs16.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="scantree.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="secpassword.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sha1.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="sha256.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="smallfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="strfn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="strlist.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="system.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="threadpool.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="timefn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ui.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="unicode.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="unpack.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="volume.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="rar.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath="dll.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
420
unrar/UnRARDll.vcxproj
Normal file
420
unrar/UnRARDll.vcxproj
Normal file
@@ -0,0 +1,420 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="release_nocrypt|Win32">
|
||||
<Configuration>release_nocrypt</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="release_nocrypt|x64">
|
||||
<Configuration>release_nocrypt</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>UnRAR</ProjectName>
|
||||
<ProjectGuid>{E815C46C-36C4-499F-BBC2-E772C6B17971}</ProjectGuid>
|
||||
<RootNamespace>UnRAR</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v140_xp</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
|
||||
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
|
||||
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
|
||||
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>Cdecl</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>Cdecl</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>Cdecl</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
|
||||
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration />
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>false</StringPooling>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>Cdecl</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration />
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<FloatingPointModel>Precise</FloatingPointModel>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>Cdecl</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
|
||||
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration />
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>false</StringPooling>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)unrar.dll</OutputFile>
|
||||
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<LinkTimeCodeGeneration />
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="archive.cpp" />
|
||||
<ClCompile Include="arcread.cpp" />
|
||||
<ClCompile Include="blake2s.cpp" />
|
||||
<ClCompile Include="cmddata.cpp" />
|
||||
<ClCompile Include="consio.cpp" />
|
||||
<ClCompile Include="crc.cpp" />
|
||||
<ClCompile Include="crypt.cpp" />
|
||||
<ClCompile Include="dll.cpp" />
|
||||
<ClCompile Include="encname.cpp" />
|
||||
<ClCompile Include="errhnd.cpp" />
|
||||
<ClCompile Include="extinfo.cpp" />
|
||||
<ClCompile Include="extract.cpp" />
|
||||
<ClCompile Include="filcreat.cpp" />
|
||||
<ClCompile Include="file.cpp" />
|
||||
<ClCompile Include="filefn.cpp" />
|
||||
<ClCompile Include="filestr.cpp" />
|
||||
<ClCompile Include="find.cpp" />
|
||||
<ClCompile Include="getbits.cpp" />
|
||||
<ClCompile Include="global.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
|
||||
</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hash.cpp" />
|
||||
<ClCompile Include="headers.cpp" />
|
||||
<ClCompile Include="isnt.cpp" />
|
||||
<ClCompile Include="match.cpp" />
|
||||
<ClCompile Include="options.cpp" />
|
||||
<ClCompile Include="pathfn.cpp" />
|
||||
<ClCompile Include="qopen.cpp" />
|
||||
<ClCompile Include="rar.cpp" />
|
||||
<ClCompile Include="rarpch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rarvm.cpp" />
|
||||
<ClCompile Include="rawread.cpp" />
|
||||
<ClCompile Include="rdwrfn.cpp" />
|
||||
<ClCompile Include="rijndael.cpp" />
|
||||
<ClCompile Include="rs.cpp" />
|
||||
<ClCompile Include="rs16.cpp" />
|
||||
<ClCompile Include="scantree.cpp" />
|
||||
<ClCompile Include="secpassword.cpp" />
|
||||
<ClCompile Include="sha1.cpp" />
|
||||
<ClCompile Include="sha256.cpp" />
|
||||
<ClCompile Include="smallfn.cpp" />
|
||||
<ClCompile Include="strfn.cpp" />
|
||||
<ClCompile Include="strlist.cpp" />
|
||||
<ClCompile Include="system.cpp" />
|
||||
<ClCompile Include="threadpool.cpp" />
|
||||
<ClCompile Include="timefn.cpp" />
|
||||
<ClCompile Include="ui.cpp" />
|
||||
<ClCompile Include="unicode.cpp" />
|
||||
<ClCompile Include="unpack.cpp" />
|
||||
<ClCompile Include="volume.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="rar.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="dll.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
92
unrar/acknow.txt
Normal file
92
unrar/acknow.txt
Normal file
@@ -0,0 +1,92 @@
|
||||
ACKNOWLEDGMENTS
|
||||
|
||||
* We used "Screaming Fast Galois Field Arithmetic Using Intel
|
||||
SIMD Instructions" paper by James S. Plank, Kevin M. Greenan
|
||||
and Ethan L. Miller to improve Reed-Solomon coding performance.
|
||||
Also we are grateful to Artem Drobanov and Bulat Ziganshin
|
||||
for samples and ideas allowed to make Reed-Solomon coding
|
||||
more efficient.
|
||||
|
||||
* RAR text compression algorithm is based on Dmitry Shkarin PPMII
|
||||
and Dmitry Subbotin carryless rangecoder public domain source code.
|
||||
You may find it in ftp.elf.stuba.sk/pub/pc/pack.
|
||||
|
||||
* RAR encryption includes parts of code from Szymon Stefanek
|
||||
and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Source code of this package also as other cryptographic technology
|
||||
and computing project related links are available on Brian Gladman's
|
||||
web site: http://www.gladman.me.uk
|
||||
|
||||
* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
|
||||
Original Intel Slicing-by-8 code is available here:
|
||||
|
||||
http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
Original Intel Slicing-by-8 code is licensed under BSD License
|
||||
available at http://www.opensource.org/licenses/bsd-license.html
|
||||
|
||||
Copyright (c) 2004-2006 Intel Corporation.
|
||||
All Rights Reserved
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
* RAR archives may optionally include BLAKE2sp hash ( https://blake2.net ),
|
||||
designed by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn
|
||||
and Christian Winnerlein.
|
||||
|
||||
* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
|
||||
to significantly improve RAR compression and speed.
|
||||
220
unrar/arccmt.cpp
220
unrar/arccmt.cpp
@@ -1,66 +1,64 @@
|
||||
bool IsAnsiComment(const char *Data,int Size);
|
||||
static bool IsAnsiEscComment(const wchar *Data,size_t Size);
|
||||
|
||||
bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
bool Archive::GetComment(Array<wchar> *CmtData)
|
||||
{
|
||||
if (!MainComment)
|
||||
return(false);
|
||||
return false;
|
||||
SaveFilePos SavePos(*this);
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
ushort CmtLength;
|
||||
if (OldFormat)
|
||||
if (Format==RARFMT14)
|
||||
{
|
||||
Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET);
|
||||
Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
|
||||
CmtLength=GetByte();
|
||||
CmtLength+=(GetByte()<<8);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (NewMhd.Flags & MHD_COMMENT)
|
||||
if (MainHead.CommentInHeader)
|
||||
{
|
||||
// Old style (RAR 2.9) archive comment embedded into the main
|
||||
// archive header.
|
||||
Seek(SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD,SEEK_SET);
|
||||
Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
|
||||
ReadHeader();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current (RAR 3.0+) version of archive comment.
|
||||
Seek(SFXSize+SIZEOF_MARKHEAD+NewMhd.HeadSize,SEEK_SET);
|
||||
return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData,CmtDataW)!=0);
|
||||
Seek(GetStartPos(),SEEK_SET);
|
||||
return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
|
||||
}
|
||||
#ifndef SFX_MODULE
|
||||
// Old style (RAR 2.9) comment header embedded into the main
|
||||
// archive header.
|
||||
if (CommHead.HeadCRC!=HeaderCRC)
|
||||
if (BrokenHeader)
|
||||
{
|
||||
Log(FileName,St(MLogCommHead));
|
||||
Alarm();
|
||||
return(false);
|
||||
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||
return false;
|
||||
}
|
||||
CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
|
||||
#endif
|
||||
}
|
||||
#ifndef SFX_MODULE
|
||||
if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT) || !OldFormat && CommHead.Method!=0x30)
|
||||
if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
|
||||
{
|
||||
if (!OldFormat && (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER || CommHead.Method > 0x35))
|
||||
return(false);
|
||||
if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
|
||||
return false;
|
||||
ComprDataIO DataIO;
|
||||
Unpack Unpack(&DataIO);
|
||||
Unpack.Init();
|
||||
DataIO.SetTestMode(true);
|
||||
uint UnpCmtLength;
|
||||
if (OldFormat)
|
||||
if (Format==RARFMT14)
|
||||
{
|
||||
#ifdef NOCRYPT
|
||||
#ifdef RAR_NOCRYPT
|
||||
return(false);
|
||||
#else
|
||||
UnpCmtLength=GetByte();
|
||||
UnpCmtLength+=(GetByte()<<8);
|
||||
CmtLength-=2;
|
||||
DataIO.SetCmt13Encryption();
|
||||
CommHead.UnpVer=15;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -68,161 +66,99 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
DataIO.SetFiles(this,NULL);
|
||||
DataIO.EnableShowProgress(false);
|
||||
DataIO.SetPackedSizeToRead(CmtLength);
|
||||
Unpack.SetDestSize(UnpCmtLength);
|
||||
Unpack.DoUnpack(CommHead.UnpVer,false);
|
||||
DataIO.UnpHash.Init(HASH_CRC32,1);
|
||||
|
||||
if (!OldFormat && ((~DataIO.UnpFileCRC)&0xffff)!=CommHead.CommCRC)
|
||||
Unpack CmtUnpack(&DataIO);
|
||||
CmtUnpack.Init(0x10000,false);
|
||||
CmtUnpack.SetDestSize(UnpCmtLength);
|
||||
CmtUnpack.DoUnpack(CommHead.UnpVer,false);
|
||||
|
||||
if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
|
||||
{
|
||||
Log(FileName,St(MLogCommBrk));
|
||||
Alarm();
|
||||
return(false);
|
||||
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte *UnpData;
|
||||
size_t UnpDataSize;
|
||||
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
|
||||
CmtData->Alloc(UnpDataSize);
|
||||
memcpy(&((*CmtData)[0]),UnpData,UnpDataSize);
|
||||
#ifdef _WIN_ALL
|
||||
// If we ever decide to extend it to Android, we'll need to alloc
|
||||
// 4x memory for OEM to UTF-8 output here.
|
||||
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
|
||||
#endif
|
||||
CmtData->Alloc(UnpDataSize+1);
|
||||
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
|
||||
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
|
||||
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CmtData->Alloc(CmtLength);
|
||||
Array<byte> CmtRaw(CmtLength);
|
||||
Read(&CmtRaw[0],CmtLength);
|
||||
|
||||
Read(&((*CmtData)[0]),CmtLength);
|
||||
if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&((*CmtData)[0]),CmtLength)&0xffff))
|
||||
if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
|
||||
{
|
||||
Log(FileName,St(MLogCommBrk));
|
||||
Alarm();
|
||||
CmtData->Reset();
|
||||
return(false);
|
||||
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CmtData->Alloc(CmtLength+1);
|
||||
CmtRaw.Push(0);
|
||||
#ifdef _WIN_ALL
|
||||
// If we ever decide to extend it to Android, we'll need to alloc
|
||||
// 4x memory for OEM to UTF-8 output here.
|
||||
OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
|
||||
#endif
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
if (CmtData->Size()>0)
|
||||
{
|
||||
size_t CmtSize=CmtData->Size();
|
||||
char *DataA=(char *)CmtData->Addr();
|
||||
OemToCharBuffA(DataA,DataA,(DWORD)CmtSize);
|
||||
|
||||
if (CmtDataW!=NULL)
|
||||
{
|
||||
CmtDataW->Alloc(CmtSize+1);
|
||||
CmtData->Push(0);
|
||||
CharToWide(DataA,CmtDataW->Addr(),CmtSize+1);
|
||||
CmtData->Alloc(CmtSize);
|
||||
CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
|
||||
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtLength);
|
||||
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return(CmtData->Size()>0);
|
||||
return CmtData->Size() > 0;
|
||||
}
|
||||
|
||||
|
||||
size_t Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
bool Archive::ReadCommentData(Array<wchar> *CmtData)
|
||||
{
|
||||
bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
|
||||
if (!ReadSubData(CmtData,NULL))
|
||||
return(0);
|
||||
size_t CmtSize=CmtData->Size();
|
||||
if (Unicode)
|
||||
{
|
||||
CmtSize/=2;
|
||||
Array<wchar> DataW(CmtSize+1);
|
||||
RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
|
||||
DataW[CmtSize]=0;
|
||||
size_t DestSize=CmtSize*4;
|
||||
CmtData->Alloc(DestSize+1);
|
||||
WideToChar(DataW.Addr(),(char *)CmtData->Addr(),DestSize);
|
||||
(*CmtData)[DestSize]=0;
|
||||
CmtSize=strlen((char *)CmtData->Addr());
|
||||
CmtData->Alloc(CmtSize);
|
||||
if (CmtDataW!=NULL)
|
||||
{
|
||||
*CmtDataW=DataW;
|
||||
CmtDataW->Alloc(CmtSize);
|
||||
}
|
||||
}
|
||||
Array<byte> CmtRaw;
|
||||
if (!ReadSubData(&CmtRaw,NULL))
|
||||
return false;
|
||||
size_t CmtSize=CmtRaw.Size();
|
||||
CmtRaw.Push(0);
|
||||
CmtData->Alloc(CmtSize+1);
|
||||
if (Format==RARFMT50)
|
||||
UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
||||
else
|
||||
if (CmtDataW!=NULL)
|
||||
{
|
||||
CmtData->Push(0);
|
||||
CmtDataW->Alloc(CmtSize+1);
|
||||
CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
|
||||
CmtData->Alloc(CmtSize);
|
||||
CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
|
||||
if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
|
||||
{
|
||||
RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
|
||||
(*CmtData)[CmtSize/2]=0;
|
||||
|
||||
}
|
||||
return(CmtSize);
|
||||
else
|
||||
{
|
||||
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
||||
}
|
||||
CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Archive::ViewComment()
|
||||
{
|
||||
#ifndef GUI
|
||||
if (Cmd->DisableComment)
|
||||
return;
|
||||
Array<byte> CmtBuf;
|
||||
if (GetComment(&CmtBuf,NULL))
|
||||
Array<wchar> CmtBuf;
|
||||
if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
|
||||
{
|
||||
size_t CmtSize=CmtBuf.Size();
|
||||
char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize);
|
||||
wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
|
||||
if (ChPtr!=NULL)
|
||||
CmtSize=ChPtr-(char *)&CmtBuf[0];
|
||||
mprintf("\n");
|
||||
OutComment((char *)&CmtBuf[0],CmtSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
// Used for archives created by old RAR versions up to and including RAR 2.9.
|
||||
// New RAR versions store file comments in separate headers and such comments
|
||||
// are displayed in ListNewSubHeader function.
|
||||
void Archive::ViewFileComment()
|
||||
{
|
||||
if (!(NewLhd.Flags & LHD_COMMENT) || Cmd->DisableComment || OldFormat)
|
||||
return;
|
||||
#ifndef GUI
|
||||
mprintf(St(MFileComment));
|
||||
#endif
|
||||
const int MaxSize=0x8000;
|
||||
Array<char> CmtBuf(MaxSize);
|
||||
SaveFilePos SavePos(*this);
|
||||
Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
|
||||
int64 SaveCurBlockPos=CurBlockPos;
|
||||
int64 SaveNextBlockPos=NextBlockPos;
|
||||
|
||||
size_t Size=ReadHeader();
|
||||
|
||||
CurBlockPos=SaveCurBlockPos;
|
||||
NextBlockPos=SaveNextBlockPos;
|
||||
|
||||
if (Size<7 || CommHead.HeadType!=COMM_HEAD)
|
||||
return;
|
||||
if (CommHead.HeadCRC!=HeaderCRC)
|
||||
{
|
||||
#ifndef GUI
|
||||
Log(FileName,St(MLogCommHead));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER ||
|
||||
CommHead.Method > 0x30 || CommHead.UnpSize > MaxSize)
|
||||
return;
|
||||
Read(&CmtBuf[0],CommHead.UnpSize);
|
||||
if (CommHead.CommCRC!=((~CRC(0xffffffff,&CmtBuf[0],CommHead.UnpSize)&0xffff)))
|
||||
{
|
||||
Log(FileName,St(MLogBrokFCmt));
|
||||
}
|
||||
else
|
||||
{
|
||||
OutComment(&CmtBuf[0],CommHead.UnpSize);
|
||||
#ifndef GUI
|
||||
mprintf("\n");
|
||||
#endif
|
||||
CmtSize=ChPtr-&CmtBuf[0];
|
||||
mprintf(L"\n");
|
||||
OutComment(&CmtBuf[0],CmtSize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,48 +1,47 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifndef SHELL_EXT
|
||||
#include "arccmt.cpp"
|
||||
#endif
|
||||
|
||||
|
||||
Archive::Archive(RAROptions *InitCmd)
|
||||
{
|
||||
Cmd=InitCmd==NULL ? &DummyCmd:InitCmd;
|
||||
Cmd=NULL; // Just in case we'll have an exception in 'new' below.
|
||||
|
||||
DummyCmd=(InitCmd==NULL);
|
||||
Cmd=DummyCmd ? (new RAROptions):InitCmd;
|
||||
|
||||
OpenShared=Cmd->OpenShared;
|
||||
OldFormat=false;
|
||||
Format=RARFMT15;
|
||||
Solid=false;
|
||||
Volume=false;
|
||||
MainComment=false;
|
||||
Locked=false;
|
||||
Signed=false;
|
||||
NotFirstVolume=false;
|
||||
FirstVolume=false;
|
||||
NewNumbering=false;
|
||||
SFXSize=0;
|
||||
LatestTime.Reset();
|
||||
Protected=false;
|
||||
Encrypted=false;
|
||||
FailedHeaderDecryption=false;
|
||||
BrokenFileHeader=false;
|
||||
BrokenHeader=false;
|
||||
LastReadBlock=0;
|
||||
|
||||
CurBlockPos=0;
|
||||
NextBlockPos=0;
|
||||
|
||||
RecoveryPos=SIZEOF_MARKHEAD;
|
||||
RecoverySectors=-1;
|
||||
RecoverySize=-1;
|
||||
RecoveryPercent=-1;
|
||||
|
||||
memset(&NewMhd,0,sizeof(NewMhd));
|
||||
NewMhd.HeadType=MAIN_HEAD;
|
||||
NewMhd.HeadSize=SIZEOF_NEWMHD;
|
||||
HeaderCRC=0;
|
||||
memset(&MainHead,0,sizeof(MainHead));
|
||||
memset(&CryptHead,0,sizeof(CryptHead));
|
||||
memset(&EndArcHead,0,sizeof(EndArcHead));
|
||||
|
||||
VolNumber=0;
|
||||
VolWrite=0;
|
||||
AddingFilesSize=0;
|
||||
AddingHeadersSize=0;
|
||||
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
|
||||
*HeadersSalt=0;
|
||||
*SubDataSalt=0;
|
||||
#endif
|
||||
*FirstVolumeName=0;
|
||||
*FirstVolumeNameW=0;
|
||||
|
||||
Splitting=false;
|
||||
NewArchive=false;
|
||||
@@ -52,83 +51,98 @@ Archive::Archive(RAROptions *InitCmd)
|
||||
}
|
||||
|
||||
|
||||
#ifndef SHELL_EXT
|
||||
Archive::~Archive()
|
||||
{
|
||||
if (DummyCmd)
|
||||
delete Cmd;
|
||||
}
|
||||
|
||||
|
||||
void Archive::CheckArc(bool EnableBroken)
|
||||
{
|
||||
if (!IsArchive(EnableBroken))
|
||||
{
|
||||
Log(FileName,St(MBadArc),FileName);
|
||||
ErrHandler.Exit(FATAL_ERROR);
|
||||
// If FailedHeaderDecryption is set, we already reported that archive
|
||||
// password is incorrect.
|
||||
if (!FailedHeaderDecryption)
|
||||
uiMsg(UIERROR_BADARCHIVE,FileName);
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
|
||||
void Archive::CheckOpen(const char *Name,const wchar *NameW)
|
||||
#if !defined(SFX_MODULE)
|
||||
void Archive::CheckOpen(const wchar *Name)
|
||||
{
|
||||
TOpen(Name,NameW);
|
||||
TOpen(Name);
|
||||
CheckArc(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool Archive::WCheckOpen(const char *Name,const wchar *NameW)
|
||||
bool Archive::WCheckOpen(const wchar *Name)
|
||||
{
|
||||
if (!WOpen(Name,NameW))
|
||||
return(false);
|
||||
if (!WOpen(Name))
|
||||
return false;
|
||||
if (!IsArchive(false))
|
||||
{
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MNotRAR),FileName);
|
||||
#endif
|
||||
uiMsg(UIERROR_BADARCHIVE,FileName);
|
||||
Close();
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
return(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Archive::IsSignature(byte *D)
|
||||
RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
|
||||
{
|
||||
bool Valid=false;
|
||||
if (D[0]==0x52)
|
||||
RARFORMAT Type=RARFMT_NONE;
|
||||
if (Size>=1 && D[0]==0x52)
|
||||
#ifndef SFX_MODULE
|
||||
if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
|
||||
{
|
||||
OldFormat=true;
|
||||
Valid=true;
|
||||
}
|
||||
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
|
||||
Type=RARFMT14;
|
||||
else
|
||||
#endif
|
||||
if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00)
|
||||
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
|
||||
{
|
||||
OldFormat=false;
|
||||
Valid=true;
|
||||
// We check the last signature byte, so we can return a sensible
|
||||
// warning in case we'll want to change the archive format
|
||||
// sometimes in the future.
|
||||
if (D[6]==0)
|
||||
Type=RARFMT15;
|
||||
else
|
||||
if (D[6]==1)
|
||||
Type=RARFMT50;
|
||||
else
|
||||
if (D[6]==2)
|
||||
Type=RARFMT_FUTURE;
|
||||
}
|
||||
return(Valid);
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
bool Archive::IsArchive(bool EnableBroken)
|
||||
{
|
||||
Encrypted=false;
|
||||
BrokenHeader=false; // Might be left from previous volume.
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
if (IsDevice())
|
||||
{
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MInvalidName),FileName);
|
||||
#endif
|
||||
return(false);
|
||||
uiMsg(UIERROR_INVALIDNAME,FileName,FileName);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
|
||||
return(false);
|
||||
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
|
||||
return false;
|
||||
SFXSize=0;
|
||||
if (IsSignature(MarkHead.Mark))
|
||||
|
||||
RARFORMAT Type;
|
||||
if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
|
||||
{
|
||||
if (OldFormat)
|
||||
Seek(0,SEEK_SET);
|
||||
Format=Type;
|
||||
if (Format==RARFMT14)
|
||||
Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -136,9 +150,10 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
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]))
|
||||
if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE)
|
||||
{
|
||||
if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
|
||||
Format=Type;
|
||||
if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31)
|
||||
{
|
||||
char *D=&Buffer[28-CurPos];
|
||||
if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
|
||||
@@ -146,55 +161,28 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
}
|
||||
SFXSize=CurPos+I;
|
||||
Seek(SFXSize,SEEK_SET);
|
||||
if (!OldFormat)
|
||||
Read(MarkHead.Mark,SIZEOF_MARKHEAD);
|
||||
if (Format==RARFMT15 || Format==RARFMT50)
|
||||
Read(MarkHead.Mark,SIZEOF_MARKHEAD3);
|
||||
break;
|
||||
}
|
||||
if (SFXSize==0)
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
ReadHeader();
|
||||
SeekToNext();
|
||||
#ifndef SFX_MODULE
|
||||
if (OldFormat)
|
||||
if (Format==RARFMT_FUTURE)
|
||||
{
|
||||
NewMhd.Flags=OldMhd.Flags & 0x3f;
|
||||
NewMhd.HeadSize=OldMhd.HeadSize;
|
||||
uiMsg(UIERROR_NEWRARFORMAT,FileName);
|
||||
return false;
|
||||
}
|
||||
if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
|
||||
{
|
||||
Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
|
||||
if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
|
||||
return false;
|
||||
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (HeaderCRC!=NewMhd.HeadCRC)
|
||||
{
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MLogMainHead));
|
||||
#endif
|
||||
Alarm();
|
||||
if (!EnableBroken)
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
Volume=(NewMhd.Flags & MHD_VOLUME);
|
||||
Solid=(NewMhd.Flags & MHD_SOLID)!=0;
|
||||
MainComment=(NewMhd.Flags & MHD_COMMENT)!=0;
|
||||
Locked=(NewMhd.Flags & MHD_LOCK)!=0;
|
||||
Signed=(NewMhd.PosAV!=0);
|
||||
Protected=(NewMhd.Flags & MHD_PROTECT)!=0;
|
||||
Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
|
||||
MarkHead.HeadSize=SIZEOF_MARKHEAD3;
|
||||
|
||||
if (NewMhd.EncryptVer>UNP_VER)
|
||||
{
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
#else
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
Log(FileName,St(MUnknownMeth),FileName);
|
||||
Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
|
||||
#endif
|
||||
#endif
|
||||
return(false);
|
||||
}
|
||||
#ifdef RARDLL
|
||||
// If callback function is not set, we cannot get the password,
|
||||
// so we skip the initial header processing for encrypted header archive.
|
||||
@@ -204,45 +192,76 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
SilentOpen=true;
|
||||
#endif
|
||||
|
||||
// If not encrypted, we'll check it below.
|
||||
NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0;
|
||||
// Skip the archive encryption header if any and read the main header.
|
||||
while (ReadHeader()!=0)
|
||||
{
|
||||
HEADER_TYPE Type=GetHeaderType();
|
||||
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
|
||||
// avoid the password prompt.
|
||||
if (Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT)
|
||||
break;
|
||||
SeekToNext();
|
||||
}
|
||||
|
||||
// This check allows to make RS based recovery even if password is incorrect.
|
||||
// But we should not do it for EnableBroken or we'll get 'not RAR archive'
|
||||
// messages when extracting encrypted archives with wrong password.
|
||||
if (FailedHeaderDecryption && !EnableBroken)
|
||||
return false;
|
||||
|
||||
SeekToNext();
|
||||
if (BrokenHeader) // Main archive header is corrupt.
|
||||
{
|
||||
uiMsg(UIERROR_MHEADERBROKEN,FileName);
|
||||
if (!EnableBroken)
|
||||
return false;
|
||||
}
|
||||
|
||||
MainComment=MainHead.CommentInHeader;
|
||||
|
||||
// If we process non-encrypted archive or can request a password,
|
||||
// we set 'first volume' flag based on file attributes below.
|
||||
// It is necessary for RAR 2.x archives, which did not have 'first volume'
|
||||
// flag in main header. Also for all RAR formats we need to scan until
|
||||
// first file header to set "comment" flag when reading service header.
|
||||
// Unless we are in silent mode, we need to know about presence of comment
|
||||
// immediately after IsArchive call.
|
||||
if (!SilentOpen || !Encrypted)
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
||||
|
||||
NotFirstVolume=false;
|
||||
while (ReadHeader()!=0)
|
||||
{
|
||||
int HeaderType=GetHeaderType();
|
||||
if (HeaderType==NEWSUB_HEAD)
|
||||
HEADER_TYPE HeaderType=GetHeaderType();
|
||||
if (HeaderType==HEAD_SERVICE)
|
||||
{
|
||||
if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
|
||||
MainComment=true;
|
||||
if ((SubHead.Flags & LHD_SPLIT_BEFORE) ||
|
||||
Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)
|
||||
NotFirstVolume=true;
|
||||
// If we have a split service headers, it surely indicates non-first
|
||||
// volume. But not split service header does not guarantee the first
|
||||
// volume, because we can have split file after non-split archive
|
||||
// comment. So we do not quit from loop here.
|
||||
FirstVolume=Volume && !SubHead.SplitBefore;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 ||
|
||||
Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
|
||||
NotFirstVolume=true;
|
||||
break;
|
||||
}
|
||||
if (HeaderType==HEAD_FILE)
|
||||
{
|
||||
FirstVolume=Volume && !FileHead.SplitBefore;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (HeaderType==HEAD_ENDARC) // Might happen if archive contains only a split service header.
|
||||
break;
|
||||
SeekToNext();
|
||||
}
|
||||
CurBlockPos=SaveCurBlockPos;
|
||||
NextBlockPos=SaveNextBlockPos;
|
||||
CurHeaderType=SaveCurHeaderType;
|
||||
}
|
||||
if (!Volume || !NotFirstVolume)
|
||||
{
|
||||
strcpy(FirstVolumeName,FileName);
|
||||
wcscpy(FirstVolumeNameW,FileNameW);
|
||||
}
|
||||
if (!Volume || FirstVolume)
|
||||
wcscpy(FirstVolumeName,FileName);
|
||||
|
||||
return(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -254,20 +273,60 @@ void Archive::SeekToNext()
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int Archive::GetRecoverySize(bool Required)
|
||||
|
||||
|
||||
|
||||
|
||||
// Calculate the block size including encryption fields and padding if any.
|
||||
uint Archive::FullHeaderSize(size_t Size)
|
||||
{
|
||||
if (!Protected)
|
||||
return(0);
|
||||
if (RecoverySectors!=-1 || !Required)
|
||||
return(RecoverySectors);
|
||||
SaveFilePos SavePos(*this);
|
||||
Seek(SFXSize,SEEK_SET);
|
||||
SearchSubBlock(SUBHEAD_TYPE_RR);
|
||||
return(RecoverySectors);
|
||||
if (Encrypted)
|
||||
{
|
||||
Size = ALIGN_VALUE(Size, CRYPT_BLOCK_SIZE); // Align to encryption block size.
|
||||
if (Format == RARFMT50)
|
||||
Size += SIZE_INITV;
|
||||
else
|
||||
Size += SIZE_SALT30;
|
||||
}
|
||||
return uint(Size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef USE_QOPEN
|
||||
bool Archive::Open(const wchar *Name,uint Mode)
|
||||
{
|
||||
// Important if we reuse Archive object and it has virtual QOpen
|
||||
// file position not matching real. For example, for 'l -v volname'.
|
||||
QOpen.Unload();
|
||||
|
||||
return File::Open(Name,Mode);
|
||||
}
|
||||
|
||||
|
||||
int Archive::Read(void *Data,size_t Size)
|
||||
{
|
||||
size_t Result;
|
||||
if (QOpen.Read(Data,Size,Result))
|
||||
return (int)Result;
|
||||
return File::Read(Data,Size);
|
||||
}
|
||||
|
||||
|
||||
void Archive::Seek(int64 Offset,int Method)
|
||||
{
|
||||
if (!QOpen.Seek(Offset,Method))
|
||||
File::Seek(Offset,Method);
|
||||
}
|
||||
|
||||
|
||||
int64 Archive::Tell()
|
||||
{
|
||||
int64 QPos;
|
||||
if (QOpen.Tell(&QPos))
|
||||
return QPos;
|
||||
return File::Tell();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,79 +1,107 @@
|
||||
#ifndef _RAR_ARCHIVE_
|
||||
#define _RAR_ARCHIVE_
|
||||
|
||||
class Pack;
|
||||
class PPack;
|
||||
class RawRead;
|
||||
class RawWrite;
|
||||
|
||||
enum {EN_LOCK=1,EN_VOL=2,EN_FIRSTVOL=4};
|
||||
enum NOMODIFY_FLAGS
|
||||
{
|
||||
NMDF_ALLOWLOCK=1,NMDF_ALLOWANYVOLUME=2,NMDF_ALLOWFIRSTVOLUME=4
|
||||
};
|
||||
|
||||
enum RARFORMAT {RARFMT_NONE,RARFMT14,RARFMT15,RARFMT50,RARFMT_FUTURE};
|
||||
|
||||
enum ADDSUBDATA_FLAGS
|
||||
{
|
||||
ASDF_SPLIT = 1, // Allow to split archive just before header if necessary.
|
||||
ASDF_COMPRESS = 2, // Allow to compress data following subheader.
|
||||
ASDF_CRYPT = 4, // Encrypt data after subheader if password is set.
|
||||
ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode.
|
||||
};
|
||||
|
||||
class Archive:public File
|
||||
{
|
||||
private:
|
||||
bool IsSignature(byte *D);
|
||||
void UpdateLatestTime(FileHeader *CurBlock);
|
||||
void ConvertNameCase(char *Name);
|
||||
void ConvertNameCase(wchar *Name);
|
||||
void ConvertUnknownHeader();
|
||||
size_t ReadOldHeader();
|
||||
void ConvertFileHeader(FileHeader *hd);
|
||||
void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
|
||||
size_t ReadHeader14();
|
||||
size_t ReadHeader15();
|
||||
size_t ReadHeader50();
|
||||
void ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb);
|
||||
void RequestArcPassword();
|
||||
void UnexpEndArcMsg();
|
||||
void BrokenHeaderMsg();
|
||||
void UnkEncVerMsg(const wchar *Name);
|
||||
void UnkEncVerMsg();
|
||||
bool ReadCommentData(Array<wchar> *CmtData);
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
|
||||
#if !defined(RAR_NOCRYPT)
|
||||
CryptData HeadersCrypt;
|
||||
byte HeadersSalt[SALT_SIZE];
|
||||
#endif
|
||||
#ifndef SHELL_EXT
|
||||
ComprDataIO SubDataIO;
|
||||
byte SubDataSalt[SALT_SIZE];
|
||||
#endif
|
||||
RAROptions *Cmd,DummyCmd;
|
||||
bool DummyCmd;
|
||||
RAROptions *Cmd;
|
||||
|
||||
MarkHeader MarkHead;
|
||||
OldMainHeader OldMhd;
|
||||
|
||||
int RecoverySectors;
|
||||
int64 RecoveryPos;
|
||||
|
||||
bool FailedHeaderDecryption;
|
||||
int64 RecoverySize;
|
||||
int RecoveryPercent;
|
||||
|
||||
RarTime LatestTime;
|
||||
int LastReadBlock;
|
||||
int CurHeaderType;
|
||||
HEADER_TYPE CurHeaderType;
|
||||
|
||||
bool SilentOpen;
|
||||
#ifdef USE_QOPEN
|
||||
QuickOpen QOpen;
|
||||
#endif
|
||||
public:
|
||||
Archive(RAROptions *InitCmd=NULL);
|
||||
~Archive();
|
||||
static RARFORMAT IsSignature(const byte *D,size_t Size);
|
||||
bool IsArchive(bool EnableBroken);
|
||||
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();
|
||||
size_t SearchBlock(HEADER_TYPE HeaderType);
|
||||
size_t SearchSubBlock(const wchar *Type);
|
||||
size_t SearchRR();
|
||||
void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false);
|
||||
void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);}
|
||||
size_t ReadHeader();
|
||||
void CheckArc(bool EnableBroken);
|
||||
void CheckOpen(const char *Name,const wchar *NameW=NULL);
|
||||
bool WCheckOpen(const char *Name,const wchar *NameW=NULL);
|
||||
bool GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW);
|
||||
void CheckOpen(const wchar *Name);
|
||||
bool WCheckOpen(const wchar *Name);
|
||||
bool GetComment(Array<wchar> *CmtData);
|
||||
void ViewComment();
|
||||
void ViewFileComment();
|
||||
void SetLatestTime(RarTime *NewTime);
|
||||
void SeekToNext();
|
||||
bool CheckAccess();
|
||||
bool IsArcDir();
|
||||
bool IsArcLabel();
|
||||
void ConvertAttributes();
|
||||
int GetRecoverySize(bool Required);
|
||||
void VolSubtractHeaderSize(size_t SubSize);
|
||||
void AddSubData(byte *SrcData,size_t DataSize,File *SrcFile,const char *Name,bool AllowSplit);
|
||||
uint FullHeaderSize(size_t Size);
|
||||
int64 GetStartPos();
|
||||
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
|
||||
const wchar *Name,uint Flags);
|
||||
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
|
||||
int GetHeaderType() {return(CurHeaderType);};
|
||||
size_t ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW);
|
||||
void WriteCommentData(byte *Data,size_t DataSize,bool FileComment);
|
||||
RAROptions* GetRAROptions() {return(Cmd);}
|
||||
HEADER_TYPE GetHeaderType() {return CurHeaderType;};
|
||||
RAROptions* GetRAROptions() {return Cmd;}
|
||||
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
|
||||
#if 0
|
||||
void GetRecoveryInfo(bool Required,int64 *Size,int *Percent);
|
||||
#endif
|
||||
#ifdef USE_QOPEN
|
||||
bool Open(const wchar *Name,uint Mode=FMF_READ);
|
||||
int Read(void *Data,size_t Size);
|
||||
void Seek(int64 Offset,int Method);
|
||||
int64 Tell();
|
||||
void QOpenUnload() {QOpen.Unload();}
|
||||
#endif
|
||||
|
||||
BaseBlock ShortBlock;
|
||||
MainHeader NewMhd;
|
||||
FileHeader NewLhd;
|
||||
MarkHeader MarkHead;
|
||||
MainHeader MainHead;
|
||||
CryptHeader CryptHead;
|
||||
FileHeader FileHead;
|
||||
EndArcHeader EndArcHead;
|
||||
SubBlockHeader SubBlockHead;
|
||||
FileHeader SubHead;
|
||||
@@ -89,30 +117,34 @@ class Archive:public File
|
||||
int64 CurBlockPos;
|
||||
int64 NextBlockPos;
|
||||
|
||||
bool OldFormat;
|
||||
RARFORMAT Format;
|
||||
bool Solid;
|
||||
bool Volume;
|
||||
bool MainComment;
|
||||
bool Locked;
|
||||
bool Signed;
|
||||
bool NotFirstVolume;
|
||||
bool FirstVolume;
|
||||
bool NewNumbering;
|
||||
bool Protected;
|
||||
bool Encrypted;
|
||||
size_t SFXSize;
|
||||
bool BrokenFileHeader;
|
||||
bool BrokenHeader;
|
||||
bool FailedHeaderDecryption;
|
||||
|
||||
#if !defined(RAR_NOCRYPT)
|
||||
byte ArcSalt[SIZE_SALT50];
|
||||
#endif
|
||||
|
||||
bool Splitting;
|
||||
|
||||
ushort HeaderCRC;
|
||||
|
||||
uint VolNumber;
|
||||
int64 VolWrite;
|
||||
int64 AddingFilesSize;
|
||||
size_t AddingHeadersSize;
|
||||
uint64 AddingFilesSize;
|
||||
uint64 AddingHeadersSize;
|
||||
|
||||
bool NewArchive;
|
||||
|
||||
char FirstVolumeName[NM];
|
||||
wchar FirstVolumeNameW[NM];
|
||||
wchar FirstVolumeName[NM];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
1596
unrar/arcread.cpp
1596
unrar/arcread.cpp
File diff suppressed because it is too large
Load Diff
@@ -9,26 +9,39 @@ template <class T> class Array
|
||||
T *Buffer;
|
||||
size_t BufSize;
|
||||
size_t AllocSize;
|
||||
size_t MaxSize;
|
||||
bool Secure; // Clean memory if true.
|
||||
public:
|
||||
Array();
|
||||
Array(size_t Size);
|
||||
Array(const Array &Src); // Copy constructor.
|
||||
~Array();
|
||||
inline void CleanData();
|
||||
inline T& operator [](size_t Item);
|
||||
inline T& operator [](size_t Item) const;
|
||||
inline T* operator + (size_t Pos);
|
||||
inline size_t Size(); // Returns the size in items, not in bytes.
|
||||
void Add(size_t Items);
|
||||
void Alloc(size_t Items);
|
||||
void Reset();
|
||||
void SoftReset();
|
||||
void operator = (Array<T> &Src);
|
||||
void Push(T Item);
|
||||
T* Addr() {return(Buffer);}
|
||||
void Append(T *Item,size_t Count);
|
||||
T* Addr(size_t Item) {return Buffer+Item;}
|
||||
void SetMaxSize(size_t Size) {MaxSize=Size;}
|
||||
T* Begin() {return Buffer;}
|
||||
T* End() {return Buffer==NULL ? NULL:Buffer+BufSize;}
|
||||
void SetSecure() {Secure=true;}
|
||||
};
|
||||
|
||||
|
||||
template <class T> void Array<T>::CleanData()
|
||||
{
|
||||
Buffer=NULL;
|
||||
BufSize=0;
|
||||
AllocSize=0;
|
||||
MaxSize=0;
|
||||
Secure=false;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,30 +53,47 @@ template <class T> Array<T>::Array()
|
||||
|
||||
template <class T> Array<T>::Array(size_t Size)
|
||||
{
|
||||
Buffer=(T *)malloc(sizeof(T)*Size);
|
||||
if (Buffer==NULL && Size!=0)
|
||||
ErrHandler.MemoryError();
|
||||
CleanData();
|
||||
Add(Size);
|
||||
}
|
||||
|
||||
AllocSize=BufSize=Size;
|
||||
|
||||
// Copy constructor in case we need to pass an object as value.
|
||||
template <class T> Array<T>::Array(const Array &Src)
|
||||
{
|
||||
CleanData();
|
||||
Alloc(Src.BufSize);
|
||||
if (Src.BufSize!=0)
|
||||
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
template <class T> Array<T>::~Array()
|
||||
{
|
||||
if (Buffer!=NULL)
|
||||
{
|
||||
if (Secure)
|
||||
cleandata(Buffer,AllocSize*sizeof(T));
|
||||
free(Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class T> inline T& Array<T>::operator [](size_t Item)
|
||||
template <class T> inline T& Array<T>::operator [](size_t Item) const
|
||||
{
|
||||
return(Buffer[Item]);
|
||||
return Buffer[Item];
|
||||
}
|
||||
|
||||
|
||||
template <class T> inline T* Array<T>::operator +(size_t Pos)
|
||||
{
|
||||
return Buffer+Pos;
|
||||
}
|
||||
|
||||
|
||||
template <class T> inline size_t Array<T>::Size()
|
||||
{
|
||||
return(BufSize);
|
||||
return BufSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,12 +102,35 @@ template <class T> void Array<T>::Add(size_t Items)
|
||||
BufSize+=Items;
|
||||
if (BufSize>AllocSize)
|
||||
{
|
||||
if (MaxSize!=0 && BufSize>MaxSize)
|
||||
{
|
||||
ErrHandler.GeneralErrMsg(L"Maximum allowed array size (%u) is exceeded",MaxSize);
|
||||
ErrHandler.MemoryError();
|
||||
}
|
||||
|
||||
size_t Suggested=AllocSize+AllocSize/4+32;
|
||||
size_t NewSize=Max(BufSize,Suggested);
|
||||
|
||||
Buffer=(T *)realloc(Buffer,NewSize*sizeof(T));
|
||||
if (Buffer==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
T *NewBuffer;
|
||||
if (Secure)
|
||||
{
|
||||
NewBuffer=(T *)malloc(NewSize*sizeof(T));
|
||||
if (NewBuffer==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
if (Buffer!=NULL)
|
||||
{
|
||||
memcpy(NewBuffer,Buffer,AllocSize*sizeof(T));
|
||||
cleandata(Buffer,AllocSize*sizeof(T));
|
||||
free(Buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T));
|
||||
if (NewBuffer==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
}
|
||||
Buffer=NewBuffer;
|
||||
AllocSize=NewSize;
|
||||
}
|
||||
}
|
||||
@@ -104,6 +157,14 @@ template <class T> void Array<T>::Reset()
|
||||
}
|
||||
|
||||
|
||||
// Reset buffer size, but preserve already allocated memory if any,
|
||||
// so we can reuse it without wasting time to allocation.
|
||||
template <class T> void Array<T>::SoftReset()
|
||||
{
|
||||
BufSize=0;
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::operator =(Array<T> &Src)
|
||||
{
|
||||
Reset();
|
||||
@@ -119,4 +180,12 @@ template <class T> void Array<T>::Push(T Item)
|
||||
(*this)[Size()-1]=Item;
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::Append(T *Items,size_t Count)
|
||||
{
|
||||
size_t CurSize=Size();
|
||||
Add(Count);
|
||||
memcpy(Buffer+CurSize,Items,Count*sizeof(T));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
113
unrar/beosea.cpp
113
unrar/beosea.cpp
@@ -1,113 +0,0 @@
|
||||
|
||||
|
||||
void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
{
|
||||
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return;
|
||||
}
|
||||
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
|
||||
{
|
||||
Log(Arc.FileName,St(MEAUnknHeader),FileName);
|
||||
return;
|
||||
}
|
||||
|
||||
ComprDataIO DataIO;
|
||||
Unpack Unpack(&DataIO);
|
||||
Unpack.Init();
|
||||
|
||||
Array<byte> UnpData(Arc.EAHead.UnpSize);
|
||||
DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
|
||||
DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
|
||||
DataIO.EnableShowProgress(false);
|
||||
DataIO.SetFiles(&Arc,NULL);
|
||||
Unpack.SetDestSize(Arc.EAHead.UnpSize);
|
||||
Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
|
||||
|
||||
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
return;
|
||||
}
|
||||
int fd = open(FileName,O_WRONLY);
|
||||
if (fd==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
int AttrPos=0;
|
||||
while (AttrPos<Arc.EAHead.UnpSize)
|
||||
{
|
||||
unsigned char *CurItem=&UnpData[AttrPos];
|
||||
int NameSize=CurItem[0]+((int)CurItem[1]<<8);
|
||||
int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
|
||||
int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
|
||||
char Name[1024];
|
||||
if (NameSize>=sizeof(Name))
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
memcpy(Name,CurItem+10,NameSize);
|
||||
Name[NameSize]=0;
|
||||
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
AttrPos+=10+NameSize+Size;
|
||||
}
|
||||
close(fd);
|
||||
mprintf(St(MShowEA));
|
||||
}
|
||||
|
||||
|
||||
void ExtractBeEANew(Archive &Arc,char *FileName)
|
||||
{
|
||||
Array<byte> SubData;
|
||||
if (!Arc.ReadSubData(&SubData,NULL))
|
||||
return;
|
||||
|
||||
int fd = open(FileName,O_WRONLY);
|
||||
if (fd==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
int AttrPos=0;
|
||||
while (AttrPos<Arc.EAHead.UnpSize)
|
||||
{
|
||||
unsigned char *CurItem=&SubData[AttrPos];
|
||||
int NameSize=CurItem[0]+((int)CurItem[1]<<8);
|
||||
int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
|
||||
int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
|
||||
char Name[1024];
|
||||
if (NameSize>=sizeof(Name))
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
memcpy(Name,CurItem+10,NameSize);
|
||||
Name[NameSize]=0;
|
||||
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
break;
|
||||
}
|
||||
AttrPos+=10+NameSize+Size;
|
||||
}
|
||||
close(fd);
|
||||
mprintf(St(MShowEA));
|
||||
}
|
||||
|
||||
183
unrar/blake2s.cpp
Normal file
183
unrar/blake2s.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
// Based on public domain code written in 2012 by Samuel Neves
|
||||
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifdef USE_SSE
|
||||
#include "blake2s_sse.cpp"
|
||||
#endif
|
||||
|
||||
static void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth);
|
||||
static void blake2s_update( blake2s_state *S, const byte *in, size_t inlen );
|
||||
static void blake2s_final( blake2s_state *S, byte *digest );
|
||||
|
||||
#include "blake2sp.cpp"
|
||||
|
||||
static const uint32 blake2s_IV[8] =
|
||||
{
|
||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||
};
|
||||
|
||||
static const byte blake2s_sigma[10][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
};
|
||||
|
||||
static inline void blake2s_set_lastnode( blake2s_state *S )
|
||||
{
|
||||
S->f[1] = ~0U;
|
||||
}
|
||||
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static inline void blake2s_set_lastblock( blake2s_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2s_set_lastnode( S );
|
||||
|
||||
S->f[0] = ~0U;
|
||||
}
|
||||
|
||||
|
||||
static inline void blake2s_increment_counter( blake2s_state *S, const uint32 inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
}
|
||||
|
||||
|
||||
/* init2 xors IV with input parameter block */
|
||||
void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth)
|
||||
{
|
||||
#ifdef USE_SSE
|
||||
if (_SSE_Version>=SSE_SSE2)
|
||||
blake2s_init_sse();
|
||||
#endif
|
||||
|
||||
S->init(); // Clean data.
|
||||
for( int i = 0; i < 8; ++i )
|
||||
S->h[i] = blake2s_IV[i];
|
||||
|
||||
S->h[0] ^= 0x02080020; // We use BLAKE2sp parameters block.
|
||||
S->h[2] ^= node_offset;
|
||||
S->h[3] ^= (node_depth<<16)|0x20000000;
|
||||
}
|
||||
|
||||
|
||||
#define G(r,i,m,a,b,c,d) \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
|
||||
d = rotr32(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 12); \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
|
||||
d = rotr32(d ^ a, 8); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 7);
|
||||
|
||||
|
||||
static void blake2s_compress( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
|
||||
{
|
||||
uint32 m[16];
|
||||
uint32 v[16];
|
||||
|
||||
for( size_t i = 0; i < 16; ++i )
|
||||
m[i] = RawGet4( block + i * 4 );
|
||||
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
v[i] = S->h[i];
|
||||
|
||||
v[ 8] = blake2s_IV[0];
|
||||
v[ 9] = blake2s_IV[1];
|
||||
v[10] = blake2s_IV[2];
|
||||
v[11] = blake2s_IV[3];
|
||||
v[12] = S->t[0] ^ blake2s_IV[4];
|
||||
v[13] = S->t[1] ^ blake2s_IV[5];
|
||||
v[14] = S->f[0] ^ blake2s_IV[6];
|
||||
v[15] = S->f[1] ^ blake2s_IV[7];
|
||||
|
||||
for ( uint r = 0; r <= 9; ++r ) // No gain on i7 if unrolled, but exe size grows.
|
||||
{
|
||||
G(r,0,m,v[ 0],v[ 4],v[ 8],v[12]);
|
||||
G(r,1,m,v[ 1],v[ 5],v[ 9],v[13]);
|
||||
G(r,2,m,v[ 2],v[ 6],v[10],v[14]);
|
||||
G(r,3,m,v[ 3],v[ 7],v[11],v[15]);
|
||||
G(r,4,m,v[ 0],v[ 5],v[10],v[15]);
|
||||
G(r,5,m,v[ 1],v[ 6],v[11],v[12]);
|
||||
G(r,6,m,v[ 2],v[ 7],v[ 8],v[13]);
|
||||
G(r,7,m,v[ 3],v[ 4],v[ 9],v[14]);
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
|
||||
|
||||
void blake2s_update( blake2s_state *S, const byte *in, size_t inlen )
|
||||
{
|
||||
while( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
|
||||
|
||||
if( inlen > fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill ); // Fill buffer
|
||||
S->buflen += fill;
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
#ifdef USE_SSE
|
||||
#ifdef _WIN_32 // We use SSSE3 _mm_shuffle_epi8 only in x64 mode.
|
||||
if (_SSE_Version>=SSE_SSE2)
|
||||
#else
|
||||
if (_SSE_Version>=SSE_SSSE3)
|
||||
#endif
|
||||
blake2s_compress_sse( S, S->buf );
|
||||
else
|
||||
blake2s_compress( S, S->buf ); // Compress
|
||||
#else
|
||||
blake2s_compress( S, S->buf ); // Compress
|
||||
#endif
|
||||
|
||||
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
|
||||
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
}
|
||||
else // inlen <= fill
|
||||
{
|
||||
memcpy( S->buf + left, in, (size_t)inlen );
|
||||
S->buflen += (size_t)inlen; // Be lazy, do not compress
|
||||
in += inlen;
|
||||
inlen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void blake2s_final( blake2s_state *S, byte *digest )
|
||||
{
|
||||
if( S->buflen > BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
blake2s_compress( S, S->buf );
|
||||
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
|
||||
}
|
||||
|
||||
blake2s_increment_counter( S, ( uint32 )S->buflen );
|
||||
blake2s_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2s_compress( S, S->buf );
|
||||
|
||||
for( int i = 0; i < 8; ++i ) /* Output full hash */
|
||||
RawPut4( S->h[i], digest + 4 * i );
|
||||
}
|
||||
|
||||
101
unrar/blake2s.hpp
Normal file
101
unrar/blake2s.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Based on public domain code written in 2012 by Samuel Neves
|
||||
#ifndef _RAR_BLAKE2_
|
||||
#define _RAR_BLAKE2_
|
||||
|
||||
#define BLAKE2_DIGEST_SIZE 32
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32
|
||||
};
|
||||
|
||||
|
||||
// Alignment to 64 improves performance of both SSE and non-SSE versions.
|
||||
// Alignment to n*16 is required for SSE version, so we selected 64.
|
||||
// We use the custom alignment scheme instead of __declspec(align(x)),
|
||||
// because it is less compiler dependent. Also the compiler directive
|
||||
// does not help if structure is a member of class allocated through
|
||||
// 'new' operator.
|
||||
struct blake2s_state
|
||||
{
|
||||
enum { BLAKE_ALIGNMENT = 64 };
|
||||
|
||||
// buffer and uint32 h[8], t[2], f[2];
|
||||
enum { BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES };
|
||||
|
||||
byte ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT];
|
||||
|
||||
byte *buf; // byte buf[2 * BLAKE2S_BLOCKBYTES].
|
||||
uint32 *h, *t, *f; // uint32 h[8], t[2], f[2].
|
||||
|
||||
size_t buflen;
|
||||
byte last_node;
|
||||
|
||||
blake2s_state()
|
||||
{
|
||||
set_pointers();
|
||||
}
|
||||
|
||||
// Required when we declare and assign in the same command.
|
||||
blake2s_state(blake2s_state &st)
|
||||
{
|
||||
set_pointers();
|
||||
*this=st;
|
||||
}
|
||||
|
||||
void set_pointers()
|
||||
{
|
||||
// Set aligned pointers. Must be done in constructor, not in Init(),
|
||||
// so assignments like 'blake2sp_state res=blake2ctx' work correctly
|
||||
// even if blake2sp_init is not called for 'res'.
|
||||
buf = (byte *) ALIGN_VALUE(ubuf, BLAKE_ALIGNMENT);
|
||||
h = (uint32 *) (buf + 2 * BLAKE2S_BLOCKBYTES);
|
||||
t = h + 8;
|
||||
f = t + 2;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
memset( ubuf, 0, sizeof( ubuf ) );
|
||||
buflen = 0;
|
||||
last_node = 0;
|
||||
}
|
||||
|
||||
// Since we use pointers, the default = would work incorrectly.
|
||||
blake2s_state& operator = (blake2s_state &st)
|
||||
{
|
||||
if (this != &st)
|
||||
{
|
||||
memcpy(buf, st.buf, BLAKE_DATA_SIZE);
|
||||
buflen = st.buflen;
|
||||
last_node = st.last_node;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef RAR_SMP
|
||||
class ThreadPool;
|
||||
#endif
|
||||
|
||||
struct blake2sp_state
|
||||
{
|
||||
blake2s_state S[8];
|
||||
blake2s_state R;
|
||||
byte buf[8 * BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
|
||||
#ifdef RAR_SMP
|
||||
ThreadPool *ThPool;
|
||||
uint MaxThreads;
|
||||
#endif
|
||||
};
|
||||
|
||||
void blake2sp_init( blake2sp_state *S );
|
||||
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen );
|
||||
void blake2sp_final( blake2sp_state *S, byte *digest );
|
||||
|
||||
#endif
|
||||
|
||||
129
unrar/blake2s_sse.cpp
Normal file
129
unrar/blake2s_sse.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
// Based on public domain code written in 2012 by Samuel Neves
|
||||
|
||||
extern const byte blake2s_sigma[10][16];
|
||||
|
||||
// Initialization vector.
|
||||
static __m128i blake2s_IV_0_3, blake2s_IV_4_7;
|
||||
|
||||
#ifdef _WIN_64
|
||||
// Constants for cyclic rotation. Used in 64-bit mode in mm_rotr_epi32 macro.
|
||||
static __m128i crotr8, crotr16;
|
||||
#endif
|
||||
|
||||
static void blake2s_init_sse()
|
||||
{
|
||||
// We cannot initialize these 128 bit variables in place when declaring
|
||||
// them globally, because global scope initialization is performed before
|
||||
// our SSE check and it would make code incompatible with older non-SSE2
|
||||
// CPUs. Also we cannot initialize them as static inside of function
|
||||
// using these variables, because SSE static initialization is not thread
|
||||
// safe: first thread starts initialization and sets "init done" flag even
|
||||
// if it is not done yet, second thread can attempt to access half-init
|
||||
// SSE data. So we moved init code here.
|
||||
|
||||
blake2s_IV_0_3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );
|
||||
blake2s_IV_4_7 = _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 );
|
||||
|
||||
#ifdef _WIN_64
|
||||
crotr8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 );
|
||||
crotr16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
|
||||
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
|
||||
|
||||
#ifdef _WIN_32
|
||||
// 32-bit mode has less SSE2 registers and in MSVC2008 it is more efficient
|
||||
// to not use _mm_shuffle_epi8 here.
|
||||
#define mm_rotr_epi32(r, c) ( \
|
||||
_mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
|
||||
#else
|
||||
#define mm_rotr_epi32(r, c) ( \
|
||||
c==8 ? _mm_shuffle_epi8(r,crotr8) \
|
||||
: c==16 ? _mm_shuffle_epi8(r,crotr16) \
|
||||
: _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
|
||||
#endif
|
||||
|
||||
|
||||
#define G1(row1,row2,row3,row4,buf) \
|
||||
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
|
||||
row4 = _mm_xor_si128( row4, row1 ); \
|
||||
row4 = mm_rotr_epi32(row4, 16); \
|
||||
row3 = _mm_add_epi32( row3, row4 ); \
|
||||
row2 = _mm_xor_si128( row2, row3 ); \
|
||||
row2 = mm_rotr_epi32(row2, 12);
|
||||
|
||||
#define G2(row1,row2,row3,row4,buf) \
|
||||
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
|
||||
row4 = _mm_xor_si128( row4, row1 ); \
|
||||
row4 = mm_rotr_epi32(row4, 8); \
|
||||
row3 = _mm_add_epi32( row3, row4 ); \
|
||||
row2 = _mm_xor_si128( row2, row3 ); \
|
||||
row2 = mm_rotr_epi32(row2, 7);
|
||||
|
||||
#define DIAGONALIZE(row1,row2,row3,row4) \
|
||||
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \
|
||||
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
|
||||
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) );
|
||||
|
||||
#define UNDIAGONALIZE(row1,row2,row3,row4) \
|
||||
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \
|
||||
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
|
||||
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) );
|
||||
|
||||
#ifdef _WIN_64
|
||||
// MSVC 2008 in x64 mode expands _mm_set_epi32 to store to stack and load
|
||||
// from stack operations, which are slower than this code.
|
||||
#define _mm_set_epi32(i3,i2,i1,i0) \
|
||||
_mm_unpacklo_epi32(_mm_unpacklo_epi32(_mm_cvtsi32_si128(i0),_mm_cvtsi32_si128(i2)), \
|
||||
_mm_unpacklo_epi32(_mm_cvtsi32_si128(i1),_mm_cvtsi32_si128(i3)))
|
||||
#endif
|
||||
|
||||
// Original BLAKE2 SSE4.1 message loading code was a little slower in x86 mode
|
||||
// and about the same in x64 mode in our test. Perhaps depends on compiler.
|
||||
// We also tried _mm_i32gather_epi32 and _mm256_i32gather_epi32 AVX2 gather
|
||||
// instructions here, but they did not show any speed gain on i7-6700K.
|
||||
#define SSE_ROUND(m,row,r) \
|
||||
{ \
|
||||
__m128i buf; \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][6]],m[blake2s_sigma[r][4]],m[blake2s_sigma[r][2]],m[blake2s_sigma[r][0]]); \
|
||||
G1(row[0],row[1],row[2],row[3],buf); \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][7]],m[blake2s_sigma[r][5]],m[blake2s_sigma[r][3]],m[blake2s_sigma[r][1]]); \
|
||||
G2(row[0],row[1],row[2],row[3],buf); \
|
||||
DIAGONALIZE(row[0],row[1],row[2],row[3]); \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][14]],m[blake2s_sigma[r][12]],m[blake2s_sigma[r][10]],m[blake2s_sigma[r][8]]); \
|
||||
G1(row[0],row[1],row[2],row[3],buf); \
|
||||
buf=_mm_set_epi32(m[blake2s_sigma[r][15]],m[blake2s_sigma[r][13]],m[blake2s_sigma[r][11]],m[blake2s_sigma[r][9]]); \
|
||||
G2(row[0],row[1],row[2],row[3],buf); \
|
||||
UNDIAGONALIZE(row[0],row[1],row[2],row[3]); \
|
||||
}
|
||||
|
||||
|
||||
static int blake2s_compress_sse( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
|
||||
{
|
||||
__m128i row[4];
|
||||
__m128i ff0, ff1;
|
||||
|
||||
const uint32 *m = ( uint32 * )block;
|
||||
|
||||
row[0] = ff0 = LOAD( &S->h[0] );
|
||||
row[1] = ff1 = LOAD( &S->h[4] );
|
||||
|
||||
row[2] = blake2s_IV_0_3;
|
||||
row[3] = _mm_xor_si128( blake2s_IV_4_7, LOAD( &S->t[0] ) );
|
||||
SSE_ROUND( m, row, 0 );
|
||||
SSE_ROUND( m, row, 1 );
|
||||
SSE_ROUND( m, row, 2 );
|
||||
SSE_ROUND( m, row, 3 );
|
||||
SSE_ROUND( m, row, 4 );
|
||||
SSE_ROUND( m, row, 5 );
|
||||
SSE_ROUND( m, row, 6 );
|
||||
SSE_ROUND( m, row, 7 );
|
||||
SSE_ROUND( m, row, 8 );
|
||||
SSE_ROUND( m, row, 9 );
|
||||
STORE( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row[0], row[2] ) ) );
|
||||
STORE( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row[1], row[3] ) ) );
|
||||
return 0;
|
||||
}
|
||||
153
unrar/blake2sp.cpp
Normal file
153
unrar/blake2sp.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#define PARALLELISM_DEGREE 8
|
||||
|
||||
void blake2sp_init( blake2sp_state *S )
|
||||
{
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
|
||||
blake2s_init_param( &S->R, 0, 1 ); // Init root.
|
||||
|
||||
for( uint i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_init_param( &S->S[i], i, 0 ); // Init leaf.
|
||||
|
||||
S->R.last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1].last_node = 1;
|
||||
}
|
||||
|
||||
|
||||
struct Blake2ThreadData
|
||||
{
|
||||
void Update();
|
||||
blake2s_state *S;
|
||||
const byte *in;
|
||||
size_t inlen;
|
||||
};
|
||||
|
||||
|
||||
void Blake2ThreadData::Update()
|
||||
{
|
||||
size_t inlen__ = inlen;
|
||||
const byte *in__ = ( const byte * )in;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
#ifdef USE_SSE
|
||||
// We gain 5% in i7 SSE mode by prefetching next data block.
|
||||
if (_SSE_Version>=SSE_SSE && inlen__ >= 2 * PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES)
|
||||
_mm_prefetch((char*)(in__ + PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES), _MM_HINT_T0);
|
||||
#endif
|
||||
blake2s_update( S, in__, BLAKE2S_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RAR_SMP
|
||||
THREAD_PROC(Blake2Thread)
|
||||
{
|
||||
Blake2ThreadData *td=(Blake2ThreadData *)Data;
|
||||
td->Update();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = sizeof( S->buf ) - left;
|
||||
|
||||
if( left && inlen >= fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill );
|
||||
|
||||
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
Blake2ThreadData btd_array[PARALLELISM_DEGREE];
|
||||
|
||||
#ifdef RAR_SMP
|
||||
uint ThreadNumber = inlen < 0x1000 ? 1 : S->MaxThreads;
|
||||
|
||||
if (ThreadNumber==6 || ThreadNumber==7) // 6 and 7 threads work slower than 4 here.
|
||||
ThreadNumber=4;
|
||||
#else
|
||||
uint ThreadNumber=1;
|
||||
#endif
|
||||
|
||||
for (size_t id__=0;id__<PARALLELISM_DEGREE;)
|
||||
{
|
||||
for (uint Thread=0;Thread<ThreadNumber && id__<PARALLELISM_DEGREE;Thread++)
|
||||
{
|
||||
Blake2ThreadData *btd=btd_array+Thread;
|
||||
|
||||
btd->inlen = inlen;
|
||||
btd->in = in + id__ * BLAKE2S_BLOCKBYTES;
|
||||
btd->S = &S->S[id__];
|
||||
|
||||
#ifdef RAR_SMP
|
||||
if (ThreadNumber>1)
|
||||
S->ThPool->AddTask(Blake2Thread,(void*)btd);
|
||||
else
|
||||
btd->Update();
|
||||
#else
|
||||
btd->Update();
|
||||
#endif
|
||||
id__++;
|
||||
}
|
||||
#ifdef RAR_SMP
|
||||
if (S->ThPool!=NULL) // Can be NULL in -mt1 mode.
|
||||
S->ThPool->WaitDone();
|
||||
#endif // RAR_SMP
|
||||
}
|
||||
|
||||
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
|
||||
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( inlen > 0 )
|
||||
memcpy( S->buf + left, in, (size_t)inlen );
|
||||
|
||||
S->buflen = left + (size_t)inlen;
|
||||
}
|
||||
|
||||
|
||||
void blake2sp_final( blake2sp_state *S, byte *digest )
|
||||
{
|
||||
byte hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||
|
||||
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
{
|
||||
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
||||
|
||||
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
||||
}
|
||||
|
||||
blake2s_final( &S->S[i], hash[i] );
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( &S->R, hash[i], BLAKE2S_OUTBYTES );
|
||||
|
||||
blake2s_final( &S->R, digest );
|
||||
}
|
||||
1772
unrar/cmddata.cpp
1772
unrar/cmddata.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,57 +1,64 @@
|
||||
#ifndef _RAR_CMDDATA_
|
||||
#define _RAR_CMDDATA_
|
||||
|
||||
#define DefaultStoreList "7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;taz;tgz;z;zip"
|
||||
|
||||
#define DefaultStoreList L"7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lz;lzh;mp3;rar;taz;tgz;xz;z;zip;zipx"
|
||||
|
||||
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
|
||||
|
||||
class CommandData:public RAROptions
|
||||
{
|
||||
private:
|
||||
void ProcessSwitchesString(char *Str);
|
||||
void ProcessSwitch(char *Switch,wchar *SwitchW=NULL);
|
||||
void BadSwitch(char *Switch);
|
||||
bool ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode);
|
||||
uint GetExclAttr(char *Str);
|
||||
void ProcessSwitchesString(const wchar *Str);
|
||||
void ProcessSwitch(const wchar *Switch);
|
||||
void BadSwitch(const wchar *Switch);
|
||||
uint GetExclAttr(const wchar *Str);
|
||||
|
||||
bool FileLists;
|
||||
bool NoMoreSwitches;
|
||||
RAR_CMD_LIST_MODE ListMode;
|
||||
bool BareOutput;
|
||||
public:
|
||||
CommandData();
|
||||
~CommandData();
|
||||
void Init();
|
||||
void Close();
|
||||
void ParseArg(char *Arg,wchar *ArgW);
|
||||
|
||||
void ParseCommandLine(bool Preprocess,int argc, char *argv[]);
|
||||
void ParseArg(wchar *ArgW);
|
||||
void ParseDone();
|
||||
void ParseEnvVar();
|
||||
void ReadConfig(int argc,char *argv[]);
|
||||
bool IsConfigEnabled(int argc,char *argv[]);
|
||||
void ReadConfig();
|
||||
void PreprocessArg(const wchar *Arg);
|
||||
void OutTitle();
|
||||
void OutHelp();
|
||||
void OutHelp(RAR_EXIT ExitCode);
|
||||
bool IsSwitch(int Ch);
|
||||
bool ExclCheck(char *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
|
||||
bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
|
||||
static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode);
|
||||
bool ExclDirByAttr(uint FileAttr);
|
||||
bool TimeCheck(RarTime &ft);
|
||||
bool SizeCheck(int64 Size);
|
||||
bool AnyFiltersActive();
|
||||
int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH);
|
||||
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH,
|
||||
wchar *MatchedArg=NULL,uint MatchedArgSize=0);
|
||||
void ProcessCommand();
|
||||
void AddArcName(const char *Name,const wchar *NameW);
|
||||
bool GetArcName(char *Name,wchar *NameW,int MaxSize);
|
||||
void AddArcName(const wchar *Name);
|
||||
bool GetArcName(wchar *Name,int MaxSize);
|
||||
bool CheckWinSize();
|
||||
|
||||
int GetRecoverySize(char *Str,int DefSize);
|
||||
int GetRecoverySize(const wchar *Str,int DefSize);
|
||||
|
||||
char Command[NM+16];
|
||||
wchar CommandW[NM+16];
|
||||
#ifndef SFX_MODULE
|
||||
void ReportWrongSwitches(RARFORMAT Format);
|
||||
#endif
|
||||
|
||||
char ArcName[NM];
|
||||
wchar ArcNameW[NM];
|
||||
wchar Command[NM+16];
|
||||
|
||||
StringList *FileArgs;
|
||||
StringList *ExclArgs;
|
||||
StringList *InclArgs;
|
||||
StringList *ArcNames;
|
||||
StringList *StoreArgs;
|
||||
wchar ArcName[NM];
|
||||
|
||||
StringList FileArgs;
|
||||
StringList ExclArgs;
|
||||
StringList InclArgs;
|
||||
StringList ArcNames;
|
||||
StringList StoreArgs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
|
||||
****************************************************************************/
|
||||
|
||||
const uint TOP=1 << 24, BOT=1 << 15;
|
||||
|
||||
class RangeCoder
|
||||
{
|
||||
|
||||
@@ -1,41 +1,50 @@
|
||||
#ifndef _RAR_COMPRESS_
|
||||
#define _RAR_COMPRESS_
|
||||
|
||||
class ComprDataIO;
|
||||
class PackingFileTable;
|
||||
// Combine pack and unpack constants to class to avoid polluting global
|
||||
// namespace with numerous short names.
|
||||
class PackDef
|
||||
{
|
||||
public:
|
||||
static const uint MAX_LZ_MATCH = 0x1001;
|
||||
static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
|
||||
static const uint LOW_DIST_REP_COUNT = 16;
|
||||
|
||||
#define MAX_LZ_MATCH 0x101
|
||||
static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
static const uint DC = 64;
|
||||
static const uint LDC = 16;
|
||||
static const uint RC = 44;
|
||||
static const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
|
||||
static const uint BC = 20;
|
||||
|
||||
#define CODEBUFSIZE 0x4000
|
||||
#define MAXWINSIZE 0x400000
|
||||
#define MAXWINMASK (MAXWINSIZE-1)
|
||||
static const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
static const uint DC30 = 60;
|
||||
static const uint LDC30 = 17;
|
||||
static const uint RC30 = 28;
|
||||
static const uint BC30 = 20;
|
||||
static const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
|
||||
|
||||
#define LOW_DIST_REP_COUNT 16
|
||||
static const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
static const uint DC20 = 48;
|
||||
static const uint RC20 = 28;
|
||||
static const uint BC20 = 19;
|
||||
static const uint MC20 = 257;
|
||||
|
||||
#define NC 299 /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
#define DC 60
|
||||
#define LDC 17
|
||||
#define RC 28
|
||||
#define HUFF_TABLE_SIZE (NC+DC+RC+LDC)
|
||||
#define BC 20
|
||||
// Largest alphabet size among all values listed above.
|
||||
static const uint LARGEST_TABLE_SIZE = 306;
|
||||
|
||||
#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
#define DC20 48
|
||||
#define RC20 28
|
||||
#define BC20 19
|
||||
#define MC20 257
|
||||
|
||||
// Largest alphabet size among all values listed above.
|
||||
#define LARGEST_TABLE_SIZE 299
|
||||
|
||||
enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
|
||||
CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA};
|
||||
enum {
|
||||
CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
|
||||
CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
enum FilterType {
|
||||
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
|
||||
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
|
||||
FILTER_ITANIUM, FILTER_E8E9V2
|
||||
// These values must not be changed, because we use them directly
|
||||
// in RAR5 compression and decompression code.
|
||||
FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
|
||||
FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
417
unrar/consio.cpp
417
unrar/consio.cpp
@@ -1,225 +1,286 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifndef GUI
|
||||
#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;
|
||||
static bool Sound=false;
|
||||
static RAR_CHARSET RedirectCharset=RCH_DEFAULT;
|
||||
|
||||
const int MaxMsgSize=2*NM+2048;
|
||||
|
||||
void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound)
|
||||
static bool StdoutRedirected=false,StderrRedirected=false,StdinRedirected=false;
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
static bool IsRedirected(DWORD nStdHandle)
|
||||
{
|
||||
::MsgStream=MsgStream;
|
||||
::Sound=Sound;
|
||||
HANDLE hStd=GetStdHandle(nStdHandle);
|
||||
DWORD Mode;
|
||||
return GetFileType(hStd)!=FILE_TYPE_CHAR || GetConsoleMode(hStd,&Mode)==0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void InitConsole()
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// We want messages like file names or progress percent to be printed
|
||||
// immediately. Use only in Windows, in Unix they can cause wprintf %ls
|
||||
// to fail with non-English strings.
|
||||
setbuf(stdout,NULL);
|
||||
setbuf(stderr,NULL);
|
||||
|
||||
// Detect if output is redirected and set output mode properly.
|
||||
// We do not want to send Unicode output to files and especially to pipes
|
||||
// like '|more', which cannot handle them correctly in Windows.
|
||||
// In Unix console output is UTF-8 and it is handled correctly
|
||||
// when redirecting, so no need to perform any adjustments.
|
||||
StdoutRedirected=IsRedirected(STD_OUTPUT_HANDLE);
|
||||
StderrRedirected=IsRedirected(STD_ERROR_HANDLE);
|
||||
StdinRedirected=IsRedirected(STD_INPUT_HANDLE);
|
||||
#ifdef _MSC_VER
|
||||
if (!StdoutRedirected)
|
||||
_setmode(_fileno(stdout), _O_U16TEXT);
|
||||
if (!StderrRedirected)
|
||||
_setmode(_fileno(stderr), _O_U16TEXT);
|
||||
#endif
|
||||
#elif defined(_UNIX)
|
||||
StdoutRedirected=!isatty(fileno(stdout));
|
||||
StderrRedirected=!isatty(fileno(stderr));
|
||||
StdinRedirected=!isatty(fileno(stdin));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
void mprintf(const char *fmt,...)
|
||||
|
||||
void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset)
|
||||
{
|
||||
::MsgStream=MsgStream;
|
||||
::RedirectCharset=RedirectCharset;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist)
|
||||
{
|
||||
// This buffer is for format string only, not for entire output,
|
||||
// so it can be short enough.
|
||||
wchar fmtw[1024];
|
||||
PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
|
||||
#ifdef _WIN_ALL
|
||||
safebuf wchar Msg[MaxMsgSize];
|
||||
if (dest==stdout && StdoutRedirected || dest==stderr && StderrRedirected)
|
||||
{
|
||||
HANDLE hOut=GetStdHandle(dest==stdout ? STD_OUTPUT_HANDLE:STD_ERROR_HANDLE);
|
||||
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
|
||||
DWORD Written;
|
||||
if (RedirectCharset==RCH_UNICODE)
|
||||
WriteFile(hOut,Msg,(DWORD)wcslen(Msg)*sizeof(*Msg),&Written,NULL);
|
||||
else
|
||||
{
|
||||
// Avoid Unicode for redirect in Windows, it does not work with pipes.
|
||||
safebuf char MsgA[MaxMsgSize];
|
||||
if (RedirectCharset==RCH_UTF8)
|
||||
WideToUtf(Msg,MsgA,ASIZE(MsgA));
|
||||
else
|
||||
WideToChar(Msg,MsgA,ASIZE(MsgA));
|
||||
if (RedirectCharset==RCH_DEFAULT || RedirectCharset==RCH_OEM)
|
||||
CharToOemA(MsgA,MsgA); // Console tools like 'more' expect OEM encoding.
|
||||
|
||||
// We already converted \n to \r\n above, so we use WriteFile instead
|
||||
// of C library to avoid unnecessary additional conversion.
|
||||
WriteFile(hOut,MsgA,(DWORD)strlen(MsgA),&Written,NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// MSVC2008 vfwprintf writes every character to console separately
|
||||
// and it is too slow. We use direct WriteConsole call instead.
|
||||
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
|
||||
HANDLE hOut=GetStdHandle(dest==stderr ? STD_ERROR_HANDLE:STD_OUTPUT_HANDLE);
|
||||
DWORD Written;
|
||||
WriteConsole(hOut,Msg,(DWORD)wcslen(Msg),&Written,NULL);
|
||||
#else
|
||||
vfwprintf(dest,fmtw,arglist);
|
||||
// We do not use setbuf(NULL) in Unix (see comments in InitConsole).
|
||||
fflush(dest);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void mprintf(const wchar *fmt,...)
|
||||
{
|
||||
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
|
||||
return;
|
||||
safebuf char Msg[MaxMsgSize];
|
||||
va_list argptr;
|
||||
va_start(argptr,fmt);
|
||||
vsprintf(Msg,fmt,argptr);
|
||||
RawPrint(Msg,MsgStream);
|
||||
va_end(argptr);
|
||||
|
||||
fflush(stderr); // Ensure proper message order.
|
||||
|
||||
va_list arglist;
|
||||
va_start(arglist,fmt);
|
||||
FILE *dest=MsgStream==MSG_STDERR ? stderr:stdout;
|
||||
cvt_wprintf(dest,fmt,arglist);
|
||||
va_end(arglist);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
void eprintf(const char *fmt,...)
|
||||
#ifndef SILENT
|
||||
void eprintf(const wchar *fmt,...)
|
||||
{
|
||||
if (MsgStream==MSG_NULL)
|
||||
return;
|
||||
safebuf char Msg[MaxMsgSize];
|
||||
va_list argptr;
|
||||
va_start(argptr,fmt);
|
||||
vsprintf(Msg,fmt,argptr);
|
||||
RawPrint(Msg,MSG_STDERR);
|
||||
va_end(argptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
fflush(stdout); // Ensure proper message order.
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
void RawPrint(char *Msg,MESSAGE_TYPE MessageType)
|
||||
{
|
||||
File OutFile;
|
||||
switch(MessageType)
|
||||
{
|
||||
case MSG_STDOUT:
|
||||
OutFile.SetHandleType(FILE_HANDLESTD);
|
||||
break;
|
||||
case MSG_STDERR:
|
||||
case MSG_ERRONLY:
|
||||
OutFile.SetHandleType(FILE_HANDLEERR);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
#ifdef _WIN_ALL
|
||||
CharToOemA(Msg,Msg);
|
||||
|
||||
char OutMsg[MaxMsgSize],*OutPos=OutMsg;
|
||||
for (int I=0;Msg[I]!=0;I++)
|
||||
{
|
||||
if (Msg[I]=='\n' && (I==0 || Msg[I-1]!='\r'))
|
||||
*(OutPos++)='\r';
|
||||
*(OutPos++)=Msg[I];
|
||||
}
|
||||
*OutPos=0;
|
||||
strcpy(Msg,OutMsg);
|
||||
#endif
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
char OutMsg[MaxMsgSize],*OutPos=OutMsg;
|
||||
for (int I=0;Msg[I]!=0;I++)
|
||||
if (Msg[I]!='\r')
|
||||
*(OutPos++)=Msg[I];
|
||||
*OutPos=0;
|
||||
strcpy(Msg,OutMsg);
|
||||
#endif
|
||||
|
||||
OutFile.Write(Msg,strlen(Msg));
|
||||
va_list arglist;
|
||||
va_start(arglist,fmt);
|
||||
cvt_wprintf(stderr,fmt,arglist);
|
||||
va_end(arglist);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
void Alarm()
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
if (Sound)
|
||||
putchar('\007');
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
#ifndef GUI
|
||||
void GetPasswordText(wchar *Str,uint MaxLength)
|
||||
static void GetPasswordText(wchar *Str,uint MaxLength)
|
||||
{
|
||||
if (MaxLength==0)
|
||||
return;
|
||||
if (StdinRedirected)
|
||||
getwstr(Str,MaxLength); // Read from pipe or redirected file.
|
||||
else
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
|
||||
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD ConInMode,ConOutMode;
|
||||
DWORD Read=0;
|
||||
GetConsoleMode(hConIn,&ConInMode);
|
||||
GetConsoleMode(hConOut,&ConOutMode);
|
||||
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
|
||||
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
|
||||
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
|
||||
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD ConInMode,ConOutMode;
|
||||
DWORD Read=0;
|
||||
GetConsoleMode(hConIn,&ConInMode);
|
||||
GetConsoleMode(hConOut,&ConOutMode);
|
||||
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
|
||||
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
|
||||
|
||||
ReadConsoleW(hConIn,Str,MaxLength-1,&Read,NULL);
|
||||
Str[Read]=0;
|
||||
SetConsoleMode(hConIn,ConInMode);
|
||||
SetConsoleMode(hConOut,ConOutMode);
|
||||
ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL);
|
||||
Str[Read]=0;
|
||||
SetConsoleMode(hConIn,ConInMode);
|
||||
SetConsoleMode(hConOut,ConOutMode);
|
||||
#else
|
||||
char StrA[MAXPASSWORD];
|
||||
#if defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
|
||||
fgets(StrA,ASIZE(StrA)-1,stdin);
|
||||
char StrA[MAXPASSWORD];
|
||||
#if defined(_EMX) || defined (__VMS)
|
||||
fgets(StrA,ASIZE(StrA)-1,stdin);
|
||||
#elif defined(__sun)
|
||||
strncpyz(StrA,getpassphrase(""),ASIZE(StrA));
|
||||
#else
|
||||
strncpyz(StrA,getpass(""),ASIZE(StrA));
|
||||
strncpyz(StrA,getpass(""),ASIZE(StrA));
|
||||
#endif
|
||||
CharToWide(StrA,Str,MaxLength);
|
||||
CharToWide(StrA,Str,MaxLength);
|
||||
cleandata(StrA,sizeof(StrA));
|
||||
#endif
|
||||
}
|
||||
Str[MaxLength-1]=0;
|
||||
RemoveLF(Str);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,wchar *Password,uint MaxLength)
|
||||
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
|
||||
{
|
||||
Alarm();
|
||||
if (!StdinRedirected)
|
||||
uiAlarm(UIALARM_QUESTION);
|
||||
|
||||
while (true)
|
||||
{
|
||||
char PromptStr[NM+256];
|
||||
#if defined(_EMX) || defined(_BEOS)
|
||||
strcpy(PromptStr,St(MAskPswEcho));
|
||||
#else
|
||||
strcpy(PromptStr,St(MAskPsw));
|
||||
#endif
|
||||
if (Type!=PASSWORD_GLOBAL)
|
||||
{
|
||||
strcat(PromptStr,St(MFor));
|
||||
char *NameOnly=PointToName(FileName);
|
||||
if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
|
||||
strcat(PromptStr,NameOnly);
|
||||
}
|
||||
eprintf("\n%s: ",PromptStr);
|
||||
GetPasswordText(Password,MaxLength);
|
||||
if (*Password==0 && Type==PASSWORD_GLOBAL)
|
||||
return(false);
|
||||
if (Type==PASSWORD_GLOBAL)
|
||||
if (!StdinRedirected)
|
||||
if (Type==UIPASSWORD_GLOBAL)
|
||||
eprintf(L"\n%s: ",St(MAskPsw));
|
||||
else
|
||||
eprintf(St(MAskPswFor),FileName);
|
||||
|
||||
wchar PlainPsw[MAXPASSWORD];
|
||||
GetPasswordText(PlainPsw,ASIZE(PlainPsw));
|
||||
if (*PlainPsw==0 && Type==UIPASSWORD_GLOBAL)
|
||||
return false;
|
||||
if (!StdinRedirected && Type==UIPASSWORD_GLOBAL)
|
||||
{
|
||||
eprintf(St(MReAskPsw));
|
||||
wchar CmpStr[MAXPASSWORD];
|
||||
GetPasswordText(CmpStr,ASIZE(CmpStr));
|
||||
if (*CmpStr==0 || wcscmp(Password,CmpStr)!=0)
|
||||
if (*CmpStr==0 || wcscmp(PlainPsw,CmpStr)!=0)
|
||||
{
|
||||
eprintf(St(MNotMatchPsw));
|
||||
memset(Password,0,MaxLength*sizeof(*Password));
|
||||
memset(CmpStr,0,sizeof(CmpStr));
|
||||
cleandata(PlainPsw,sizeof(PlainPsw));
|
||||
cleandata(CmpStr,sizeof(CmpStr));
|
||||
continue;
|
||||
}
|
||||
memset(CmpStr,0,sizeof(CmpStr));
|
||||
cleandata(CmpStr,sizeof(CmpStr));
|
||||
}
|
||||
Password->Set(PlainPsw);
|
||||
cleandata(PlainPsw,sizeof(PlainPsw));
|
||||
break;
|
||||
}
|
||||
return(true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
uint GetKey()
|
||||
#ifndef SILENT
|
||||
bool getwstr(wchar *str,size_t n)
|
||||
{
|
||||
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)
|
||||
// Print buffered prompt title function before waiting for input.
|
||||
fflush(stderr);
|
||||
|
||||
*str=0;
|
||||
#if defined(_WIN_ALL)
|
||||
// fgetws does not work well with non-English text in Windows,
|
||||
// so we do not use it.
|
||||
if (StdinRedirected) // ReadConsole does not work if redirected.
|
||||
{
|
||||
// Looks like stdin is a null device. We can enter to infinite loop
|
||||
// calling Ask(), so let's better exit.
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
// fgets does not work well with pipes in Windows in our test.
|
||||
// Let's use files.
|
||||
Array<char> StrA(n*4); // Up to 4 UTF-8 characters per wchar_t.
|
||||
File SrcFile;
|
||||
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||
int ReadSize=SrcFile.Read(&StrA[0],StrA.Size()-1);
|
||||
if (ReadSize<=0)
|
||||
{
|
||||
// Looks like stdin is a null device. We can enter to infinite loop
|
||||
// calling Ask(), so let's better exit.
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
StrA[ReadSize]=0;
|
||||
CharToWide(&StrA[0],str,n);
|
||||
cleandata(&StrA[0],StrA.Size()); // We can use this function to enter passwords.
|
||||
}
|
||||
return(Str[0]);
|
||||
else
|
||||
{
|
||||
DWORD ReadSize=0;
|
||||
if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),str,DWORD(n-1),&ReadSize,NULL)==0)
|
||||
return false;
|
||||
str[ReadSize]=0;
|
||||
}
|
||||
#else
|
||||
if (fgetws(str,n,stdin)==NULL)
|
||||
ErrHandler.Exit(RARX_USERBREAK); // Avoid infinite Ask() loop.
|
||||
#endif
|
||||
RemoveLF(str);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
int Ask(const char *AskStr)
|
||||
#ifndef SILENT
|
||||
// We allow this function to return 0 in case of invalid input,
|
||||
// because it might be convenient to press Enter to some not dangerous
|
||||
// prompts like "insert disk with next volume". We should call this function
|
||||
// again in case of 0 in dangerous prompt such as overwriting file.
|
||||
int Ask(const wchar *AskStr)
|
||||
{
|
||||
uiAlarm(UIALARM_QUESTION);
|
||||
|
||||
const int MaxItems=10;
|
||||
char Item[MaxItems][40];
|
||||
wchar Item[MaxItems][40];
|
||||
int ItemKeyPos[MaxItems],NumItems=0;
|
||||
|
||||
for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
|
||||
for (const wchar *NextItem=AskStr;NextItem!=NULL;NextItem=wcschr(NextItem+1,'_'))
|
||||
{
|
||||
char *CurItem=Item[NumItems];
|
||||
strncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
|
||||
char *EndItem=strchr(CurItem,'_');
|
||||
wchar *CurItem=Item[NumItems];
|
||||
wcsncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
|
||||
wchar *EndItem=wcschr(CurItem,'_');
|
||||
if (EndItem!=NULL)
|
||||
*EndItem=0;
|
||||
int KeyPos=0,CurKey;
|
||||
@@ -227,7 +288,7 @@ int Ask(const char *AskStr)
|
||||
{
|
||||
bool Found=false;
|
||||
for (int I=0;I<NumItems && !Found;I++)
|
||||
if (loctoupper(Item[I][ItemKeyPos[I]])==loctoupper(CurKey))
|
||||
if (toupperw(Item[I][ItemKeyPos[I]])==toupperw(CurKey))
|
||||
Found=true;
|
||||
if (!Found && CurKey!=' ')
|
||||
break;
|
||||
@@ -239,61 +300,53 @@ int Ask(const char *AskStr)
|
||||
|
||||
for (int I=0;I<NumItems;I++)
|
||||
{
|
||||
eprintf(I==0 ? (NumItems>4 ? "\n":" "):", ");
|
||||
eprintf(I==0 ? (NumItems>4 ? L"\n":L" "):L", ");
|
||||
int KeyPos=ItemKeyPos[I];
|
||||
for (int J=0;J<KeyPos;J++)
|
||||
eprintf("%c",Item[I][J]);
|
||||
eprintf("[%c]%s",Item[I][KeyPos],&Item[I][KeyPos+1]);
|
||||
eprintf(L"%c",Item[I][J]);
|
||||
eprintf(L"[%c]%ls",Item[I][KeyPos],&Item[I][KeyPos+1]);
|
||||
}
|
||||
eprintf(" ");
|
||||
int Ch=GetKey();
|
||||
#if defined(_WIN_ALL)
|
||||
OemToCharBuff((LPCSTR)&Ch,(LPTSTR)&Ch,1);
|
||||
#endif
|
||||
Ch=loctoupper(Ch);
|
||||
eprintf(L" ");
|
||||
wchar Str[50];
|
||||
getwstr(Str,ASIZE(Str));
|
||||
wchar Ch=toupperw(Str[0]);
|
||||
for (int I=0;I<NumItems;I++)
|
||||
if (Ch==Item[I][ItemKeyPos[I]])
|
||||
return(I+1);
|
||||
return(0);
|
||||
return I+1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int KbdAnsi(char *Addr,size_t Size)
|
||||
static bool IsCommentUnsafe(const wchar *Data,size_t Size)
|
||||
{
|
||||
int RetCode=0;
|
||||
#ifndef GUI
|
||||
for (size_t I=0;I<Size;I++)
|
||||
if (Addr[I]==27 && Addr[I+1]=='[')
|
||||
{
|
||||
if (Data[I]==27 && Data[I+1]=='[')
|
||||
for (size_t J=I+2;J<Size;J++)
|
||||
{
|
||||
if (Addr[J]=='\"')
|
||||
return(2);
|
||||
if (!IsDigit(Addr[J]) && Addr[J]!=';')
|
||||
// Return true for <ESC>[{key};"{string}"p used to redefine
|
||||
// a keyboard key on some terminals.
|
||||
if (Data[J]=='\"')
|
||||
return true;
|
||||
if (!IsDigit(Data[J]) && Data[J]!=';')
|
||||
break;
|
||||
}
|
||||
RetCode=1;
|
||||
}
|
||||
#endif
|
||||
return(RetCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void OutComment(char *Comment,size_t Size)
|
||||
void OutComment(const wchar *Comment,size_t Size)
|
||||
{
|
||||
#ifndef GUI
|
||||
if (KbdAnsi(Comment,Size)==2)
|
||||
if (IsCommentUnsafe(Comment,Size))
|
||||
return;
|
||||
const size_t MaxOutSize=0x400;
|
||||
for (size_t I=0;I<Size;I+=MaxOutSize)
|
||||
{
|
||||
char Msg[MaxOutSize+1];
|
||||
wchar Msg[MaxOutSize+1];
|
||||
size_t CopySize=Min(MaxOutSize,Size-I);
|
||||
strncpy(Msg,Comment+I,CopySize);
|
||||
wcsncpy(Msg,Comment+I,CopySize);
|
||||
Msg[CopySize]=0;
|
||||
mprintf("%s",Msg);
|
||||
mprintf(L"%s",Msg);
|
||||
}
|
||||
mprintf("\n");
|
||||
#endif
|
||||
mprintf(L"\n");
|
||||
}
|
||||
|
||||
@@ -1,37 +1,26 @@
|
||||
#ifndef _RAR_CONSIO_
|
||||
#define _RAR_CONSIO_
|
||||
|
||||
#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};
|
||||
|
||||
void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound);
|
||||
void InitConsole();
|
||||
void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset);
|
||||
void OutComment(const wchar *Comment,size_t Size);
|
||||
|
||||
#ifndef SILENT
|
||||
void mprintf(const char *fmt,...);
|
||||
void eprintf(const char *fmt,...);
|
||||
void Alarm();
|
||||
void GetPasswordText(wchar *Str,uint MaxLength);
|
||||
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,wchar *Password,uint MaxLength);
|
||||
int Ask(const char *AskStr);
|
||||
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password);
|
||||
#endif
|
||||
|
||||
void OutComment(char *Comment,size_t Size);
|
||||
|
||||
#ifdef SILENT
|
||||
#ifdef __GNUC__
|
||||
#define mprintf(args...)
|
||||
#define eprintf(args...)
|
||||
#else
|
||||
inline void mprintf(const char *fmt,...) {}
|
||||
inline void eprintf(const char *fmt,...) {}
|
||||
#endif
|
||||
inline void mprintf(const wchar *fmt,...) {}
|
||||
inline void eprintf(const wchar *fmt,...) {}
|
||||
inline void Alarm() {}
|
||||
inline void GetPasswordText(wchar *Str,uint MaxLength) {}
|
||||
inline bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,wchar *Password,uint MaxLength) {return(false);}
|
||||
inline int Ask(const char *AskStr) {return(0);}
|
||||
inline int Ask(const wchar *AskStr) {return 0;}
|
||||
inline bool getwstr(wchar *str,size_t n) {return false;}
|
||||
#else
|
||||
void mprintf(const wchar *fmt,...);
|
||||
void eprintf(const wchar *fmt,...);
|
||||
void Alarm();
|
||||
int Ask(const wchar *AskStr);
|
||||
bool getwstr(wchar *str,size_t n);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
111
unrar/crc.cpp
111
unrar/crc.cpp
@@ -1,56 +1,93 @@
|
||||
// This CRC function is based on Intel Slicing-by-8 algorithm.
|
||||
//
|
||||
// Original Intel Slicing-by-8 code is available here:
|
||||
//
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
//
|
||||
// Original Intel Slicing-by-8 code is licensed as:
|
||||
//
|
||||
// Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
|
||||
//
|
||||
// This software program is licensed subject to the BSD License,
|
||||
// available at http://www.opensource.org/licenses/bsd-license.html
|
||||
|
||||
|
||||
#include "rar.hpp"
|
||||
|
||||
uint CRCTab[256];
|
||||
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
|
||||
|
||||
void InitCRC()
|
||||
|
||||
// Build the classic CRC32 lookup table.
|
||||
// We also provide this function to legacy RAR and ZIP decryption code.
|
||||
void InitCRC32(uint *CRCTab)
|
||||
{
|
||||
for (int I=0;I<256;I++)
|
||||
if (CRCTab[1]!=0)
|
||||
return;
|
||||
for (uint I=0;I<256;I++)
|
||||
{
|
||||
uint C=I;
|
||||
for (int J=0;J<8;J++)
|
||||
C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
|
||||
for (uint J=0;J<8;J++)
|
||||
C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
|
||||
CRCTab[I]=C;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint CRC(uint StartCRC,const void *Addr,size_t Size)
|
||||
static void InitTables()
|
||||
{
|
||||
if (CRCTab[1]==0)
|
||||
InitCRC();
|
||||
byte *Data=(byte *)Addr;
|
||||
InitCRC32(crc_tables[0]);
|
||||
|
||||
#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
|
||||
while (Size>0 && ((long)Data & 7))
|
||||
for (uint I=0;I<256;I++) // Build additional lookup tables.
|
||||
{
|
||||
StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
Size--;
|
||||
Data++;
|
||||
uint C=crc_tables[0][I];
|
||||
for (uint J=1;J<8;J++)
|
||||
{
|
||||
C=crc_tables[0][(byte)C]^(C>>8);
|
||||
crc_tables[J][I]=C;
|
||||
}
|
||||
}
|
||||
while (Size>=8)
|
||||
{
|
||||
StartCRC^=*(uint32 *)Data;
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC^=*(uint32 *)(Data+4);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
|
||||
Data+=8;
|
||||
Size-=8;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t I=0;I<Size;I++)
|
||||
StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
|
||||
return(StartCRC);
|
||||
}
|
||||
|
||||
|
||||
struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32;
|
||||
|
||||
uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
byte *Data=(byte *)Addr;
|
||||
|
||||
// Align Data to 8 for better performance.
|
||||
for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
|
||||
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
|
||||
for (;Size>=8;Size-=8,Data+=8)
|
||||
{
|
||||
#ifdef BIG_ENDIAN
|
||||
StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
|
||||
uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
|
||||
#else
|
||||
StartCRC ^= *(uint32 *) Data;
|
||||
uint NextData = *(uint32 *) (Data +4);
|
||||
#endif
|
||||
StartCRC = crc_tables[7][(byte) StartCRC ] ^
|
||||
crc_tables[6][(byte)(StartCRC >> 8) ] ^
|
||||
crc_tables[5][(byte)(StartCRC >> 16)] ^
|
||||
crc_tables[4][(byte)(StartCRC >> 24)] ^
|
||||
crc_tables[3][(byte) NextData ] ^
|
||||
crc_tables[2][(byte)(NextData >>8 ) ] ^
|
||||
crc_tables[1][(byte)(NextData >> 16)] ^
|
||||
crc_tables[0][(byte)(NextData >> 24)];
|
||||
}
|
||||
|
||||
for (;Size>0;Size--,Data++) // Process left data.
|
||||
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
|
||||
return StartCRC;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
|
||||
// For RAR 1.4 archives in case somebody still has them.
|
||||
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
byte *Data=(byte *)Addr;
|
||||
for (size_t I=0;I<Size;I++)
|
||||
@@ -58,6 +95,8 @@ ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
|
||||
StartCRC=(StartCRC+Data[I])&0xffff;
|
||||
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
|
||||
}
|
||||
return(StartCRC);
|
||||
return StartCRC;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#ifndef _RAR_CRC_
|
||||
#define _RAR_CRC_
|
||||
|
||||
extern uint CRCTab[256];
|
||||
// This function is only to intialize external CRC tables. We do not need to
|
||||
// call it before calculating CRC32.
|
||||
void InitCRC32(uint *CRCTab);
|
||||
|
||||
uint CRC32(uint StartCRC,const void *Addr,size_t Size);
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size);
|
||||
#endif
|
||||
|
||||
void InitCRC();
|
||||
uint CRC(uint StartCRC,const void *Addr,size_t Size);
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size);
|
||||
|
||||
#endif
|
||||
|
||||
480
unrar/crypt.cpp
480
unrar/crypt.cpp
@@ -1,380 +1,134 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
extern uint CRCTab[256];
|
||||
#include "crypt1.cpp"
|
||||
#include "crypt2.cpp"
|
||||
#endif
|
||||
|
||||
#define NROUNDS 32
|
||||
|
||||
#define rol(x,n,xsize) (((x)<<(n)) | ((x)>>(xsize-(n))))
|
||||
#define ror(x,n,xsize) (((x)>>(n)) | ((x)<<(xsize-(n))))
|
||||
|
||||
#define substLong(t) ( (uint)SubstTable[(uint)t&255] | \
|
||||
((uint)SubstTable[(int)(t>> 8)&255]<< 8) | \
|
||||
((uint)SubstTable[(int)(t>>16)&255]<<16) | \
|
||||
((uint)SubstTable[(int)(t>>24)&255]<<24) )
|
||||
|
||||
CryptKeyCacheItem CryptData::Cache[4];
|
||||
int CryptData::CachePos=0;
|
||||
#include "crypt3.cpp"
|
||||
#include "crypt5.cpp"
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
static byte InitSubstTable[256]={
|
||||
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
|
||||
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
|
||||
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
|
||||
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
|
||||
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
|
||||
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
|
||||
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
|
||||
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
|
||||
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
|
||||
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
|
||||
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
|
||||
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
|
||||
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
|
||||
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
|
||||
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
|
||||
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
|
||||
};
|
||||
#endif
|
||||
CryptData::CryptData()
|
||||
{
|
||||
Method=CRYPT_NONE;
|
||||
memset(KDF3Cache,0,sizeof(KDF3Cache));
|
||||
memset(KDF5Cache,0,sizeof(KDF5Cache));
|
||||
KDF3CachePos=0;
|
||||
KDF5CachePos=0;
|
||||
memset(CRCTab,0,sizeof(CRCTab));
|
||||
}
|
||||
|
||||
|
||||
CryptData::~CryptData()
|
||||
{
|
||||
cleandata(KDF3Cache,sizeof(KDF3Cache));
|
||||
cleandata(KDF5Cache,sizeof(KDF5Cache));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CryptData::DecryptBlock(byte *Buf,size_t Size)
|
||||
{
|
||||
rin.blockDecrypt(Buf,Size,Buf);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void CryptData::EncryptBlock20(byte *Buf)
|
||||
{
|
||||
uint A,B,C,D,T,TA,TB;
|
||||
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
|
||||
A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0];
|
||||
B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1];
|
||||
C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2];
|
||||
D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3];
|
||||
#else
|
||||
uint32 *BufPtr=(uint32 *)Buf;
|
||||
A=BufPtr[0]^Key[0];
|
||||
B=BufPtr[1]^Key[1];
|
||||
C=BufPtr[2]^Key[2];
|
||||
D=BufPtr[3]^Key[3];
|
||||
#endif
|
||||
for(int I=0;I<NROUNDS;I++)
|
||||
{
|
||||
T=((C+rol(D,11,32))^Key[I&3]);
|
||||
TA=A^substLong(T);
|
||||
T=((D^rol(C,17,32))+Key[I&3]);
|
||||
TB=B^substLong(T);
|
||||
A=C;
|
||||
B=D;
|
||||
C=TA;
|
||||
D=TB;
|
||||
}
|
||||
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
|
||||
C^=Key[0];
|
||||
Buf[0]=(byte)C;
|
||||
Buf[1]=(byte)(C>>8);
|
||||
Buf[2]=(byte)(C>>16);
|
||||
Buf[3]=(byte)(C>>24);
|
||||
D^=Key[1];
|
||||
Buf[4]=(byte)D;
|
||||
Buf[5]=(byte)(D>>8);
|
||||
Buf[6]=(byte)(D>>16);
|
||||
Buf[7]=(byte)(D>>24);
|
||||
A^=Key[2];
|
||||
Buf[8]=(byte)A;
|
||||
Buf[9]=(byte)(A>>8);
|
||||
Buf[10]=(byte)(A>>16);
|
||||
Buf[11]=(byte)(A>>24);
|
||||
B^=Key[3];
|
||||
Buf[12]=(byte)B;
|
||||
Buf[13]=(byte)(B>>8);
|
||||
Buf[14]=(byte)(B>>16);
|
||||
Buf[15]=(byte)(B>>24);
|
||||
#else
|
||||
BufPtr[0]=C^Key[0];
|
||||
BufPtr[1]=D^Key[1];
|
||||
BufPtr[2]=A^Key[2];
|
||||
BufPtr[3]=B^Key[3];
|
||||
#endif
|
||||
UpdKeys(Buf);
|
||||
}
|
||||
|
||||
|
||||
void CryptData::DecryptBlock20(byte *Buf)
|
||||
{
|
||||
byte InBuf[16];
|
||||
uint A,B,C,D,T,TA,TB;
|
||||
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
|
||||
A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0];
|
||||
B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1];
|
||||
C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2];
|
||||
D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3];
|
||||
#else
|
||||
uint32 *BufPtr=(uint32 *)Buf;
|
||||
A=BufPtr[0]^Key[0];
|
||||
B=BufPtr[1]^Key[1];
|
||||
C=BufPtr[2]^Key[2];
|
||||
D=BufPtr[3]^Key[3];
|
||||
#endif
|
||||
memcpy(InBuf,Buf,sizeof(InBuf));
|
||||
for(int I=NROUNDS-1;I>=0;I--)
|
||||
{
|
||||
T=((C+rol(D,11,32))^Key[I&3]);
|
||||
TA=A^substLong(T);
|
||||
T=((D^rol(C,17,32))+Key[I&3]);
|
||||
TB=B^substLong(T);
|
||||
A=C;
|
||||
B=D;
|
||||
C=TA;
|
||||
D=TB;
|
||||
}
|
||||
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
|
||||
C^=Key[0];
|
||||
Buf[0]=(byte)C;
|
||||
Buf[1]=(byte)(C>>8);
|
||||
Buf[2]=(byte)(C>>16);
|
||||
Buf[3]=(byte)(C>>24);
|
||||
D^=Key[1];
|
||||
Buf[4]=(byte)D;
|
||||
Buf[5]=(byte)(D>>8);
|
||||
Buf[6]=(byte)(D>>16);
|
||||
Buf[7]=(byte)(D>>24);
|
||||
A^=Key[2];
|
||||
Buf[8]=(byte)A;
|
||||
Buf[9]=(byte)(A>>8);
|
||||
Buf[10]=(byte)(A>>16);
|
||||
Buf[11]=(byte)(A>>24);
|
||||
B^=Key[3];
|
||||
Buf[12]=(byte)B;
|
||||
Buf[13]=(byte)(B>>8);
|
||||
Buf[14]=(byte)(B>>16);
|
||||
Buf[15]=(byte)(B>>24);
|
||||
#else
|
||||
BufPtr[0]=C^Key[0];
|
||||
BufPtr[1]=D^Key[1];
|
||||
BufPtr[2]=A^Key[2];
|
||||
BufPtr[3]=B^Key[3];
|
||||
#endif
|
||||
UpdKeys(InBuf);
|
||||
}
|
||||
|
||||
|
||||
void CryptData::UpdKeys(byte *Buf)
|
||||
{
|
||||
for (int I=0;I<16;I+=4)
|
||||
{
|
||||
Key[0]^=CRCTab[Buf[I]];
|
||||
Key[1]^=CRCTab[Buf[I+1]];
|
||||
Key[2]^=CRCTab[Buf[I+2]];
|
||||
Key[3]^=CRCTab[Buf[I+3]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Swap(byte *Ch1,byte *Ch2)
|
||||
{
|
||||
byte Ch=*Ch1;
|
||||
*Ch1=*Ch2;
|
||||
*Ch2=Ch;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
|
||||
{
|
||||
if (*Password==0)
|
||||
return;
|
||||
if (OldOnly)
|
||||
switch(Method)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
if (CRCTab[1]==0)
|
||||
InitCRC();
|
||||
char Psw[MAXPASSWORD];
|
||||
memset(Psw,0,sizeof(Psw));
|
||||
|
||||
// We need to use ASCII password for older encryption algorithms.
|
||||
WideToChar(Password,Psw,ASIZE(Psw));
|
||||
Psw[ASIZE(Psw)-1]=0;
|
||||
|
||||
size_t PswLength=strlen(Psw);
|
||||
|
||||
SetOldKeys(Psw);
|
||||
Key[0]=0xD3A3B879L;
|
||||
Key[1]=0x3F6D12F7L;
|
||||
Key[2]=0x7515A235L;
|
||||
Key[3]=0xA4E7F123L;
|
||||
|
||||
memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
|
||||
for (int J=0;J<256;J++)
|
||||
for (size_t I=0;I<PswLength;I+=2)
|
||||
{
|
||||
uint N1=(byte)CRCTab [ (byte(Psw[I]) - J) &0xff];
|
||||
uint N2=(byte)CRCTab [ (byte(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 (size_t I=0;I<PswLength;I+=16)
|
||||
EncryptBlock20((byte *)&Psw[I]);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
bool Cached=false;
|
||||
for (uint I=0;I<ASIZE(Cache);I++)
|
||||
if (wcscmp(Cache[I].Password,Password)==0 &&
|
||||
(Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
|
||||
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&
|
||||
Cache[I].HandsOffHash==HandsOffHash)
|
||||
{
|
||||
memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey));
|
||||
memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit));
|
||||
Cached=true;
|
||||
case CRYPT_RAR13:
|
||||
Decrypt13(Buf,Size);
|
||||
break;
|
||||
case CRYPT_RAR15:
|
||||
Crypt15(Buf,Size);
|
||||
break;
|
||||
case CRYPT_RAR20:
|
||||
for (size_t I=0;I<Size;I+=CRYPT_BLOCK_SIZE)
|
||||
DecryptBlock20(Buf+I);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Cached)
|
||||
{
|
||||
byte RawPsw[2*MAXPASSWORD+SALT_SIZE];
|
||||
WideToRaw(Password,RawPsw);
|
||||
size_t RawLength=2*wcslen(Password);
|
||||
if (Salt!=NULL)
|
||||
{
|
||||
memcpy(RawPsw+RawLength,Salt,SALT_SIZE);
|
||||
RawLength+=SALT_SIZE;
|
||||
}
|
||||
hash_context c;
|
||||
hash_initial(&c);
|
||||
|
||||
const int HashRounds=0x40000;
|
||||
for (int I=0;I<HashRounds;I++)
|
||||
{
|
||||
hash_process( &c, RawPsw, RawLength, HandsOffHash);
|
||||
byte PswNum[3];
|
||||
PswNum[0]=(byte)I;
|
||||
PswNum[1]=(byte)(I>>8);
|
||||
PswNum[2]=(byte)(I>>16);
|
||||
hash_process( &c, PswNum, 3, HandsOffHash);
|
||||
if (I%(HashRounds/16)==0)
|
||||
{
|
||||
hash_context tempc=c;
|
||||
uint32 digest[5];
|
||||
hash_final( &tempc, digest, HandsOffHash);
|
||||
AESInit[I/(HashRounds/16)]=(byte)digest[4];
|
||||
}
|
||||
}
|
||||
uint32 digest[5];
|
||||
hash_final( &c, digest, HandsOffHash);
|
||||
for (int I=0;I<4;I++)
|
||||
for (int J=0;J<4;J++)
|
||||
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
||||
|
||||
wcscpy(Cache[CachePos].Password,Password);
|
||||
if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true)
|
||||
memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE);
|
||||
Cache[CachePos].HandsOffHash=HandsOffHash;
|
||||
memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey));
|
||||
memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit));
|
||||
CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0]));
|
||||
}
|
||||
rin.init(Encrypt ? Rijndael::Encrypt : Rijndael::Decrypt,AESKey,AESInit);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void CryptData::SetOldKeys(const char *Password)
|
||||
{
|
||||
uint PswCRC=CRC(0xffffffff,Password,strlen(Password));
|
||||
OldKey[0]=PswCRC&0xffff;
|
||||
OldKey[1]=(PswCRC>>16)&0xffff;
|
||||
OldKey[2]=OldKey[3]=0;
|
||||
PN1=PN2=PN3=0;
|
||||
byte Ch;
|
||||
while ((Ch=*Password)!=0)
|
||||
{
|
||||
PN1+=Ch;
|
||||
PN2^=Ch;
|
||||
PN3+=Ch;
|
||||
PN3=(byte)rol(PN3,1,8);
|
||||
OldKey[2]^=Ch^CRCTab[Ch];
|
||||
OldKey[3]+=Ch+(CRCTab[Ch]>>16);
|
||||
Password++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::SetAV15Encryption()
|
||||
{
|
||||
OldKey[0]=0x4765;
|
||||
OldKey[1]=0x9021;
|
||||
OldKey[2]=0x7382;
|
||||
OldKey[3]=0x5215;
|
||||
}
|
||||
|
||||
|
||||
void CryptData::SetCmt13Encryption()
|
||||
{
|
||||
PN1=0;
|
||||
PN2=7;
|
||||
PN3=77;
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Crypt(byte *Data,uint Count,int Method)
|
||||
{
|
||||
if (Method==OLD_DECODE)
|
||||
Decode13(Data,Count);
|
||||
else
|
||||
if (Method==OLD_ENCODE)
|
||||
Encode13(Data,Count);
|
||||
else
|
||||
Crypt15(Data,Count);
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Encode13(byte *Data,uint Count)
|
||||
{
|
||||
while (Count--)
|
||||
{
|
||||
PN2+=PN3;
|
||||
PN1+=PN2;
|
||||
*Data+=PN1;
|
||||
Data++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Decode13(byte *Data,uint Count)
|
||||
{
|
||||
while (Count--)
|
||||
{
|
||||
PN2+=PN3;
|
||||
PN1+=PN2;
|
||||
*Data-=PN1;
|
||||
Data++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Crypt15(byte *Data,uint Count)
|
||||
{
|
||||
while (Count--)
|
||||
{
|
||||
OldKey[0]+=0x1234;
|
||||
OldKey[1]^=CRCTab[(OldKey[0] & 0x1fe)>>1];
|
||||
OldKey[2]-=CRCTab[(OldKey[0] & 0x1fe)>>1]>>16;
|
||||
OldKey[0]^=OldKey[2];
|
||||
OldKey[3]=ror(OldKey[3]&0xffff,1,16)^OldKey[1];
|
||||
OldKey[3]=ror(OldKey[3]&0xffff,1,16);
|
||||
OldKey[0]^=OldKey[3];
|
||||
*Data^=(byte)(OldKey[0]>>8);
|
||||
Data++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
case CRYPT_RAR30:
|
||||
case CRYPT_RAR50:
|
||||
rin.blockDecrypt(Buf,Size,Buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CryptData::SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,
|
||||
SecPassword *Password,const byte *Salt,
|
||||
const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck)
|
||||
{
|
||||
if (!Password->IsSet() || Method==CRYPT_NONE)
|
||||
return false;
|
||||
|
||||
CryptData::Method=Method;
|
||||
|
||||
wchar PwdW[MAXPASSWORD];
|
||||
Password->Get(PwdW,ASIZE(PwdW));
|
||||
char PwdA[MAXPASSWORD];
|
||||
WideToChar(PwdW,PwdA,ASIZE(PwdA));
|
||||
|
||||
switch(Method)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
case CRYPT_RAR13:
|
||||
SetKey13(PwdA);
|
||||
break;
|
||||
case CRYPT_RAR15:
|
||||
SetKey15(PwdA);
|
||||
break;
|
||||
case CRYPT_RAR20:
|
||||
SetKey20(PwdA);
|
||||
break;
|
||||
#endif
|
||||
case CRYPT_RAR30:
|
||||
SetKey30(Encrypt,Password,PwdW,Salt);
|
||||
break;
|
||||
case CRYPT_RAR50:
|
||||
SetKey50(Encrypt,Password,PwdW,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
|
||||
break;
|
||||
}
|
||||
cleandata(PwdA,sizeof(PwdA));
|
||||
cleandata(PwdW,sizeof(PwdW));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Use the current system time to additionally randomize data.
|
||||
static void TimeRandomize(byte *RndBuf,size_t BufSize)
|
||||
{
|
||||
static uint Count=0;
|
||||
RarTime CurTime;
|
||||
CurTime.SetCurrentTime();
|
||||
uint64 Random=CurTime.GetWin()+clock();
|
||||
for (size_t I=0;I<BufSize;I++)
|
||||
{
|
||||
byte RndByte = byte (Random >> ( (I & 7) * 8 ));
|
||||
RndBuf[I]=byte( (RndByte ^ I) + Count++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Fill buffer with random data.
|
||||
void GetRnd(byte *RndBuf,size_t BufSize)
|
||||
{
|
||||
bool Success=false;
|
||||
#if defined(_WIN_ALL)
|
||||
HCRYPTPROV hProvider = 0;
|
||||
if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
{
|
||||
Success=CryptGenRandom(hProvider, (DWORD)BufSize, RndBuf) == TRUE;
|
||||
CryptReleaseContext(hProvider, 0);
|
||||
}
|
||||
#elif defined(_UNIX)
|
||||
FILE *rndf = fopen("/dev/urandom", "r");
|
||||
if (rndf!=NULL)
|
||||
{
|
||||
Success=fread(RndBuf, BufSize, 1, rndf) == BufSize;
|
||||
fclose(rndf);
|
||||
}
|
||||
#endif
|
||||
// We use this code only as the last resort if code above failed.
|
||||
if (!Success)
|
||||
TimeRandomize(RndBuf,BufSize);
|
||||
}
|
||||
|
||||
127
unrar/crypt.hpp
127
unrar/crypt.hpp
@@ -1,62 +1,101 @@
|
||||
#ifndef _RAR_CRYPT_
|
||||
#define _RAR_CRYPT_
|
||||
|
||||
enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
|
||||
|
||||
|
||||
struct CryptKeyCacheItem
|
||||
{
|
||||
#ifndef _SFX_RTL_
|
||||
CryptKeyCacheItem()
|
||||
{
|
||||
*Password=0;
|
||||
}
|
||||
|
||||
~CryptKeyCacheItem()
|
||||
{
|
||||
memset(AESKey,0,sizeof(AESKey));
|
||||
memset(AESInit,0,sizeof(AESInit));
|
||||
memset(Password,0,sizeof(Password));
|
||||
}
|
||||
#endif
|
||||
byte AESKey[16],AESInit[16];
|
||||
wchar Password[MAXPASSWORD];
|
||||
bool SaltPresent;
|
||||
byte Salt[SALT_SIZE];
|
||||
bool HandsOffHash;
|
||||
enum CRYPT_METHOD {
|
||||
CRYPT_NONE,CRYPT_RAR13,CRYPT_RAR15,CRYPT_RAR20,CRYPT_RAR30,CRYPT_RAR50
|
||||
};
|
||||
|
||||
#define SIZE_SALT50 16
|
||||
#define SIZE_SALT30 8
|
||||
#define SIZE_INITV 16
|
||||
#define SIZE_PSWCHECK 8
|
||||
#define SIZE_PSWCHECK_CSUM 4
|
||||
|
||||
#define CRYPT_BLOCK_SIZE 16
|
||||
#define CRYPT_BLOCK_MASK (CRYPT_BLOCK_SIZE-1) // 0xf
|
||||
|
||||
#define CRYPT5_KDF_LG2_COUNT 15 // LOG2 of PDKDF2 iteration count.
|
||||
#define CRYPT5_KDF_LG2_COUNT_MAX 24 // LOG2 of maximum accepted iteration count.
|
||||
#define CRYPT_VERSION 0 // Supported encryption version.
|
||||
|
||||
|
||||
class CryptData
|
||||
{
|
||||
struct KDF5CacheItem
|
||||
{
|
||||
SecPassword Pwd;
|
||||
byte Salt[SIZE_SALT50];
|
||||
byte Key[32];
|
||||
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||
byte PswCheckValue[SHA256_DIGEST_SIZE];
|
||||
byte HashKeyValue[SHA256_DIGEST_SIZE];
|
||||
};
|
||||
|
||||
struct KDF3CacheItem
|
||||
{
|
||||
SecPassword Pwd;
|
||||
byte Salt[SIZE_SALT30];
|
||||
byte Key[16];
|
||||
byte Init[16];
|
||||
bool SaltPresent;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
void Encode13(byte *Data,uint Count);
|
||||
void Decode13(byte *Data,uint Count);
|
||||
void Crypt15(byte *Data,uint Count);
|
||||
void UpdKeys(byte *Buf);
|
||||
void Swap(byte *Ch1,byte *Ch2);
|
||||
void SetOldKeys(const char *Password);
|
||||
void SetKey13(const char *Password);
|
||||
void Decrypt13(byte *Data,size_t Count);
|
||||
|
||||
Rijndael rin;
|
||||
|
||||
byte SubstTable[256];
|
||||
uint Key[4];
|
||||
ushort OldKey[4];
|
||||
byte PN1,PN2,PN3;
|
||||
void SetKey15(const char *Password);
|
||||
void Crypt15(byte *Data,size_t Count);
|
||||
|
||||
byte AESKey[16],AESInit[16];
|
||||
|
||||
static CryptKeyCacheItem Cache[4];
|
||||
static int CachePos;
|
||||
public:
|
||||
void SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
|
||||
void SetAV15Encryption();
|
||||
void SetCmt13Encryption();
|
||||
void SetKey20(const char *Password);
|
||||
void Swap20(byte *Ch1,byte *Ch2);
|
||||
void UpdKeys20(byte *Buf);
|
||||
void EncryptBlock20(byte *Buf);
|
||||
void DecryptBlock20(byte *Buf);
|
||||
|
||||
void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt);
|
||||
void SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck);
|
||||
|
||||
KDF3CacheItem KDF3Cache[4];
|
||||
uint KDF3CachePos;
|
||||
|
||||
KDF5CacheItem KDF5Cache[4];
|
||||
uint KDF5CachePos;
|
||||
|
||||
CRYPT_METHOD Method;
|
||||
|
||||
Rijndael rin;
|
||||
|
||||
uint CRCTab[256]; // For RAR 1.5 and RAR 2.0 encryption.
|
||||
|
||||
byte SubstTable20[256];
|
||||
uint Key20[4];
|
||||
|
||||
byte Key13[3];
|
||||
ushort Key15[4];
|
||||
public:
|
||||
CryptData();
|
||||
~CryptData();
|
||||
bool SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
|
||||
const byte *Salt,const byte *InitV,uint Lg2Cnt,
|
||||
byte *HashKey,byte *PswCheck);
|
||||
void SetAV15Encryption();
|
||||
void SetCmt13Encryption();
|
||||
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);
|
||||
static void SetSalt(byte *Salt,size_t SaltSize);
|
||||
};
|
||||
|
||||
void GetRnd(byte *RndBuf,size_t BufSize);
|
||||
|
||||
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
|
||||
size_t DataLength,byte *ResDigest);
|
||||
void pbkdf2(const byte *pass, size_t pass_len, const byte *salt,
|
||||
size_t salt_len,byte *key, byte *Value1, byte *Value2,
|
||||
uint rounds);
|
||||
|
||||
void ConvertHashToMAC(HashValue *Value,byte *Key);
|
||||
|
||||
#endif
|
||||
|
||||
79
unrar/crypt1.cpp
Normal file
79
unrar/crypt1.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
extern uint CRCTab[256];
|
||||
|
||||
void CryptData::SetKey13(const char *Password)
|
||||
{
|
||||
Key13[0]=Key13[1]=Key13[2]=0;
|
||||
for (size_t I=0;Password[I]!=0;I++)
|
||||
{
|
||||
byte P=Password[I];
|
||||
Key13[0]+=P;
|
||||
Key13[1]^=P;
|
||||
Key13[2]+=P;
|
||||
Key13[2]=(byte)rotls(Key13[2],1,8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::SetKey15(const char *Password)
|
||||
{
|
||||
InitCRC32(CRCTab);
|
||||
uint PswCRC=CRC32(0xffffffff,Password,strlen(Password));
|
||||
Key15[0]=PswCRC&0xffff;
|
||||
Key15[1]=(PswCRC>>16)&0xffff;
|
||||
Key15[2]=Key15[3]=0;
|
||||
for (size_t I=0;Password[I]!=0;I++)
|
||||
{
|
||||
byte P=Password[I];
|
||||
Key15[2]^=P^CRCTab[P];
|
||||
Key15[3]+=P+(CRCTab[P]>>16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::SetAV15Encryption()
|
||||
{
|
||||
InitCRC32(CRCTab);
|
||||
Method=CRYPT_RAR15;
|
||||
Key15[0]=0x4765;
|
||||
Key15[1]=0x9021;
|
||||
Key15[2]=0x7382;
|
||||
Key15[3]=0x5215;
|
||||
}
|
||||
|
||||
|
||||
void CryptData::SetCmt13Encryption()
|
||||
{
|
||||
Method=CRYPT_RAR13;
|
||||
Key13[0]=0;
|
||||
Key13[1]=7;
|
||||
Key13[2]=77;
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Decrypt13(byte *Data,size_t Count)
|
||||
{
|
||||
while (Count--)
|
||||
{
|
||||
Key13[1]+=Key13[2];
|
||||
Key13[0]+=Key13[1];
|
||||
*Data-=Key13[0];
|
||||
Data++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Crypt15(byte *Data,size_t Count)
|
||||
{
|
||||
while (Count--)
|
||||
{
|
||||
Key15[0]+=0x1234;
|
||||
Key15[1]^=CRCTab[(Key15[0] & 0x1fe)>>1];
|
||||
Key15[2]-=CRCTab[(Key15[0] & 0x1fe)>>1]>>16;
|
||||
Key15[0]^=Key15[2];
|
||||
Key15[3]=rotrs(Key15[3]&0xffff,1,16)^Key15[1];
|
||||
Key15[3]=rotrs(Key15[3]&0xffff,1,16);
|
||||
Key15[0]^=Key15[3];
|
||||
*Data^=(byte)(Key15[0]>>8);
|
||||
Data++;
|
||||
}
|
||||
}
|
||||
133
unrar/crypt2.cpp
Normal file
133
unrar/crypt2.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#define NROUNDS 32
|
||||
|
||||
#define substLong(t) ( (uint)SubstTable20[(uint)t&255] | \
|
||||
((uint)SubstTable20[(int)(t>> 8)&255]<< 8) | \
|
||||
((uint)SubstTable20[(int)(t>>16)&255]<<16) | \
|
||||
((uint)SubstTable20[(int)(t>>24)&255]<<24) )
|
||||
|
||||
|
||||
static byte InitSubstTable20[256]={
|
||||
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
|
||||
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
|
||||
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
|
||||
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
|
||||
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
|
||||
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
|
||||
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
|
||||
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
|
||||
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
|
||||
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
|
||||
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
|
||||
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
|
||||
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
|
||||
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
|
||||
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
|
||||
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
|
||||
};
|
||||
|
||||
|
||||
void CryptData::SetKey20(const char *Password)
|
||||
{
|
||||
InitCRC32(CRCTab);
|
||||
|
||||
char Psw[MAXPASSWORD];
|
||||
strncpyz(Psw,Password,ASIZE(Psw)); // We'll need to modify it below.
|
||||
size_t PswLength=strlen(Psw);
|
||||
|
||||
Key20[0]=0xD3A3B879L;
|
||||
Key20[1]=0x3F6D12F7L;
|
||||
Key20[2]=0x7515A235L;
|
||||
Key20[3]=0xA4E7F123L;
|
||||
|
||||
memcpy(SubstTable20,InitSubstTable20,sizeof(SubstTable20));
|
||||
for (uint J=0;J<256;J++)
|
||||
for (size_t I=0;I<PswLength;I+=2)
|
||||
{
|
||||
uint N1=(byte)CRCTab [ (byte(Password[I]) - J) &0xff];
|
||||
uint N2=(byte)CRCTab [ (byte(Password[I+1]) + J) &0xff];
|
||||
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
|
||||
Swap20(&SubstTable20[N1],&SubstTable20[(N1+I+K)&0xff]);
|
||||
}
|
||||
|
||||
// Incomplete last block of password must be zero padded.
|
||||
if ((PswLength & CRYPT_BLOCK_MASK)!=0)
|
||||
for (size_t I=PswLength;I<=(PswLength|CRYPT_BLOCK_MASK);I++)
|
||||
Psw[I]=0;
|
||||
|
||||
for (size_t I=0;I<PswLength;I+=CRYPT_BLOCK_SIZE)
|
||||
EncryptBlock20((byte *)Psw+I);
|
||||
}
|
||||
|
||||
|
||||
void CryptData::EncryptBlock20(byte *Buf)
|
||||
{
|
||||
uint A,B,C,D,T,TA,TB;
|
||||
A=RawGet4(Buf+0)^Key20[0];
|
||||
B=RawGet4(Buf+4)^Key20[1];
|
||||
C=RawGet4(Buf+8)^Key20[2];
|
||||
D=RawGet4(Buf+12)^Key20[3];
|
||||
for(int I=0;I<NROUNDS;I++)
|
||||
{
|
||||
T=((C+rotls(D,11,32))^Key20[I&3]);
|
||||
TA=A^substLong(T);
|
||||
T=((D^rotls(C,17,32))+Key20[I&3]);
|
||||
TB=B^substLong(T);
|
||||
A=C;
|
||||
B=D;
|
||||
C=TA;
|
||||
D=TB;
|
||||
}
|
||||
RawPut4(C^Key20[0],Buf+0);
|
||||
RawPut4(D^Key20[1],Buf+4);
|
||||
RawPut4(A^Key20[2],Buf+8);
|
||||
RawPut4(B^Key20[3],Buf+12);
|
||||
UpdKeys20(Buf);
|
||||
}
|
||||
|
||||
|
||||
void CryptData::DecryptBlock20(byte *Buf)
|
||||
{
|
||||
byte InBuf[16];
|
||||
uint A,B,C,D,T,TA,TB;
|
||||
A=RawGet4(Buf+0)^Key20[0];
|
||||
B=RawGet4(Buf+4)^Key20[1];
|
||||
C=RawGet4(Buf+8)^Key20[2];
|
||||
D=RawGet4(Buf+12)^Key20[3];
|
||||
memcpy(InBuf,Buf,sizeof(InBuf));
|
||||
for(int I=NROUNDS-1;I>=0;I--)
|
||||
{
|
||||
T=((C+rotls(D,11,32))^Key20[I&3]);
|
||||
TA=A^substLong(T);
|
||||
T=((D^rotls(C,17,32))+Key20[I&3]);
|
||||
TB=B^substLong(T);
|
||||
A=C;
|
||||
B=D;
|
||||
C=TA;
|
||||
D=TB;
|
||||
}
|
||||
RawPut4(C^Key20[0],Buf+0);
|
||||
RawPut4(D^Key20[1],Buf+4);
|
||||
RawPut4(A^Key20[2],Buf+8);
|
||||
RawPut4(B^Key20[3],Buf+12);
|
||||
UpdKeys20(InBuf);
|
||||
}
|
||||
|
||||
|
||||
void CryptData::UpdKeys20(byte *Buf)
|
||||
{
|
||||
for (int I=0;I<16;I+=4)
|
||||
{
|
||||
Key20[0]^=CRCTab[Buf[I]];
|
||||
Key20[1]^=CRCTab[Buf[I+1]];
|
||||
Key20[2]^=CRCTab[Buf[I+2]];
|
||||
Key20[3]^=CRCTab[Buf[I+3]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CryptData::Swap20(byte *Ch1,byte *Ch2)
|
||||
{
|
||||
byte Ch=*Ch1;
|
||||
*Ch1=*Ch2;
|
||||
*Ch2=Ch;
|
||||
}
|
||||
7
unrar/crypt2.loT
Normal file
7
unrar/crypt2.loT
Normal file
@@ -0,0 +1,7 @@
|
||||
# unrar/crypt2.lo - a libtool object file
|
||||
# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.492 2008/01/30 06:40:56)
|
||||
#
|
||||
# Please DO NOT delete this file!
|
||||
# It is necessary for linking the library.
|
||||
|
||||
# Name of the PIC object.
|
||||
68
unrar/crypt3.cpp
Normal file
68
unrar/crypt3.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt)
|
||||
{
|
||||
byte AESKey[16],AESInit[16];
|
||||
|
||||
bool Cached=false;
|
||||
for (uint I=0;I<ASIZE(KDF3Cache);I++)
|
||||
if (KDF3Cache[I].Pwd==*Password &&
|
||||
(Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL &&
|
||||
KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0))
|
||||
{
|
||||
memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey));
|
||||
SecHideData(AESKey,sizeof(AESKey),false,false);
|
||||
memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit));
|
||||
Cached=true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Cached)
|
||||
{
|
||||
byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
|
||||
WideToRaw(PwdW,RawPsw,ASIZE(RawPsw));
|
||||
size_t RawLength=2*wcslen(PwdW);
|
||||
if (Salt!=NULL)
|
||||
{
|
||||
memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
|
||||
RawLength+=SIZE_SALT30;
|
||||
}
|
||||
sha1_context c;
|
||||
sha1_init(&c);
|
||||
|
||||
const int HashRounds=0x40000;
|
||||
for (int I=0;I<HashRounds;I++)
|
||||
{
|
||||
sha1_process_rar29( &c, RawPsw, RawLength );
|
||||
byte PswNum[3];
|
||||
PswNum[0]=(byte)I;
|
||||
PswNum[1]=(byte)(I>>8);
|
||||
PswNum[2]=(byte)(I>>16);
|
||||
sha1_process(&c, PswNum, 3);
|
||||
if (I%(HashRounds/16)==0)
|
||||
{
|
||||
sha1_context tempc=c;
|
||||
uint32 digest[5];
|
||||
sha1_done( &tempc, digest );
|
||||
AESInit[I/(HashRounds/16)]=(byte)digest[4];
|
||||
}
|
||||
}
|
||||
uint32 digest[5];
|
||||
sha1_done( &c, digest );
|
||||
for (int I=0;I<4;I++)
|
||||
for (int J=0;J<4;J++)
|
||||
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
||||
|
||||
KDF3Cache[KDF3CachePos].Pwd=*Password;
|
||||
if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true)
|
||||
memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30);
|
||||
memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey));
|
||||
SecHideData(KDF3Cache[KDF3CachePos].Key,sizeof(KDF3Cache[KDF3CachePos].Key),true,false);
|
||||
memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit));
|
||||
KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache);
|
||||
|
||||
cleandata(RawPsw,sizeof(RawPsw));
|
||||
}
|
||||
rin.Init(Encrypt, AESKey, 128, AESInit);
|
||||
cleandata(AESKey,sizeof(AESKey));
|
||||
cleandata(AESInit,sizeof(AESInit));
|
||||
}
|
||||
|
||||
233
unrar/crypt5.cpp
Normal file
233
unrar/crypt5.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
|
||||
size_t DataLength,byte *ResDigest,
|
||||
sha256_context *ICtxOpt,bool *SetIOpt,
|
||||
sha256_context *RCtxOpt,bool *SetROpt)
|
||||
{
|
||||
const size_t Sha256BlockSize=64; // As defined in RFC 4868.
|
||||
|
||||
byte KeyHash[SHA256_DIGEST_SIZE];
|
||||
if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash.
|
||||
{
|
||||
sha256_context KCtx;
|
||||
sha256_init(&KCtx);
|
||||
sha256_process(&KCtx, Key, KeyLength);
|
||||
sha256_done(&KCtx, KeyHash);
|
||||
|
||||
Key = KeyHash;
|
||||
KeyLength = SHA256_DIGEST_SIZE;
|
||||
}
|
||||
|
||||
byte KeyBuf[Sha256BlockSize]; // Store the padded key here.
|
||||
sha256_context ICtx;
|
||||
|
||||
if (ICtxOpt!=NULL && *SetIOpt)
|
||||
ICtx=*ICtxOpt; // Use already calculated first block context.
|
||||
else
|
||||
{
|
||||
// This calculation is the same for all iterations with same password.
|
||||
// So for PBKDF2 we can calculate it only for first block and then reuse
|
||||
// to improve performance.
|
||||
|
||||
for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest.
|
||||
KeyBuf[I] = Key[I] ^ 0x36;
|
||||
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
|
||||
KeyBuf[I] = 0x36;
|
||||
|
||||
sha256_init(&ICtx);
|
||||
sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key.
|
||||
}
|
||||
|
||||
if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse.
|
||||
{
|
||||
*ICtxOpt=ICtx;
|
||||
*SetIOpt=true;
|
||||
}
|
||||
|
||||
sha256_process(&ICtx, Data, DataLength); // Hash data.
|
||||
|
||||
byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data.
|
||||
sha256_done(&ICtx, IDig);
|
||||
|
||||
sha256_context RCtx;
|
||||
|
||||
if (RCtxOpt!=NULL && *SetROpt)
|
||||
RCtx=*RCtxOpt; // Use already calculated first block context.
|
||||
else
|
||||
{
|
||||
// This calculation is the same for all iterations with same password.
|
||||
// So for PBKDF2 we can calculate it only for first block and then reuse
|
||||
// to improve performance.
|
||||
|
||||
for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding.
|
||||
KeyBuf[I] = Key[I] ^ 0x5c;
|
||||
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
|
||||
KeyBuf[I] = 0x5c;
|
||||
|
||||
sha256_init(&RCtx);
|
||||
sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key.
|
||||
}
|
||||
|
||||
if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse.
|
||||
{
|
||||
*RCtxOpt=RCtx;
|
||||
*SetROpt=true;
|
||||
}
|
||||
|
||||
sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest.
|
||||
|
||||
sha256_done(&RCtx, ResDigest);
|
||||
}
|
||||
|
||||
|
||||
// PBKDF2 for 32 byte key length. We generate the key for specified number
|
||||
// of iteration count also as two supplementary values (key for checksums
|
||||
// and password verification) for iterations+16 and iterations+32.
|
||||
void pbkdf2(const byte *Pwd, size_t PwdLength,
|
||||
const byte *Salt, size_t SaltLength,
|
||||
byte *Key, byte *V1, byte *V2, uint Count)
|
||||
{
|
||||
const size_t MaxSalt=64;
|
||||
byte SaltData[MaxSalt+4];
|
||||
memcpy(SaltData, Salt, Min(SaltLength,MaxSalt));
|
||||
|
||||
SaltData[SaltLength + 0] = 0; // Salt concatenated to 1.
|
||||
SaltData[SaltLength + 1] = 0;
|
||||
SaltData[SaltLength + 2] = 0;
|
||||
SaltData[SaltLength + 3] = 1;
|
||||
|
||||
// First iteration: HMAC of password, salt and block index (1).
|
||||
byte U1[SHA256_DIGEST_SIZE];
|
||||
hmac_sha256(Pwd, PwdLength, SaltData, SaltLength + 4, U1, NULL, NULL, NULL, NULL);
|
||||
byte Fn[SHA256_DIGEST_SIZE]; // Current function value.
|
||||
memcpy(Fn, U1, sizeof(Fn)); // Function at first iteration.
|
||||
|
||||
uint CurCount[] = { Count-1, 16, 16 };
|
||||
byte *CurValue[] = { Key , V1, V2 };
|
||||
|
||||
sha256_context ICtxOpt,RCtxOpt;
|
||||
bool SetIOpt=false,SetROpt=false;
|
||||
|
||||
byte U2[SHA256_DIGEST_SIZE];
|
||||
for (uint I = 0; I < 3; I++) // For output key and 2 supplementary values.
|
||||
{
|
||||
for (uint J = 0; J < CurCount[I]; J++)
|
||||
{
|
||||
// U2 = PRF (P, U1).
|
||||
hmac_sha256(Pwd, PwdLength, U1, sizeof(U1), U2, &ICtxOpt, &SetIOpt, &RCtxOpt, &SetROpt);
|
||||
memcpy(U1, U2, sizeof(U1));
|
||||
for (uint K = 0; K < sizeof(Fn); K++) // Function ^= U.
|
||||
Fn[K] ^= U1[K];
|
||||
}
|
||||
memcpy(CurValue[I], Fn, SHA256_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
cleandata(SaltData, sizeof(SaltData));
|
||||
cleandata(Fn, sizeof(Fn));
|
||||
cleandata(U1, sizeof(U1));
|
||||
cleandata(U2, sizeof(U2));
|
||||
}
|
||||
|
||||
|
||||
void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,
|
||||
const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,
|
||||
byte *PswCheck)
|
||||
{
|
||||
if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX)
|
||||
return;
|
||||
|
||||
byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE];
|
||||
bool Found=false;
|
||||
for (uint I=0;I<ASIZE(KDF5Cache);I++)
|
||||
{
|
||||
KDF5CacheItem *Item=KDF5Cache+I;
|
||||
if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password &&
|
||||
memcmp(Item->Salt,Salt,SIZE_SALT50)==0)
|
||||
{
|
||||
memcpy(Key,Item->Key,sizeof(Key));
|
||||
SecHideData(Key,sizeof(Key),false,false);
|
||||
|
||||
memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue));
|
||||
memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue));
|
||||
Found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Found)
|
||||
{
|
||||
char PwdUtf[MAXPASSWORD*4];
|
||||
WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf));
|
||||
|
||||
pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt));
|
||||
cleandata(PwdUtf,sizeof(PwdUtf));
|
||||
|
||||
KDF5CacheItem *Item=KDF5Cache+(KDF5CachePos++ % ASIZE(KDF5Cache));
|
||||
Item->Lg2Count=Lg2Cnt;
|
||||
Item->Pwd=*Password;
|
||||
memcpy(Item->Salt,Salt,SIZE_SALT50);
|
||||
memcpy(Item->Key,Key,sizeof(Item->Key));
|
||||
memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue));
|
||||
memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue));
|
||||
SecHideData(Item->Key,sizeof(Item->Key),true,false);
|
||||
}
|
||||
if (HashKey!=NULL)
|
||||
memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE);
|
||||
if (PswCheck!=NULL)
|
||||
{
|
||||
memset(PswCheck,0,SIZE_PSWCHECK);
|
||||
for (uint I=0;I<SHA256_DIGEST_SIZE;I++)
|
||||
PswCheck[I%SIZE_PSWCHECK]^=PswCheckValue[I];
|
||||
cleandata(PswCheckValue,sizeof(PswCheckValue));
|
||||
}
|
||||
|
||||
// NULL initialization vector is possible if we only need the password
|
||||
// check value for archive encryption header.
|
||||
if (InitV!=NULL)
|
||||
rin.Init(Encrypt, Key, 256, InitV);
|
||||
|
||||
cleandata(Key,sizeof(Key));
|
||||
}
|
||||
|
||||
|
||||
void ConvertHashToMAC(HashValue *Value,byte *Key)
|
||||
{
|
||||
if (Value->Type==HASH_CRC32)
|
||||
{
|
||||
byte RawCRC[4];
|
||||
RawPut4(Value->CRC32,RawCRC);
|
||||
byte Digest[SHA256_DIGEST_SIZE];
|
||||
hmac_sha256(Key,SHA256_DIGEST_SIZE,RawCRC,sizeof(RawCRC),Digest,NULL,NULL,NULL,NULL);
|
||||
Value->CRC32=0;
|
||||
for (uint I=0;I<ASIZE(Digest);I++)
|
||||
Value->CRC32^=Digest[I] << ((I & 3) * 8);
|
||||
}
|
||||
if (Value->Type==HASH_BLAKE2)
|
||||
{
|
||||
byte Digest[BLAKE2_DIGEST_SIZE];
|
||||
hmac_sha256(Key,BLAKE2_DIGEST_SIZE,Value->Digest,sizeof(Value->Digest),Digest,NULL,NULL,NULL,NULL);
|
||||
memcpy(Value->Digest,Digest,sizeof(Value->Digest));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void TestPBKDF2();
|
||||
struct TestKDF {TestKDF() {TestPBKDF2();exit(0);}} GlobalTestKDF;
|
||||
|
||||
void TestPBKDF2() // Test PBKDF2 HMAC-SHA256
|
||||
{
|
||||
byte Key[32],V1[32],V2[32];
|
||||
|
||||
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 1);
|
||||
byte Res1[32]={0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, 0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48, 0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b };
|
||||
mprintf(L"\nPBKDF2 test1: %s", memcmp(Key,Res1,32)==0 ? L"OK":L"Failed");
|
||||
|
||||
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 4096);
|
||||
byte Res2[32]={0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, 0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11, 0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a };
|
||||
mprintf(L"\nPBKDF2 test2: %s", memcmp(Key,Res2,32)==0 ? L"OK":L"Failed");
|
||||
|
||||
pbkdf2((byte *)"just some long string pretending to be a password", 49, (byte *)"salt, salt, salt, a lot of salt", 31, Key, V1, V2, 65536);
|
||||
byte Res3[32]={0x08, 0x0f, 0xa3, 0x1d, 0x42, 0x2d, 0xb0, 0x47, 0x83, 0x9b, 0xce, 0x3a, 0x3b, 0xce, 0x49, 0x51, 0xe2, 0x62, 0xb9, 0xff, 0x76, 0x2f, 0x57, 0xe9, 0xc4, 0x71, 0x96, 0xce, 0x4b, 0x6b, 0x6e, 0xbf};
|
||||
mprintf(L"\nPBKDF2 test3: %s", memcmp(Key,Res3,32)==0 ? L"OK":L"Failed");
|
||||
}
|
||||
#endif
|
||||
463
unrar/dll.cpp
463
unrar/dll.cpp
@@ -1,17 +1,16 @@
|
||||
#include "rar.hpp"
|
||||
#include "dll.hpp"
|
||||
|
||||
static int RarErrorToDll(int ErrCode);
|
||||
static int RarErrorToDll(RAR_EXIT ErrCode);
|
||||
|
||||
struct DataSet
|
||||
{
|
||||
CommandData Cmd;
|
||||
CmdExtract Extract;
|
||||
Archive Arc;
|
||||
CmdExtract Extract;
|
||||
int OpenMode;
|
||||
int HeaderSize;
|
||||
|
||||
DataSet():Arc(&Cmd) {};
|
||||
DataSet():Arc(&Cmd),Extract(&Cmd) {};
|
||||
};
|
||||
|
||||
|
||||
@@ -27,52 +26,97 @@ HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
|
||||
r->OpenResult=rx.OpenResult;
|
||||
r->CmtSize=rx.CmtSize;
|
||||
r->CmtState=rx.CmtState;
|
||||
return(hArc);
|
||||
return hArc;
|
||||
}
|
||||
|
||||
|
||||
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
{
|
||||
DataSet *Data=NULL;
|
||||
try
|
||||
{
|
||||
r->OpenResult=0;
|
||||
DataSet *Data=new DataSet;
|
||||
Data=new DataSet;
|
||||
Data->Cmd.DllError=0;
|
||||
Data->OpenMode=r->OpenMode;
|
||||
Data->Cmd.FileArgs->AddString("*");
|
||||
Data->Cmd.FileArgs.AddString(L"*");
|
||||
|
||||
char an[NM];
|
||||
if (r->ArcName==NULL && r->ArcNameW!=NULL)
|
||||
char AnsiArcName[NM];
|
||||
*AnsiArcName=0;
|
||||
if (r->ArcName!=NULL)
|
||||
{
|
||||
WideToChar(r->ArcNameW,an,NM);
|
||||
r->ArcName=an;
|
||||
strncpyz(AnsiArcName,r->ArcName,ASIZE(AnsiArcName));
|
||||
#ifdef _WIN_ALL
|
||||
if (!AreFileApisANSI())
|
||||
{
|
||||
OemToCharBuffA(r->ArcName,AnsiArcName,ASIZE(AnsiArcName));
|
||||
AnsiArcName[ASIZE(AnsiArcName)-1]=0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Data->Cmd.AddArcName(r->ArcName,r->ArcNameW);
|
||||
wchar ArcName[NM];
|
||||
GetWideName(AnsiArcName,r->ArcNameW,ArcName,ASIZE(ArcName));
|
||||
|
||||
Data->Cmd.AddArcName(ArcName);
|
||||
Data->Cmd.Overwrite=OVERWRITE_ALL;
|
||||
Data->Cmd.VersionControl=1;
|
||||
|
||||
Data->Cmd.Callback=r->Callback;
|
||||
Data->Cmd.UserData=r->UserData;
|
||||
|
||||
if (!Data->Arc.Open(r->ArcName,r->ArcNameW))
|
||||
// Open shared mode is added by request of dll users, who need to
|
||||
// browse and unpack archives while downloading.
|
||||
Data->Cmd.OpenShared = true;
|
||||
if (!Data->Arc.Open(ArcName,FMF_OPENSHARED))
|
||||
{
|
||||
r->OpenResult=ERAR_EOPEN;
|
||||
delete Data;
|
||||
return(NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (!Data->Arc.IsArchive(false))
|
||||
if (!Data->Arc.IsArchive(true))
|
||||
{
|
||||
r->OpenResult=Data->Cmd.DllError!=0 ? Data->Cmd.DllError:ERAR_BAD_ARCHIVE;
|
||||
if (Data->Cmd.DllError!=0)
|
||||
r->OpenResult=Data->Cmd.DllError;
|
||||
else
|
||||
{
|
||||
RAR_EXIT ErrCode=ErrHandler.GetErrorCode();
|
||||
if (ErrCode!=RARX_SUCCESS && ErrCode!=RARX_WARNING)
|
||||
r->OpenResult=RarErrorToDll(ErrCode);
|
||||
else
|
||||
r->OpenResult=ERAR_BAD_ARCHIVE;
|
||||
}
|
||||
delete Data;
|
||||
return(NULL);
|
||||
return NULL;
|
||||
}
|
||||
r->Flags=Data->Arc.NewMhd.Flags;
|
||||
Array<byte> CmtData;
|
||||
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
|
||||
r->Flags=0;
|
||||
|
||||
if (Data->Arc.Volume)
|
||||
r->Flags|=0x01;
|
||||
if (Data->Arc.Locked)
|
||||
r->Flags|=0x04;
|
||||
if (Data->Arc.Solid)
|
||||
r->Flags|=0x08;
|
||||
if (Data->Arc.NewNumbering)
|
||||
r->Flags|=0x10;
|
||||
if (Data->Arc.Signed)
|
||||
r->Flags|=0x20;
|
||||
if (Data->Arc.Protected)
|
||||
r->Flags|=0x40;
|
||||
if (Data->Arc.Encrypted)
|
||||
r->Flags|=0x80;
|
||||
if (Data->Arc.FirstVolume)
|
||||
r->Flags|=0x100;
|
||||
|
||||
Array<wchar> CmtDataW;
|
||||
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
|
||||
{
|
||||
Array<char> CmtData(CmtDataW.Size()*4+1);
|
||||
memset(&CmtData[0],0,CmtData.Size());
|
||||
WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
|
||||
size_t Size=strlen(&CmtData[0])+1;
|
||||
|
||||
r->Flags|=2;
|
||||
size_t Size=CmtData.Size()+1;
|
||||
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
||||
@@ -81,16 +125,26 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
}
|
||||
else
|
||||
r->CmtState=r->CmtSize=0;
|
||||
if (Data->Arc.Signed)
|
||||
r->Flags|=0x20;
|
||||
Data->Extract.ExtractArchiveInit(&Data->Cmd,Data->Arc);
|
||||
return((HANDLE)Data);
|
||||
Data->Extract.ExtractArchiveInit(Data->Arc);
|
||||
return (HANDLE)Data;
|
||||
}
|
||||
catch (int ErrCode)
|
||||
catch (RAR_EXIT ErrCode)
|
||||
{
|
||||
r->OpenResult=RarErrorToDll(ErrCode);
|
||||
return(NULL);
|
||||
if (Data!=NULL && Data->Cmd.DllError!=0)
|
||||
r->OpenResult=Data->Cmd.DllError;
|
||||
else
|
||||
r->OpenResult=RarErrorToDll(ErrCode);
|
||||
if (Data != NULL)
|
||||
delete Data;
|
||||
return NULL;
|
||||
}
|
||||
catch (std::bad_alloc&) // Catch 'new' exception.
|
||||
{
|
||||
r->OpenResult=ERAR_NO_MEMORY;
|
||||
if (Data != NULL)
|
||||
delete Data;
|
||||
}
|
||||
return NULL; // To make compilers happy.
|
||||
}
|
||||
|
||||
|
||||
@@ -99,130 +153,150 @@ int PASCAL RARCloseArchive(HANDLE hArcData)
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
bool Success=Data==NULL ? false:Data->Arc.Close();
|
||||
delete Data;
|
||||
return(Success ? 0:ERAR_ECLOSE);
|
||||
return Success ? ERAR_SUCCESS : ERAR_ECLOSE;
|
||||
}
|
||||
|
||||
|
||||
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
|
||||
{
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
try
|
||||
{
|
||||
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));
|
||||
}
|
||||
else
|
||||
return(ERAR_EOPEN);
|
||||
return(Data->Arc.BrokenFileHeader ? ERAR_BAD_DATA:ERAR_END_ARCHIVE);
|
||||
}
|
||||
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
|
||||
{
|
||||
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
|
||||
if (Code==0)
|
||||
return(RARReadHeader(hArcData,D));
|
||||
else
|
||||
return(Code);
|
||||
}
|
||||
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;
|
||||
D->HostOS=Data->Arc.NewLhd.HostOS;
|
||||
D->FileCRC=Data->Arc.NewLhd.FileCRC;
|
||||
D->FileTime=Data->Arc.NewLhd.FileTime;
|
||||
D->UnpVer=Data->Arc.NewLhd.UnpVer;
|
||||
D->Method=Data->Arc.NewLhd.Method;
|
||||
D->FileAttr=Data->Arc.NewLhd.FileAttr;
|
||||
D->CmtSize=0;
|
||||
D->CmtState=0;
|
||||
}
|
||||
catch (int ErrCode)
|
||||
{
|
||||
return(RarErrorToDll(ErrCode));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
struct RARHeaderDataEx X;
|
||||
memset(&X,0,sizeof(X));
|
||||
|
||||
int Code=RARReadHeaderEx(hArcData,&X);
|
||||
|
||||
strncpyz(D->ArcName,X.ArcName,ASIZE(D->ArcName));
|
||||
strncpyz(D->FileName,X.FileName,ASIZE(D->FileName));
|
||||
D->Flags=X.Flags;
|
||||
D->PackSize=X.PackSize;
|
||||
D->UnpSize=X.UnpSize;
|
||||
D->HostOS=X.HostOS;
|
||||
D->FileCRC=X.FileCRC;
|
||||
D->FileTime=X.FileTime;
|
||||
D->UnpVer=X.UnpVer;
|
||||
D->Method=X.Method;
|
||||
D->FileAttr=X.FileAttr;
|
||||
D->CmtSize=0;
|
||||
D->CmtState=0;
|
||||
|
||||
return Code;
|
||||
}
|
||||
|
||||
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||
{
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
try
|
||||
{
|
||||
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
|
||||
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(HEAD_FILE))<=0)
|
||||
{
|
||||
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
|
||||
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
|
||||
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_ENDARC &&
|
||||
Data->Arc.EndArcHead.NextVolume)
|
||||
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
||||
{
|
||||
Data->Extract.SignatureFound=false;
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
return(RARReadHeaderEx(hArcData,D));
|
||||
return RARReadHeaderEx(hArcData,D);
|
||||
}
|
||||
else
|
||||
return(ERAR_EOPEN);
|
||||
return(Data->Arc.BrokenFileHeader ? ERAR_BAD_DATA:ERAR_END_ARCHIVE);
|
||||
return ERAR_EOPEN;
|
||||
|
||||
if (Data->Arc.BrokenHeader)
|
||||
return ERAR_BAD_DATA;
|
||||
|
||||
// Might be necessary if RARSetPassword is still called instead of
|
||||
// open callback for RAR5 archives and if password is invalid.
|
||||
if (Data->Arc.FailedHeaderDecryption)
|
||||
return ERAR_BAD_PASSWORD;
|
||||
|
||||
return ERAR_END_ARCHIVE;
|
||||
}
|
||||
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
|
||||
FileHeader *hd=&Data->Arc.FileHead;
|
||||
if (Data->OpenMode==RAR_OM_LIST && hd->SplitBefore)
|
||||
{
|
||||
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
|
||||
if (Code==0)
|
||||
return(RARReadHeaderEx(hArcData,D));
|
||||
return RARReadHeaderEx(hArcData,D);
|
||||
else
|
||||
return(Code);
|
||||
return Code;
|
||||
}
|
||||
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
|
||||
if (*Data->Arc.FileNameW)
|
||||
wcsncpy(D->ArcNameW,Data->Arc.FileNameW,ASIZE(D->ArcNameW));
|
||||
else
|
||||
CharToWide(Data->Arc.FileName,D->ArcNameW);
|
||||
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
|
||||
if (*Data->Arc.NewLhd.FileNameW)
|
||||
wcsncpy(D->FileNameW,Data->Arc.NewLhd.FileNameW,ASIZE(D->FileNameW));
|
||||
else
|
||||
{
|
||||
wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
|
||||
WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName));
|
||||
|
||||
wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
|
||||
WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName));
|
||||
#ifdef _WIN_ALL
|
||||
char AnsiName[NM];
|
||||
OemToCharA(Data->Arc.NewLhd.FileName,AnsiName);
|
||||
if (!CharToWide(AnsiName,D->FileNameW,ASIZE(D->FileNameW)))
|
||||
*D->FileNameW=0;
|
||||
#else
|
||||
if (!CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW,ASIZE(D->FileNameW)))
|
||||
*D->FileNameW=0;
|
||||
CharToOemA(D->FileName,D->FileName);
|
||||
#endif
|
||||
}
|
||||
D->Flags=Data->Arc.NewLhd.Flags;
|
||||
D->PackSize=Data->Arc.NewLhd.PackSize;
|
||||
D->PackSizeHigh=Data->Arc.NewLhd.HighPackSize;
|
||||
D->UnpSize=Data->Arc.NewLhd.UnpSize;
|
||||
D->UnpSizeHigh=Data->Arc.NewLhd.HighUnpSize;
|
||||
D->HostOS=Data->Arc.NewLhd.HostOS;
|
||||
D->FileCRC=Data->Arc.NewLhd.FileCRC;
|
||||
D->FileTime=Data->Arc.NewLhd.FileTime;
|
||||
D->UnpVer=Data->Arc.NewLhd.UnpVer;
|
||||
D->Method=Data->Arc.NewLhd.Method;
|
||||
D->FileAttr=Data->Arc.NewLhd.FileAttr;
|
||||
|
||||
D->Flags=0;
|
||||
if (hd->SplitBefore)
|
||||
D->Flags|=RHDF_SPLITBEFORE;
|
||||
if (hd->SplitAfter)
|
||||
D->Flags|=RHDF_SPLITAFTER;
|
||||
if (hd->Encrypted)
|
||||
D->Flags|=RHDF_ENCRYPTED;
|
||||
if (hd->Solid)
|
||||
D->Flags|=RHDF_SOLID;
|
||||
if (hd->Dir)
|
||||
D->Flags|=RHDF_DIRECTORY;
|
||||
|
||||
D->PackSize=uint(hd->PackSize & 0xffffffff);
|
||||
D->PackSizeHigh=uint(hd->PackSize>>32);
|
||||
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
|
||||
D->UnpSizeHigh=uint(hd->UnpSize>>32);
|
||||
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
|
||||
if (Data->Arc.Format==RARFMT50)
|
||||
D->UnpVer=Data->Arc.FileHead.UnpVer==0 ? 50 : 200; // If it is not 0, just set it to something big.
|
||||
else
|
||||
D->UnpVer=Data->Arc.FileHead.UnpVer;
|
||||
D->FileCRC=hd->FileHash.CRC32;
|
||||
D->FileTime=hd->mtime.GetDos();
|
||||
|
||||
uint64 MRaw=hd->mtime.GetWin();
|
||||
D->MtimeLow=(uint)MRaw;
|
||||
D->MtimeHigh=(uint)(MRaw>>32);
|
||||
uint64 CRaw=hd->ctime.GetWin();
|
||||
D->CtimeLow=(uint)CRaw;
|
||||
D->CtimeHigh=(uint)(CRaw>>32);
|
||||
uint64 ARaw=hd->atime.GetWin();
|
||||
D->AtimeLow=(uint)ARaw;
|
||||
D->AtimeHigh=(uint)(ARaw>>32);
|
||||
|
||||
D->Method=hd->Method+0x30;
|
||||
D->FileAttr=hd->FileAttr;
|
||||
D->CmtSize=0;
|
||||
D->CmtState=0;
|
||||
/* these four next lines were added by me */
|
||||
Data->Arc.NewLhd.mtime.GetLocal((RarLocalTime *) &D->mtime);
|
||||
Data->Arc.NewLhd.ctime.GetLocal((RarLocalTime *) &D->ctime);
|
||||
Data->Arc.NewLhd.atime.GetLocal((RarLocalTime *) &D->atime);
|
||||
Data->Arc.NewLhd.arctime.GetLocal((RarLocalTime *) &D->arctime);
|
||||
|
||||
D->DictSize=uint(hd->WinSize/1024);
|
||||
|
||||
switch (hd->FileHash.Type)
|
||||
{
|
||||
case HASH_RAR14:
|
||||
case HASH_CRC32:
|
||||
D->HashType=RAR_HASH_CRC32;
|
||||
break;
|
||||
case HASH_BLAKE2:
|
||||
D->HashType=RAR_HASH_BLAKE2;
|
||||
memcpy(D->Hash,hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
|
||||
break;
|
||||
default:
|
||||
D->HashType=RAR_HASH_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
D->RedirType=hd->RedirType;
|
||||
// RedirNameSize sanity check is useful in case some developer
|
||||
// did not initialize Reserved area with 0 as required in docs.
|
||||
// We have taken 'Redir*' fields from Reserved area. We may remove
|
||||
// this RedirNameSize check sometimes later.
|
||||
if (hd->RedirType!=FSREDIR_NONE && D->RedirName!=NULL &&
|
||||
D->RedirNameSize>0 && D->RedirNameSize<100000)
|
||||
wcsncpyz(D->RedirName,hd->RedirName,D->RedirNameSize);
|
||||
D->DirTarget=hd->DirTarget;
|
||||
}
|
||||
catch (int ErrCode)
|
||||
catch (RAR_EXIT ErrCode)
|
||||
{
|
||||
return(RarErrorToDll(ErrCode));
|
||||
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
|
||||
}
|
||||
return(0);
|
||||
return ERAR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,59 +326,60 @@ int PASCAL ProcessFile(HANDLE hArcData, int Operation, char *DestPath,
|
||||
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
|
||||
Operation==RAR_SKIP && !Data->Arc.Solid)
|
||||
{
|
||||
if (Data->Arc.Volume &&
|
||||
Data->Arc.GetHeaderType()==FILE_HEAD &&
|
||||
(Data->Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0)
|
||||
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_FILE &&
|
||||
Data->Arc.FileHead.SplitAfter)
|
||||
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
||||
{
|
||||
Data->Extract.SignatureFound=false;
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
return(0);
|
||||
return ERAR_SUCCESS;
|
||||
}
|
||||
else
|
||||
return(ERAR_EOPEN);
|
||||
return ERAR_EOPEN;
|
||||
Data->Arc.SeekToNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
Data->Cmd.DllOpMode=Operation;
|
||||
|
||||
if (DestPath!=NULL || DestName!=NULL)
|
||||
*Data->Cmd.ExtrPath=0;
|
||||
*Data->Cmd.DllDestName=0;
|
||||
|
||||
if (DestPath!=NULL)
|
||||
{
|
||||
char ExtrPathA[NM];
|
||||
strncpyz(ExtrPathA,DestPath,ASIZE(ExtrPathA)-2);
|
||||
#ifdef _WIN_ALL
|
||||
OemToCharA(NullToEmpty(DestPath),Data->Cmd.ExtrPath);
|
||||
#else
|
||||
strcpy(Data->Cmd.ExtrPath,NullToEmpty(DestPath));
|
||||
// We must not apply OemToCharBuffA directly to DestPath,
|
||||
// because we do not know DestPath length and OemToCharBuffA
|
||||
// does not stop at 0.
|
||||
OemToCharA(ExtrPathA,ExtrPathA);
|
||||
#endif
|
||||
AddEndSlash(Data->Cmd.ExtrPath);
|
||||
CharToWide(ExtrPathA,Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
|
||||
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
|
||||
}
|
||||
if (DestName!=NULL)
|
||||
{
|
||||
char DestNameA[NM];
|
||||
strncpyz(DestNameA,DestName,ASIZE(DestNameA)-2);
|
||||
#ifdef _WIN_ALL
|
||||
OemToCharA(NullToEmpty(DestName),Data->Cmd.DllDestName);
|
||||
#else
|
||||
strcpy(Data->Cmd.DllDestName,NullToEmpty(DestName));
|
||||
// We must not apply OemToCharBuffA directly to DestName,
|
||||
// because we do not know DestName length and OemToCharBuffA
|
||||
// does not stop at 0.
|
||||
OemToCharA(DestNameA,DestNameA);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
*Data->Cmd.ExtrPath=0;
|
||||
*Data->Cmd.DllDestName=0;
|
||||
CharToWide(DestNameA,Data->Cmd.DllDestName,ASIZE(Data->Cmd.DllDestName));
|
||||
}
|
||||
|
||||
if (DestPathW!=NULL || DestNameW!=NULL)
|
||||
if (DestPathW!=NULL)
|
||||
{
|
||||
wcsncpy(Data->Cmd.ExtrPathW,NullToEmpty(DestPathW),NM-2);
|
||||
AddEndSlash(Data->Cmd.ExtrPathW);
|
||||
wcsncpy(Data->Cmd.DllDestNameW,NullToEmpty(DestNameW),NM-1);
|
||||
|
||||
if (*Data->Cmd.DllDestNameW!=0 && *Data->Cmd.DllDestName==0)
|
||||
WideToChar(Data->Cmd.DllDestNameW,Data->Cmd.DllDestName);
|
||||
}
|
||||
else
|
||||
{
|
||||
*Data->Cmd.ExtrPathW=0;
|
||||
*Data->Cmd.DllDestNameW=0;
|
||||
wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
|
||||
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
|
||||
}
|
||||
|
||||
strcpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? "X":"T");
|
||||
if (DestNameW!=NULL)
|
||||
wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
|
||||
|
||||
wcscpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T");
|
||||
Data->Cmd.Test=Operation!=RAR_EXTRACT;
|
||||
if (Operation == RAR_EXTRACT_CHUNK)
|
||||
{
|
||||
@@ -318,14 +393,13 @@ int PASCAL ProcessFile(HANDLE hArcData, int Operation, char *DestPath,
|
||||
|
||||
bool Repeat=false;
|
||||
if (Operation != RAR_EXTRACT_CHUNK)
|
||||
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,
|
||||
Data->HeaderSize,Repeat);
|
||||
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
|
||||
else
|
||||
{
|
||||
if (InitDataIO) //chunk, init
|
||||
{
|
||||
bool res;
|
||||
res = Data->Extract.ExtractCurrentFileChunkInit(&Data->Cmd, Data->Arc,
|
||||
res = Data->Extract.ExtractCurrentFileChunkInit(Data->Arc,
|
||||
Data->HeaderSize, Repeat);
|
||||
if (!res && Data->Cmd.DllError == 0)
|
||||
Data->Cmd.DllError = ERAR_UNKNOWN;
|
||||
@@ -338,26 +412,37 @@ int PASCAL ProcessFile(HANDLE hArcData, int Operation, char *DestPath,
|
||||
ReadSize, finished);
|
||||
}
|
||||
|
||||
// Now we process extra file information if any.
|
||||
//
|
||||
// Archive can be closed if we process volumes, next volume is missing
|
||||
// and current one is already removed or deleted. So we need to check
|
||||
// if archive is still open to avoid calling file operations on
|
||||
// the invalid file handle. Some of our file operations like Seek()
|
||||
// process such invalid handle correctly, some not.
|
||||
/* 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);
|
||||
while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 &&
|
||||
Data->Arc.GetHeaderType()==HEAD_SERVICE)
|
||||
{
|
||||
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
|
||||
Data->Arc.SeekToNext();
|
||||
}
|
||||
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (int ErrCode)
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
return(RarErrorToDll(ErrCode));
|
||||
return ERAR_NO_MEMORY;
|
||||
}
|
||||
return(Data->Cmd.DllError);
|
||||
catch (RAR_EXIT ErrCode)
|
||||
{
|
||||
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
|
||||
}
|
||||
return Data->Cmd.DllError;
|
||||
}
|
||||
|
||||
|
||||
@@ -419,42 +504,46 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro
|
||||
Data->Cmd.ProcessDataProc=ProcessDataProc;
|
||||
}
|
||||
|
||||
#ifndef NOCRYPT
|
||||
|
||||
#ifndef RAR_NOCRYPT
|
||||
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
|
||||
{
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
GetWideName(Password,NULL,Data->Cmd.Password,ASIZE(Data->Cmd.Password));
|
||||
wchar PasswordW[MAXPASSWORD];
|
||||
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
|
||||
Data->Cmd.Password.Set(PasswordW);
|
||||
cleandata(PasswordW,sizeof(PasswordW));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int PASCAL RARGetDllVersion()
|
||||
{
|
||||
return(RAR_DLL_VERSION);
|
||||
return RAR_DLL_VERSION;
|
||||
}
|
||||
|
||||
|
||||
static int RarErrorToDll(int ErrCode)
|
||||
static int RarErrorToDll(RAR_EXIT ErrCode)
|
||||
{
|
||||
switch(ErrCode)
|
||||
{
|
||||
case FATAL_ERROR:
|
||||
return(ERAR_EREAD);
|
||||
case CRC_ERROR:
|
||||
return(ERAR_BAD_DATA);
|
||||
case WRITE_ERROR:
|
||||
return(ERAR_EWRITE);
|
||||
case OPEN_ERROR:
|
||||
return(ERAR_EOPEN);
|
||||
case CREATE_ERROR:
|
||||
return(ERAR_ECREATE);
|
||||
case MEMORY_ERROR:
|
||||
return(ERAR_NO_MEMORY);
|
||||
case NO_PASSWORD_ERROR: //not in original
|
||||
return(ERAR_MISSING_PASSWORD);
|
||||
case SUCCESS:
|
||||
return(0);
|
||||
case RARX_FATAL:
|
||||
return ERAR_EREAD;
|
||||
case RARX_CRC:
|
||||
return ERAR_BAD_DATA;
|
||||
case RARX_WRITE:
|
||||
return ERAR_EWRITE;
|
||||
case RARX_OPEN:
|
||||
return ERAR_EOPEN;
|
||||
case RARX_CREATE:
|
||||
return ERAR_ECREATE;
|
||||
case RARX_MEMORY:
|
||||
return ERAR_NO_MEMORY;
|
||||
case RARX_BADPWD:
|
||||
return ERAR_BAD_PASSWORD;
|
||||
case RARX_SUCCESS:
|
||||
return ERAR_SUCCESS; // 0.
|
||||
default:
|
||||
return(ERAR_UNKNOWN);
|
||||
return ERAR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define ERAR_SUCCESS 0
|
||||
#define ERAR_END_ARCHIVE 10
|
||||
#define ERAR_NO_MEMORY 11
|
||||
#define ERAR_BAD_DATA 12
|
||||
@@ -16,6 +17,8 @@
|
||||
#define ERAR_SMALL_BUF 20
|
||||
#define ERAR_UNKNOWN 21
|
||||
#define ERAR_MISSING_PASSWORD 22
|
||||
#define ERAR_EREFERENCE 23
|
||||
#define ERAR_BAD_PASSWORD 24
|
||||
|
||||
#define RAR_OM_LIST 0
|
||||
#define RAR_OM_EXTRACT 1
|
||||
@@ -29,9 +32,13 @@
|
||||
#define RAR_VOL_ASK 0
|
||||
#define RAR_VOL_NOTIFY 1
|
||||
|
||||
#define RAR_DLL_VERSION 5
|
||||
#define RAR_DLL_VERSION 8
|
||||
#define RAR_DLL_EXT_VERSION 1 //added by me
|
||||
|
||||
#define RAR_HASH_NONE 0
|
||||
#define RAR_HASH_CRC32 1
|
||||
#define RAR_HASH_BLAKE2 2
|
||||
|
||||
//Must be the same as MAXWINSIZE
|
||||
//not in original
|
||||
#define RAR_CHUNK_BUFFER_SIZE 0x400000
|
||||
@@ -60,6 +67,13 @@ typedef struct RARTime
|
||||
unsigned int yDay;
|
||||
} RARTime;
|
||||
|
||||
#define RHDF_SPLITBEFORE 0x01
|
||||
#define RHDF_SPLITAFTER 0x02
|
||||
#define RHDF_ENCRYPTED 0x04
|
||||
#define RHDF_SOLID 0x10
|
||||
#define RHDF_DIRECTORY 0x20
|
||||
|
||||
|
||||
struct RARHeaderData
|
||||
{
|
||||
char ArcName[260];
|
||||
@@ -101,15 +115,22 @@ struct RARHeaderDataEx
|
||||
unsigned int CmtBufSize;
|
||||
unsigned int CmtSize;
|
||||
unsigned int CmtState;
|
||||
/* these four were added by me and are optional (not all archives have them)
|
||||
* check if year is 0 to decide if they are set */
|
||||
RARTime mtime;
|
||||
RARTime ctime;
|
||||
RARTime atime;
|
||||
RARTime arctime;
|
||||
unsigned int DictSize;
|
||||
unsigned int HashType;
|
||||
char Hash[32];
|
||||
unsigned int RedirType;
|
||||
wchar_t *RedirName;
|
||||
unsigned int RedirNameSize;
|
||||
unsigned int DirTarget;
|
||||
unsigned int MtimeLow;
|
||||
unsigned int MtimeHigh;
|
||||
unsigned int CtimeLow;
|
||||
unsigned int CtimeHigh;
|
||||
unsigned int AtimeLow;
|
||||
unsigned int AtimeHigh;
|
||||
/* removed by me: we don't need to retain binary compatibility in case new
|
||||
* fields are added, so we avoid wasting space here */
|
||||
/* unsigned int Reserved[1024]; */
|
||||
/* unsigned int Reserved[988]; */
|
||||
};
|
||||
|
||||
|
||||
@@ -126,6 +147,16 @@ struct RAROpenArchiveData
|
||||
|
||||
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
|
||||
|
||||
#define ROADF_VOLUME 0x0001
|
||||
#define ROADF_COMMENT 0x0002
|
||||
#define ROADF_LOCK 0x0004
|
||||
#define ROADF_SOLID 0x0008
|
||||
#define ROADF_NEWNUMBERING 0x0010
|
||||
#define ROADF_SIGNED 0x0020
|
||||
#define ROADF_RECOVERY 0x0040
|
||||
#define ROADF_ENCHEADERS 0x0080
|
||||
#define ROADF_FIRSTVOLUME 0x0100
|
||||
|
||||
struct RAROpenArchiveDataEx
|
||||
{
|
||||
char *ArcName;
|
||||
@@ -144,7 +175,8 @@ struct RAROpenArchiveDataEx
|
||||
};
|
||||
|
||||
enum UNRARCALLBACK_MESSAGES {
|
||||
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD
|
||||
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD,UCM_CHANGEVOLUMEW,
|
||||
UCM_NEEDPASSWORDW
|
||||
};
|
||||
|
||||
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
|
||||
|
||||
28
unrar/dll.rc
Normal file
28
unrar/dll.rc
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 5, 50, 5, 2378
|
||||
PRODUCTVERSION 5, 50, 5, 2378
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904E4"
|
||||
{
|
||||
VALUE "CompanyName", "Alexander Roshal\0"
|
||||
VALUE "ProductName", "RAR decompression library\0"
|
||||
VALUE "FileDescription", "RAR decompression library\0"
|
||||
VALUE "FileVersion", "5.50.5\0"
|
||||
VALUE "ProductVersion", "5.50.5\0"
|
||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2017\0"
|
||||
VALUE "OriginalFilename", "Unrar.dll\0"
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo"
|
||||
{
|
||||
VALUE "Translation", 0x0409, 0x04E4
|
||||
}
|
||||
}
|
||||
|
||||
321
unrar/errhnd.cpp
321
unrar/errhnd.cpp
@@ -1,8 +1,5 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
|
||||
static bool UserBreak;
|
||||
|
||||
ErrorHandler::ErrorHandler()
|
||||
{
|
||||
Clean();
|
||||
@@ -11,267 +8,239 @@ ErrorHandler::ErrorHandler()
|
||||
|
||||
void ErrorHandler::Clean()
|
||||
{
|
||||
ExitCode=SUCCESS;
|
||||
ExitCode=RARX_SUCCESS;
|
||||
ErrCount=0;
|
||||
EnableBreak=true;
|
||||
Silent=false;
|
||||
DoShutdown=false;
|
||||
UserBreak=false;
|
||||
MainExit=false;
|
||||
DisableShutdown=false;
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::MemoryError()
|
||||
{
|
||||
MemoryErrorMsg();
|
||||
Throw(MEMORY_ERROR);
|
||||
Exit(RARX_MEMORY);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::OpenError(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::OpenError(const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
OpenErrorMsg(FileName);
|
||||
Throw(OPEN_ERROR);
|
||||
Exit(RARX_OPEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::CloseError(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::CloseError(const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
if (!UserBreak)
|
||||
{
|
||||
ErrMsg(NULL,St(MErrFClose),FileName);
|
||||
uiMsg(UIERROR_FILECLOSE,FileName);
|
||||
SysErrMsg();
|
||||
}
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(FATAL_ERROR);
|
||||
Exit(RARX_FATAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::ReadError(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::ReadError(const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
ReadErrorMsg(NULL,NULL,FileName,FileNameW);
|
||||
ReadErrorMsg(FileName);
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(FATAL_ERROR);
|
||||
Exit(RARX_FATAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool ErrorHandler::AskRepeatRead(const char *FileName,const wchar *FileNameW)
|
||||
bool ErrorHandler::AskRepeatRead(const wchar *FileName)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE)
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
if (!Silent)
|
||||
{
|
||||
SysErrMsg();
|
||||
mprintf("\n");
|
||||
Log(NULL,St(MErrRead),FileName);
|
||||
return(Ask(St(MRetryAbort))==1);
|
||||
bool Repeat=uiAskRepeatRead(FileName);
|
||||
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
|
||||
DisableShutdown=true;
|
||||
return Repeat;
|
||||
}
|
||||
#endif
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::WriteError(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::WriteError(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
WriteErrorMsg(ArcName,ArcNameW,FileName,FileNameW);
|
||||
WriteErrorMsg(ArcName,FileName);
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(WRITE_ERROR);
|
||||
Exit(RARX_WRITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
void ErrorHandler::WriteErrorFAT(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::WriteErrorFAT(const wchar *FileName)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
SysErrMsg();
|
||||
ErrMsg(NULL,St(MNTFSRequired),FileName);
|
||||
#endif
|
||||
uiMsg(UIERROR_NTFSREQUIRED,FileName);
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
|
||||
Throw(WRITE_ERROR);
|
||||
Exit(RARX_WRITE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool ErrorHandler::AskRepeatWrite(const char *FileName,const wchar *FileNameW,bool DiskFull)
|
||||
bool ErrorHandler::AskRepeatWrite(const wchar *FileName,bool DiskFull)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
#ifndef SILENT
|
||||
if (!Silent)
|
||||
{
|
||||
// We do not display "repeat write" prompt in Android, so we do not
|
||||
// need the matching system error message.
|
||||
SysErrMsg();
|
||||
mprintf("\n");
|
||||
Log(NULL,St(DiskFull ? MNotEnoughDisk:MErrWrite),FileName);
|
||||
return(Ask(St(MRetryAbort))==1);
|
||||
bool Repeat=uiAskRepeatWrite(FileName,DiskFull);
|
||||
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
|
||||
DisableShutdown=true;
|
||||
return Repeat;
|
||||
}
|
||||
#endif
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::SeekError(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::SeekError(const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
if (!UserBreak)
|
||||
{
|
||||
ErrMsg(NULL,St(MErrSeek),FileName);
|
||||
uiMsg(UIERROR_FILESEEK,FileName);
|
||||
SysErrMsg();
|
||||
}
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(FATAL_ERROR);
|
||||
Exit(RARX_FATAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::GeneralErrMsg(const char *Msg)
|
||||
void ErrorHandler::GeneralErrMsg(const wchar *fmt,...)
|
||||
{
|
||||
#ifndef SILENT
|
||||
Log(NULL,"%s",Msg);
|
||||
va_list arglist;
|
||||
va_start(arglist,fmt);
|
||||
wchar Msg[1024];
|
||||
vswprintf(Msg,ASIZE(Msg),fmt,arglist);
|
||||
uiMsg(UIERROR_GENERALERRMSG,Msg);
|
||||
SysErrMsg();
|
||||
#endif
|
||||
va_end(arglist);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::MemoryErrorMsg()
|
||||
{
|
||||
#ifndef SILENT
|
||||
ErrMsg(NULL,St(MErrOutMem));
|
||||
#endif
|
||||
uiMsg(UIERROR_MEMORY);
|
||||
SetErrorCode(RARX_MEMORY);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::OpenErrorMsg(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::OpenErrorMsg(const wchar *FileName)
|
||||
{
|
||||
OpenErrorMsg(NULL,NULL,FileName,FileNameW);
|
||||
OpenErrorMsg(NULL,FileName);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::OpenErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
if (FileName!=NULL)
|
||||
Log(ArcName,St(MCannotOpen),FileName);
|
||||
Alarm();
|
||||
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
|
||||
SysErrMsg();
|
||||
#endif
|
||||
SetErrorCode(RARX_OPEN);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::CreateErrorMsg(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::CreateErrorMsg(const wchar *FileName)
|
||||
{
|
||||
CreateErrorMsg(NULL,NULL,FileName,FileNameW);
|
||||
CreateErrorMsg(NULL,FileName);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::CreateErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::CreateErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
if (FileName!=NULL)
|
||||
Log(ArcName,St(MCannotCreate),FileName);
|
||||
Alarm();
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE) && defined(MAX_PATH)
|
||||
CheckLongPathErrMsg(FileName,FileNameW);
|
||||
#endif
|
||||
|
||||
uiMsg(UIERROR_FILECREATE,ArcName,FileName);
|
||||
SysErrMsg();
|
||||
#endif
|
||||
SetErrorCode(RARX_CREATE);
|
||||
}
|
||||
|
||||
|
||||
// Check the path length and display the error message if it is too long.
|
||||
void ErrorHandler::CheckLongPathErrMsg(const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::ReadErrorMsg(const wchar *FileName)
|
||||
{
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined (SILENT) && defined(MAX_PATH)
|
||||
if (GetLastError()==ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
wchar WideFileName[NM];
|
||||
GetWideName(FileName,FileNameW,WideFileName,ASIZE(WideFileName));
|
||||
size_t NameLength=wcslen(WideFileName);
|
||||
if (!IsFullPath(WideFileName))
|
||||
{
|
||||
wchar CurDir[NM];
|
||||
GetCurrentDirectoryW(ASIZE(CurDir),CurDir);
|
||||
NameLength+=wcslen(CurDir)+1;
|
||||
}
|
||||
if (NameLength>MAX_PATH)
|
||||
{
|
||||
Log(NULL,St(MMaxPathLimit),MAX_PATH);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ReadErrorMsg(NULL,FileName);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::ReadErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::ReadErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
ErrMsg(ArcName,St(MErrRead),FileName);
|
||||
uiMsg(UIERROR_FILEREAD,ArcName,FileName);
|
||||
SysErrMsg();
|
||||
#endif
|
||||
SetErrorCode(RARX_FATAL);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::WriteErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW)
|
||||
void ErrorHandler::WriteErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
#ifndef SILENT
|
||||
ErrMsg(ArcName,St(MErrWrite),FileName);
|
||||
uiMsg(UIERROR_FILEWRITE,ArcName,FileName);
|
||||
SysErrMsg();
|
||||
#endif
|
||||
SetErrorCode(RARX_WRITE);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::Exit(int ExitCode)
|
||||
void ErrorHandler::ArcBrokenMsg(const wchar *ArcName)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
Alarm();
|
||||
#endif
|
||||
uiMsg(UIERROR_ARCBROKEN,ArcName);
|
||||
SetErrorCode(RARX_CRC);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
uiMsg(UIERROR_CHECKSUM,ArcName,FileName);
|
||||
SetErrorCode(RARX_CRC);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::UnknownMethodMsg(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
uiMsg(UIERROR_UNKNOWNMETHOD,ArcName,FileName);
|
||||
ErrHandler.SetErrorCode(RARX_FATAL);
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::Exit(RAR_EXIT ExitCode)
|
||||
{
|
||||
uiAlarm(UIALARM_ERROR);
|
||||
Throw(ExitCode);
|
||||
}
|
||||
|
||||
|
||||
#ifndef GUI
|
||||
void ErrorHandler::ErrMsg(const char *ArcName,const char *fmt,...)
|
||||
{
|
||||
safebuf char Msg[NM+1024];
|
||||
va_list argptr;
|
||||
va_start(argptr,fmt);
|
||||
vsprintf(Msg,fmt,argptr);
|
||||
va_end(argptr);
|
||||
#ifdef _WIN_ALL
|
||||
if (UserBreak)
|
||||
Sleep(5000);
|
||||
#endif
|
||||
Alarm();
|
||||
if (*Msg)
|
||||
{
|
||||
Log(ArcName,"\n%s",Msg);
|
||||
mprintf("\n%s\n",St(MProgAborted));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void ErrorHandler::SetErrorCode(int Code)
|
||||
void ErrorHandler::SetErrorCode(RAR_EXIT Code)
|
||||
{
|
||||
switch(Code)
|
||||
{
|
||||
case WARNING:
|
||||
case USER_BREAK:
|
||||
if (ExitCode==SUCCESS)
|
||||
case RARX_WARNING:
|
||||
case RARX_USERBREAK:
|
||||
if (ExitCode==RARX_SUCCESS)
|
||||
ExitCode=Code;
|
||||
break;
|
||||
case FATAL_ERROR:
|
||||
if (ExitCode==SUCCESS || ExitCode==WARNING)
|
||||
ExitCode=FATAL_ERROR;
|
||||
case RARX_CRC:
|
||||
if (ExitCode!=RARX_BADPWD)
|
||||
ExitCode=Code;
|
||||
break;
|
||||
case RARX_FATAL:
|
||||
if (ExitCode==RARX_SUCCESS || ExitCode==RARX_WARNING)
|
||||
ExitCode=RARX_FATAL;
|
||||
break;
|
||||
default:
|
||||
ExitCode=Code;
|
||||
@@ -281,7 +250,6 @@ void ErrorHandler::SetErrorCode(int Code)
|
||||
}
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(_SFX_RTL_)
|
||||
#ifdef _WIN_ALL
|
||||
BOOL __stdcall ProcessSignal(DWORD SigType)
|
||||
#else
|
||||
@@ -295,54 +263,62 @@ void _stdfunction ProcessSignal(int SigType)
|
||||
// When a console application is run as a service, this allows the service
|
||||
// to continue running after the user logs off.
|
||||
if (SigType==CTRL_LOGOFF_EVENT)
|
||||
return(TRUE);
|
||||
return TRUE;
|
||||
#endif
|
||||
UserBreak=true;
|
||||
|
||||
ErrHandler.UserBreak=true;
|
||||
mprintf(St(MBreak));
|
||||
for (int I=0;!File::RemoveCreated() && I<3;I++)
|
||||
{
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
// Let the main thread to handle 'throw' and destroy file objects.
|
||||
for (uint I=0;!ErrHandler.MainExit && I<50;I++)
|
||||
Sleep(100);
|
||||
#endif
|
||||
}
|
||||
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE) && !defined(RARDLL)
|
||||
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(RARDLL)
|
||||
ExtRes.UnloadDLL();
|
||||
#endif
|
||||
exit(USER_BREAK);
|
||||
exit(RARX_USERBREAK);
|
||||
#endif
|
||||
|
||||
#ifdef _UNIX
|
||||
static uint BreakCount=0;
|
||||
// User continues to press Ctrl+C, exit immediately without cleanup.
|
||||
if (++BreakCount>1)
|
||||
exit(RARX_USERBREAK);
|
||||
// Otherwise return from signal handler and let Wait() function to close
|
||||
// files and quit. We cannot use the same approach as in Windows,
|
||||
// because Unix signal handler can block execution of our main code.
|
||||
#endif
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_MSC_VER)
|
||||
// never reached, just to avoid a compiler warning
|
||||
return(TRUE);
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void ErrorHandler::SetSignalHandlers(bool Enable)
|
||||
{
|
||||
EnableBreak=Enable;
|
||||
#if !defined(GUI) && !defined(_SFX_RTL_)
|
||||
#ifdef _WIN_ALL
|
||||
SetConsoleCtrlHandler(Enable ? ProcessSignal:NULL,TRUE);
|
||||
// signal(SIGBREAK,Enable ? ProcessSignal:SIG_IGN);
|
||||
#else
|
||||
signal(SIGINT,Enable ? ProcessSignal:SIG_IGN);
|
||||
signal(SIGTERM,Enable ? ProcessSignal:SIG_IGN);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::Throw(int Code)
|
||||
void ErrorHandler::Throw(RAR_EXIT Code)
|
||||
{
|
||||
if (Code==USER_BREAK && !EnableBreak)
|
||||
if (Code==RARX_USERBREAK && !EnableBreak)
|
||||
return;
|
||||
ErrHandler.SetErrorCode(Code);
|
||||
#ifdef ALLOW_EXCEPTIONS
|
||||
throw Code;
|
||||
#else
|
||||
File::RemoveCreated();
|
||||
exit(Code);
|
||||
#if !defined(SILENT)
|
||||
// Do not write "aborted" when just displaying online help.
|
||||
if (Code!=RARX_SUCCESS && Code!=RARX_USERERROR)
|
||||
mprintf(L"\n%s\n",St(MProgAborted));
|
||||
#endif
|
||||
SetErrorCode(Code);
|
||||
throw Code;
|
||||
}
|
||||
|
||||
|
||||
@@ -371,17 +347,7 @@ void ErrorHandler::SysErrMsg()
|
||||
*EndMsg=0;
|
||||
EndMsg++;
|
||||
}
|
||||
// We use ASCII for output in Windows console, so let's convert Unicode
|
||||
// message to single byte.
|
||||
size_t Length=wcslen(CurMsg)*2; // Must be enough for DBCS characters.
|
||||
char *MsgA=(char *)malloc(Length+2);
|
||||
if (MsgA!=NULL)
|
||||
{
|
||||
WideToChar(CurMsg,MsgA,Length+1);
|
||||
MsgA[Length]=0;
|
||||
Log(NULL,"\n%s",MsgA);
|
||||
free(MsgA);
|
||||
}
|
||||
uiMsg(UIERROR_SYSERRMSG,CurMsg);
|
||||
CurMsg=EndMsg;
|
||||
}
|
||||
}
|
||||
@@ -389,14 +355,37 @@ void ErrorHandler::SysErrMsg()
|
||||
#endif
|
||||
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
char *err=strerror(errno);
|
||||
if (err!=NULL)
|
||||
Log(NULL,"\n%s",err);
|
||||
if (errno!=0)
|
||||
{
|
||||
char *err=strerror(errno);
|
||||
if (err!=NULL)
|
||||
{
|
||||
wchar Msg[1024];
|
||||
CharToWide(err,Msg,ASIZE(Msg));
|
||||
uiMsg(UIERROR_SYSERRMSG,Msg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int ErrorHandler::GetSystemErrorCode()
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
return GetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::SetSystemErrorCode(int Code)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
SetLastError(Code);
|
||||
#else
|
||||
errno=Code;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,57 +1,69 @@
|
||||
#ifndef _RAR_ERRHANDLER_
|
||||
#define _RAR_ERRHANDLER_
|
||||
|
||||
#if (defined(GUI) || !defined(_WIN_ALL)) && !defined(SFX_MODULE) && !defined(_WIN_CE) || defined(RARDLL)
|
||||
#define ALLOW_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
|
||||
//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_FILES_ERROR,
|
||||
NO_PASSWORD_ERROR,
|
||||
USER_BREAK=255};
|
||||
enum RAR_EXIT // RAR exit code.
|
||||
{
|
||||
RARX_SUCCESS = 0,
|
||||
RARX_WARNING = 1,
|
||||
RARX_FATAL = 2,
|
||||
RARX_CRC = 3,
|
||||
RARX_LOCK = 4,
|
||||
RARX_WRITE = 5,
|
||||
RARX_OPEN = 6,
|
||||
RARX_USERERROR = 7,
|
||||
RARX_MEMORY = 8,
|
||||
RARX_CREATE = 9,
|
||||
RARX_NOFILES = 10,
|
||||
RARX_BADPWD = 11,
|
||||
RARX_USERBREAK = 255
|
||||
};
|
||||
|
||||
class ErrorHandler
|
||||
{
|
||||
private:
|
||||
void ErrMsg(const char *ArcName,const char *fmt,...);
|
||||
|
||||
int ExitCode;
|
||||
int ErrCount;
|
||||
RAR_EXIT ExitCode;
|
||||
uint ErrCount;
|
||||
bool EnableBreak;
|
||||
bool Silent;
|
||||
bool DoShutdown;
|
||||
bool DisableShutdown; // Shutdown is not suitable after last error.
|
||||
public:
|
||||
ErrorHandler();
|
||||
void Clean();
|
||||
void MemoryError();
|
||||
void OpenError(const char *FileName,const wchar *FileNameW);
|
||||
void CloseError(const char *FileName,const wchar *FileNameW);
|
||||
void ReadError(const char *FileName,const wchar *FileNameW);
|
||||
bool AskRepeatRead(const char *FileName,const wchar *FileNameW);
|
||||
void WriteError(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
|
||||
void WriteErrorFAT(const char *FileName,const wchar *FileNameW);
|
||||
bool AskRepeatWrite(const char *FileName,const wchar *FileNameW,bool DiskFull);
|
||||
void SeekError(const char *FileName,const wchar *FileNameW);
|
||||
void GeneralErrMsg(const char *Msg);
|
||||
void OpenError(const wchar *FileName);
|
||||
void CloseError(const wchar *FileName);
|
||||
void ReadError(const wchar *FileName);
|
||||
bool AskRepeatRead(const wchar *FileName);
|
||||
void WriteError(const wchar *ArcName,const wchar *FileName);
|
||||
void WriteErrorFAT(const wchar *FileName);
|
||||
bool AskRepeatWrite(const wchar *FileName,bool DiskFull);
|
||||
void SeekError(const wchar *FileName);
|
||||
void GeneralErrMsg(const wchar *fmt,...);
|
||||
void MemoryErrorMsg();
|
||||
void OpenErrorMsg(const char *FileName,const wchar *FileNameW=NULL);
|
||||
void OpenErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
|
||||
void CreateErrorMsg(const char *FileName,const wchar *FileNameW=NULL);
|
||||
void CreateErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
|
||||
void CheckLongPathErrMsg(const char *FileName,const wchar *FileNameW);
|
||||
void ReadErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
|
||||
void WriteErrorMsg(const char *ArcName,const wchar *ArcNameW,const char *FileName,const wchar *FileNameW);
|
||||
void Exit(int ExitCode);
|
||||
void SetErrorCode(int Code);
|
||||
int GetErrorCode() {return(ExitCode);}
|
||||
int GetErrorCount() {return(ErrCount);}
|
||||
void OpenErrorMsg(const wchar *FileName);
|
||||
void OpenErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||
void CreateErrorMsg(const wchar *FileName);
|
||||
void CreateErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||
void ReadErrorMsg(const wchar *FileName);
|
||||
void ReadErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||
void WriteErrorMsg(const wchar *ArcName,const wchar *FileName);
|
||||
void ArcBrokenMsg(const wchar *ArcName);
|
||||
void ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName);
|
||||
void UnknownMethodMsg(const wchar *ArcName,const wchar *FileName);
|
||||
void Exit(RAR_EXIT ExitCode);
|
||||
void SetErrorCode(RAR_EXIT Code);
|
||||
RAR_EXIT GetErrorCode() {return ExitCode;}
|
||||
uint GetErrorCount() {return ErrCount;}
|
||||
void SetSignalHandlers(bool Enable);
|
||||
void Throw(int Code);
|
||||
void Throw(RAR_EXIT Code);
|
||||
void SetSilent(bool Mode) {Silent=Mode;};
|
||||
void SetShutdown(bool Mode) {DoShutdown=Mode;};
|
||||
void SysErrMsg();
|
||||
int GetSystemErrorCode();
|
||||
void SetSystemErrorCode(int Code);
|
||||
bool IsShutdownEnabled() {return !DisableShutdown;}
|
||||
|
||||
bool UserBreak; // Ctrl+Break is pressed.
|
||||
bool MainExit; // main() is completed.
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,51 +1,43 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
#include "hardlinks.cpp"
|
||||
#include "win32stm.cpp"
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
#include "win32acl.cpp"
|
||||
#include "win32stm.cpp"
|
||||
#endif
|
||||
#ifdef _BEOS
|
||||
#include "beosea.cpp"
|
||||
#endif
|
||||
#if defined(_EMX) && !defined(_DJGPP)
|
||||
#include "os2ea.cpp"
|
||||
#include "win32lnk.cpp"
|
||||
#endif
|
||||
|
||||
#ifdef _UNIX
|
||||
#include "uowners.cpp"
|
||||
#ifdef SAVE_LINKS
|
||||
#include "ulinks.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// RAR2 service header extra records.
|
||||
#ifndef SFX_MODULE
|
||||
void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW)
|
||||
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name)
|
||||
{
|
||||
if (Cmd->Test)
|
||||
return;
|
||||
switch(Arc.SubBlockHead.SubType)
|
||||
{
|
||||
#if defined(_EMX) && !defined(_DJGPP)
|
||||
case EA_HEAD:
|
||||
if (Cmd->ProcessEA)
|
||||
ExtractOS2EA(Arc,Name);
|
||||
break;
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
case UO_HEAD:
|
||||
if (Cmd->ProcessOwners)
|
||||
ExtractUnixOwner(Arc,Name);
|
||||
break;
|
||||
#endif
|
||||
#ifdef _BEOS
|
||||
case BEEA_HEAD:
|
||||
if (Cmd->ProcessEA)
|
||||
ExtractBeEA(Arc,Name);
|
||||
ExtractUnixOwner20(Arc,Name);
|
||||
break;
|
||||
#endif
|
||||
#ifdef _WIN_ALL
|
||||
case NTACL_HEAD:
|
||||
if (Cmd->ProcessOwners)
|
||||
ExtractACL(Arc,Name,NameW);
|
||||
ExtractACL20(Arc,Name);
|
||||
break;
|
||||
case STREAM_HEAD:
|
||||
ExtractStreams(Arc,Name,NameW);
|
||||
ExtractStreams20(Arc,Name);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -53,24 +45,108 @@ void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW)
|
||||
#endif
|
||||
|
||||
|
||||
void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW)
|
||||
// RAR3 and RAR5 service header extra records.
|
||||
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name)
|
||||
{
|
||||
#if defined(_EMX) && !defined(_DJGPP)
|
||||
if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_OS2EA))
|
||||
ExtractOS2EANew(Arc,Name);
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
|
||||
ExtractUnixOwnerNew(Arc,Name);
|
||||
#endif
|
||||
#ifdef _BEOS
|
||||
if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
|
||||
ExtractUnixOwnerNew(Arc,Name);
|
||||
if (!Cmd->Test && Cmd->ProcessOwners && Arc.Format==RARFMT15 &&
|
||||
Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
|
||||
ExtractUnixOwner30(Arc,Name);
|
||||
#endif
|
||||
#ifdef _WIN_ALL
|
||||
if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
|
||||
ExtractACLNew(Arc,Name,NameW);
|
||||
if (!Cmd->Test && Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
|
||||
ExtractACL(Arc,Name);
|
||||
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
|
||||
ExtractStreamsNew(Arc,Name,NameW);
|
||||
ExtractStreams(Arc,Name,Cmd->Test);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Extra data stored directly in file header.
|
||||
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name)
|
||||
{
|
||||
#ifdef _UNIX
|
||||
if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet)
|
||||
SetUnixOwner(Arc,Name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Calculate a number of path components except \. and \..
|
||||
static int CalcAllowedDepth(const wchar *Name)
|
||||
{
|
||||
int AllowedDepth=0;
|
||||
while (*Name!=0)
|
||||
{
|
||||
if (IsPathDiv(Name[0]) && Name[1]!=0 && !IsPathDiv(Name[1]))
|
||||
{
|
||||
bool Dot=Name[1]=='.' && (IsPathDiv(Name[2]) || Name[2]==0);
|
||||
bool Dot2=Name[1]=='.' && Name[2]=='.' && (IsPathDiv(Name[3]) || Name[3]==0);
|
||||
if (!Dot && !Dot2)
|
||||
AllowedDepth++;
|
||||
}
|
||||
Name++;
|
||||
}
|
||||
return AllowedDepth;
|
||||
}
|
||||
|
||||
|
||||
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
|
||||
{
|
||||
// Catch root dir based /path/file paths also as stuff like \\?\.
|
||||
// Do not check PrepSrcName here, it can be root based if destination path
|
||||
// is a root based.
|
||||
if (IsFullRootPath(SrcName) || IsFullRootPath(TargetName))
|
||||
return false;
|
||||
|
||||
// We could check just prepared src name, but for extra safety
|
||||
// we check both original (as from archive header) and prepared
|
||||
// (after applying the destination path and -ep switches) names.
|
||||
|
||||
int AllowedDepth=CalcAllowedDepth(SrcName); // Original name depth.
|
||||
|
||||
// Remove the destination path from prepared name if any. We should not
|
||||
// count the destination path depth, because the link target must point
|
||||
// inside of this path, not outside of it.
|
||||
size_t ExtrPathLength=wcslen(Cmd->ExtrPath);
|
||||
if (ExtrPathLength>0 && wcsncmp(PrepSrcName,Cmd->ExtrPath,ExtrPathLength)==0)
|
||||
{
|
||||
PrepSrcName+=ExtrPathLength;
|
||||
while (IsPathDiv(*PrepSrcName))
|
||||
PrepSrcName++;
|
||||
}
|
||||
int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName);
|
||||
|
||||
// Number of ".." in link target.
|
||||
int UpLevels=0;
|
||||
for (int Pos=0;*TargetName!=0;Pos++)
|
||||
{
|
||||
bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' &&
|
||||
(IsPathDiv(TargetName[2]) || TargetName[2]==0) &&
|
||||
(Pos==0 || IsPathDiv(*(TargetName-1)));
|
||||
if (Dot2)
|
||||
UpLevels++;
|
||||
TargetName++;
|
||||
}
|
||||
return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels;
|
||||
}
|
||||
|
||||
|
||||
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName)
|
||||
{
|
||||
#if defined(SAVE_LINKS) && defined(_UNIX)
|
||||
// For RAR 3.x archives we process links even in test mode to skip link data.
|
||||
if (Arc.Format==RARFMT15)
|
||||
return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName);
|
||||
if (Arc.Format==RARFMT50)
|
||||
return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead);
|
||||
#elif defined _WIN_ALL
|
||||
// RAR 5.0 archives store link information in file header, so there is
|
||||
// no need to additionally test it if we do not create a file.
|
||||
if (Arc.Format==RARFMT50)
|
||||
return CreateReparsePoint(Cmd,LinkName,&Arc.FileHead);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
#ifndef _RAR_EXTINFO_
|
||||
#define _RAR_EXTINFO_
|
||||
|
||||
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName);
|
||||
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName);
|
||||
#ifdef _UNIX
|
||||
void SetUnixOwner(Archive &Arc,const wchar *FileName);
|
||||
#endif
|
||||
|
||||
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
|
||||
|
||||
void GetStreamNameNTFS(Archive &Arc,wchar *StreamName,size_t MaxSize);
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
bool SetPrivilege(LPCTSTR PrivName);
|
||||
#endif
|
||||
|
||||
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name);
|
||||
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name);
|
||||
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name);
|
||||
|
||||
void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW);
|
||||
void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW);
|
||||
|
||||
#endif
|
||||
|
||||
1454
unrar/extract.cpp
1454
unrar/extract.cpp
File diff suppressed because it is too large
Load Diff
@@ -6,9 +6,25 @@ enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
|
||||
class CmdExtract
|
||||
{
|
||||
private:
|
||||
EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
|
||||
EXTRACT_ARC_CODE ExtractArchive();
|
||||
bool ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
|
||||
void ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize);
|
||||
#ifdef RARDLL
|
||||
bool ExtrDllGetPassword();
|
||||
#else
|
||||
bool ExtrGetPassword(Archive &Arc,const wchar *ArcFileName);
|
||||
#endif
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
void ConvertDosPassword(Archive &Arc,SecPassword &DestPwd);
|
||||
#endif
|
||||
void ExtrCreateDir(Archive &Arc,const wchar *ArcFileName);
|
||||
bool ExtrCreateFile(Archive &Arc,File &CurFile);
|
||||
bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName);
|
||||
|
||||
RarTime StartTime; // time when extraction started
|
||||
|
||||
CommandData *Cmd;
|
||||
|
||||
ComprDataIO DataIO;
|
||||
Unpack *Unp;
|
||||
unsigned long TotalFileCount;
|
||||
@@ -25,29 +41,25 @@ class CmdExtract
|
||||
// any wrong password hints.
|
||||
bool AnySolidDataUnpackedWell;
|
||||
|
||||
char ArcName[NM];
|
||||
wchar ArcNameW[NM];
|
||||
wchar ArcName[NM];
|
||||
|
||||
wchar Password[MAXPASSWORD];
|
||||
bool PasswordAll;
|
||||
bool PrevExtracted;
|
||||
char DestFileName[NM];
|
||||
wchar DestFileNameW[NM];
|
||||
bool PrevProcessed; // If previous file was successfully extracted or tested.
|
||||
wchar DestFileName[NM];
|
||||
bool PasswordCancelled;
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
|
||||
bool Fat32,NotFat32;
|
||||
#endif
|
||||
public:
|
||||
CmdExtract();
|
||||
CmdExtract(CommandData *Cmd);
|
||||
~CmdExtract();
|
||||
void DoExtract(CommandData *Cmd);
|
||||
void ExtractArchiveInit(CommandData *Cmd,Archive &Arc);
|
||||
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,
|
||||
bool &Repeat);
|
||||
bool ExtractCurrentFileChunkInit(CommandData *Cmd, Archive &Arc,
|
||||
size_t HeaderSize, bool &Repeat);
|
||||
void DoExtract();
|
||||
void ExtractArchiveInit(Archive &Arc);
|
||||
bool ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat);
|
||||
bool ExtractCurrentFileChunkInit(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;
|
||||
|
||||
@@ -1,39 +1,35 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
|
||||
Archive &Arc,
|
||||
bool CmdExtract::ExtractCurrentFileChunkInit(Archive &Arc,
|
||||
size_t HeaderSize,
|
||||
bool &Repeat)
|
||||
{
|
||||
char Command = 'T';
|
||||
wchar Command = L'T';
|
||||
|
||||
Cmd->DllError=0;
|
||||
Cmd->DllError = false;
|
||||
Repeat = false;
|
||||
|
||||
//turn on checks reserved for the first files extracted from an archive?
|
||||
FirstFile = true;
|
||||
|
||||
if (HeaderSize==0) {
|
||||
if (HeaderSize==0)
|
||||
if (DataIO.UnpVolume)
|
||||
{
|
||||
#ifdef NOVOLUME
|
||||
return(false);
|
||||
return false;
|
||||
#else
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command)) //command irrelevant
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return false;
|
||||
}
|
||||
SignatureFound=false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int HeadType=Arc.GetHeaderType();
|
||||
if (HeadType!=FILE_HEAD)
|
||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||
if (HeaderType!=HEAD_FILE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DataIO.SetUnpackToMemory((byte*) this->Buffer, this->BufferSize);
|
||||
DataIO.SetSkipUnpCRC(true);
|
||||
@@ -42,71 +38,85 @@ bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
|
||||
//there'll be no operations in the filesystem
|
||||
DataIO.SetTestMode(true);
|
||||
|
||||
if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
|
||||
if (Arc.FileHead.SplitBefore && FirstFile)
|
||||
{
|
||||
char CurVolName[NM];
|
||||
strncpyz(ArcName, Arc.FileName, NM);
|
||||
strncpyz(CurVolName, ArcName, sizeof CurVolName);
|
||||
wchar CurVolName[NM];
|
||||
wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName));
|
||||
VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),Arc.NewNumbering);
|
||||
|
||||
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
|
||||
if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
||||
if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
||||
{
|
||||
*ArcNameW=0;
|
||||
// If first volume name does not match the current name and if such
|
||||
// volume name really exists, let's unpack from this first volume.
|
||||
*ArcName=0;
|
||||
Repeat=true;
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
/* Actually known. The problem is that the file doesn't start on this volume. */
|
||||
Cmd->DllError = ERAR_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
strcpy(ArcName,CurVolName);
|
||||
wcsncpyz(ArcName,CurVolName,ASIZE(ArcName));
|
||||
}
|
||||
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0;
|
||||
|
||||
DataIO.UnpVolume=Arc.FileHead.SplitAfter;
|
||||
DataIO.NextVolumeMissing=false;
|
||||
|
||||
Arc.Seek(Arc.NextBlockPos - Arc.NewLhd.FullPackSize, SEEK_SET);
|
||||
Arc.Seek(Arc.NextBlockPos-Arc.FileHead.PackSize,SEEK_SET);
|
||||
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
|
||||
if (Arc.FileHead.Encrypted)
|
||||
{
|
||||
if (*Cmd->Password==0)
|
||||
if (!ExtrDllGetPassword())
|
||||
{
|
||||
char PasswordA[MAXPASSWORD];
|
||||
|
||||
if (Cmd->Callback==NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
Cmd->DllError = ERAR_MISSING_PASSWORD;
|
||||
return false;
|
||||
}
|
||||
GetWideName(PasswordA,NULL,Cmd->Password,ASIZE(Cmd->Password));
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
Cmd->DllError=ERAR_MISSING_PASSWORD;
|
||||
return false;
|
||||
}
|
||||
wcscpy(Password,Cmd->Password);
|
||||
}
|
||||
|
||||
if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
|
||||
if (*Cmd->DllDestName!=0)
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
|
||||
// Do we need this code?
|
||||
// if (Cmd->DllOpMode!=RAR_EXTRACT)
|
||||
// ExtrFile=false;
|
||||
}
|
||||
|
||||
wchar ArcFileName[NM];
|
||||
ConvertPath(Arc.FileHead.FileName,ArcFileName);
|
||||
if (!CheckUnpVer(Arc,ArcFileName))
|
||||
{
|
||||
ErrHandler.SetErrorCode(RARX_FATAL);
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsLink(Arc.NewLhd.FileAttr))
|
||||
return true;
|
||||
|
||||
if (Arc.IsArcDir())
|
||||
return true;
|
||||
SecPassword FilePassword=Cmd->Password;
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
ConvertDosPassword(Arc,FilePassword);
|
||||
#endif
|
||||
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
DataIO.SetEncryption(false,Arc.FileHead.CryptMethod,&FilePassword,
|
||||
Arc.FileHead.SaltSet ? Arc.FileHead.Salt:NULL,
|
||||
Arc.FileHead.InitV,Arc.FileHead.Lg2Count,
|
||||
Arc.FileHead.HashKey,PswCheck);
|
||||
|
||||
// If header is damaged, we cannot rely on password check value,
|
||||
// because it can be damaged too.
|
||||
if (Arc.FileHead.Encrypted && Arc.FileHead.UsePswCheck &&
|
||||
memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 &&
|
||||
!Arc.BrokenHeader)
|
||||
{
|
||||
ErrHandler.SetErrorCode(RARX_BADPWD);
|
||||
}
|
||||
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.UnpHash.Init(Arc.FileHead.FileHash.Type,Cmd->Threads);
|
||||
DataIO.PackedDataHash.Init(Arc.FileHead.FileHash.Type,Cmd->Threads);
|
||||
DataIO.SetPackedSizeToRead(Arc.FileHead.PackSize);
|
||||
DataIO.SetFiles(&Arc,NULL);
|
||||
DataIO.SetTestMode(true);
|
||||
DataIO.SetSkipUnpCRC(true);
|
||||
DataIO.SetFiles(&Arc, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -115,7 +125,7 @@ bool CmdExtract::ExtractCurrentFileChunk(CommandData *Cmd, Archive &Arc,
|
||||
size_t *ReadSize,
|
||||
int *finished)
|
||||
{
|
||||
if (IsLink(Arc.NewLhd.FileAttr) || Arc.IsArcDir()) {
|
||||
if (Arc.FileHead.RedirType!=FSREDIR_NONE|| Arc.IsArcDir()) {
|
||||
*ReadSize = 0;
|
||||
*finished = TRUE;
|
||||
return true;
|
||||
@@ -123,7 +133,7 @@ bool CmdExtract::ExtractCurrentFileChunk(CommandData *Cmd, Archive &Arc,
|
||||
|
||||
DataIO.SetUnpackToMemory((byte*) this->Buffer, this->BufferSize);
|
||||
|
||||
if (Arc.NewLhd.Method==0x30) {
|
||||
if (Arc.FileHead.Method==0) {
|
||||
UnstoreFile(DataIO, this->BufferSize);
|
||||
/* not very sophisticated and may result in a subsequent
|
||||
* unnecessary call to this function (and probably will if
|
||||
@@ -133,12 +143,12 @@ bool CmdExtract::ExtractCurrentFileChunk(CommandData *Cmd, Archive &Arc,
|
||||
}
|
||||
else
|
||||
{
|
||||
Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
|
||||
if (Arc.NewLhd.UnpVer<=15)
|
||||
Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid);
|
||||
Unp->SetDestSize(Arc.FileHead.UnpSize);
|
||||
if (Arc.Format!=RARFMT50 && Arc.FileHead.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);
|
||||
Unp->DoUnpack(Arc.FileHead.UnpVer,Arc.FileHead.Solid, this->Buffer != NULL);
|
||||
*finished = Unp->IsFileExtracted();
|
||||
}
|
||||
*ReadSize = this->BufferSize - DataIO.GetUnpackToMemorySizeLeft();
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize,
|
||||
uint FileTime)
|
||||
// If NewFile==NULL, we delete created file after user confirmation.
|
||||
// It is useful we we need to overwrite an existing folder or file,
|
||||
// but need user confirmation for that.
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||
bool *UserReject,int64 FileSize,RarTime *FileTime,bool WriteOnly)
|
||||
{
|
||||
if (UserReject!=NULL)
|
||||
*UserReject=false;
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
#ifdef _WIN_ALL
|
||||
bool ShortNameChanged=false;
|
||||
#endif
|
||||
while (FileExist(Name,NameW))
|
||||
while (FileExist(Name))
|
||||
{
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
#if defined(_WIN_ALL)
|
||||
if (!ShortNameChanged)
|
||||
{
|
||||
// Avoid the infinite loop if UpdateExistingShortName returns
|
||||
@@ -20,183 +22,85 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
|
||||
// Maybe our long name matches the short name of existing file.
|
||||
// Let's check if we can change the short name.
|
||||
wchar WideName[NM];
|
||||
GetWideName(Name,NameW,WideName,ASIZE(WideName));
|
||||
if (UpdateExistingShortName(WideName))
|
||||
{
|
||||
if (Name!=NULL && *Name!=0)
|
||||
WideToChar(WideName,Name);
|
||||
if (NameW!=NULL && *NameW!=0)
|
||||
wcscpy(NameW,WideName);
|
||||
if (UpdateExistingShortName(Name))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Allow short name check again. It is necessary, because rename and
|
||||
// autorename below can change the name, so we need to check it again.
|
||||
ShortNameChanged=false;
|
||||
#endif
|
||||
if (Mode==OVERWRITE_NONE)
|
||||
UIASKREP_RESULT Choice=uiAskReplaceEx(Cmd,Name,MaxNameSize,FileSize,FileTime,(NewFile==NULL ? UIASKREP_F_NORENAME:0));
|
||||
|
||||
if (Choice==UIASKREP_R_REPLACE)
|
||||
break;
|
||||
if (Choice==UIASKREP_R_SKIP)
|
||||
{
|
||||
if (UserReject!=NULL)
|
||||
*UserReject=true;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// Must be before Cmd->AllYes check or -y switch would override -or.
|
||||
if (Mode==OVERWRITE_AUTORENAME)
|
||||
{
|
||||
if (!GetAutoRenamedName(Name,NameW))
|
||||
Mode=OVERWRITE_DEFAULT;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef SILENT
|
||||
Mode=OVERWRITE_ALL;
|
||||
#endif
|
||||
|
||||
// This check must be after OVERWRITE_AUTORENAME processing or -y switch
|
||||
// would override -or.
|
||||
if (Cmd->AllYes || Mode==OVERWRITE_ALL)
|
||||
break;
|
||||
|
||||
if (Mode==OVERWRITE_DEFAULT || Mode==OVERWRITE_FORCE_ASK)
|
||||
{
|
||||
char NewName[NM];
|
||||
wchar NewNameW[NM];
|
||||
*NewNameW=0;
|
||||
eprintf(St(MFileExists),Name);
|
||||
int Choice=Ask(St(MYesNoAllRenQ));
|
||||
if (Choice==1)
|
||||
break;
|
||||
if (Choice==2)
|
||||
{
|
||||
if (UserReject!=NULL)
|
||||
*UserReject=true;
|
||||
return(false);
|
||||
}
|
||||
if (Choice==3)
|
||||
{
|
||||
Cmd->Overwrite=OVERWRITE_ALL;
|
||||
break;
|
||||
}
|
||||
if (Choice==4)
|
||||
{
|
||||
if (UserReject!=NULL)
|
||||
*UserReject=true;
|
||||
Cmd->Overwrite=OVERWRITE_NONE;
|
||||
return(false);
|
||||
}
|
||||
if (Choice==5)
|
||||
{
|
||||
#ifndef GUI
|
||||
mprintf(St(MAskNewName));
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
File SrcFile;
|
||||
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||
int Size=SrcFile.Read(NewName,sizeof(NewName)-1);
|
||||
NewName[Size]=0;
|
||||
OemToCharA(NewName,NewName);
|
||||
#else
|
||||
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);
|
||||
#endif
|
||||
if (PointToName(NewName)==NewName)
|
||||
strcpy(PointToName(Name),NewName);
|
||||
else
|
||||
strcpy(Name,NewName);
|
||||
|
||||
if (NameW!=NULL)
|
||||
if (PointToName(NewNameW)==NewNameW)
|
||||
wcscpy(PointToName(NameW),NewNameW);
|
||||
else
|
||||
wcscpy(NameW,NewNameW);
|
||||
continue;
|
||||
}
|
||||
if (Choice==6)
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
return false;
|
||||
}
|
||||
if (Choice==UIASKREP_R_CANCEL)
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
if (NewFile!=NULL && NewFile->Create(Name,NameW))
|
||||
return(true);
|
||||
PrepareToDelete(Name,NameW);
|
||||
CreatePath(Name,NameW,true);
|
||||
return(NewFile!=NULL ? NewFile->Create(Name,NameW):DelFile(Name,NameW));
|
||||
|
||||
// Try to truncate the existing file first instead of delete,
|
||||
// so we preserve existing file permissions such as NTFS permissions.
|
||||
uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
|
||||
if (NewFile!=NULL && NewFile->Create(Name,FileMode))
|
||||
return true;
|
||||
|
||||
CreatePath(Name,true);
|
||||
return NewFile!=NULL ? NewFile->Create(Name,FileMode):DelFile(Name);
|
||||
}
|
||||
|
||||
|
||||
bool GetAutoRenamedName(char *Name,wchar *NameW)
|
||||
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize)
|
||||
{
|
||||
char NewName[NM];
|
||||
wchar NewNameW[NM];
|
||||
|
||||
if (Name!=NULL && strlen(Name)>ASIZE(NewName)-10 ||
|
||||
NameW!=NULL && wcslen(NameW)>ASIZE(NewNameW)-10)
|
||||
return(false);
|
||||
char *Ext=NULL;
|
||||
if (Name!=NULL && *Name!=0)
|
||||
wchar NewName[NM];
|
||||
size_t NameLength=wcslen(Name);
|
||||
wchar *Ext=GetExt(Name);
|
||||
if (Ext==NULL)
|
||||
Ext=Name+NameLength;
|
||||
for (uint FileVer=1;;FileVer++)
|
||||
{
|
||||
Ext=GetExt(Name);
|
||||
if (Ext==NULL)
|
||||
Ext=Name+strlen(Name);
|
||||
}
|
||||
wchar *ExtW=NULL;
|
||||
if (NameW!=NULL && *NameW!=0)
|
||||
{
|
||||
ExtW=GetExt(NameW);
|
||||
if (ExtW==NULL)
|
||||
ExtW=NameW+wcslen(NameW);
|
||||
}
|
||||
*NewName=0;
|
||||
*NewNameW=0;
|
||||
for (int FileVer=1;;FileVer++)
|
||||
{
|
||||
if (Name!=NULL && *Name!=0)
|
||||
sprintf(NewName,"%.*s(%d)%s",int(Ext-Name),Name,FileVer,Ext);
|
||||
if (NameW!=NULL && *NameW!=0)
|
||||
sprintfw(NewNameW,ASIZE(NewNameW),L"%.*s(%d)%s",int(ExtW-NameW),NameW,FileVer,ExtW);
|
||||
if (!FileExist(NewName,NewNameW))
|
||||
swprintf(NewName,ASIZE(NewName),L"%.*ls(%u)%ls",uint(Ext-Name),Name,FileVer,Ext);
|
||||
if (!FileExist(NewName))
|
||||
{
|
||||
if (Name!=NULL && *Name!=0)
|
||||
strcpy(Name,NewName);
|
||||
if (NameW!=NULL && *NameW!=0)
|
||||
wcscpy(NameW,NewNameW);
|
||||
wcsncpyz(Name,NewName,MaxNameSize);
|
||||
break;
|
||||
}
|
||||
if (FileVer>=1000000)
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
return(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
#if defined(_WIN_ALL)
|
||||
// If we find a file, which short name is equal to 'Name', we try to change
|
||||
// its short name, while preserving the long name. It helps when unpacking
|
||||
// an archived file, which long name is equal to short name of already
|
||||
// existing file. Otherwise we would overwrite the already existing file,
|
||||
// even though its long name does not match the name of unpacking file.
|
||||
bool UpdateExistingShortName(wchar *Name)
|
||||
bool UpdateExistingShortName(const wchar *Name)
|
||||
{
|
||||
// 'Name' is the name of file which we want to create. Let's check
|
||||
// if file with such name is exist. If it does not, we return.
|
||||
FindData fd;
|
||||
if (!FindFile::FastFind(NULL,Name,&fd))
|
||||
return(false);
|
||||
wchar LongPathName[NM];
|
||||
DWORD Res=GetLongPathName(Name,LongPathName,ASIZE(LongPathName));
|
||||
if (Res==0 || Res>=ASIZE(LongPathName))
|
||||
return false;
|
||||
wchar ShortPathName[NM];
|
||||
Res=GetShortPathName(Name,ShortPathName,ASIZE(ShortPathName));
|
||||
if (Res==0 || Res>=ASIZE(ShortPathName))
|
||||
return false;
|
||||
wchar *LongName=PointToName(LongPathName);
|
||||
wchar *ShortName=PointToName(ShortPathName);
|
||||
|
||||
// We continue only if file has a short name, which does not match its
|
||||
// long name, and this short name is equal to name of file which we need
|
||||
// to create.
|
||||
if (*fd.ShortName==0 || wcsicomp(PointToName(fd.NameW),fd.ShortName)==0 ||
|
||||
wcsicomp(PointToName(Name),fd.ShortName)!=0)
|
||||
return(false);
|
||||
if (*ShortName==0 || wcsicomp(LongName,ShortName)==0 ||
|
||||
wcsicomp(PointToName(Name),ShortName)!=0)
|
||||
return false;
|
||||
|
||||
// Generate the temporary new name for existing file.
|
||||
wchar NewName[NM];
|
||||
@@ -208,28 +112,28 @@ bool UpdateExistingShortName(wchar *Name)
|
||||
wcsncpyz(NewName,Name,ASIZE(NewName));
|
||||
|
||||
// Here we set the random name part.
|
||||
sprintfw(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
|
||||
swprintf(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
|
||||
|
||||
// If such file is already exist, try next random name.
|
||||
if (FileExist(NULL,NewName))
|
||||
if (FileExist(NewName))
|
||||
*NewName=0;
|
||||
}
|
||||
|
||||
// If we could not generate the name not used by any other file, we return.
|
||||
if (*NewName==0)
|
||||
return(false);
|
||||
return false;
|
||||
|
||||
// FastFind returns the name without path, but we need the fully qualified
|
||||
// name for renaming, so we use the path from file to create and long name
|
||||
// from existing file.
|
||||
wchar FullName[NM];
|
||||
wcsncpyz(FullName,Name,ASIZE(FullName));
|
||||
wcscpy(PointToName(FullName),PointToName(fd.NameW));
|
||||
SetName(FullName,LongName,ASIZE(FullName));
|
||||
|
||||
// Rename the existing file to randomly generated name. Normally it changes
|
||||
// the short name too.
|
||||
if (!MoveFileW(FullName,NewName))
|
||||
return(false);
|
||||
if (!MoveFile(FullName,NewName))
|
||||
return false;
|
||||
|
||||
// Now we need to create the temporary empty file with same name as
|
||||
// short name of our already existing file. We do it to occupy its previous
|
||||
@@ -237,13 +141,13 @@ bool UpdateExistingShortName(wchar *Name)
|
||||
// its original long name.
|
||||
File KeepShortFile;
|
||||
bool Created=false;
|
||||
if (!FileExist(NULL,Name))
|
||||
Created=KeepShortFile.Create(NULL,Name);
|
||||
if (!FileExist(Name))
|
||||
Created=KeepShortFile.Create(Name,FMF_WRITE|FMF_SHAREREAD);
|
||||
|
||||
// Now we rename the existing file from temporary name to original long name.
|
||||
// Since its previous short name is occupied by another file, it should
|
||||
// get another short name.
|
||||
MoveFileW(NewName,FullName);
|
||||
MoveFile(NewName,FullName);
|
||||
|
||||
if (Created)
|
||||
{
|
||||
@@ -254,6 +158,6 @@ bool UpdateExistingShortName(wchar *Name)
|
||||
// We successfully changed the short name. Maybe sometimes we'll simplify
|
||||
// this function by use of SetFileShortName Windows API call.
|
||||
// But SetFileShortName is not available in older Windows.
|
||||
return(true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#ifndef _RAR_FILECREATE_
|
||||
#define _RAR_FILECREATE_
|
||||
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize=INT64NDF,
|
||||
uint FileTime=0);
|
||||
bool GetAutoRenamedName(char *Name,wchar *NameW);
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||
bool *UserReject,int64 FileSize=INT64NDF,
|
||||
RarTime *FileTime=NULL,bool WriteOnly=false);
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
bool UpdateExistingShortName(wchar *Name);
|
||||
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize);
|
||||
|
||||
#if defined(_WIN_ALL)
|
||||
bool UpdateExistingShortName(const wchar *Name);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
581
unrar/file.cpp
581
unrar/file.cpp
@@ -1,13 +1,9 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
static File *CreatedFiles[256];
|
||||
static int RemoveCreatedActive=0;
|
||||
|
||||
File::File()
|
||||
{
|
||||
hFile=BAD_HANDLE;
|
||||
hFile=FILE_BAD_HANDLE;
|
||||
*FileName=0;
|
||||
*FileNameW=0;
|
||||
NewFile=false;
|
||||
LastWrite=false;
|
||||
HandleType=FILE_HANDLENORMAL;
|
||||
@@ -16,17 +12,17 @@ File::File()
|
||||
ErrorType=FILE_SUCCESS;
|
||||
OpenShared=false;
|
||||
AllowDelete=true;
|
||||
CloseCount=0;
|
||||
AllowExceptions=true;
|
||||
#ifdef _WIN_ALL
|
||||
NoSequentialRead=false;
|
||||
CreateMode=FMF_UNDEFINED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
File::~File()
|
||||
{
|
||||
if (hFile!=BAD_HANDLE && !SkipClose)
|
||||
if (hFile!=FILE_BAD_HANDLE && !SkipClose)
|
||||
if (NewFile)
|
||||
Delete();
|
||||
else
|
||||
@@ -37,270 +33,274 @@ File::~File()
|
||||
void File::operator = (File &SrcFile)
|
||||
{
|
||||
hFile=SrcFile.hFile;
|
||||
strcpy(FileName,SrcFile.FileName);
|
||||
NewFile=SrcFile.NewFile;
|
||||
LastWrite=SrcFile.LastWrite;
|
||||
HandleType=SrcFile.HandleType;
|
||||
wcsncpyz(FileName,SrcFile.FileName,ASIZE(FileName));
|
||||
SrcFile.SkipClose=true;
|
||||
}
|
||||
|
||||
|
||||
bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
|
||||
bool File::Open(const wchar *Name,uint Mode)
|
||||
{
|
||||
ErrorType=FILE_SUCCESS;
|
||||
FileHandle hNewFile;
|
||||
if (File::OpenShared)
|
||||
OpenShared=true;
|
||||
bool OpenShared=File::OpenShared || (Mode & FMF_OPENSHARED)!=0;
|
||||
bool UpdateMode=(Mode & FMF_UPDATE)!=0;
|
||||
bool WriteMode=(Mode & FMF_WRITE)!=0;
|
||||
#ifdef _WIN_ALL
|
||||
uint Access=GENERIC_READ;
|
||||
if (Update)
|
||||
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ;
|
||||
if (UpdateMode)
|
||||
Access|=GENERIC_WRITE;
|
||||
uint ShareMode=FILE_SHARE_READ;
|
||||
uint ShareMode=(Mode & FMF_OPENEXCLUSIVE) ? 0 : FILE_SHARE_READ;
|
||||
if (OpenShared)
|
||||
ShareMode|=FILE_SHARE_WRITE;
|
||||
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
hNewFile=CreateFileW(NameW,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
||||
else
|
||||
hNewFile=CreateFileA(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
||||
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
||||
|
||||
if (hNewFile==BAD_HANDLE && GetLastError()==ERROR_FILE_NOT_FOUND)
|
||||
DWORD LastError;
|
||||
if (hNewFile==FILE_BAD_HANDLE)
|
||||
{
|
||||
LastError=GetLastError();
|
||||
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
{
|
||||
hNewFile=CreateFile(LongName,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
||||
|
||||
// For archive names longer than 260 characters first CreateFile
|
||||
// (without \\?\) fails and sets LastError to 3 (access denied).
|
||||
// We need the correct "file not found" error code to decide
|
||||
// if we create a new archive or quit with "cannot create" error.
|
||||
// So we need to check the error code after \\?\ CreateFile again,
|
||||
// otherwise we'll fail to create new archives with long names.
|
||||
// But we cannot simply assign the new code to LastError,
|
||||
// because it would break "..\arcname.rar" relative names processing.
|
||||
// First CreateFile returns the correct "file not found" code for such
|
||||
// names, but "\\?\" CreateFile returns ERROR_INVALID_NAME treating
|
||||
// dots as a directory name. So we check only for "file not found"
|
||||
// error here and for other errors use the first CreateFile result.
|
||||
if (GetLastError()==ERROR_FILE_NOT_FOUND)
|
||||
LastError=ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
|
||||
ErrorType=FILE_NOTFOUND;
|
||||
|
||||
#else
|
||||
int flags=Update ? O_RDWR:O_RDONLY;
|
||||
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
|
||||
#ifdef O_BINARY
|
||||
flags|=O_BINARY;
|
||||
#if defined(_AIX) && defined(_LARGE_FILE_API)
|
||||
flags|=O_LARGEFILE;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_EMX) && !defined(_DJGPP)
|
||||
int sflags=OpenShared ? SH_DENYNO:SH_DENYWR;
|
||||
int handle=sopen(Name,flags,sflags);
|
||||
#else
|
||||
int handle=open(Name,flags);
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
|
||||
int handle=open(NameA,flags);
|
||||
#ifdef LOCK_EX
|
||||
|
||||
#ifdef _OSF_SOURCE
|
||||
extern "C" int flock(int, int);
|
||||
#endif
|
||||
|
||||
if (!OpenShared && Update && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
|
||||
if (!OpenShared && UpdateMode && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
|
||||
{
|
||||
close(handle);
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (handle==-1)
|
||||
hNewFile=FILE_BAD_HANDLE;
|
||||
else
|
||||
{
|
||||
#ifdef FILE_USE_OPEN
|
||||
hNewFile=handle;
|
||||
#else
|
||||
hNewFile=fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
|
||||
#endif
|
||||
hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,Update ? UPDATEBINARY:READBINARY);
|
||||
if (hNewFile==BAD_HANDLE && errno==ENOENT)
|
||||
}
|
||||
if (hNewFile==FILE_BAD_HANDLE && errno==ENOENT)
|
||||
ErrorType=FILE_NOTFOUND;
|
||||
#endif
|
||||
NewFile=false;
|
||||
HandleType=FILE_HANDLENORMAL;
|
||||
SkipClose=false;
|
||||
bool Success=hNewFile!=BAD_HANDLE;
|
||||
bool Success=hNewFile!=FILE_BAD_HANDLE;
|
||||
if (Success)
|
||||
{
|
||||
hFile=hNewFile;
|
||||
|
||||
// We use memove instead of strcpy and wcscpy to avoid problems
|
||||
// with overlapped buffers. While we do not call this function with
|
||||
// really overlapped buffers yet, we do call it with Name equal to
|
||||
// FileName like Arc.Open(Arc.FileName,Arc.FileNameW).
|
||||
if (NameW!=NULL)
|
||||
memmove(FileNameW,NameW,(wcslen(NameW)+1)*sizeof(*NameW));
|
||||
else
|
||||
*FileNameW=0;
|
||||
if (Name!=NULL)
|
||||
memmove(FileName,Name,strlen(Name)+1);
|
||||
else
|
||||
WideToChar(NameW,FileName);
|
||||
AddFileToList(hFile);
|
||||
wcsncpyz(FileName,Name,ASIZE(FileName));
|
||||
}
|
||||
return(Success);
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
|
||||
void File::TOpen(const char *Name,const wchar *NameW)
|
||||
#if !defined(SFX_MODULE)
|
||||
void File::TOpen(const wchar *Name)
|
||||
{
|
||||
if (!WOpen(Name,NameW))
|
||||
ErrHandler.Exit(OPEN_ERROR);
|
||||
if (!WOpen(Name))
|
||||
ErrHandler.Exit(RARX_OPEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool File::WOpen(const char *Name,const wchar *NameW)
|
||||
bool File::WOpen(const wchar *Name)
|
||||
{
|
||||
if (Open(Name,NameW))
|
||||
return(true);
|
||||
ErrHandler.OpenErrorMsg(Name,NameW);
|
||||
return(false);
|
||||
if (Open(Name))
|
||||
return true;
|
||||
ErrHandler.OpenErrorMsg(Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool File::Create(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
bool File::Create(const wchar *Name,uint Mode)
|
||||
{
|
||||
// OpenIndiana based NAS and CIFS shares fail to set the file time if file
|
||||
// was created in read+write mode and some data was written and not flushed
|
||||
// before SetFileTime call. So we should use the write only mode if we plan
|
||||
// SetFileTime call and do not need to read from file.
|
||||
bool WriteMode=(Mode & FMF_WRITE)!=0;
|
||||
bool ShareRead=(Mode & FMF_SHAREREAD)!=0 || File::OpenShared;
|
||||
#ifdef _WIN_ALL
|
||||
DWORD ShareMode=(ShareRead || File::OpenShared) ? FILE_SHARE_READ:0;
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
|
||||
CREATE_ALWAYS,0,NULL);
|
||||
CreateMode=Mode;
|
||||
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ|GENERIC_WRITE;
|
||||
DWORD ShareMode=ShareRead ? FILE_SHARE_READ:0;
|
||||
|
||||
// Windows automatically removes dots and spaces in the end of file name,
|
||||
// So we detect such names and process them with \\?\ prefix.
|
||||
wchar *LastChar=PointToLastChar(Name);
|
||||
bool Special=*LastChar=='.' || *LastChar==' ';
|
||||
|
||||
if (Special)
|
||||
hFile=FILE_BAD_HANDLE;
|
||||
else
|
||||
hFile=CreateFileA(Name,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
|
||||
CREATE_ALWAYS,0,NULL);
|
||||
hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
|
||||
|
||||
if (hFile==FILE_BAD_HANDLE)
|
||||
{
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
hFile=CreateFile(LongName,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
hFile=fopen(Name,CREATEBINARY);
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
#ifdef FILE_USE_OPEN
|
||||
hFile=open(NameA,(O_CREAT|O_TRUNC) | (WriteMode ? O_WRONLY : O_RDWR),0666);
|
||||
#else
|
||||
hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY);
|
||||
#endif
|
||||
#endif
|
||||
NewFile=true;
|
||||
HandleType=FILE_HANDLENORMAL;
|
||||
SkipClose=false;
|
||||
if (NameW!=NULL)
|
||||
wcscpy(FileNameW,NameW);
|
||||
else
|
||||
*FileNameW=0;
|
||||
if (Name!=NULL)
|
||||
strcpy(FileName,Name);
|
||||
else
|
||||
WideToChar(NameW,FileName);
|
||||
AddFileToList(hFile);
|
||||
return(hFile!=BAD_HANDLE);
|
||||
wcsncpyz(FileName,Name,ASIZE(FileName));
|
||||
return hFile!=FILE_BAD_HANDLE;
|
||||
}
|
||||
|
||||
|
||||
void File::AddFileToList(FileHandle hFile)
|
||||
#if !defined(SFX_MODULE)
|
||||
void File::TCreate(const wchar *Name,uint Mode)
|
||||
{
|
||||
if (hFile!=BAD_HANDLE)
|
||||
for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
|
||||
if (CreatedFiles[I]==NULL)
|
||||
{
|
||||
CreatedFiles[I]=this;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
|
||||
void File::TCreate(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
{
|
||||
if (!WCreate(Name,NameW,ShareRead))
|
||||
ErrHandler.Exit(FATAL_ERROR);
|
||||
if (!WCreate(Name,Mode))
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool File::WCreate(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
bool File::WCreate(const wchar *Name,uint Mode)
|
||||
{
|
||||
if (Create(Name,NameW,ShareRead))
|
||||
return(true);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
ErrHandler.CreateErrorMsg(Name,NameW);
|
||||
return(false);
|
||||
if (Create(Name,Mode))
|
||||
return true;
|
||||
ErrHandler.CreateErrorMsg(Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool File::Close()
|
||||
{
|
||||
bool Success=true;
|
||||
if (HandleType!=FILE_HANDLENORMAL)
|
||||
HandleType=FILE_HANDLENORMAL;
|
||||
else
|
||||
if (hFile!=BAD_HANDLE)
|
||||
|
||||
if (hFile!=FILE_BAD_HANDLE)
|
||||
{
|
||||
if (!SkipClose)
|
||||
{
|
||||
if (!SkipClose)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// We use the standard system handle for stdout in Windows
|
||||
// and it must not be closed here.
|
||||
if (HandleType==FILE_HANDLENORMAL)
|
||||
Success=CloseHandle(hFile)==TRUE;
|
||||
#else
|
||||
Success=fclose(hFile)!=EOF;
|
||||
#endif
|
||||
if (Success || !RemoveCreatedActive)
|
||||
for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
|
||||
if (CreatedFiles[I]==this)
|
||||
{
|
||||
CreatedFiles[I]=NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
hFile=BAD_HANDLE;
|
||||
if (!Success && AllowExceptions)
|
||||
ErrHandler.CloseError(FileName,FileNameW);
|
||||
}
|
||||
CloseCount++;
|
||||
return(Success);
|
||||
}
|
||||
|
||||
|
||||
void File::Flush()
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
FlushFileBuffers(hFile);
|
||||
#ifdef FILE_USE_OPEN
|
||||
Success=close(hFile)!=-1;
|
||||
#else
|
||||
fflush(hFile);
|
||||
Success=fclose(hFile)!=EOF;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
hFile=FILE_BAD_HANDLE;
|
||||
}
|
||||
HandleType=FILE_HANDLENORMAL;
|
||||
if (!Success && AllowExceptions)
|
||||
ErrHandler.CloseError(FileName);
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
bool File::Delete()
|
||||
{
|
||||
if (HandleType!=FILE_HANDLENORMAL)
|
||||
return(false);
|
||||
if (hFile!=BAD_HANDLE)
|
||||
return false;
|
||||
if (hFile!=FILE_BAD_HANDLE)
|
||||
Close();
|
||||
if (!AllowDelete)
|
||||
return(false);
|
||||
return(DelFile(FileName,FileNameW));
|
||||
return false;
|
||||
return DelFile(FileName);
|
||||
}
|
||||
|
||||
|
||||
bool File::Rename(const char *NewName,const wchar *NewNameW)
|
||||
bool File::Rename(const wchar *NewName)
|
||||
{
|
||||
// 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=wcscmp(FileNameW,NewNameW)==0;
|
||||
// No need to rename if names are already same.
|
||||
bool Success=wcscmp(FileName,NewName)==0;
|
||||
|
||||
if (!Success)
|
||||
Success=RenameFile(FileName,FileNameW,NewName,NewNameW);
|
||||
Success=RenameFile(FileName,NewName);
|
||||
|
||||
if (Success)
|
||||
{
|
||||
// renamed successfully, storing the new name
|
||||
strcpy(FileName,NewName);
|
||||
wcscpy(FileNameW,NullToEmpty(NewNameW));
|
||||
}
|
||||
return(Success);
|
||||
wcscpy(FileName,NewName);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
void File::Write(const void *Data,size_t Size)
|
||||
bool File::Write(const void *Data,size_t Size)
|
||||
{
|
||||
if (Size==0)
|
||||
return;
|
||||
#ifndef _WIN_CE
|
||||
if (HandleType!=FILE_HANDLENORMAL)
|
||||
switch(HandleType)
|
||||
return true;
|
||||
if (HandleType==FILE_HANDLESTD)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
hFile=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
#else
|
||||
// Cannot use the standard stdout here, because it already has wide orientation.
|
||||
if (hFile==FILE_BAD_HANDLE)
|
||||
{
|
||||
case FILE_HANDLESTD:
|
||||
#ifdef _WIN_ALL
|
||||
hFile=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
#ifdef FILE_USE_OPEN
|
||||
hFile=dup(STDOUT_FILENO); // Open new stdout stream.
|
||||
#else
|
||||
hFile=stdout;
|
||||
hFile=fdopen(dup(STDOUT_FILENO),"w"); // Open new stdout stream.
|
||||
#endif
|
||||
break;
|
||||
case FILE_HANDLEERR:
|
||||
#ifdef _WIN_ALL
|
||||
hFile=GetStdHandle(STD_ERROR_HANDLE);
|
||||
#else
|
||||
hFile=stderr;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
bool Success;
|
||||
while (1)
|
||||
{
|
||||
bool Success=false;
|
||||
Success=false;
|
||||
#ifdef _WIN_ALL
|
||||
DWORD Written=0;
|
||||
if (HandleType!=FILE_HANDLENORMAL)
|
||||
@@ -316,9 +316,14 @@ void File::Write(const void *Data,size_t Size)
|
||||
}
|
||||
else
|
||||
Success=WriteFile(hFile,Data,(DWORD)Size,&Written,NULL)==TRUE;
|
||||
#else
|
||||
#ifdef FILE_USE_OPEN
|
||||
ssize_t Written=write(hFile,Data,Size);
|
||||
Success=Written==Size;
|
||||
#else
|
||||
int Written=fwrite(Data,1,Size,hFile);
|
||||
Success=Written==Size && !ferror(hFile);
|
||||
#endif
|
||||
#endif
|
||||
if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
|
||||
{
|
||||
@@ -328,22 +333,23 @@ void File::Write(const void *Data,size_t Size)
|
||||
uint64 FreeSize=GetFreeDisk(FileName);
|
||||
SetLastError(ErrCode);
|
||||
if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
|
||||
ErrHandler.WriteErrorFAT(FileName,FileNameW);
|
||||
ErrHandler.WriteErrorFAT(FileName);
|
||||
#endif
|
||||
if (ErrHandler.AskRepeatWrite(FileName,FileNameW,false))
|
||||
if (ErrHandler.AskRepeatWrite(FileName,false))
|
||||
{
|
||||
#ifndef _WIN_ALL
|
||||
#if !defined(_WIN_ALL) && !defined(FILE_USE_OPEN)
|
||||
clearerr(hFile);
|
||||
#endif
|
||||
if (Written<Size && Written>0)
|
||||
Seek(Tell()-Written,SEEK_SET);
|
||||
continue;
|
||||
}
|
||||
ErrHandler.WriteError(NULL,NULL,FileName,FileNameW);
|
||||
ErrHandler.WriteError(NULL,FileName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
LastWrite=true;
|
||||
return Success; // It can return false only if AllowExceptions is disabled.
|
||||
}
|
||||
|
||||
|
||||
@@ -374,14 +380,14 @@ int File::Read(void *Data,size_t Size)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName,FileNameW))
|
||||
if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName))
|
||||
continue;
|
||||
ErrHandler.ReadError(FileName,FileNameW);
|
||||
ErrHandler.ReadError(FileName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return(ReadSize);
|
||||
return ReadSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -390,30 +396,52 @@ int File::DirectRead(void *Data,size_t Size)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
const size_t MaxDeviceRead=20000;
|
||||
const size_t MaxLockedRead=32768;
|
||||
#endif
|
||||
#ifndef _WIN_CE
|
||||
if (HandleType==FILE_HANDLESTD)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
if (Size>MaxDeviceRead)
|
||||
Size=MaxDeviceRead;
|
||||
// if (Size>MaxDeviceRead)
|
||||
// Size=MaxDeviceRead;
|
||||
hFile=GetStdHandle(STD_INPUT_HANDLE);
|
||||
#else
|
||||
#ifdef FILE_USE_OPEN
|
||||
hFile=STDIN_FILENO;
|
||||
#else
|
||||
hFile=stdin;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef _WIN_ALL
|
||||
// For pipes like 'type file.txt | rar -si arcname' ReadFile may return
|
||||
// data in small ~4KB blocks. It may slightly reduce the compression ratio.
|
||||
DWORD Read;
|
||||
if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
|
||||
{
|
||||
if (IsDevice() && Size>MaxDeviceRead)
|
||||
return(DirectRead(Data,MaxDeviceRead));
|
||||
return DirectRead(Data,MaxDeviceRead);
|
||||
if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE)
|
||||
return(0);
|
||||
return(-1);
|
||||
return 0;
|
||||
|
||||
// We had a bug report about failure to archive 1C database lock file
|
||||
// 1Cv8tmp.1CL, which is a zero length file with a region above 200 KB
|
||||
// permanently locked. If our first read request uses too large buffer
|
||||
// and if we are in -dh mode, so we were able to open the file,
|
||||
// we'll fail with "Read error". So now we use try a smaller buffer size
|
||||
// in case of lock error.
|
||||
if (HandleType==FILE_HANDLENORMAL && Size>MaxLockedRead &&
|
||||
GetLastError()==ERROR_LOCK_VIOLATION)
|
||||
return DirectRead(Data,MaxLockedRead);
|
||||
|
||||
return -1;
|
||||
}
|
||||
return(Read);
|
||||
return Read;
|
||||
#else
|
||||
#ifdef FILE_USE_OPEN
|
||||
ssize_t ReadSize=read(hFile,Data,Size);
|
||||
if (ReadSize==-1)
|
||||
return -1;
|
||||
return (int)ReadSize;
|
||||
#else
|
||||
if (LastWrite)
|
||||
{
|
||||
@@ -423,8 +451,9 @@ int File::DirectRead(void *Data,size_t Size)
|
||||
clearerr(hFile);
|
||||
size_t ReadSize=fread(Data,1,Size,hFile);
|
||||
if (ferror(hFile))
|
||||
return(-1);
|
||||
return((int)ReadSize);
|
||||
return -1;
|
||||
return (int)ReadSize;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -432,14 +461,14 @@ int File::DirectRead(void *Data,size_t Size)
|
||||
void File::Seek(int64 Offset,int Method)
|
||||
{
|
||||
if (!RawSeek(Offset,Method) && AllowExceptions)
|
||||
ErrHandler.SeekError(FileName,FileNameW);
|
||||
ErrHandler.SeekError(FileName);
|
||||
}
|
||||
|
||||
|
||||
bool File::RawSeek(int64 Offset,int Method)
|
||||
{
|
||||
if (hFile==BAD_HANDLE)
|
||||
return(true);
|
||||
if (hFile==FILE_BAD_HANDLE)
|
||||
return true;
|
||||
if (Offset<0 && Method!=SEEK_SET)
|
||||
{
|
||||
Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
|
||||
@@ -449,41 +478,47 @@ bool File::RawSeek(int64 Offset,int Method)
|
||||
LONG HighDist=(LONG)(Offset>>32);
|
||||
if (SetFilePointer(hFile,(LONG)Offset,&HighDist,Method)==0xffffffff &&
|
||||
GetLastError()!=NO_ERROR)
|
||||
return(false);
|
||||
return false;
|
||||
#else
|
||||
LastWrite=false;
|
||||
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
|
||||
#ifdef FILE_USE_OPEN
|
||||
if (lseek(hFile,(off_t)Offset,Method)==-1)
|
||||
return false;
|
||||
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
|
||||
if (fseeko(hFile,Offset,Method)!=0)
|
||||
return false;
|
||||
#else
|
||||
if (fseek(hFile,(long)Offset,Method)!=0)
|
||||
return false;
|
||||
#endif
|
||||
return(false);
|
||||
#endif
|
||||
return(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int64 File::Tell()
|
||||
{
|
||||
if (hFile==BAD_HANDLE)
|
||||
if (hFile==FILE_BAD_HANDLE)
|
||||
if (AllowExceptions)
|
||||
ErrHandler.SeekError(FileName,FileNameW);
|
||||
ErrHandler.SeekError(FileName);
|
||||
else
|
||||
return(-1);
|
||||
return -1;
|
||||
#ifdef _WIN_ALL
|
||||
LONG HighDist=0;
|
||||
uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
|
||||
if (LowDist==0xffffffff && GetLastError()!=NO_ERROR)
|
||||
if (AllowExceptions)
|
||||
ErrHandler.SeekError(FileName,FileNameW);
|
||||
ErrHandler.SeekError(FileName);
|
||||
else
|
||||
return(-1);
|
||||
return(INT32TO64(HighDist,LowDist));
|
||||
return -1;
|
||||
return INT32TO64(HighDist,LowDist);
|
||||
#else
|
||||
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
|
||||
return(ftello(hFile));
|
||||
#ifdef FILE_USE_OPEN
|
||||
return lseek(hFile,0,SEEK_CUR);
|
||||
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
|
||||
return ftello(hFile);
|
||||
#else
|
||||
return(ftell(hFile));
|
||||
return ftell(hFile);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -498,6 +533,14 @@ void File::Prealloc(int64 Size)
|
||||
Seek(0,SEEK_SET);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_UNIX) && defined(USE_FALLOCATE)
|
||||
// fallocate is rather new call. Only latest kernels support it.
|
||||
// So we are not using it by default yet.
|
||||
int fd = GetFD();
|
||||
if (fd >= 0)
|
||||
fallocate(fd, 0, 0, Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -505,7 +548,7 @@ byte File::GetByte()
|
||||
{
|
||||
byte Byte=0;
|
||||
Read(&Byte,1);
|
||||
return(Byte);
|
||||
return Byte;
|
||||
}
|
||||
|
||||
|
||||
@@ -518,9 +561,22 @@ void File::PutByte(byte Byte)
|
||||
bool File::Truncate()
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
return(SetEndOfFile(hFile)==TRUE);
|
||||
return SetEndOfFile(hFile)==TRUE;
|
||||
#else
|
||||
return(false);
|
||||
return ftruncate(GetFD(),(off_t)Tell())==0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void File::Flush()
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
FlushFileBuffers(hFile);
|
||||
#else
|
||||
#ifndef FILE_USE_OPEN
|
||||
fflush(hFile);
|
||||
#endif
|
||||
fsync(GetFD());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -528,16 +584,22 @@ bool File::Truncate()
|
||||
void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// Workaround for OpenIndiana NAS time bug. If we cannot create a file
|
||||
// in write only mode, we need to flush the write buffer before calling
|
||||
// SetFileTime or file time will not be changed.
|
||||
if (CreateMode!=FMF_UNDEFINED && (CreateMode & FMF_WRITE)==0)
|
||||
FlushFileBuffers(hFile);
|
||||
|
||||
bool sm=ftm!=NULL && ftm->IsSet();
|
||||
bool sc=ftc!=NULL && ftc->IsSet();
|
||||
bool sa=fta!=NULL && fta->IsSet();
|
||||
FILETIME fm,fc,fa;
|
||||
if (sm)
|
||||
ftm->GetWin32(&fm);
|
||||
ftm->GetWinFT(&fm);
|
||||
if (sc)
|
||||
ftc->GetWin32(&fc);
|
||||
ftc->GetWinFT(&fc);
|
||||
if (sa)
|
||||
fta->GetWin32(&fa);
|
||||
fta->GetWinFT(&fa);
|
||||
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
|
||||
#endif
|
||||
}
|
||||
@@ -545,29 +607,47 @@ void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
|
||||
void File::SetCloseFileTime(RarTime *ftm,RarTime *fta)
|
||||
{
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
// Android APP_PLATFORM := android-14 does not support futimens and futimes.
|
||||
// Newer platforms support futimens, but fail on Android 4.2.
|
||||
// We have to use utime for Android.
|
||||
// Also we noticed futimens fail to set timestamps on NTFS partition
|
||||
// mounted to virtual Linux x86 machine, but utimensat worked correctly.
|
||||
// So we set timestamps for already closed files in Unix.
|
||||
#ifdef _UNIX
|
||||
SetCloseFileTimeByName(FileName,ftm,fta);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void File::SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta)
|
||||
void File::SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta)
|
||||
{
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
#ifdef _UNIX
|
||||
bool setm=ftm!=NULL && ftm->IsSet();
|
||||
bool seta=fta!=NULL && fta->IsSet();
|
||||
if (setm || seta)
|
||||
{
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
|
||||
#ifdef UNIX_TIME_NS
|
||||
timespec times[2];
|
||||
times[0].tv_sec=seta ? fta->GetUnix() : 0;
|
||||
times[0].tv_nsec=seta ? long(fta->GetUnixNS()%1000000000) : UTIME_NOW;
|
||||
times[1].tv_sec=setm ? ftm->GetUnix() : 0;
|
||||
times[1].tv_nsec=setm ? long(ftm->GetUnixNS()%1000000000) : UTIME_NOW;
|
||||
utimensat(AT_FDCWD,NameA,times,0);
|
||||
#else
|
||||
utimbuf ut;
|
||||
if (setm)
|
||||
ut.modtime=ftm->GetUnix();
|
||||
else
|
||||
ut.modtime=fta->GetUnix();
|
||||
ut.modtime=fta->GetUnix(); // Need to set something, cannot left it 0.
|
||||
if (seta)
|
||||
ut.actime=fta->GetUnix();
|
||||
else
|
||||
ut.actime=ut.modtime;
|
||||
utime(Name,&ut);
|
||||
ut.actime=ut.modtime; // Need to set something, cannot left it 0.
|
||||
utime(NameA,&ut);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -578,12 +658,12 @@ void File::GetOpenFileTime(RarTime *ft)
|
||||
#ifdef _WIN_ALL
|
||||
FILETIME FileTime;
|
||||
GetFileTime(hFile,NULL,NULL,&FileTime);
|
||||
*ft=FileTime;
|
||||
ft->SetWinFT(&FileTime);
|
||||
#endif
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
struct stat st;
|
||||
fstat(fileno(hFile),&st);
|
||||
*ft=st.st_mtime;
|
||||
fstat(GetFD(),&st);
|
||||
ft->SetUnix(st.st_mtime);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -592,82 +672,27 @@ int64 File::FileLength()
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
Seek(0,SEEK_END);
|
||||
return(Tell());
|
||||
}
|
||||
|
||||
|
||||
void File::SetHandleType(FILE_HANDLETYPE Type)
|
||||
{
|
||||
HandleType=Type;
|
||||
return Tell();
|
||||
}
|
||||
|
||||
|
||||
bool File::IsDevice()
|
||||
{
|
||||
if (hFile==BAD_HANDLE)
|
||||
return(false);
|
||||
if (hFile==FILE_BAD_HANDLE)
|
||||
return false;
|
||||
#ifdef _WIN_ALL
|
||||
uint Type=GetFileType(hFile);
|
||||
return(Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE);
|
||||
return Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE;
|
||||
#else
|
||||
return(isatty(fileno(hFile)));
|
||||
return isatty(GetFD());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void File::fprintf(const char *fmt,...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr,fmt);
|
||||
safebuf char Msg[2*NM+1024],OutMsg[2*NM+1024];
|
||||
vsprintf(Msg,fmt,argptr);
|
||||
#ifdef _WIN_ALL
|
||||
for (int Src=0,Dest=0;;Src++)
|
||||
{
|
||||
char CurChar=Msg[Src];
|
||||
if (CurChar=='\n')
|
||||
OutMsg[Dest++]='\r';
|
||||
OutMsg[Dest++]=CurChar;
|
||||
if (CurChar==0)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
strcpy(OutMsg,Msg);
|
||||
#endif
|
||||
Write(OutMsg,strlen(OutMsg));
|
||||
va_end(argptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool File::RemoveCreated()
|
||||
{
|
||||
RemoveCreatedActive++;
|
||||
bool RetCode=true;
|
||||
for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
|
||||
if (CreatedFiles[I]!=NULL)
|
||||
{
|
||||
CreatedFiles[I]->SetExceptions(false);
|
||||
bool Success;
|
||||
if (CreatedFiles[I]->NewFile)
|
||||
Success=CreatedFiles[I]->Delete();
|
||||
else
|
||||
Success=CreatedFiles[I]->Close();
|
||||
if (Success)
|
||||
CreatedFiles[I]=NULL;
|
||||
else
|
||||
RetCode=false;
|
||||
}
|
||||
RemoveCreatedActive--;
|
||||
return(RetCode);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int64 File::Copy(File &Dest,int64 Length)
|
||||
{
|
||||
Array<char> Buffer(0x10000);
|
||||
Array<char> Buffer(0x40000);
|
||||
int64 CopySize=0;
|
||||
bool CopyAll=(Length==INT64NDF);
|
||||
|
||||
@@ -675,14 +700,30 @@ int64 File::Copy(File &Dest,int64 Length)
|
||||
{
|
||||
Wait();
|
||||
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
|
||||
int ReadSize=Read(&Buffer[0],SizeToRead);
|
||||
char *Buf=&Buffer[0];
|
||||
int ReadSize=Read(Buf,SizeToRead);
|
||||
if (ReadSize==0)
|
||||
break;
|
||||
Dest.Write(&Buffer[0],ReadSize);
|
||||
size_t WriteSize=ReadSize;
|
||||
#ifdef _WIN_ALL
|
||||
// For FAT32 USB flash drives in Windows if first write is 4 KB or more,
|
||||
// write caching is disabled and "write through" is enabled, resulting
|
||||
// in bad performance, especially for many small files. It happens when
|
||||
// we create SFX archive on USB drive, because SFX module is written first.
|
||||
// So we split the first write to small 1 KB followed by rest of data.
|
||||
if (CopySize==0 && WriteSize>=4096)
|
||||
{
|
||||
const size_t FirstWrite=1024;
|
||||
Dest.Write(Buf,FirstWrite);
|
||||
Buf+=FirstWrite;
|
||||
WriteSize-=FirstWrite;
|
||||
}
|
||||
#endif
|
||||
Dest.Write(Buf,WriteSize);
|
||||
CopySize+=ReadSize;
|
||||
if (!CopyAll)
|
||||
Length-=ReadSize;
|
||||
}
|
||||
return(CopySize);
|
||||
return CopySize;
|
||||
}
|
||||
#endif
|
||||
|
||||
101
unrar/file.hpp
101
unrar/file.hpp
@@ -1,34 +1,52 @@
|
||||
#ifndef _RAR_FILE_
|
||||
#define _RAR_FILE_
|
||||
|
||||
#define FILE_USE_OPEN
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
typedef HANDLE FileHandle;
|
||||
#define BAD_HANDLE INVALID_HANDLE_VALUE
|
||||
typedef HANDLE FileHandle;
|
||||
#define FILE_BAD_HANDLE INVALID_HANDLE_VALUE
|
||||
#elif defined(FILE_USE_OPEN)
|
||||
typedef off_t FileHandle;
|
||||
#define FILE_BAD_HANDLE -1
|
||||
#else
|
||||
typedef FILE* FileHandle;
|
||||
#define BAD_HANDLE NULL
|
||||
typedef FILE* FileHandle;
|
||||
#define FILE_BAD_HANDLE NULL
|
||||
#endif
|
||||
|
||||
class RAROptions;
|
||||
|
||||
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD,FILE_HANDLEERR};
|
||||
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD};
|
||||
|
||||
enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR};
|
||||
|
||||
struct FileStat
|
||||
{
|
||||
uint FileAttr;
|
||||
uint FileTime;
|
||||
int64 FileSize;
|
||||
bool IsDir;
|
||||
enum FILE_MODE_FLAGS {
|
||||
// Request read only access to file. Default for Open.
|
||||
FMF_READ=0,
|
||||
|
||||
// Request both read and write access to file. Default for Create.
|
||||
FMF_UPDATE=1,
|
||||
|
||||
// Request write only access to file.
|
||||
FMF_WRITE=2,
|
||||
|
||||
// Open files which are already opened for write by other programs.
|
||||
FMF_OPENSHARED=4,
|
||||
|
||||
// Open files only if no other program is opened it even in shared mode.
|
||||
FMF_OPENEXCLUSIVE=8,
|
||||
|
||||
// Provide read access to created file for other programs.
|
||||
FMF_SHAREREAD=16,
|
||||
|
||||
// Mode flags are not defined yet.
|
||||
FMF_UNDEFINED=256
|
||||
};
|
||||
|
||||
|
||||
class File
|
||||
{
|
||||
private:
|
||||
void AddFileToList(FileHandle hFile);
|
||||
|
||||
FileHandle hFile;
|
||||
bool LastWrite;
|
||||
FILE_HANDLETYPE HandleType;
|
||||
@@ -39,60 +57,67 @@ class File
|
||||
bool AllowExceptions;
|
||||
#ifdef _WIN_ALL
|
||||
bool NoSequentialRead;
|
||||
uint CreateMode;
|
||||
#endif
|
||||
protected:
|
||||
bool OpenShared;
|
||||
bool OpenShared; // Set by 'Archive' class.
|
||||
public:
|
||||
char FileName[NM];
|
||||
wchar FileNameW[NM];
|
||||
wchar FileName[NM];
|
||||
|
||||
FILE_ERRORTYPE ErrorType;
|
||||
|
||||
uint CloseCount;
|
||||
public:
|
||||
File();
|
||||
virtual ~File();
|
||||
void operator = (File &SrcFile);
|
||||
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,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);
|
||||
virtual bool Open(const wchar *Name,uint Mode=FMF_READ);
|
||||
void TOpen(const wchar *Name);
|
||||
bool WOpen(const wchar *Name);
|
||||
bool Create(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||
void TCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||
bool WCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||
bool Close();
|
||||
void Flush();
|
||||
bool Delete();
|
||||
bool Rename(const char *NewName,const wchar *NewNameW=NULL);
|
||||
void Write(const void *Data,size_t Size);
|
||||
int Read(void *Data,size_t Size);
|
||||
bool Rename(const wchar *NewName);
|
||||
bool Write(const void *Data,size_t Size);
|
||||
virtual int Read(void *Data,size_t Size);
|
||||
int DirectRead(void *Data,size_t Size);
|
||||
void Seek(int64 Offset,int Method);
|
||||
virtual void Seek(int64 Offset,int Method);
|
||||
bool RawSeek(int64 Offset,int Method);
|
||||
int64 Tell();
|
||||
virtual int64 Tell();
|
||||
void Prealloc(int64 Size);
|
||||
byte GetByte();
|
||||
void PutByte(byte Byte);
|
||||
bool Truncate();
|
||||
void Flush();
|
||||
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);
|
||||
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
|
||||
void GetOpenFileTime(RarTime *ft);
|
||||
bool IsOpened() {return(hFile!=BAD_HANDLE);};
|
||||
bool IsOpened() {return hFile!=FILE_BAD_HANDLE;};
|
||||
int64 FileLength();
|
||||
void SetHandleType(FILE_HANDLETYPE Type);
|
||||
FILE_HANDLETYPE GetHandleType() {return(HandleType);};
|
||||
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
|
||||
FILE_HANDLETYPE GetHandleType() {return HandleType;}
|
||||
bool IsDevice();
|
||||
void fprintf(const char *fmt,...);
|
||||
static bool RemoveCreated();
|
||||
FileHandle GetHandle() {return(hFile);};
|
||||
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;};
|
||||
char *GetName() {return(FileName);}
|
||||
FileHandle GetHandle() {return hFile;}
|
||||
void SetHandle(FileHandle Handle) {Close();hFile=Handle;}
|
||||
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;}
|
||||
int64 Copy(File &Dest,int64 Length=INT64NDF);
|
||||
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
|
||||
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
|
||||
#ifdef _WIN_ALL
|
||||
void RemoveSequentialFlag() {NoSequentialRead=true;}
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
int GetFD()
|
||||
{
|
||||
#ifdef FILE_USE_OPEN
|
||||
return hFile;
|
||||
#else
|
||||
return fileno(hFile);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
684
unrar/filefn.cpp
684
unrar/filefn.cpp
@@ -1,104 +1,47 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr)
|
||||
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
BOOL RetCode;
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
RetCode=CreateDirectoryW(NameW,NULL);
|
||||
else
|
||||
if (Name!=NULL)
|
||||
RetCode=CreateDirectoryA(Name,NULL);
|
||||
else
|
||||
return(MKDIR_BADPATH);
|
||||
// Windows automatically removes dots and spaces in the end of directory
|
||||
// name. So we detect such names and process them with \\?\ prefix.
|
||||
wchar *LastChar=PointToLastChar(Name);
|
||||
bool Special=*LastChar=='.' || *LastChar==' ';
|
||||
BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL);
|
||||
if (RetCode==0 && !FileExist(Name))
|
||||
{
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
RetCode=CreateDirectory(LongName,NULL);
|
||||
}
|
||||
if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
|
||||
{
|
||||
if (SetAttr)
|
||||
SetFileAttr(Name,NameW,Attr);
|
||||
return(MKDIR_SUCCESS);
|
||||
SetFileAttr(Name,Attr);
|
||||
return MKDIR_SUCCESS;
|
||||
}
|
||||
int ErrCode=GetLastError();
|
||||
if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
|
||||
return(MKDIR_BADPATH);
|
||||
return(MKDIR_ERROR);
|
||||
#else
|
||||
|
||||
// No Unicode in the rest of function, so Name must be not NULL.
|
||||
if (Name==NULL)
|
||||
return(MKDIR_BADPATH);
|
||||
#endif
|
||||
|
||||
#ifdef _EMX
|
||||
#ifdef _DJGPP
|
||||
if (mkdir(Name,(Attr & FA_RDONLY) ? 0:S_IWUSR)==0)
|
||||
#else
|
||||
if (__mkdir(Name)==0)
|
||||
#endif
|
||||
{
|
||||
if (SetAttr)
|
||||
SetFileAttr(Name,NameW,Attr);
|
||||
return(MKDIR_SUCCESS);
|
||||
}
|
||||
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
|
||||
#endif
|
||||
|
||||
#ifdef _UNIX
|
||||
return MKDIR_BADPATH;
|
||||
return MKDIR_ERROR;
|
||||
#elif defined(_UNIX)
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
mode_t uattr=SetAttr ? (mode_t)Attr:0777;
|
||||
int ErrCode=mkdir(Name,uattr);
|
||||
int ErrCode=mkdir(NameA,uattr);
|
||||
if (ErrCode==-1)
|
||||
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
|
||||
return(MKDIR_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CreatePath(const char *Path,bool SkipLastName)
|
||||
{
|
||||
if (Path==NULL || *Path==0)
|
||||
return(false);
|
||||
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
uint DirAttr=0;
|
||||
return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR;
|
||||
return MKDIR_SUCCESS;
|
||||
#else
|
||||
uint DirAttr=0777;
|
||||
return MKDIR_ERROR;
|
||||
#endif
|
||||
|
||||
bool Success=true;
|
||||
|
||||
for (const char *s=Path;*s!=0;s=charnext(s))
|
||||
{
|
||||
if (s-Path>=NM)
|
||||
break;
|
||||
|
||||
if (*s==CPATHDIVIDER)
|
||||
{
|
||||
char DirName[NM];
|
||||
strncpy(DirName,Path,s-Path);
|
||||
DirName[s-Path]=0;
|
||||
|
||||
if (MakeDir(DirName,NULL,true,DirAttr)==MKDIR_SUCCESS)
|
||||
{
|
||||
#ifndef GUI
|
||||
mprintf(St(MCreatDir),DirName);
|
||||
mprintf(" %s",St(MOk));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
Success=false;
|
||||
}
|
||||
}
|
||||
if (!SkipLastName)
|
||||
if (!IsPathDiv(*PointToLastChar(Path)))
|
||||
if (MakeDir(Path,NULL,true,DirAttr)!=MKDIR_SUCCESS)
|
||||
Success=false;
|
||||
return(Success);
|
||||
}
|
||||
|
||||
|
||||
bool CreatePath(const wchar *Path,bool SkipLastName)
|
||||
{
|
||||
if (Path==NULL || *Path==0)
|
||||
return(false);
|
||||
return false;
|
||||
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
uint DirAttr=0;
|
||||
@@ -110,83 +53,74 @@ bool CreatePath(const wchar *Path,bool SkipLastName)
|
||||
|
||||
for (const wchar *s=Path;*s!=0;s++)
|
||||
{
|
||||
if (s-Path>=NM)
|
||||
wchar DirName[NM];
|
||||
if (s-Path>=ASIZE(DirName))
|
||||
break;
|
||||
|
||||
if (*s==CPATHDIVIDER)
|
||||
// Process all kinds of path separators, so user can enter Unix style
|
||||
// path in Windows or Windows in Unix. s>Path check avoids attempting
|
||||
// creating an empty directory for paths starting from path separator.
|
||||
if (IsPathDiv(*s) && s>Path)
|
||||
{
|
||||
wchar DirName[NM];
|
||||
#ifdef _WIN_ALL
|
||||
// We must not attempt to create "D:" directory, because first
|
||||
// CreateDirectory will fail, so we'll use \\?\D:, which forces Wine
|
||||
// to create "D:" directory.
|
||||
if (s==Path+2 && Path[1]==':')
|
||||
continue;
|
||||
#endif
|
||||
wcsncpy(DirName,Path,s-Path);
|
||||
DirName[s-Path]=0;
|
||||
|
||||
if (MakeDir(NULL,DirName,true,DirAttr)==MKDIR_SUCCESS)
|
||||
Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS;
|
||||
if (Success)
|
||||
{
|
||||
#ifndef GUI
|
||||
char DirNameA[NM];
|
||||
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
|
||||
DirNameA[ASIZE(DirNameA)-1]=0;
|
||||
mprintf(St(MCreatDir),DirNameA);
|
||||
mprintf(" %s",St(MOk));
|
||||
#endif
|
||||
mprintf(St(MCreatDir),DirName);
|
||||
mprintf(L" %s",St(MOk));
|
||||
}
|
||||
else
|
||||
Success=false;
|
||||
}
|
||||
}
|
||||
if (!SkipLastName)
|
||||
if (!IsPathDiv(*PointToLastChar(Path)))
|
||||
if (MakeDir(NULL,Path,true,DirAttr)!=MKDIR_SUCCESS)
|
||||
Success=false;
|
||||
return(Success);
|
||||
if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
|
||||
Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS;
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
|
||||
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// If we are in Windows, let's try Unicode path first. In Unix we do not
|
||||
// need it (Unix MakeDir will fails with Unicode only name).
|
||||
if (PathW!=NULL && *PathW!=0)
|
||||
return(CreatePath(PathW,SkipLastName));
|
||||
#endif
|
||||
if (Path!=NULL && *Path!=0)
|
||||
return(CreatePath(Path,SkipLastName));
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
if (!WinNT())
|
||||
return;
|
||||
|
||||
#if defined(_WIN_ALL)
|
||||
bool sm=ftm!=NULL && ftm->IsSet();
|
||||
bool sc=ftc!=NULL && ftc->IsSet();
|
||||
bool sa=fta!=NULL && fta->IsSet();
|
||||
|
||||
unsigned int DirAttr=GetFileAttr(Name,NameW);
|
||||
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0);
|
||||
uint DirAttr=GetFileAttr(Name);
|
||||
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FILE_ATTRIBUTE_READONLY)!=0);
|
||||
if (ResetAttr)
|
||||
SetFileAttr(Name,NameW,0);
|
||||
SetFileAttr(Name,0);
|
||||
|
||||
wchar DirNameW[NM];
|
||||
GetWideName(Name,NameW,DirNameW,ASIZE(DirNameW));
|
||||
HANDLE hFile=CreateFileW(DirNameW,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
hFile=CreateFile(LongName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
|
||||
}
|
||||
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
FILETIME fm,fc,fa;
|
||||
if (sm)
|
||||
ftm->GetWin32(&fm);
|
||||
ftm->GetWinFT(&fm);
|
||||
if (sc)
|
||||
ftc->GetWin32(&fc);
|
||||
ftc->GetWinFT(&fc);
|
||||
if (sa)
|
||||
fta->GetWin32(&fa);
|
||||
fta->GetWinFT(&fa);
|
||||
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
|
||||
CloseHandle(hFile);
|
||||
if (ResetAttr)
|
||||
SetFileAttr(Name,NameW,DirAttr);
|
||||
SetFileAttr(Name,DirAttr);
|
||||
#endif
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
File::SetCloseFileTimeByName(Name,ftm,fta);
|
||||
@@ -194,157 +128,100 @@ void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,Ra
|
||||
}
|
||||
|
||||
|
||||
bool IsRemovable(const char *Name)
|
||||
bool IsRemovable(const wchar *Name)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
char Root[NM];
|
||||
GetPathRoot(Name,Root);
|
||||
int Type=GetDriveTypeA(*Root!=0 ? Root:NULL);
|
||||
return(Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM);
|
||||
#elif defined(_EMX)
|
||||
char Drive=etoupper(Name[0]);
|
||||
return((Drive=='A' || Drive=='B') && Name[1]==':');
|
||||
#if defined(_WIN_ALL)
|
||||
wchar Root[NM];
|
||||
GetPathRoot(Name,Root,ASIZE(Root));
|
||||
int Type=GetDriveType(*Root!=0 ? Root:NULL);
|
||||
return Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM;
|
||||
#else
|
||||
return(false);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int64 GetFreeDisk(const char *Name)
|
||||
int64 GetFreeDisk(const wchar *Name)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
char Root[NM];
|
||||
GetPathRoot(Name,Root);
|
||||
|
||||
typedef BOOL (WINAPI *GETDISKFREESPACEEX)(
|
||||
LPCSTR,PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER
|
||||
);
|
||||
static GETDISKFREESPACEEX pGetDiskFreeSpaceEx=NULL;
|
||||
|
||||
if (pGetDiskFreeSpaceEx==NULL)
|
||||
{
|
||||
HMODULE hKernel=GetModuleHandleW(L"kernel32.dll");
|
||||
if (hKernel!=NULL)
|
||||
pGetDiskFreeSpaceEx=(GETDISKFREESPACEEX)GetProcAddress(hKernel,"GetDiskFreeSpaceExA");
|
||||
}
|
||||
if (pGetDiskFreeSpaceEx!=NULL)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
// We are here if we failed to load GetDiskFreeSpaceExA.
|
||||
DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters;
|
||||
if (!GetDiskFreeSpaceA(*Root ? Root:NULL,&SectorsPerCluster,&BytesPerSector,&FreeClusters,&TotalClusters))
|
||||
return(1457664);
|
||||
int64 FreeSize=SectorsPerCluster*BytesPerSector;
|
||||
FreeSize=FreeSize*FreeClusters;
|
||||
return(FreeSize);
|
||||
#elif defined(_BEOS)
|
||||
char Root[NM];
|
||||
wchar Root[NM];
|
||||
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;
|
||||
FreeSize=FreeSize*Info.free_blocks;
|
||||
return(FreeSize);
|
||||
|
||||
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
|
||||
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
|
||||
if (GetDiskFreeSpaceEx(*Root!=0 ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
|
||||
uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
|
||||
return INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart);
|
||||
return 0;
|
||||
#elif defined(_UNIX)
|
||||
return(1457664);
|
||||
#elif defined(_EMX)
|
||||
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;
|
||||
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);
|
||||
wchar Root[NM];
|
||||
GetFilePath(Name,Root,ASIZE(Root));
|
||||
char RootA[NM];
|
||||
WideToChar(Root,RootA,ASIZE(RootA));
|
||||
struct statvfs sfs;
|
||||
if (statvfs(*RootA!=0 ? RootA:".",&sfs)!=0)
|
||||
return 0;
|
||||
int64 FreeSize=sfs.f_bsize;
|
||||
FreeSize=FreeSize*sfs.f_bavail;
|
||||
return FreeSize;
|
||||
#else
|
||||
_int86 (0x21,®s,&outregs);
|
||||
#endif
|
||||
if (outregs.x.ax==0xffff)
|
||||
return(1457664);
|
||||
int64 FreeSize=outregs.x.ax*outregs.x.cx;
|
||||
FreeSize=FreeSize*outregs.x.bx;
|
||||
return(FreeSize);
|
||||
}
|
||||
#else
|
||||
#define DISABLEAUTODETECT
|
||||
return(1457664);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool FileExist(const char *Name,const wchar *NameW)
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
|
||||
// Return 'true' for FAT and FAT32, so we can adjust the maximum supported
|
||||
// file size to 4 GB for these file systems.
|
||||
bool IsFAT(const wchar *Name)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
return(GetFileAttributesW(NameW)!=0xffffffff);
|
||||
else
|
||||
return(Name!=NULL && GetFileAttributesA(Name)!=0xffffffff);
|
||||
#elif defined(ENABLE_ACCESS)
|
||||
return(access(Name,0)==0);
|
||||
#else
|
||||
FindData FD;
|
||||
return(FindFile::FastFind(Name,NameW,&FD));
|
||||
#endif
|
||||
wchar Root[NM];
|
||||
GetPathRoot(Name,Root,ASIZE(Root));
|
||||
wchar FileSystem[MAX_PATH+1];
|
||||
if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem)))
|
||||
return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool FileExist(const wchar *Name)
|
||||
{
|
||||
return FileExist(NULL,Name);
|
||||
#ifdef _WIN_ALL
|
||||
return GetFileAttr(Name)!=0xffffffff;
|
||||
#elif defined(ENABLE_ACCESS)
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
return access(NameA,0)==0;
|
||||
#else
|
||||
FindData FD;
|
||||
return FindFile::FastFind(Name,&FD);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool WildFileExist(const char *Name,const wchar *NameW)
|
||||
bool WildFileExist(const wchar *Name)
|
||||
{
|
||||
if (IsWildcard(Name,NameW))
|
||||
if (IsWildcard(Name))
|
||||
{
|
||||
FindFile Find;
|
||||
Find.SetMask(Name);
|
||||
Find.SetMaskW(NameW);
|
||||
FindData fd;
|
||||
return(Find.Next(&fd));
|
||||
return Find.Next(&fd);
|
||||
}
|
||||
return(FileExist(Name,NameW));
|
||||
return FileExist(Name);
|
||||
}
|
||||
|
||||
|
||||
bool IsDir(uint Attr)
|
||||
{
|
||||
#if defined (_WIN_ALL) || defined(_EMX)
|
||||
return(Attr!=0xffffffff && (Attr & 0x10)!=0);
|
||||
#ifdef _WIN_ALL
|
||||
return Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_DIRECTORY)!=0;
|
||||
#endif
|
||||
#if defined(_UNIX)
|
||||
return((Attr & 0xF000)==0x4000);
|
||||
return (Attr & 0xF000)==0x4000;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -352,28 +229,20 @@ bool IsDir(uint Attr)
|
||||
bool IsUnreadable(uint Attr)
|
||||
{
|
||||
#if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
|
||||
return(S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr));
|
||||
#endif
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
bool IsLabel(uint Attr)
|
||||
{
|
||||
#if defined (_WIN_ALL) || defined(_EMX)
|
||||
return((Attr & 8)!=0);
|
||||
#else
|
||||
return(false);
|
||||
return S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool IsLink(uint Attr)
|
||||
{
|
||||
#ifdef _UNIX
|
||||
return((Attr & 0xF000)==0xA000);
|
||||
return (Attr & 0xF000)==0xA000;
|
||||
#elif defined(_WIN_ALL)
|
||||
return (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0;
|
||||
#else
|
||||
return(false);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -384,144 +253,134 @@ bool IsLink(uint Attr)
|
||||
|
||||
bool IsDeleteAllowed(uint FileAttr)
|
||||
{
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
return((FileAttr & (FA_RDONLY|FA_SYSTEM|FA_HIDDEN))==0);
|
||||
#ifdef _WIN_ALL
|
||||
return (FileAttr & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN))==0;
|
||||
#else
|
||||
return((FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR));
|
||||
return (FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PrepareToDelete(const char *Name,const wchar *NameW)
|
||||
void PrepareToDelete(const wchar *Name)
|
||||
{
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
SetFileAttr(Name,NameW,0);
|
||||
SetFileAttr(Name,0);
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
if (Name!=NULL)
|
||||
chmod(Name,S_IRUSR|S_IWUSR|S_IXUSR);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uint GetFileAttr(const char *Name,const wchar *NameW)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
return(GetFileAttributesW(NameW));
|
||||
else
|
||||
return(GetFileAttributesA(Name));
|
||||
#elif defined(_DJGPP)
|
||||
return(_chmod(Name,0));
|
||||
#else
|
||||
struct stat st;
|
||||
if (stat(Name,&st)!=0)
|
||||
return(0);
|
||||
#ifdef _EMX
|
||||
return(st.st_attr);
|
||||
#else
|
||||
return(st.st_mode);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr)
|
||||
{
|
||||
bool Success;
|
||||
#ifdef _WIN_ALL
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
Success=SetFileAttributesW(NameW,Attr)!=0;
|
||||
else
|
||||
if (Name!=NULL)
|
||||
Success=SetFileAttributesA(Name,Attr)!=0;
|
||||
else
|
||||
Success=false;
|
||||
#elif defined(_DJGPP)
|
||||
Success=_chmod(Name,1,Attr)!=-1;
|
||||
#elif defined(_EMX)
|
||||
Success=__chmod(Name,1,Attr)!=-1;
|
||||
#elif defined(_UNIX)
|
||||
Success=chmod(Name,(mode_t)Attr)==0;
|
||||
#else
|
||||
Success=false;
|
||||
#endif
|
||||
return(Success);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
char *MkTemp(char *Name)
|
||||
{
|
||||
size_t Length=strlen(Name);
|
||||
if (Length<=6)
|
||||
return(NULL);
|
||||
|
||||
// We need some kind of random start point for first temporary name.
|
||||
RarTime CurTime;
|
||||
CurTime.SetCurrentTime();
|
||||
int Random=(int)CurTime.GetRaw();
|
||||
|
||||
for (int Attempt=0;;Attempt++)
|
||||
{
|
||||
sprintf(Name+Length-6,"%06u",(Random+Attempt)%1000000);
|
||||
Name[Length-4]='.';
|
||||
if (!FileExist(Name))
|
||||
break;
|
||||
if (Attempt==1000)
|
||||
return(NULL);
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
chmod(NameA,S_IRUSR|S_IWUSR|S_IXUSR);
|
||||
}
|
||||
return(Name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
wchar *MkTemp(wchar *Name)
|
||||
uint GetFileAttr(const wchar *Name)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
DWORD Attr=GetFileAttributes(Name);
|
||||
if (Attr==0xffffffff)
|
||||
{
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
Attr=GetFileAttributes(LongName);
|
||||
}
|
||||
return Attr;
|
||||
#else
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
struct stat st;
|
||||
if (stat(NameA,&st)!=0)
|
||||
return 0;
|
||||
return st.st_mode;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool SetFileAttr(const wchar *Name,uint Attr)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
bool Success=SetFileAttributes(Name,Attr)!=0;
|
||||
if (!Success)
|
||||
{
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
Success=SetFileAttributes(LongName,Attr)!=0;
|
||||
}
|
||||
return Success;
|
||||
#elif defined(_UNIX)
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
return chmod(NameA,(mode_t)Attr)==0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||
{
|
||||
size_t Length=wcslen(Name);
|
||||
if (Length<=6)
|
||||
return(NULL);
|
||||
|
||||
// We need some kind of random start point for first temporary name.
|
||||
RarTime CurTime;
|
||||
CurTime.SetCurrentTime();
|
||||
int Random=(int)CurTime.GetRaw();
|
||||
|
||||
// We cannot use CurTime.GetWin() as is, because its lowest bits can
|
||||
// have low informational value, like being a zero or few fixed numbers.
|
||||
uint Random=(uint)(CurTime.GetWin()/100000);
|
||||
|
||||
// Using PID we guarantee that different RAR copies use different temp names
|
||||
// even if started in exactly the same time.
|
||||
uint PID=0;
|
||||
#ifdef _WIN_ALL
|
||||
PID=(uint)GetCurrentProcessId();
|
||||
#elif defined(_UNIX)
|
||||
PID=(uint)getpid();
|
||||
#endif
|
||||
|
||||
for (uint Attempt=0;;Attempt++)
|
||||
{
|
||||
sprintfw(Name+Length-6,7,L"%06u",(Random+Attempt)%1000000);
|
||||
Name[Length-4]='.';
|
||||
if (!FileExist(NULL,Name))
|
||||
uint Ext=Random%50000+Attempt;
|
||||
wchar RndText[50];
|
||||
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
|
||||
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
|
||||
return NULL;
|
||||
wcscpy(Name+Length,RndText);
|
||||
if (!FileExist(Name))
|
||||
break;
|
||||
if (Attempt==1000)
|
||||
return(NULL);
|
||||
}
|
||||
return(Name);
|
||||
return Name;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)
|
||||
#if !defined(SFX_MODULE)
|
||||
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
|
||||
{
|
||||
SaveFilePos SavePos(*SrcFile);
|
||||
const size_t BufSize=0x10000;
|
||||
Array<byte> Data(BufSize);
|
||||
int64 BlockCount=0;
|
||||
uint DataCRC=0xffffffff;
|
||||
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
int64 FileLength=SrcFile->FileLength();
|
||||
if (ShowMode!=CALCCRC_SHOWNONE)
|
||||
{
|
||||
mprintf(St(MCalcCRC));
|
||||
mprintf(" ");
|
||||
}
|
||||
|
||||
#ifndef SILENT
|
||||
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
|
||||
#endif
|
||||
|
||||
SrcFile->Seek(0,SEEK_SET);
|
||||
if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWPERCENT))!=0)
|
||||
uiMsg(UIEVENT_FILESUMSTART);
|
||||
|
||||
if ((Flags & CALCFSUM_CURPOS)==0)
|
||||
SrcFile->Seek(0,SEEK_SET);
|
||||
|
||||
const size_t BufSize=0x100000;
|
||||
Array<byte> Data(BufSize);
|
||||
|
||||
|
||||
DataHash HashCRC,HashBlake2;
|
||||
HashCRC.Init(HASH_CRC32,Threads);
|
||||
HashBlake2.Init(HASH_BLAKE2,Threads);
|
||||
|
||||
int64 BlockCount=0;
|
||||
int64 TotalRead=0;
|
||||
while (true)
|
||||
{
|
||||
size_t SizeToRead;
|
||||
@@ -532,69 +391,111 @@ uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)
|
||||
int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
|
||||
if (ReadSize==0)
|
||||
break;
|
||||
TotalRead+=ReadSize;
|
||||
|
||||
++BlockCount;
|
||||
if ((BlockCount & 15)==0)
|
||||
if ((++BlockCount & 0xf)==0)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
if (ShowMode==CALCCRC_SHOWALL)
|
||||
mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength));
|
||||
#ifndef SILENT
|
||||
if ((Flags & CALCFSUM_SHOWPROGRESS)!=0)
|
||||
uiExtractProgress(TotalRead,FileLength,TotalRead,FileLength);
|
||||
else
|
||||
{
|
||||
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||
uiMsg(UIEVENT_FILESUMPROGRESS,ToPercent(TotalRead,FileLength));
|
||||
}
|
||||
#endif
|
||||
Wait();
|
||||
}
|
||||
DataCRC=CRC(DataCRC,&Data[0],ReadSize);
|
||||
|
||||
if (CRC32!=NULL)
|
||||
HashCRC.Update(&Data[0],ReadSize);
|
||||
if (Blake2!=NULL)
|
||||
HashBlake2.Update(&Data[0],ReadSize);
|
||||
|
||||
if (Size!=INT64NDF)
|
||||
Size-=ReadSize;
|
||||
}
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
if (ShowMode==CALCCRC_SHOWALL)
|
||||
mprintf("\b\b\b\b ");
|
||||
#endif
|
||||
return(DataCRC^0xffffffff);
|
||||
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||
uiMsg(UIEVENT_FILESUMEND);
|
||||
|
||||
if (CRC32!=NULL)
|
||||
*CRC32=HashCRC.GetCRC32();
|
||||
if (Blake2!=NULL)
|
||||
{
|
||||
HashValue Result;
|
||||
HashBlake2.Result(&Result);
|
||||
memcpy(Blake2,Result.Digest,sizeof(Result.Digest));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW)
|
||||
bool RenameFile(const wchar *SrcName,const wchar *DestName)
|
||||
{
|
||||
return(rename(SrcName,DestName)==0);
|
||||
#ifdef _WIN_ALL
|
||||
bool Success=MoveFile(SrcName,DestName)!=0;
|
||||
if (!Success)
|
||||
{
|
||||
wchar LongName1[NM],LongName2[NM];
|
||||
if (GetWinLongPath(SrcName,LongName1,ASIZE(LongName1)) &&
|
||||
GetWinLongPath(DestName,LongName2,ASIZE(LongName2)))
|
||||
Success=MoveFile(LongName1,LongName2)!=0;
|
||||
}
|
||||
return Success;
|
||||
#else
|
||||
char SrcNameA[NM],DestNameA[NM];
|
||||
WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA));
|
||||
WideToChar(DestName,DestNameA,ASIZE(DestNameA));
|
||||
bool Success=rename(SrcNameA,DestNameA)==0;
|
||||
return Success;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool DelFile(const char *Name)
|
||||
bool DelFile(const wchar *Name)
|
||||
{
|
||||
return(DelFile(Name,NULL));
|
||||
#ifdef _WIN_ALL
|
||||
bool Success=DeleteFile(Name)!=0;
|
||||
if (!Success)
|
||||
{
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
Success=DeleteFile(LongName)!=0;
|
||||
}
|
||||
return Success;
|
||||
#else
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
bool Success=remove(NameA)==0;
|
||||
return Success;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool DelFile(const char *Name,const wchar *NameW)
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
bool SetFileCompression(const wchar *Name,bool State)
|
||||
{
|
||||
return(Name!=NULL && remove(Name)==0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
|
||||
bool SetFileCompression(char *Name,wchar *NameW,bool State)
|
||||
{
|
||||
wchar FileNameW[NM];
|
||||
GetWideName(Name,NameW,FileNameW,ASIZE(FileNameW));
|
||||
HANDLE hFile=CreateFileW(FileNameW,FILE_READ_DATA|FILE_WRITE_DATA,
|
||||
HANDLE hFile=CreateFile(Name,FILE_READ_DATA|FILE_WRITE_DATA,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
return(false);
|
||||
{
|
||||
wchar LongName[NM];
|
||||
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
|
||||
hFile=CreateFile(LongName,FILE_READ_DATA|FILE_WRITE_DATA,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
}
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
|
||||
DWORD Result;
|
||||
int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
|
||||
sizeof(NewState),NULL,0,&Result,NULL);
|
||||
CloseHandle(hFile);
|
||||
return(RetCode!=0);
|
||||
return RetCode!=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -605,3 +506,4 @@ bool SetFileCompression(char *Name,wchar *NameW,bool State)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,48 +3,48 @@
|
||||
|
||||
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
|
||||
|
||||
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr);
|
||||
bool CreatePath(const char *Path,bool SkipLastName);
|
||||
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr);
|
||||
bool CreatePath(const wchar *Path,bool SkipLastName);
|
||||
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);
|
||||
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
|
||||
bool IsRemovable(const wchar *Name);
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int64 GetFreeDisk(const char *Name);
|
||||
int64 GetFreeDisk(const wchar *Name);
|
||||
#endif
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
|
||||
bool IsFAT(const wchar *Root);
|
||||
#endif
|
||||
|
||||
bool FileExist(const char *Name,const wchar *NameW=NULL);
|
||||
bool FileExist(const wchar *Name);
|
||||
bool WildFileExist(const char *Name,const wchar *NameW=NULL);
|
||||
bool WildFileExist(const wchar *Name);
|
||||
bool IsDir(uint Attr);
|
||||
bool IsUnreadable(uint Attr);
|
||||
bool IsLabel(uint Attr);
|
||||
bool IsLink(uint Attr);
|
||||
void SetSFXMode(const char *FileName);
|
||||
void EraseDiskContents(const char *FileName);
|
||||
void SetSFXMode(const wchar *FileName);
|
||||
void EraseDiskContents(const wchar *FileName);
|
||||
bool IsDeleteAllowed(uint FileAttr);
|
||||
void PrepareToDelete(const char *Name,const wchar *NameW=NULL);
|
||||
uint GetFileAttr(const char *Name,const wchar *NameW=NULL);
|
||||
bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr);
|
||||
char* MkTemp(char *Name);
|
||||
wchar* MkTemp(wchar *Name);
|
||||
void PrepareToDelete(const wchar *Name);
|
||||
uint GetFileAttr(const wchar *Name);
|
||||
bool SetFileAttr(const wchar *Name,uint Attr);
|
||||
#if 0
|
||||
wchar* MkTemp(wchar *Name,size_t MaxSize);
|
||||
#endif
|
||||
|
||||
enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL};
|
||||
uint CalcFileCRC(File *SrcFile,int64 Size=INT64NDF,CALCCRC_SHOWMODE ShowMode=CALCCRC_SHOWNONE);
|
||||
enum CALCFSUM_FLAGS {CALCFSUM_SHOWTEXT=1,CALCFSUM_SHOWPERCENT=2,CALCFSUM_SHOWPROGRESS=4,CALCFSUM_CURPOS=8};
|
||||
|
||||
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);
|
||||
bool DelDir(const char *Name);
|
||||
bool DelDir(const char *Name,const wchar *NameW);
|
||||
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size=INT64NDF,uint Flags=0);
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
bool SetFileCompression(char *Name,wchar *NameW,bool State);
|
||||
bool RenameFile(const wchar *SrcName,const wchar *DestName);
|
||||
bool DelFile(const wchar *Name);
|
||||
bool DelDir(const wchar *Name);
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
bool SetFileCompression(const wchar *Name,bool State);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
static bool IsUnicode(byte *Data,int Size);
|
||||
|
||||
bool ReadTextFile(
|
||||
const char *Name,
|
||||
const wchar *NameW,
|
||||
const wchar *Name,
|
||||
StringList *List,
|
||||
bool Config,
|
||||
bool AbortOnError,
|
||||
@@ -13,196 +10,153 @@ bool ReadTextFile(
|
||||
bool SkipComments,
|
||||
bool ExpandEnvStr)
|
||||
{
|
||||
char FileName[NM];
|
||||
wchar FileName[NM];
|
||||
*FileName=0;
|
||||
|
||||
if (Name!=NULL)
|
||||
if (Config)
|
||||
GetConfigName(Name,FileName,true);
|
||||
GetConfigName(Name,FileName,ASIZE(FileName),true,false);
|
||||
else
|
||||
strcpy(FileName,Name);
|
||||
|
||||
wchar FileNameW[NM];
|
||||
*FileNameW=0;
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
if (NameW!=NULL)
|
||||
if (Config)
|
||||
GetConfigName(NameW,FileNameW,true);
|
||||
else
|
||||
wcscpy(FileNameW,NameW);
|
||||
#endif
|
||||
wcsncpyz(FileName,Name,ASIZE(FileName));
|
||||
|
||||
File SrcFile;
|
||||
if (FileName!=NULL && *FileName!=0 || FileNameW!=NULL && *FileNameW!=0)
|
||||
if (*FileName!=0)
|
||||
{
|
||||
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName,FileNameW):SrcFile.Open(FileName,FileNameW);
|
||||
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName):SrcFile.Open(FileName,0);
|
||||
|
||||
if (!OpenCode)
|
||||
{
|
||||
if (AbortOnError)
|
||||
ErrHandler.Exit(OPEN_ERROR);
|
||||
return(false);
|
||||
ErrHandler.Exit(RARX_OPEN);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||
|
||||
unsigned int DataSize=0,ReadSize;
|
||||
const int ReadBlock=1024;
|
||||
Array<char> Data(ReadBlock+5);
|
||||
uint DataSize=0,ReadSize;
|
||||
const int ReadBlock=4096;
|
||||
|
||||
Array<byte> Data(ReadBlock);
|
||||
while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0)
|
||||
{
|
||||
DataSize+=ReadSize;
|
||||
Data.Add(ReadSize);
|
||||
Data.Add(ReadSize); // Always have ReadBlock available for next data.
|
||||
}
|
||||
// Set to really read size, so we can zero terminate it correctly.
|
||||
Data.Alloc(DataSize);
|
||||
|
||||
memset(&Data[DataSize],0,5);
|
||||
int LowEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0;
|
||||
int BigEndian=DataSize>=2 && Data[0]==254 && Data[1]==255 ? 1:0;
|
||||
bool Utf8=DataSize>=3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf;
|
||||
|
||||
if (SrcCharset==RCH_UNICODE ||
|
||||
SrcCharset==RCH_DEFAULT && IsUnicode((byte *)&Data[0],DataSize))
|
||||
if (SrcCharset==RCH_DEFAULT)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
wchar *NextStr=CurStr,*CmtPtr=NULL;
|
||||
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
|
||||
{
|
||||
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
|
||||
if (LowEndian || BigEndian)
|
||||
for (size_t I=2;I<DataSize;I++)
|
||||
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
|
||||
{
|
||||
*NextStr=0;
|
||||
CmtPtr=NextStr;
|
||||
}
|
||||
NextStr++;
|
||||
}
|
||||
*NextStr=0;
|
||||
for (wchar *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
|
||||
{
|
||||
if (*SpacePtr!=' ' && *SpacePtr!='\t')
|
||||
SrcCharset=RCH_UNICODE; // High byte in UTF-16 char is found.
|
||||
break;
|
||||
*SpacePtr=0;
|
||||
}
|
||||
if (*CurStr)
|
||||
{
|
||||
// Length and AddSize must be defined as signed, because AddSize
|
||||
// can be negative.
|
||||
int Length=(int)wcslen(CurStr);
|
||||
int AddSize=4*(Length-(int)AnsiName.Size()+1);
|
||||
|
||||
if (AddSize>0)
|
||||
AnsiName.Add(AddSize);
|
||||
if (Unquote && *CurStr=='\"' && CurStr[Length-1]=='\"')
|
||||
{
|
||||
CurStr[Length-1]=0;
|
||||
CurStr++;
|
||||
}
|
||||
WideToChar(CurStr,&AnsiName[0],AnsiName.Size());
|
||||
|
||||
bool Expanded=false;
|
||||
#if defined(_WIN_ALL) && !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=ExpandEnvironmentStringsA(&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')
|
||||
CurStr++;
|
||||
if (Utf8)
|
||||
{
|
||||
Data.Push(0); // Need a zero terminated string for UtfToWide.
|
||||
if (IsTextUtf8((const char *)(Data+3)))
|
||||
SrcCharset=RCH_UTF8;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Array<wchar> DataW;
|
||||
|
||||
if (SrcCharset==RCH_DEFAULT || SrcCharset==RCH_OEM || SrcCharset==RCH_ANSI)
|
||||
{
|
||||
char *CurStr=&Data[0];
|
||||
while (*CurStr!=0)
|
||||
{
|
||||
char *NextStr=CurStr,*CmtPtr=NULL;
|
||||
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
|
||||
{
|
||||
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
|
||||
{
|
||||
*NextStr=0;
|
||||
CmtPtr=NextStr;
|
||||
}
|
||||
NextStr++;
|
||||
}
|
||||
*NextStr=0;
|
||||
for (char *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
|
||||
{
|
||||
if (*SpacePtr!=' ' && *SpacePtr!='\t')
|
||||
break;
|
||||
*SpacePtr=0;
|
||||
}
|
||||
if (*CurStr)
|
||||
{
|
||||
if (Unquote && *CurStr=='\"')
|
||||
{
|
||||
size_t Length=strlen(CurStr);
|
||||
if (CurStr[Length-1]=='\"')
|
||||
{
|
||||
CurStr[Length-1]=0;
|
||||
CurStr++;
|
||||
}
|
||||
}
|
||||
Data.Push(0); // Zero terminate.
|
||||
#if defined(_WIN_ALL)
|
||||
if (SrcCharset==RCH_OEM)
|
||||
OemToCharA(CurStr,CurStr);
|
||||
if (SrcCharset==RCH_OEM)
|
||||
OemToCharA((char *)&Data[0],(char *)&Data[0]);
|
||||
#endif
|
||||
|
||||
bool Expanded=false;
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
if (ExpandEnvStr && *CurStr=='%')
|
||||
{
|
||||
// Expanding environment variables in Windows version.
|
||||
char ExpName[NM];
|
||||
int ret=ExpandEnvironmentStringsA(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')
|
||||
CurStr++;
|
||||
}
|
||||
DataW.Alloc(Data.Size());
|
||||
CharToWide((char *)&Data[0],&DataW[0],DataW.Size());
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
if (SrcCharset==RCH_UNICODE)
|
||||
{
|
||||
size_t Start=2; // Skip byte order mark.
|
||||
if (!LowEndian && !BigEndian) // No byte order mask.
|
||||
{
|
||||
Start=0;
|
||||
LowEndian=1;
|
||||
}
|
||||
|
||||
DataW.Alloc(Data.Size()/2+1);
|
||||
size_t End=Data.Size() & ~1; // We need even bytes number for UTF-16.
|
||||
for (size_t I=Start;I<End;I+=2)
|
||||
DataW[(I-Start)/2]=Data[I+BigEndian]+Data[I+LowEndian]*256;
|
||||
DataW[(End-Start)/2]=0;
|
||||
}
|
||||
|
||||
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 && Data[I]!='\r' && Data[I]!='\n')
|
||||
return(true);
|
||||
return(false);
|
||||
if (SrcCharset==RCH_UTF8)
|
||||
{
|
||||
Data.Push(0); // Zero terminate data.
|
||||
DataW.Alloc(Data.Size());
|
||||
UtfToWide((const char *)(Data+(Utf8 ? 3:0)),&DataW[0],DataW.Size());
|
||||
}
|
||||
|
||||
wchar *CurStr=&DataW[0];
|
||||
|
||||
while (*CurStr!=0)
|
||||
{
|
||||
wchar *NextStr=CurStr,*CmtPtr=NULL;
|
||||
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
|
||||
{
|
||||
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
|
||||
{
|
||||
*NextStr=0;
|
||||
CmtPtr=NextStr;
|
||||
}
|
||||
NextStr++;
|
||||
}
|
||||
bool Done=*NextStr==0;
|
||||
|
||||
*NextStr=0;
|
||||
for (wchar *SpacePtr=(CmtPtr!=NULL ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
|
||||
{
|
||||
if (*SpacePtr!=' ' && *SpacePtr!='\t')
|
||||
break;
|
||||
*SpacePtr=0;
|
||||
}
|
||||
|
||||
if (Unquote && *CurStr=='\"')
|
||||
{
|
||||
size_t Length=wcslen(CurStr);
|
||||
if (CurStr[Length-1]=='\"')
|
||||
{
|
||||
CurStr[Length-1]=0;
|
||||
CurStr++;
|
||||
}
|
||||
}
|
||||
|
||||
bool Expanded=false;
|
||||
#if defined(_WIN_ALL)
|
||||
if (ExpandEnvStr && *CurStr=='%') // Expand environment variables in Windows.
|
||||
{
|
||||
wchar ExpName[NM];
|
||||
*ExpName=0;
|
||||
DWORD Result=ExpandEnvironmentStrings(CurStr,ExpName,ASIZE(ExpName));
|
||||
Expanded=Result!=0 && Result<ASIZE(ExpName);
|
||||
if (Expanded && *ExpName!=0)
|
||||
List->AddString(ExpName);
|
||||
}
|
||||
#endif
|
||||
if (!Expanded && *CurStr!=0)
|
||||
List->AddString(CurStr);
|
||||
|
||||
if (Done)
|
||||
break;
|
||||
CurStr=NextStr+1;
|
||||
while (*CurStr=='\r' || *CurStr=='\n')
|
||||
CurStr++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
#define _RAR_FILESTR_
|
||||
|
||||
bool ReadTextFile(
|
||||
const char *Name,
|
||||
const wchar *NameW,
|
||||
const wchar *Name,
|
||||
StringList *List,
|
||||
bool Config,
|
||||
bool AbortOnError=false,
|
||||
|
||||
265
unrar/find.cpp
265
unrar/find.cpp
@@ -3,7 +3,6 @@
|
||||
FindFile::FindFile()
|
||||
{
|
||||
*FindMask=0;
|
||||
*FindMaskW=0;
|
||||
FirstCall=true;
|
||||
#ifdef _WIN_ALL
|
||||
hFind=INVALID_HANDLE_VALUE;
|
||||
@@ -25,267 +24,195 @@ FindFile::~FindFile()
|
||||
}
|
||||
|
||||
|
||||
void FindFile::SetMask(const char *FindMask)
|
||||
void FindFile::SetMask(const wchar *Mask)
|
||||
{
|
||||
strcpy(FindFile::FindMask,NullToEmpty(FindMask));
|
||||
if (*FindMaskW==0)
|
||||
CharToWide(FindMask,FindMaskW);
|
||||
wcscpy(FindMask,Mask);
|
||||
FirstCall=true;
|
||||
}
|
||||
|
||||
|
||||
void FindFile::SetMaskW(const wchar *FindMaskW)
|
||||
{
|
||||
if (FindMaskW==NULL)
|
||||
return;
|
||||
wcscpy(FindFile::FindMaskW,FindMaskW);
|
||||
if (*FindMask==0)
|
||||
WideToChar(FindMaskW,FindMask);
|
||||
FirstCall=true;
|
||||
}
|
||||
|
||||
|
||||
bool FindFile::Next(struct FindData *fd,bool GetSymLink)
|
||||
bool FindFile::Next(FindData *fd,bool GetSymLink)
|
||||
{
|
||||
fd->Error=false;
|
||||
if (*FindMask==0)
|
||||
return(false);
|
||||
return false;
|
||||
#ifdef _WIN_ALL
|
||||
if (FirstCall)
|
||||
{
|
||||
if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE)
|
||||
return(false);
|
||||
if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE)
|
||||
return(false);
|
||||
if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
#else
|
||||
if (FirstCall)
|
||||
{
|
||||
char DirName[NM];
|
||||
strcpy(DirName,FindMask);
|
||||
wchar DirName[NM];
|
||||
wcsncpyz(DirName,FindMask,ASIZE(DirName));
|
||||
RemoveNameFromPath(DirName);
|
||||
if (*DirName==0)
|
||||
strcpy(DirName,".");
|
||||
if ((dirp=opendir(DirName))==NULL)
|
||||
wcscpy(DirName,L".");
|
||||
char DirNameA[NM];
|
||||
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
|
||||
if ((dirp=opendir(DirNameA))==NULL)
|
||||
{
|
||||
fd->Error=(errno!=ENOENT);
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
struct dirent *ent=readdir(dirp);
|
||||
if (ent==NULL)
|
||||
return(false);
|
||||
return false;
|
||||
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
|
||||
continue;
|
||||
if (CmpName(FindMask,ent->d_name,MATCH_NAMES))
|
||||
wchar Name[NM];
|
||||
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
|
||||
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
|
||||
|
||||
if (CmpName(FindMask,Name,MATCH_NAMES))
|
||||
{
|
||||
char FullName[NM];
|
||||
strcpy(FullName,FindMask);
|
||||
wchar FullName[NM];
|
||||
wcscpy(FullName,FindMask);
|
||||
*PointToName(FullName)=0;
|
||||
if (strlen(FullName)+strlen(ent->d_name)>=ASIZE(FullName)-1)
|
||||
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
|
||||
{
|
||||
#ifndef SILENT
|
||||
Log(NULL,"\n%s%s",FullName,ent->d_name);
|
||||
Log(NULL,St(MPathTooLong));
|
||||
#endif
|
||||
return(false);
|
||||
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
|
||||
return false;
|
||||
}
|
||||
strcat(FullName,ent->d_name);
|
||||
if (!FastFind(FullName,NULL,fd,GetSymLink))
|
||||
wcscat(FullName,Name);
|
||||
if (!FastFind(FullName,fd,GetSymLink))
|
||||
{
|
||||
ErrHandler.OpenErrorMsg(FullName);
|
||||
continue;
|
||||
}
|
||||
strcpy(fd->Name,FullName);
|
||||
wcscpy(fd->Name,FullName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
*fd->NameW=0;
|
||||
#ifdef _APPLE
|
||||
if (!LowAscii(fd->Name))
|
||||
UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
|
||||
#elif defined(UNICODE_SUPPORTED)
|
||||
if (!LowAscii(fd->Name) && UnicodeEnabled())
|
||||
CharToWide(fd->Name,fd->NameW);
|
||||
#endif
|
||||
#endif
|
||||
fd->Flags=0;
|
||||
fd->IsDir=IsDir(fd->FileAttr);
|
||||
fd->IsLink=IsLink(fd->FileAttr);
|
||||
|
||||
FirstCall=false;
|
||||
char *Name=PointToName(fd->Name);
|
||||
if (strcmp(Name,".")==0 || strcmp(Name,"..")==0)
|
||||
return(Next(fd));
|
||||
return(true);
|
||||
wchar *NameOnly=PointToName(fd->Name);
|
||||
if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
|
||||
return Next(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FindFile::FastFind(const char *FindMask,const wchar *FindMaskW,FindData *fd,bool GetSymLink)
|
||||
bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
|
||||
{
|
||||
fd->Error=false;
|
||||
#ifndef _UNIX
|
||||
if (IsWildcard(FindMask,FindMaskW))
|
||||
return(false);
|
||||
if (IsWildcard(FindMask))
|
||||
return false;
|
||||
#endif
|
||||
#ifdef _WIN_ALL
|
||||
HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd);
|
||||
HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd);
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
return(false);
|
||||
return false;
|
||||
FindClose(hFind);
|
||||
#else
|
||||
char FindMaskA[NM];
|
||||
WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA));
|
||||
|
||||
struct stat st;
|
||||
if (GetSymLink)
|
||||
{
|
||||
#ifdef SAVE_LINKS
|
||||
if (lstat(FindMask,&st)!=0)
|
||||
if (lstat(FindMaskA,&st)!=0)
|
||||
#else
|
||||
if (stat(FindMask,&st)!=0)
|
||||
if (stat(FindMaskA,&st)!=0)
|
||||
#endif
|
||||
{
|
||||
fd->Error=(errno!=ENOENT);
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (stat(FindMask,&st)!=0)
|
||||
if (stat(FindMaskA,&st)!=0)
|
||||
{
|
||||
fd->Error=(errno!=ENOENT);
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
#ifdef _DJGPP
|
||||
fd->FileAttr=_chmod(FindMask,0);
|
||||
#elif defined(_EMX)
|
||||
fd->FileAttr=st.st_attr;
|
||||
#else
|
||||
fd->FileAttr=st.st_mode;
|
||||
#endif
|
||||
fd->IsDir=IsDir(st.st_mode);
|
||||
fd->Size=st.st_size;
|
||||
fd->mtime=st.st_mtime;
|
||||
fd->atime=st.st_atime;
|
||||
fd->ctime=st.st_ctime;
|
||||
fd->FileTime=fd->mtime.GetDos();
|
||||
strcpy(fd->Name,FindMask);
|
||||
|
||||
*fd->NameW=0;
|
||||
#ifdef _APPLE
|
||||
if (!LowAscii(fd->Name))
|
||||
UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
|
||||
#elif defined(UNICODE_SUPPORTED)
|
||||
if (!LowAscii(fd->Name) && UnicodeEnabled())
|
||||
CharToWide(fd->Name,fd->NameW);
|
||||
#ifdef UNIX_TIME_NS
|
||||
fd->mtime.SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec);
|
||||
fd->atime.SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec);
|
||||
fd->ctime.SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec);
|
||||
#else
|
||||
fd->mtime.SetUnix(st.st_mtime);
|
||||
fd->atime.SetUnix(st.st_atime);
|
||||
fd->ctime.SetUnix(st.st_ctime);
|
||||
#endif
|
||||
|
||||
wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name));
|
||||
#endif
|
||||
fd->Flags=0;
|
||||
fd->IsDir=IsDir(fd->FileAttr);
|
||||
return(true);
|
||||
fd->IsLink=IsLink(fd->FileAttr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
HANDLE FindFile::Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,FindData *fd)
|
||||
HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd)
|
||||
{
|
||||
#ifndef _WIN_CE
|
||||
if (WinNT())
|
||||
#endif
|
||||
WIN32_FIND_DATA FindData;
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
wchar WideMask[NM];
|
||||
if (MaskW!=NULL && *MaskW!=0)
|
||||
wcscpy(WideMask,MaskW);
|
||||
else
|
||||
CharToWide(Mask,WideMask);
|
||||
|
||||
WIN32_FIND_DATAW FindData;
|
||||
hFind=FindFirstFile(Mask,&FindData);
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hFind=FindFirstFileW(WideMask,&FindData);
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
int SysErr=GetLastError();
|
||||
fd->Error=(SysErr!=ERROR_FILE_NOT_FOUND &&
|
||||
SysErr!=ERROR_PATH_NOT_FOUND &&
|
||||
SysErr!=ERROR_NO_MORE_FILES);
|
||||
}
|
||||
wchar LongMask[NM];
|
||||
if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask)))
|
||||
hFind=FindFirstFile(LongMask,&FindData);
|
||||
}
|
||||
else
|
||||
if (!FindNextFileW(hFind,&FindData))
|
||||
{
|
||||
hFind=INVALID_HANDLE_VALUE;
|
||||
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
if (hFind!=INVALID_HANDLE_VALUE)
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
wcscpy(fd->NameW,WideMask);
|
||||
wcscpy(PointToName(fd->NameW),FindData.cFileName);
|
||||
WideToChar(fd->NameW,fd->Name);
|
||||
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
|
||||
fd->FileAttr=FindData.dwFileAttributes;
|
||||
wcscpy(fd->ShortName,FindData.cAlternateFileName);
|
||||
fd->ftCreationTime=FindData.ftCreationTime;
|
||||
fd->ftLastAccessTime=FindData.ftLastAccessTime;
|
||||
fd->ftLastWriteTime=FindData.ftLastWriteTime;
|
||||
fd->mtime=FindData.ftLastWriteTime;
|
||||
fd->ctime=FindData.ftCreationTime;
|
||||
fd->atime=FindData.ftLastAccessTime;
|
||||
fd->FileTime=fd->mtime.GetDos();
|
||||
|
||||
#ifndef _WIN_CE
|
||||
// if (LowAscii(fd->NameW))
|
||||
// *fd->NameW=0;
|
||||
#endif
|
||||
int SysErr=GetLastError();
|
||||
// We must not issue an error for "file not found" and "path not found",
|
||||
// because it is normal to not find anything for wildcard mask when
|
||||
// archiving. Also searching for non-existent file is normal in some
|
||||
// other modules, like WinRAR scanning for winrar_theme_description.txt
|
||||
// to check if any themes are available.
|
||||
fd->Error=SysErr!=ERROR_FILE_NOT_FOUND &&
|
||||
SysErr!=ERROR_PATH_NOT_FOUND &&
|
||||
SysErr!=ERROR_NO_MORE_FILES;
|
||||
}
|
||||
}
|
||||
#ifndef _WIN_CE
|
||||
else
|
||||
if (!FindNextFile(hFind,&FindData))
|
||||
{
|
||||
hFind=INVALID_HANDLE_VALUE;
|
||||
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
if (hFind!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
char CharMask[NM];
|
||||
if (Mask!=NULL && *Mask!=0)
|
||||
strcpy(CharMask,Mask);
|
||||
else
|
||||
WideToChar(MaskW,CharMask);
|
||||
wcsncpyz(fd->Name,Mask,ASIZE(fd->Name));
|
||||
SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name));
|
||||
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
|
||||
fd->FileAttr=FindData.dwFileAttributes;
|
||||
fd->ftCreationTime=FindData.ftCreationTime;
|
||||
fd->ftLastAccessTime=FindData.ftLastAccessTime;
|
||||
fd->ftLastWriteTime=FindData.ftLastWriteTime;
|
||||
fd->mtime.SetWinFT(&FindData.ftLastWriteTime);
|
||||
fd->ctime.SetWinFT(&FindData.ftCreationTime);
|
||||
fd->atime.SetWinFT(&FindData.ftLastAccessTime);
|
||||
|
||||
WIN32_FIND_DATAA FindData;
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hFind=FindFirstFileA(CharMask,&FindData);
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
int SysErr=GetLastError();
|
||||
fd->Error=SysErr!=ERROR_FILE_NOT_FOUND && SysErr!=ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!FindNextFileA(hFind,&FindData))
|
||||
{
|
||||
hFind=INVALID_HANDLE_VALUE;
|
||||
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
if (hFind!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
strcpy(fd->Name,CharMask);
|
||||
strcpy(PointToName(fd->Name),FindData.cFileName);
|
||||
CharToWide(fd->Name,fd->NameW);
|
||||
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
|
||||
fd->FileAttr=FindData.dwFileAttributes;
|
||||
CharToWide(FindData.cAlternateFileName,fd->ShortName);
|
||||
fd->ftCreationTime=FindData.ftCreationTime;
|
||||
fd->ftLastAccessTime=FindData.ftLastAccessTime;
|
||||
fd->ftLastWriteTime=FindData.ftLastWriteTime;
|
||||
fd->mtime=FindData.ftLastWriteTime;
|
||||
fd->ctime=FindData.ftCreationTime;
|
||||
fd->atime=FindData.ftLastAccessTime;
|
||||
fd->FileTime=fd->mtime.GetDos();
|
||||
// if (LowAscii(fd->Name))
|
||||
// *fd->NameW=0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fd->Flags=0;
|
||||
return(hFind);
|
||||
return hFind;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -7,17 +7,15 @@ enum FINDDATA_FLAGS {
|
||||
|
||||
struct FindData
|
||||
{
|
||||
char Name[NM];
|
||||
wchar NameW[NM];
|
||||
int64 Size;
|
||||
wchar Name[NM];
|
||||
uint64 Size;
|
||||
uint FileAttr;
|
||||
uint FileTime;
|
||||
bool IsDir;
|
||||
bool IsLink;
|
||||
RarTime mtime;
|
||||
RarTime ctime;
|
||||
RarTime atime;
|
||||
#ifdef _WIN_ALL
|
||||
wchar ShortName[NM];
|
||||
FILETIME ftCreationTime;
|
||||
FILETIME ftLastAccessTime;
|
||||
FILETIME ftLastWriteTime;
|
||||
@@ -30,11 +28,10 @@ class FindFile
|
||||
{
|
||||
private:
|
||||
#ifdef _WIN_ALL
|
||||
static HANDLE Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd);
|
||||
static HANDLE Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd);
|
||||
#endif
|
||||
|
||||
char FindMask[NM];
|
||||
wchar FindMaskW[NM];
|
||||
wchar FindMask[NM];
|
||||
bool FirstCall;
|
||||
#ifdef _WIN_ALL
|
||||
HANDLE hFind;
|
||||
@@ -44,10 +41,9 @@ class FindFile
|
||||
public:
|
||||
FindFile();
|
||||
~FindFile();
|
||||
void SetMask(const char *FindMask);
|
||||
void SetMaskW(const wchar *FindMaskW);
|
||||
void SetMask(const wchar *Mask);
|
||||
bool Next(FindData *fd,bool GetSymLink=false);
|
||||
static bool FastFind(const char *FindMask,const wchar *FindMaskW,FindData *fd,bool GetSymLink=false);
|
||||
static bool FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink=false);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
BitInput::BitInput()
|
||||
BitInput::BitInput(bool AllocBuffer)
|
||||
{
|
||||
// getbits attempts to read data from InAddr, InAddr+1, InAddr+2 positions.
|
||||
// So let's allocate two additional bytes for situation, when we need to
|
||||
// read only 1 byte from the last position of buffer and avoid a crash
|
||||
// from access to next 2 bytes, which contents we do not need.
|
||||
size_t BufSize=MAX_SIZE+2;
|
||||
InBuf=new byte[BufSize];
|
||||
ExternalBuffer=false;
|
||||
if (AllocBuffer)
|
||||
{
|
||||
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
|
||||
// So let's allocate 3 additional bytes for situation, when we need to
|
||||
// read only 1 byte from the last position of buffer and avoid a crash
|
||||
// from access to next 3 bytes, which contents we do not need.
|
||||
size_t BufSize=MAX_SIZE+3;
|
||||
InBuf=new byte[BufSize];
|
||||
|
||||
// Ensure that we get predictable results when accessing bytes in area
|
||||
// not filled with read data.
|
||||
memset(InBuf,0,BufSize);
|
||||
// Ensure that we get predictable results when accessing bytes in area
|
||||
// not filled with read data.
|
||||
memset(InBuf,0,BufSize);
|
||||
}
|
||||
else
|
||||
InBuf=NULL;
|
||||
}
|
||||
|
||||
|
||||
BitInput::~BitInput()
|
||||
{
|
||||
delete[] InBuf;
|
||||
if (!ExternalBuffer)
|
||||
delete[] InBuf;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,5 +38,15 @@ void BitInput::faddbits(uint Bits)
|
||||
uint BitInput::fgetbits()
|
||||
{
|
||||
// Function wrapped version of inline getbits to save code size.
|
||||
return(getbits());
|
||||
return getbits();
|
||||
}
|
||||
|
||||
|
||||
void BitInput::SetExternalBuffer(byte *Buf)
|
||||
{
|
||||
if (InBuf!=NULL && !ExternalBuffer)
|
||||
delete[] InBuf;
|
||||
InBuf=Buf;
|
||||
ExternalBuffer=true;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ class BitInput
|
||||
{
|
||||
public:
|
||||
enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer.
|
||||
protected:
|
||||
|
||||
int InAddr; // Curent byte position in the buffer.
|
||||
int InBit; // Current bit position in the current byte.
|
||||
|
||||
bool ExternalBuffer;
|
||||
public:
|
||||
BitInput();
|
||||
BitInput(bool AllocBuffer);
|
||||
~BitInput();
|
||||
|
||||
byte *InBuf; // Dynamically allocated input buffer.
|
||||
@@ -35,7 +37,20 @@ class BitInput
|
||||
BitField|=(uint)InBuf[InAddr+1] << 8;
|
||||
BitField|=(uint)InBuf[InAddr+2];
|
||||
BitField >>= (8-InBit);
|
||||
return(BitField & 0xffff);
|
||||
return BitField & 0xffff;
|
||||
}
|
||||
|
||||
// Return 32 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
uint getbits32()
|
||||
{
|
||||
uint BitField=(uint)InBuf[InAddr] << 24;
|
||||
BitField|=(uint)InBuf[InAddr+1] << 16;
|
||||
BitField|=(uint)InBuf[InAddr+2] << 8;
|
||||
BitField|=(uint)InBuf[InAddr+3];
|
||||
BitField <<= InBit;
|
||||
BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
|
||||
return BitField & 0xffffffff;
|
||||
}
|
||||
|
||||
void faddbits(uint Bits);
|
||||
@@ -45,7 +60,9 @@ class BitInput
|
||||
// if buffer will be overflown.
|
||||
bool Overflow(uint IncPtr)
|
||||
{
|
||||
return(InAddr+IncPtr>=MAX_SIZE);
|
||||
return InAddr+IncPtr>=MAX_SIZE;
|
||||
}
|
||||
|
||||
void SetExternalBuffer(byte *Buf);
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#define INCLUDEGLOBAL
|
||||
|
||||
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "rar.hpp"
|
||||
|
||||
34
unrar/hardlinks.cpp
Normal file
34
unrar/hardlinks.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
|
||||
{
|
||||
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
|
||||
|
||||
if (!FileExist(NameExisting))
|
||||
return false;
|
||||
CreatePath(NameNew,true);
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
bool Success=CreateHardLink(NameNew,NameExisting,NULL)!=0;
|
||||
if (!Success)
|
||||
{
|
||||
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
}
|
||||
return Success;
|
||||
#elif defined(_UNIX)
|
||||
char NameExistingA[NM],NameNewA[NM];
|
||||
WideToChar(NameExisting,NameExistingA,ASIZE(NameExistingA));
|
||||
WideToChar(NameNew,NameNewA,ASIZE(NameNewA));
|
||||
bool Success=link(NameExistingA,NameNewA)==0;
|
||||
if (!Success)
|
||||
{
|
||||
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
}
|
||||
return Success;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
135
unrar/hash.cpp
Normal file
135
unrar/hash.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
void HashValue::Init(HASH_TYPE Type)
|
||||
{
|
||||
HashValue::Type=Type;
|
||||
|
||||
// Zero length data CRC32 is 0. It is important to set it when creating
|
||||
// headers with no following data like directories or symlinks.
|
||||
if (Type==HASH_RAR14 || Type==HASH_CRC32)
|
||||
CRC32=0;
|
||||
if (Type==HASH_BLAKE2)
|
||||
{
|
||||
// dd0e891776933f43c7d032b08a917e25741f8aa9a12c12e1cac8801500f2ca4f
|
||||
// is BLAKE2sp hash of empty data. We init the structure to this value,
|
||||
// so if we create a file or service header with no following data like
|
||||
// "file copy" or "symlink", we set the checksum to proper value avoiding
|
||||
// additional header type or size checks when extracting.
|
||||
static byte EmptyHash[32]={
|
||||
0xdd, 0x0e, 0x89, 0x17, 0x76, 0x93, 0x3f, 0x43,
|
||||
0xc7, 0xd0, 0x32, 0xb0, 0x8a, 0x91, 0x7e, 0x25,
|
||||
0x74, 0x1f, 0x8a, 0xa9, 0xa1, 0x2c, 0x12, 0xe1,
|
||||
0xca, 0xc8, 0x80, 0x15, 0x00, 0xf2, 0xca, 0x4f
|
||||
};
|
||||
memcpy(Digest,EmptyHash,sizeof(Digest));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool HashValue::operator == (const HashValue &cmp)
|
||||
{
|
||||
if (Type==HASH_NONE || cmp.Type==HASH_NONE)
|
||||
return true;
|
||||
if (Type==HASH_RAR14 && cmp.Type==HASH_RAR14 ||
|
||||
Type==HASH_CRC32 && cmp.Type==HASH_CRC32)
|
||||
return CRC32==cmp.CRC32;
|
||||
if (Type==HASH_BLAKE2 && cmp.Type==HASH_BLAKE2)
|
||||
return memcmp(Digest,cmp.Digest,sizeof(Digest))==0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DataHash::DataHash()
|
||||
{
|
||||
blake2ctx=NULL;
|
||||
HashType=HASH_NONE;
|
||||
#ifdef RAR_SMP
|
||||
ThPool=NULL;
|
||||
MaxThreads=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
DataHash::~DataHash()
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(ThPool);
|
||||
#endif
|
||||
cleandata(&CurCRC32, sizeof(CurCRC32));
|
||||
if (blake2ctx!=NULL)
|
||||
{
|
||||
cleandata(blake2ctx, sizeof(blake2sp_state));
|
||||
delete blake2ctx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DataHash::Init(HASH_TYPE Type,uint MaxThreads)
|
||||
{
|
||||
if (blake2ctx==NULL)
|
||||
blake2ctx=new blake2sp_state;
|
||||
HashType=Type;
|
||||
if (Type==HASH_RAR14)
|
||||
CurCRC32=0;
|
||||
if (Type==HASH_CRC32)
|
||||
CurCRC32=0xffffffff; // Initial CRC32 value.
|
||||
if (Type==HASH_BLAKE2)
|
||||
blake2sp_init(blake2ctx);
|
||||
#ifdef RAR_SMP
|
||||
DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void DataHash::Update(const void *Data,size_t DataSize)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
if (HashType==HASH_RAR14)
|
||||
CurCRC32=Checksum14((ushort)CurCRC32,Data,DataSize);
|
||||
#endif
|
||||
if (HashType==HASH_CRC32)
|
||||
CurCRC32=CRC32(CurCRC32,Data,DataSize);
|
||||
|
||||
if (HashType==HASH_BLAKE2)
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
if (MaxThreads>1 && ThPool==NULL)
|
||||
ThPool=CreateThreadPool();
|
||||
blake2ctx->ThPool=ThPool;
|
||||
blake2ctx->MaxThreads=MaxThreads;
|
||||
#endif
|
||||
blake2sp_update( blake2ctx, (byte *)Data, DataSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DataHash::Result(HashValue *Result)
|
||||
{
|
||||
Result->Type=HashType;
|
||||
if (HashType==HASH_RAR14)
|
||||
Result->CRC32=CurCRC32;
|
||||
if (HashType==HASH_CRC32)
|
||||
Result->CRC32=CurCRC32^0xffffffff;
|
||||
if (HashType==HASH_BLAKE2)
|
||||
{
|
||||
// Preserve the original context, so we can continue hashing if necessary.
|
||||
blake2sp_state res=*blake2ctx;
|
||||
blake2sp_final(&res,Result->Digest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint DataHash::GetCRC32()
|
||||
{
|
||||
return HashType==HASH_CRC32 ? CurCRC32^0xffffffff : 0;
|
||||
}
|
||||
|
||||
|
||||
bool DataHash::Cmp(HashValue *CmpValue,byte *Key)
|
||||
{
|
||||
HashValue Final;
|
||||
Result(&Final);
|
||||
if (Key!=NULL)
|
||||
ConvertHashToMAC(&Final,Key);
|
||||
return Final==*CmpValue;
|
||||
}
|
||||
52
unrar/hash.hpp
Normal file
52
unrar/hash.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _RAR_DATAHASH_
|
||||
#define _RAR_DATAHASH_
|
||||
|
||||
enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
|
||||
|
||||
struct HashValue
|
||||
{
|
||||
void Init(HASH_TYPE Type);
|
||||
bool operator == (const HashValue &cmp);
|
||||
bool operator != (const HashValue &cmp) {return !(*this==cmp);}
|
||||
|
||||
HASH_TYPE Type;
|
||||
union
|
||||
{
|
||||
uint CRC32;
|
||||
byte Digest[SHA256_DIGEST_SIZE];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#ifdef RAR_SMP
|
||||
class ThreadPool;
|
||||
class DataHash;
|
||||
#endif
|
||||
|
||||
|
||||
class DataHash
|
||||
{
|
||||
private:
|
||||
HASH_TYPE HashType;
|
||||
uint CurCRC32;
|
||||
blake2sp_state *blake2ctx;
|
||||
|
||||
#ifdef RAR_SMP
|
||||
ThreadPool *ThPool;
|
||||
|
||||
uint MaxThreads;
|
||||
// Upper limit for maximum threads to prevent wasting threads in pool.
|
||||
static const uint MaxHashThreads=8;
|
||||
#endif
|
||||
public:
|
||||
DataHash();
|
||||
~DataHash();
|
||||
void Init(HASH_TYPE Type,uint MaxThreads);
|
||||
void Update(const void *Data,size_t DataSize);
|
||||
void Result(HashValue *Result);
|
||||
uint GetCRC32();
|
||||
bool Cmp(HashValue *CmpValue,byte *Key);
|
||||
HASH_TYPE Type() {return HashType;}
|
||||
};
|
||||
|
||||
#endif
|
||||
61
unrar/headers.cpp
Normal file
61
unrar/headers.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
void FileHeader::Reset(size_t SubDataSize)
|
||||
{
|
||||
SubData.Alloc(SubDataSize);
|
||||
BaseBlock::Reset();
|
||||
FileHash.Init(HASH_NONE);
|
||||
mtime.Reset();
|
||||
atime.Reset();
|
||||
ctime.Reset();
|
||||
SplitBefore=false;
|
||||
SplitAfter=false;
|
||||
|
||||
UnknownUnpSize=0;
|
||||
|
||||
SubFlags=0; // Important for RAR 3.0 subhead.
|
||||
|
||||
CryptMethod=CRYPT_NONE;
|
||||
Encrypted=false;
|
||||
SaltSet=false;
|
||||
UsePswCheck=false;
|
||||
UseHashKey=false;
|
||||
Lg2Count=0;
|
||||
|
||||
Solid=false;
|
||||
Dir=false;
|
||||
WinSize=0;
|
||||
Inherited=false;
|
||||
SubBlock=false;
|
||||
CommentInHeader=false;
|
||||
Version=false;
|
||||
LargeFile=false;
|
||||
|
||||
RedirType=FSREDIR_NONE;
|
||||
DirTarget=false;
|
||||
UnixOwnerSet=false;
|
||||
}
|
||||
|
||||
|
||||
FileHeader& FileHeader::operator = (FileHeader &hd)
|
||||
{
|
||||
SubData.Reset();
|
||||
memcpy(this,&hd,sizeof(*this));
|
||||
SubData.CleanData();
|
||||
SubData=hd.SubData;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void MainHeader::Reset()
|
||||
{
|
||||
HighPosAV=0;
|
||||
PosAV=0;
|
||||
CommentInHeader=false;
|
||||
PackComment=false;
|
||||
Locator=false;
|
||||
QOpenOffset=0;
|
||||
QOpenMaxSize=0;
|
||||
RROffset=0;
|
||||
RRMaxSize=0;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef _RAR_HEADERS_
|
||||
#define _RAR_HEADERS_
|
||||
|
||||
#define SIZEOF_MARKHEAD 7
|
||||
#define SIZEOF_OLDMHD 7
|
||||
#define SIZEOF_NEWMHD 13
|
||||
#define SIZEOF_OLDLHD 21
|
||||
#define SIZEOF_NEWLHD 32
|
||||
#define SIZEOF_MARKHEAD3 7 // Size of RAR 4.x archive mark header.
|
||||
#define SIZEOF_MAINHEAD14 7 // Size of RAR 1.4 main archive header.
|
||||
#define SIZEOF_MAINHEAD3 13 // Size of RAR 4.x main archive header.
|
||||
#define SIZEOF_FILEHEAD14 21 // Size of RAR 1.4 file header.
|
||||
#define SIZEOF_FILEHEAD3 32 // Size of RAR 3.0 file header.
|
||||
#define SIZEOF_SHORTBLOCKHEAD 7
|
||||
#define SIZEOF_LONGBLOCKHEAD 11
|
||||
#define SIZEOF_SUBBLOCKHEAD 14
|
||||
@@ -19,20 +19,15 @@
|
||||
#define SIZEOF_BEEAHEAD 24
|
||||
#define SIZEOF_STREAMHEAD 26
|
||||
|
||||
#define PACK_VER 29
|
||||
#define PACK_CRYPT_VER 29
|
||||
#define UNP_VER 36
|
||||
#define CRYPT_VER 29
|
||||
#define AV_VER 20
|
||||
#define PROTECT_VER 20
|
||||
|
||||
#define VER_PACK 29
|
||||
#define VER_PACK5 50 // It is stored as 0, but we subtract 50 when saving an archive.
|
||||
#define VER_UNPACK 29
|
||||
#define VER_UNPACK5 50 // It is stored as 0, but we add 50 when reading an archive.
|
||||
|
||||
#define MHD_VOLUME 0x0001U
|
||||
|
||||
// Old style main archive comment embed into main archive header. Must not
|
||||
// be used in new archives anymore. Must never be used with MHD_ENCRYPTVER
|
||||
// or other flags chaning the size of main header. RAR expects the fixed
|
||||
// size of main header preceding the comment if MHD_COMMENT is found.
|
||||
// be used in new archives anymore.
|
||||
#define MHD_COMMENT 0x0002U
|
||||
|
||||
#define MHD_LOCK 0x0004U
|
||||
@@ -43,7 +38,6 @@
|
||||
#define MHD_PROTECT 0x0040U
|
||||
#define MHD_PASSWORD 0x0080U
|
||||
#define MHD_FIRSTVOLUME 0x0100U
|
||||
#define MHD_ENCRYPTVER 0x0200U
|
||||
|
||||
#define LHD_SPLIT_BEFORE 0x0001U
|
||||
#define LHD_SPLIT_AFTER 0x0002U
|
||||
@@ -52,6 +46,7 @@
|
||||
// Old style file comment embed into file header. Must not be used
|
||||
// in new archives anymore.
|
||||
#define LHD_COMMENT 0x0008U
|
||||
// For non-file subheaders it denotes 'subblock having a parent file' flag.
|
||||
#define LHD_SOLID 0x0010U
|
||||
|
||||
#define LHD_WINDOWMASK 0x00e0U
|
||||
@@ -69,96 +64,96 @@
|
||||
#define LHD_SALT 0x0400U
|
||||
#define LHD_VERSION 0x0800U
|
||||
#define LHD_EXTTIME 0x1000U
|
||||
#define LHD_EXTFLAGS 0x2000U
|
||||
|
||||
#define SKIP_IF_UNKNOWN 0x4000U
|
||||
#define LONG_BLOCK 0x8000U
|
||||
|
||||
#define EARC_NEXT_VOLUME 0x0001U // not last volume
|
||||
#define EARC_DATACRC 0x0002U // store CRC32 of RAR archive (now used only in volumes)
|
||||
#define EARC_REVSPACE 0x0004U // reserve space for end of REV file 7 byte record
|
||||
#define EARC_VOLNUMBER 0x0008U // store a number of current volume
|
||||
#define EARC_NEXT_VOLUME 0x0001U // Not last volume.
|
||||
#define EARC_DATACRC 0x0002U // Store CRC32 of RAR archive (now is used only in volumes).
|
||||
#define EARC_REVSPACE 0x0004U // Reserve space for end of REV file 7 byte record.
|
||||
#define EARC_VOLNUMBER 0x0008U // Store a number of current volume.
|
||||
|
||||
enum HEADER_TYPE {
|
||||
MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76,
|
||||
SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a,
|
||||
ENDARC_HEAD=0x7b
|
||||
// RAR 5.0 header types.
|
||||
HEAD_MARK=0x00, HEAD_MAIN=0x01, HEAD_FILE=0x02, HEAD_SERVICE=0x03,
|
||||
HEAD_CRYPT=0x04, HEAD_ENDARC=0x05, HEAD_UNKNOWN=0xff,
|
||||
|
||||
// RAR 1.5 - 4.x header types.
|
||||
HEAD3_MARK=0x72,HEAD3_MAIN=0x73,HEAD3_FILE=0x74,HEAD3_CMT=0x75,
|
||||
HEAD3_AV=0x76,HEAD3_OLDSERVICE=0x77,HEAD3_PROTECT=0x78,HEAD3_SIGN=0x79,
|
||||
HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b
|
||||
};
|
||||
|
||||
enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
|
||||
NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
|
||||
|
||||
|
||||
// Internal implementation, depends on archive format version.
|
||||
enum HOST_SYSTEM {
|
||||
// RAR 5.0 host OS
|
||||
HOST5_WINDOWS=0,HOST5_UNIX=1,
|
||||
|
||||
// RAR 3.0 host OS.
|
||||
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
|
||||
HOST_BEOS=5,HOST_MAX
|
||||
};
|
||||
|
||||
#define SUBHEAD_TYPE_CMT "CMT"
|
||||
#define SUBHEAD_TYPE_ACL "ACL"
|
||||
#define SUBHEAD_TYPE_STREAM "STM"
|
||||
#define SUBHEAD_TYPE_UOWNER "UOW"
|
||||
#define SUBHEAD_TYPE_AV "AV"
|
||||
#define SUBHEAD_TYPE_RR "RR"
|
||||
#define SUBHEAD_TYPE_OS2EA "EA2"
|
||||
#define SUBHEAD_TYPE_BEOSEA "EABE"
|
||||
// Unified archive format independent implementation.
|
||||
enum HOST_SYSTEM_TYPE {
|
||||
HSYS_WINDOWS, HSYS_UNIX, HSYS_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
// We also use these values in extra field, so do not modify them.
|
||||
enum FILE_SYSTEM_REDIRECT {
|
||||
FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
|
||||
FSREDIR_HARDLINK, FSREDIR_FILECOPY
|
||||
};
|
||||
|
||||
|
||||
#define SUBHEAD_TYPE_CMT L"CMT"
|
||||
#define SUBHEAD_TYPE_QOPEN L"QO"
|
||||
#define SUBHEAD_TYPE_ACL L"ACL"
|
||||
#define SUBHEAD_TYPE_STREAM L"STM"
|
||||
#define SUBHEAD_TYPE_UOWNER L"UOW"
|
||||
#define SUBHEAD_TYPE_AV L"AV"
|
||||
#define SUBHEAD_TYPE_RR L"RR"
|
||||
#define SUBHEAD_TYPE_OS2EA L"EA2"
|
||||
|
||||
/* new file inherits a subblock when updating a host file */
|
||||
#define SUBHEAD_FLAGS_INHERITED 0x80000000
|
||||
|
||||
#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001
|
||||
|
||||
struct OldMainHeader
|
||||
{
|
||||
byte Mark[4];
|
||||
ushort HeadSize;
|
||||
byte Flags;
|
||||
};
|
||||
|
||||
|
||||
struct OldFileHeader
|
||||
{
|
||||
uint PackSize;
|
||||
uint UnpSize;
|
||||
ushort FileCRC;
|
||||
ushort HeadSize;
|
||||
uint FileTime;
|
||||
byte FileAttr;
|
||||
byte Flags;
|
||||
byte UnpVer;
|
||||
byte NameSize;
|
||||
byte Method;
|
||||
};
|
||||
|
||||
|
||||
struct MarkHeader
|
||||
{
|
||||
byte Mark[7];
|
||||
byte Mark[8];
|
||||
|
||||
// Following fields are virtual and not present in real blocks.
|
||||
uint HeadSize;
|
||||
};
|
||||
|
||||
|
||||
struct BaseBlock
|
||||
{
|
||||
ushort HeadCRC;
|
||||
HEADER_TYPE HeadType;//byte
|
||||
ushort Flags;
|
||||
ushort HeadSize;
|
||||
uint HeadCRC; // 'ushort' for RAR 1.5.
|
||||
HEADER_TYPE HeaderType; // 1 byte for RAR 1.5.
|
||||
uint Flags; // 'ushort' for RAR 1.5.
|
||||
uint HeadSize; // 'ushort' for RAR 1.5, up to 2 MB for RAR 5.0.
|
||||
|
||||
bool IsSubBlock()
|
||||
bool SkipIfUnknown;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (HeadType==SUB_HEAD)
|
||||
return(true);
|
||||
if (HeadType==NEWSUB_HEAD && (Flags & LHD_SOLID)!=0)
|
||||
return(true);
|
||||
return(false);
|
||||
SkipIfUnknown=false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct BlockHeader:BaseBlock
|
||||
{
|
||||
union {
|
||||
uint DataSize;
|
||||
uint PackSize;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -166,75 +161,141 @@ struct MainHeader:BaseBlock
|
||||
{
|
||||
ushort HighPosAV;
|
||||
uint PosAV;
|
||||
byte EncryptVer;
|
||||
bool CommentInHeader;
|
||||
bool PackComment; // For RAR 1.4 archive format only.
|
||||
bool Locator;
|
||||
uint64 QOpenOffset; // Offset of quick list record.
|
||||
uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
|
||||
uint64 RROffset; // Offset of recovery record.
|
||||
uint64 RRMaxSize; // Maximum size of RR offset in locator extra field.
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
#define SALT_SIZE 8
|
||||
|
||||
struct FileHeader:BlockHeader
|
||||
{
|
||||
uint UnpSize;
|
||||
byte HostOS;
|
||||
uint FileCRC;
|
||||
uint FileTime;
|
||||
byte UnpVer;
|
||||
byte Method;
|
||||
ushort NameSize;
|
||||
union {
|
||||
uint FileAttr;
|
||||
uint SubFlags;
|
||||
};
|
||||
/* optional */
|
||||
uint HighPackSize;
|
||||
uint HighUnpSize;
|
||||
/* names */
|
||||
char FileName[NM];
|
||||
wchar FileNameW[NM];
|
||||
/* optional */
|
||||
wchar FileName[NM];
|
||||
|
||||
Array<byte> SubData;
|
||||
byte Salt[SALT_SIZE];
|
||||
|
||||
RarTime mtime;
|
||||
RarTime ctime;
|
||||
RarTime atime;
|
||||
RarTime arctime;
|
||||
/* dummy */
|
||||
int64 FullPackSize;
|
||||
int64 FullUnpSize;
|
||||
|
||||
void Clear(size_t SubDataSize)
|
||||
int64 PackSize;
|
||||
int64 UnpSize;
|
||||
int64 MaxSize; // Reserve size bytes for vint of this size.
|
||||
|
||||
HashValue FileHash;
|
||||
|
||||
uint FileFlags;
|
||||
|
||||
bool SplitBefore;
|
||||
bool SplitAfter;
|
||||
|
||||
bool UnknownUnpSize;
|
||||
|
||||
bool Encrypted;
|
||||
CRYPT_METHOD CryptMethod;
|
||||
bool SaltSet;
|
||||
byte Salt[SIZE_SALT50];
|
||||
byte InitV[SIZE_INITV];
|
||||
bool UsePswCheck;
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
|
||||
// Use HMAC calculated from HashKey and checksum instead of plain checksum.
|
||||
bool UseHashKey;
|
||||
|
||||
// Key to convert checksum to HMAC. Derived from password with PBKDF2
|
||||
// using additional iterations.
|
||||
byte HashKey[SHA256_DIGEST_SIZE];
|
||||
|
||||
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||
|
||||
bool Solid;
|
||||
bool Dir;
|
||||
bool CommentInHeader; // RAR 2.0 file comment.
|
||||
bool Version; // name.ext;ver file name containing the version number.
|
||||
size_t WinSize;
|
||||
bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only).
|
||||
|
||||
// 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0.
|
||||
bool LargeFile;
|
||||
|
||||
// 'true' for HEAD_SERVICE block, which is a child of preceding file block.
|
||||
// RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
|
||||
bool SubBlock;
|
||||
|
||||
HOST_SYSTEM_TYPE HSType;
|
||||
|
||||
FILE_SYSTEM_REDIRECT RedirType;
|
||||
wchar RedirName[NM];
|
||||
bool DirTarget;
|
||||
|
||||
bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric;
|
||||
char UnixOwnerName[256],UnixGroupName[256];
|
||||
#ifdef _UNIX
|
||||
uid_t UnixOwnerID;
|
||||
gid_t UnixGroupID;
|
||||
#else // Need these Unix fields in Windows too for 'list' command.
|
||||
uint UnixOwnerID;
|
||||
uint UnixGroupID;
|
||||
#endif
|
||||
|
||||
void Reset(size_t SubDataSize=0);
|
||||
|
||||
bool CmpName(const wchar *Name)
|
||||
{
|
||||
SubData.Alloc(SubDataSize);
|
||||
Flags=LONG_BLOCK;
|
||||
SubFlags=0;
|
||||
return(wcscmp(FileName,Name)==0);
|
||||
}
|
||||
|
||||
bool CmpName(const char *Name)
|
||||
{
|
||||
return(strcmp(FileName,Name)==0);
|
||||
}
|
||||
|
||||
FileHeader& operator = (FileHeader &hd)
|
||||
{
|
||||
SubData.Reset();
|
||||
memcpy(this,&hd,sizeof(*this));
|
||||
SubData.CleanData();
|
||||
SubData=hd.SubData;
|
||||
return(*this);
|
||||
}
|
||||
FileHeader& operator = (FileHeader &hd);
|
||||
};
|
||||
|
||||
|
||||
struct EndArcHeader:BaseBlock
|
||||
{
|
||||
uint ArcDataCRC; // optional archive CRC32
|
||||
ushort VolNumber; // optional current volume number
|
||||
// Optional CRC32 of entire archive up to start of EndArcHeader block.
|
||||
// Present in RAR 4.x archives if EARC_DATACRC flag is set.
|
||||
uint ArcDataCRC;
|
||||
|
||||
uint VolNumber; // Optional number of current volume.
|
||||
|
||||
// 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
|
||||
|
||||
bool NextVolume; // Not last volume.
|
||||
bool DataCRC;
|
||||
bool RevSpace;
|
||||
bool StoreVolNumber;
|
||||
void Reset()
|
||||
{
|
||||
BaseBlock::Reset();
|
||||
NextVolume=false;
|
||||
DataCRC=false;
|
||||
RevSpace=false;
|
||||
StoreVolNumber=false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CryptHeader:BaseBlock
|
||||
{
|
||||
bool UsePswCheck;
|
||||
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||
byte Salt[SIZE_SALT50];
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
};
|
||||
|
||||
|
||||
// SubBlockHeader and its successors were used in RAR 2.x format.
|
||||
// RAR 3.x uses FileHeader with NEWSUB_HEAD HeadType for subblocks.
|
||||
// RAR 4.x uses FileHeader with HEAD_SERVICE HeaderType for subblocks.
|
||||
struct SubBlockHeader:BlockHeader
|
||||
{
|
||||
ushort SubType;
|
||||
@@ -282,8 +343,8 @@ struct UnixOwnersHeader:SubBlockHeader
|
||||
ushort OwnerNameSize;
|
||||
ushort GroupNameSize;
|
||||
/* dummy */
|
||||
char OwnerName[NM];
|
||||
char GroupName[NM];
|
||||
char OwnerName[256];
|
||||
char GroupName[256];
|
||||
};
|
||||
|
||||
|
||||
@@ -303,8 +364,7 @@ struct StreamHeader:SubBlockHeader
|
||||
byte Method;
|
||||
uint StreamCRC;
|
||||
ushort StreamNameSize;
|
||||
/* dummy */
|
||||
byte StreamName[NM];
|
||||
char StreamName[260];
|
||||
};
|
||||
|
||||
|
||||
|
||||
100
unrar/headers5.hpp
Normal file
100
unrar/headers5.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#ifndef _RAR_HEADERS5_
|
||||
#define _RAR_HEADERS5_
|
||||
|
||||
#define SIZEOF_MARKHEAD5 8 // RAR 5.0 signature length.
|
||||
#define SIZEOF_SHORTBLOCKHEAD5 7 // Smallest RAR 5.0 block size.
|
||||
|
||||
// RAR 5.0 block flags common for all blocks.
|
||||
|
||||
// Additional extra area is present in the end of block header.
|
||||
#define HFL_EXTRA 0x0001
|
||||
// Additional data area is present in the end of block header.
|
||||
#define HFL_DATA 0x0002
|
||||
// Unknown blocks with this flag must be skipped when updating an archive.
|
||||
#define HFL_SKIPIFUNKNOWN 0x0004
|
||||
// Data area of this block is continuing from previous volume.
|
||||
#define HFL_SPLITBEFORE 0x0008
|
||||
// Data area of this block is continuing in next volume.
|
||||
#define HFL_SPLITAFTER 0x0010
|
||||
// Block depends on preceding file block.
|
||||
#define HFL_CHILD 0x0020
|
||||
// Preserve a child block if host is modified.
|
||||
#define HFL_INHERITED 0x0040
|
||||
|
||||
// RAR 5.0 main archive header specific flags.
|
||||
#define MHFL_VOLUME 0x0001 // Volume.
|
||||
#define MHFL_VOLNUMBER 0x0002 // Volume number field is present. True for all volumes except first.
|
||||
#define MHFL_SOLID 0x0004 // Solid archive.
|
||||
#define MHFL_PROTECT 0x0008 // Recovery record is present.
|
||||
#define MHFL_LOCK 0x0010 // Locked archive.
|
||||
|
||||
// RAR 5.0 file header specific flags.
|
||||
#define FHFL_DIRECTORY 0x0001 // Directory.
|
||||
#define FHFL_UTIME 0x0002 // Time field in Unix format is present.
|
||||
#define FHFL_CRC32 0x0004 // CRC32 field is present.
|
||||
#define FHFL_UNPUNKNOWN 0x0008 // Unknown unpacked size.
|
||||
|
||||
// RAR 5.0 end of archive header specific flags.
|
||||
#define EHFL_NEXTVOLUME 0x0001 // Not last volume.
|
||||
|
||||
// RAR 5.0 archive encryption header specific flags.
|
||||
#define CHFL_CRYPT_PSWCHECK 0x0001 // Password check data is present.
|
||||
|
||||
|
||||
// RAR 5.0 file compression flags.
|
||||
#define FCI_ALGO_BIT0 0x0001 // Version of compression algorithm.
|
||||
#define FCI_ALGO_BIT1 0x0002 // 0 .. 63.
|
||||
#define FCI_ALGO_BIT2 0x0004
|
||||
#define FCI_ALGO_BIT3 0x0008
|
||||
#define FCI_ALGO_BIT4 0x0010
|
||||
#define FCI_ALGO_BIT5 0x0020
|
||||
#define FCI_SOLID 0x0040 // Solid flag.
|
||||
#define FCI_METHOD_BIT0 0x0080 // Compression method.
|
||||
#define FCI_METHOD_BIT1 0x0100 // 0 .. 5 (6 and 7 are not used).
|
||||
#define FCI_METHOD_BIT2 0x0200
|
||||
#define FCI_DICT_BIT0 0x0400 // Dictionary size.
|
||||
#define FCI_DICT_BIT1 0x0800 // 128 KB .. 4 GB.
|
||||
#define FCI_DICT_BIT2 0x1000
|
||||
#define FCI_DICT_BIT3 0x2000
|
||||
|
||||
// Main header extra field values.
|
||||
#define MHEXTRA_LOCATOR 0x01 // Position of quick list and other blocks.
|
||||
|
||||
// Flags for MHEXTRA_LOCATOR.
|
||||
#define MHEXTRA_LOCATOR_QLIST 0x01 // Quick open offset is present.
|
||||
#define MHEXTRA_LOCATOR_RR 0x02 // Recovery record offset is present.
|
||||
|
||||
// File and service header extra field values.
|
||||
#define FHEXTRA_CRYPT 0x01 // Encryption parameters.
|
||||
#define FHEXTRA_HASH 0x02 // File hash.
|
||||
#define FHEXTRA_HTIME 0x03 // High precision file time.
|
||||
#define FHEXTRA_VERSION 0x04 // File version information.
|
||||
#define FHEXTRA_REDIR 0x05 // File system redirection (links, etc.).
|
||||
#define FHEXTRA_UOWNER 0x06 // Unix owner and group information.
|
||||
#define FHEXTRA_SUBDATA 0x07 // Service header subdata array.
|
||||
|
||||
|
||||
// Hash type values for FHEXTRA_HASH.
|
||||
#define FHEXTRA_HASH_BLAKE2 0x00
|
||||
|
||||
// Flags for FHEXTRA_HTIME.
|
||||
#define FHEXTRA_HTIME_UNIXTIME 0x01 // Use Unix time_t format.
|
||||
#define FHEXTRA_HTIME_MTIME 0x02 // mtime is present.
|
||||
#define FHEXTRA_HTIME_CTIME 0x04 // ctime is present.
|
||||
#define FHEXTRA_HTIME_ATIME 0x08 // atime is present.
|
||||
#define FHEXTRA_HTIME_UNIX_NS 0x10 // Unix format with nanosecond precision.
|
||||
|
||||
// Flags for FHEXTRA_CRYPT.
|
||||
#define FHEXTRA_CRYPT_PSWCHECK 0x01 // Store password check data.
|
||||
#define FHEXTRA_CRYPT_HASHMAC 0x02 // Use MAC for unpacked data checksums.
|
||||
|
||||
// Flags for FHEXTRA_REDIR.
|
||||
#define FHEXTRA_REDIR_DIR 0x01 // Link target is directory.
|
||||
|
||||
// Flags for FHEXTRA_UOWNER.
|
||||
#define FHEXTRA_UOWNER_UNAME 0x01 // User name string is present.
|
||||
#define FHEXTRA_UOWNER_GNAME 0x02 // Group name string is present.
|
||||
#define FHEXTRA_UOWNER_NUMUID 0x04 // Numeric user ID is present.
|
||||
#define FHEXTRA_UOWNER_NUMGID 0x08 // Numeric group ID is present.
|
||||
|
||||
#endif
|
||||
@@ -19,6 +19,6 @@ DWORD WinNT()
|
||||
Result=dwMajorVersion*0x100+dwMinorVersion;
|
||||
|
||||
|
||||
return(Result);
|
||||
return Result;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
enum WINNT_VERSION {
|
||||
WNT_NONE=0,WNT_NT351=0x0333,WNT_NT4=0x0400,WNT_W2000=0x0500,
|
||||
WNT_WXP=0x0501,WNT_W2003=0x0502,WNT_VISTA=0x0600,WNT_W7=0x0601
|
||||
WNT_WXP=0x0501,WNT_W2003=0x0502,WNT_VISTA=0x0600,WNT_W7=0x0601,
|
||||
WNT_W8=0x0602,WNT_W81=0x0603,WNT_W10=0x0a00
|
||||
};
|
||||
|
||||
DWORD WinNT();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
628
unrar/list.cpp
628
unrar/list.cpp
@@ -1,29 +1,31 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
static void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare);
|
||||
static void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare);
|
||||
static void ListSymLink(Archive &Arc);
|
||||
static void ListFileAttr(uint A,int HostOS);
|
||||
static void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize);
|
||||
static void ListOldSubHeader(Archive &Arc);
|
||||
static void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical);
|
||||
static void ListNewSubHeader(CommandData *Cmd,Archive &Arc);
|
||||
|
||||
void ListArchive(CommandData *Cmd)
|
||||
{
|
||||
int64 SumPackSize=0,SumUnpSize=0;
|
||||
uint ArcCount=0,SumFileCount=0;
|
||||
bool Technical=(Cmd->Command[1]=='T');
|
||||
bool ShowService=Technical && Cmd->Command[2]=='A';
|
||||
bool Bare=(Cmd->Command[1]=='B');
|
||||
bool Verbose=(*Cmd->Command=='V');
|
||||
bool Verbose=(Cmd->Command[0]=='V');
|
||||
|
||||
char ArcName[NM];
|
||||
wchar ArcNameW[NM];
|
||||
|
||||
while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
|
||||
wchar ArcName[NM];
|
||||
while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
|
||||
{
|
||||
if (Cmd->ManualPassword)
|
||||
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
||||
|
||||
Archive Arc(Cmd);
|
||||
#ifdef _WIN_ALL
|
||||
Arc.RemoveSequentialFlag();
|
||||
#endif
|
||||
if (!Arc.WOpen(ArcName,ArcNameW))
|
||||
if (!Arc.WOpen(ArcName))
|
||||
continue;
|
||||
bool FileMatched=true;
|
||||
while (1)
|
||||
@@ -32,110 +34,111 @@ void ListArchive(CommandData *Cmd)
|
||||
uint FileCount=0;
|
||||
if (Arc.IsArchive(true))
|
||||
{
|
||||
// if (!Arc.IsOpened())
|
||||
// break;
|
||||
bool TitleShown=false;
|
||||
if (!Bare)
|
||||
{
|
||||
Arc.ViewComment();
|
||||
|
||||
// RAR can close a corrupt encrypted archive.
|
||||
// if (!Arc.IsOpened())
|
||||
// break;
|
||||
|
||||
mprintf("\n");
|
||||
mprintf(L"\n%s: %s",St(MListArchive),Arc.FileName);
|
||||
mprintf(L"\n%s: ",St(MListDetails));
|
||||
uint SetCount=0;
|
||||
const wchar *Fmt=Arc.Format==RARFMT14 ? L"RAR 1.4":(Arc.Format==RARFMT15 ? L"RAR 4":L"RAR 5");
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", Fmt);
|
||||
if (Arc.Solid)
|
||||
mprintf(St(MListSolid));
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSolid));
|
||||
if (Arc.SFXSize>0)
|
||||
mprintf(St(MListSFX));
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSFX));
|
||||
if (Arc.Volume)
|
||||
if (Arc.Solid)
|
||||
mprintf(St(MListVol1));
|
||||
if (Arc.Format==RARFMT50)
|
||||
{
|
||||
// RAR 5.0 archives store the volume number in main header,
|
||||
// so it is already available now.
|
||||
if (SetCount++ > 0)
|
||||
mprintf(L", ");
|
||||
mprintf(St(MVolumeNumber),Arc.VolNumber+1);
|
||||
}
|
||||
else
|
||||
mprintf(St(MListVol2));
|
||||
else
|
||||
if (Arc.Solid)
|
||||
mprintf(St(MListArc1));
|
||||
else
|
||||
mprintf(St(MListArc2));
|
||||
mprintf(" %s\n",Arc.FileName);
|
||||
if (Technical)
|
||||
{
|
||||
if (Arc.Protected)
|
||||
mprintf(St(MListRecRec));
|
||||
if (Arc.Locked)
|
||||
mprintf(St(MListLock));
|
||||
}
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListVolume));
|
||||
if (Arc.Protected)
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListRR));
|
||||
if (Arc.Locked)
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListLock));
|
||||
if (Arc.Encrypted)
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListEncHead));
|
||||
mprintf(L"\n");
|
||||
}
|
||||
|
||||
wchar VolNumText[50];
|
||||
*VolNumText=0;
|
||||
while(Arc.ReadHeader()>0)
|
||||
{
|
||||
int HeaderType=Arc.GetHeaderType();
|
||||
if (HeaderType==ENDARC_HEAD)
|
||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||
if (HeaderType==HEAD_ENDARC)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
// Only RAR 1.5 archives store the volume number in end record.
|
||||
if (Arc.EndArcHead.StoreVolNumber && Arc.Format==RARFMT15)
|
||||
swprintf(VolNumText,ASIZE(VolNumText),L"%.10ls %u",St(MListVolume),Arc.VolNumber+1);
|
||||
#endif
|
||||
if (Technical && ShowService)
|
||||
{
|
||||
mprintf(L"\n%12ls: %ls",St(MListService),L"EOF");
|
||||
if (*VolNumText!=0)
|
||||
mprintf(L"\n%12ls: %ls",St(MListFlags),VolNumText);
|
||||
mprintf(L"\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch(HeaderType)
|
||||
{
|
||||
case FILE_HEAD:
|
||||
IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName);
|
||||
FileMatched=Cmd->IsProcessFile(Arc.NewLhd)!=0;
|
||||
if (FileMatched)
|
||||
case HEAD_FILE:
|
||||
FileMatched=Cmd->IsProcessFile(Arc.FileHead)!=0;
|
||||
if (FileMatched)
|
||||
{
|
||||
ListFileHeader(Arc.NewLhd,Verbose,Technical,TitleShown,Bare);
|
||||
if (!(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
|
||||
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
|
||||
if (!Arc.FileHead.SplitBefore)
|
||||
{
|
||||
TotalUnpSize+=Arc.NewLhd.FullUnpSize;
|
||||
TotalUnpSize+=Arc.FileHead.UnpSize;
|
||||
FileCount++;
|
||||
}
|
||||
TotalPackSize+=Arc.NewLhd.FullPackSize;
|
||||
if (Technical)
|
||||
ListSymLink(Arc);
|
||||
#ifndef SFX_MODULE
|
||||
if (Verbose)
|
||||
Arc.ViewFileComment();
|
||||
#endif
|
||||
TotalPackSize+=Arc.FileHead.PackSize;
|
||||
}
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case SUB_HEAD:
|
||||
if (Technical && FileMatched && !Bare)
|
||||
ListOldSubHeader(Arc);
|
||||
break;
|
||||
#endif
|
||||
case NEWSUB_HEAD:
|
||||
case HEAD_SERVICE:
|
||||
if (FileMatched && !Bare)
|
||||
{
|
||||
if (Technical)
|
||||
ListFileHeader(Arc.SubHead,Verbose,true,TitleShown,false);
|
||||
ListNewSubHeader(Cmd,Arc,Technical);
|
||||
if (Technical && ShowService)
|
||||
ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Arc.SeekToNext();
|
||||
}
|
||||
if (!Bare)
|
||||
if (!Bare && !Technical)
|
||||
if (TitleShown)
|
||||
{
|
||||
mprintf("\n");
|
||||
for (int I=0;I<79;I++)
|
||||
mprintf("-");
|
||||
char UnpSizeText[20];
|
||||
itoa(TotalUnpSize,UnpSizeText);
|
||||
wchar UnpSizeText[20];
|
||||
itoa(TotalUnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||
|
||||
char PackSizeText[20];
|
||||
itoa(TotalPackSize,PackSizeText);
|
||||
wchar PackSizeText[20];
|
||||
itoa(TotalPackSize,PackSizeText,ASIZE(PackSizeText));
|
||||
|
||||
mprintf("\n%5lu %16s %8s %3d%%",FileCount,UnpSizeText,
|
||||
PackSizeText,ToPercentUnlim(TotalPackSize,TotalUnpSize));
|
||||
if (Verbose)
|
||||
{
|
||||
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
|
||||
mprintf(L"\n%21ls %9ls %3d%% %-27ls %u",UnpSizeText,
|
||||
PackSizeText,ToPercentUnlim(TotalPackSize,TotalUnpSize),
|
||||
VolNumText,FileCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
mprintf(L"\n----------- --------- ---------- ----- ----");
|
||||
mprintf(L"\n%21ls %-16ls %u",UnpSizeText,VolNumText,FileCount);
|
||||
}
|
||||
|
||||
SumFileCount+=FileCount;
|
||||
SumUnpSize+=TotalUnpSize;
|
||||
SumPackSize+=TotalPackSize;
|
||||
#ifndef SFX_MODULE
|
||||
if (Arc.EndArcHead.Flags & EARC_VOLNUMBER)
|
||||
{
|
||||
mprintf(" ");
|
||||
mprintf(St(MVolumeNumber),Arc.EndArcHead.VolNumber+1);
|
||||
}
|
||||
#endif
|
||||
mprintf("\n");
|
||||
mprintf(L"\n");
|
||||
}
|
||||
else
|
||||
mprintf(St(MListNoFiles));
|
||||
@@ -143,254 +146,327 @@ void ListArchive(CommandData *Cmd)
|
||||
ArcCount++;
|
||||
|
||||
#ifndef NOVOLUME
|
||||
if (Cmd->VolSize!=0 && ((Arc.NewLhd.Flags & LHD_SPLIT_AFTER) ||
|
||||
Arc.GetHeaderType()==ENDARC_HEAD &&
|
||||
(Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)!=0) &&
|
||||
MergeArchive(Arc,NULL,false,*Cmd->Command))
|
||||
{
|
||||
if (Cmd->VolSize!=0 && (Arc.FileHead.SplitAfter ||
|
||||
Arc.GetHeaderType()==HEAD_ENDARC && Arc.EndArcHead.NextVolume) &&
|
||||
MergeArchive(Arc,NULL,false,Cmd->Command[0]))
|
||||
Arc.Seek(0,SEEK_SET);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Cmd->ArcNames->ItemsCount()<2 && !Bare)
|
||||
if (Cmd->ArcNames.ItemsCount()<2 && !Bare)
|
||||
mprintf(St(MNotRAR),Arc.FileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ArcCount>1 && !Bare)
|
||||
|
||||
// Clean user entered password. Not really required, just for extra safety.
|
||||
if (Cmd->ManualPassword)
|
||||
Cmd->Password.Clean();
|
||||
|
||||
if (ArcCount>1 && !Bare && !Technical)
|
||||
{
|
||||
char UnpSizeText[20],PackSizeText[20];
|
||||
itoa(SumUnpSize,UnpSizeText);
|
||||
itoa(SumPackSize,PackSizeText);
|
||||
mprintf("\n%5lu %16s %8s %3d%%\n",SumFileCount,UnpSizeText,
|
||||
PackSizeText,ToPercentUnlim(SumPackSize,SumUnpSize));
|
||||
wchar UnpSizeText[20],PackSizeText[20];
|
||||
itoa(SumUnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||
itoa(SumPackSize,PackSizeText,ASIZE(PackSizeText));
|
||||
|
||||
if (Verbose)
|
||||
mprintf(L"%21ls %9ls %3d%% %28ls %u",UnpSizeText,PackSizeText,
|
||||
ToPercentUnlim(SumPackSize,SumUnpSize),L"",SumFileCount);
|
||||
else
|
||||
mprintf(L"%21ls %18s %lu",UnpSizeText,L"",SumFileCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare)
|
||||
enum LISTCOL_TYPE {
|
||||
LCOL_NAME,LCOL_ATTR,LCOL_SIZE,LCOL_PACKED,LCOL_RATIO,LCOL_CSUM,LCOL_ENCR
|
||||
};
|
||||
|
||||
|
||||
void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare)
|
||||
{
|
||||
if (!Bare)
|
||||
{
|
||||
if (!TitleShown)
|
||||
{
|
||||
if (Verbose)
|
||||
mprintf(St(MListPathComm));
|
||||
else
|
||||
mprintf(St(MListName));
|
||||
mprintf(St(MListTitle));
|
||||
if (Technical)
|
||||
mprintf(St(MListTechTitle));
|
||||
for (int I=0;I<79;I++)
|
||||
mprintf("-");
|
||||
TitleShown=true;
|
||||
}
|
||||
|
||||
if (hd.HeadType==NEWSUB_HEAD)
|
||||
mprintf(St(MSubHeadType),hd.FileName);
|
||||
|
||||
mprintf("\n%c",(hd.Flags & LHD_PASSWORD) ? '*' : ' ');
|
||||
}
|
||||
|
||||
char *Name=hd.FileName;
|
||||
|
||||
#ifdef UNICODE_SUPPORTED
|
||||
char ConvertedName[NM];
|
||||
if ((hd.Flags & LHD_UNICODE)!=0 && *hd.FileNameW!=0 && UnicodeEnabled())
|
||||
{
|
||||
if (WideToChar(hd.FileNameW,ConvertedName) && *ConvertedName!=0)
|
||||
Name=ConvertedName;
|
||||
}
|
||||
#endif
|
||||
wchar *Name=hd.FileName;
|
||||
RARFORMAT Format=Arc.Format;
|
||||
|
||||
if (Bare)
|
||||
{
|
||||
mprintf("%s\n",Verbose ? Name:PointToName(Name));
|
||||
mprintf(L"%s\n",Name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Verbose)
|
||||
mprintf("%s\n%12s ",Name,"");
|
||||
else
|
||||
mprintf("%-12s",PointToName(Name));
|
||||
|
||||
char UnpSizeText[20],PackSizeText[20];
|
||||
if (hd.FullUnpSize==INT64NDF)
|
||||
strcpy(UnpSizeText,"?");
|
||||
else
|
||||
itoa(hd.FullUnpSize,UnpSizeText);
|
||||
itoa(hd.FullPackSize,PackSizeText);
|
||||
|
||||
mprintf(" %8s %8s ",UnpSizeText,PackSizeText);
|
||||
|
||||
if ((hd.Flags & LHD_SPLIT_BEFORE) && (hd.Flags & LHD_SPLIT_AFTER))
|
||||
mprintf(" <->");
|
||||
else
|
||||
if (hd.Flags & LHD_SPLIT_BEFORE)
|
||||
mprintf(" <--");
|
||||
else
|
||||
if (hd.Flags & LHD_SPLIT_AFTER)
|
||||
mprintf(" -->");
|
||||
else
|
||||
mprintf("%3d%%",ToPercentUnlim(hd.FullPackSize,hd.FullUnpSize));
|
||||
|
||||
char DateStr[50];
|
||||
hd.mtime.GetText(DateStr,false);
|
||||
mprintf(" %s ",DateStr);
|
||||
|
||||
if (hd.HeadType==NEWSUB_HEAD)
|
||||
mprintf(" %c....B ",(hd.SubFlags & SUBHEAD_FLAGS_INHERITED) ? 'I' : '.');
|
||||
else
|
||||
ListFileAttr(hd.FileAttr,hd.HostOS);
|
||||
|
||||
mprintf(" %8.8X",hd.FileCRC);
|
||||
mprintf(" m%d",hd.Method-0x30);
|
||||
if ((hd.Flags & LHD_WINDOWMASK)<=6*32)
|
||||
mprintf("%c",((hd.Flags&LHD_WINDOWMASK)>>5)+'a');
|
||||
else
|
||||
mprintf(" ");
|
||||
mprintf(" %d.%d",hd.UnpVer/10,hd.UnpVer%10);
|
||||
|
||||
static const char *RarOS[]={
|
||||
"DOS","OS/2","Windows","Unix","Mac OS","BeOS","WinCE","","",""
|
||||
};
|
||||
|
||||
if (Technical)
|
||||
mprintf("\n%22s %8s %4s",
|
||||
(hd.HostOS<ASIZE(RarOS) ? RarOS[hd.HostOS]:""),
|
||||
(hd.Flags & LHD_SOLID) ? St(MYes):St(MNo),
|
||||
(hd.Flags & LHD_VERSION) ? St(MYes):St(MNo));
|
||||
}
|
||||
|
||||
|
||||
void ListSymLink(Archive &Arc)
|
||||
{
|
||||
if (Arc.NewLhd.HostOS==HOST_UNIX && (Arc.NewLhd.FileAttr & 0xF000)==0xA000)
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)==0)
|
||||
if (!TitleShown && !Technical)
|
||||
{
|
||||
if (Verbose)
|
||||
{
|
||||
char FileName[NM];
|
||||
int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1);
|
||||
Arc.Read(FileName,DataSize);
|
||||
FileName[DataSize]=0;
|
||||
mprintf("\n%22s %s","-->",FileName);
|
||||
mprintf(L"\n%ls",St(MListTitleV));
|
||||
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
|
||||
}
|
||||
else
|
||||
{
|
||||
mprintf(L"\n%ls",St(MListTitleL));
|
||||
mprintf(L"\n----------- --------- ---------- ----- ----");
|
||||
}
|
||||
TitleShown=true;
|
||||
}
|
||||
|
||||
wchar UnpSizeText[30],PackSizeText[30];
|
||||
if (hd.UnpSize==INT64NDF)
|
||||
wcscpy(UnpSizeText,L"?");
|
||||
else
|
||||
itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||
itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));
|
||||
|
||||
wchar AttrStr[30];
|
||||
if (hd.HeaderType==HEAD_SERVICE)
|
||||
swprintf(AttrStr,ASIZE(AttrStr),L"%cB",hd.Inherited ? 'I' : '.');
|
||||
else
|
||||
ListFileAttr(hd.FileAttr,hd.HSType,AttrStr,ASIZE(AttrStr));
|
||||
|
||||
wchar RatioStr[10];
|
||||
|
||||
if (hd.SplitBefore && hd.SplitAfter)
|
||||
wcscpy(RatioStr,L"<->");
|
||||
else
|
||||
if (hd.SplitBefore)
|
||||
wcscpy(RatioStr,L"<--");
|
||||
else
|
||||
if (hd.SplitAfter)
|
||||
wcscpy(RatioStr,L"-->");
|
||||
else
|
||||
swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));
|
||||
|
||||
wchar DateStr[50];
|
||||
hd.mtime.GetText(DateStr,ASIZE(DateStr),Technical);
|
||||
|
||||
if (Technical)
|
||||
{
|
||||
mprintf(L"\n%12s: %s",St(MListName),Name);
|
||||
|
||||
bool FileBlock=hd.HeaderType==HEAD_FILE;
|
||||
|
||||
if (!FileBlock && Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
|
||||
{
|
||||
mprintf(L"\n%12ls: %ls",St(MListType),St(MListStream));
|
||||
wchar StreamName[NM];
|
||||
GetStreamNameNTFS(Arc,StreamName,ASIZE(StreamName));
|
||||
mprintf(L"\n%12ls: %ls",St(MListTarget),StreamName);
|
||||
}
|
||||
else
|
||||
{
|
||||
const wchar *Type=St(FileBlock ? (hd.Dir ? MListDir:MListFile):MListService);
|
||||
|
||||
if (hd.RedirType!=FSREDIR_NONE)
|
||||
switch(hd.RedirType)
|
||||
{
|
||||
case FSREDIR_UNIXSYMLINK:
|
||||
Type=St(MListUSymlink); break;
|
||||
case FSREDIR_WINSYMLINK:
|
||||
Type=St(MListWSymlink); break;
|
||||
case FSREDIR_JUNCTION:
|
||||
Type=St(MListJunction); break;
|
||||
case FSREDIR_HARDLINK:
|
||||
Type=St(MListHardlink); break;
|
||||
case FSREDIR_FILECOPY:
|
||||
Type=St(MListCopy); break;
|
||||
}
|
||||
mprintf(L"\n%12ls: %ls",St(MListType),Type);
|
||||
if (hd.RedirType!=FSREDIR_NONE)
|
||||
if (Format==RARFMT15)
|
||||
{
|
||||
char LinkTargetA[NM];
|
||||
if (Arc.FileHead.Encrypted)
|
||||
{
|
||||
// Link data are encrypted. We would need to ask for password
|
||||
// and initialize decryption routine to display the link target.
|
||||
strncpyz(LinkTargetA,"*<-?->",ASIZE(LinkTargetA));
|
||||
}
|
||||
else
|
||||
{
|
||||
int DataSize=(int)Min(hd.PackSize,ASIZE(LinkTargetA)-1);
|
||||
Arc.Read(LinkTargetA,DataSize);
|
||||
LinkTargetA[DataSize > 0 ? DataSize : 0] = 0;
|
||||
}
|
||||
wchar LinkTarget[NM];
|
||||
CharToWide(LinkTargetA,LinkTarget,ASIZE(LinkTarget));
|
||||
mprintf(L"\n%12ls: %ls",St(MListTarget),LinkTarget);
|
||||
}
|
||||
else
|
||||
mprintf(L"\n%12ls: %ls",St(MListTarget),hd.RedirName);
|
||||
}
|
||||
if (!hd.Dir)
|
||||
{
|
||||
mprintf(L"\n%12ls: %ls",St(MListSize),UnpSizeText);
|
||||
mprintf(L"\n%12ls: %ls",St(MListPacked),PackSizeText);
|
||||
mprintf(L"\n%12ls: %ls",St(MListRatio),RatioStr);
|
||||
}
|
||||
if (hd.mtime.IsSet())
|
||||
mprintf(L"\n%12ls: %ls",St(MListMtime),DateStr);
|
||||
if (hd.ctime.IsSet())
|
||||
{
|
||||
hd.ctime.GetText(DateStr,ASIZE(DateStr),true);
|
||||
mprintf(L"\n%12ls: %ls",St(MListCtime),DateStr);
|
||||
}
|
||||
if (hd.atime.IsSet())
|
||||
{
|
||||
hd.atime.GetText(DateStr,ASIZE(DateStr),true);
|
||||
mprintf(L"\n%12ls: %ls",St(MListAtime),DateStr);
|
||||
}
|
||||
mprintf(L"\n%12ls: %ls",St(MListAttr),AttrStr);
|
||||
if (hd.FileHash.Type==HASH_CRC32)
|
||||
mprintf(L"\n%12ls: %8.8X",
|
||||
hd.UseHashKey ? L"CRC32 MAC":hd.SplitAfter ? L"Pack-CRC32":L"CRC32",
|
||||
hd.FileHash.CRC32);
|
||||
if (hd.FileHash.Type==HASH_BLAKE2)
|
||||
{
|
||||
wchar BlakeStr[BLAKE2_DIGEST_SIZE*2+1];
|
||||
BinToHex(hd.FileHash.Digest,BLAKE2_DIGEST_SIZE,NULL,BlakeStr,ASIZE(BlakeStr));
|
||||
mprintf(L"\n%12ls: %ls",
|
||||
hd.UseHashKey ? L"BLAKE2 MAC":hd.SplitAfter ? L"Pack-BLAKE2":L"BLAKE2",
|
||||
BlakeStr);
|
||||
}
|
||||
|
||||
const wchar *HostOS=L"";
|
||||
if (Format==RARFMT50 && hd.HSType!=HSYS_UNKNOWN)
|
||||
HostOS=hd.HSType==HSYS_WINDOWS ? L"Windows":L"Unix";
|
||||
if (Format==RARFMT15)
|
||||
{
|
||||
static const wchar *RarOS[]={
|
||||
L"DOS",L"OS/2",L"Windows",L"Unix",L"Mac OS",L"BeOS",L"WinCE",L"",L"",L""
|
||||
};
|
||||
if (hd.HostOS<ASIZE(RarOS))
|
||||
HostOS=RarOS[hd.HostOS];
|
||||
}
|
||||
if (*HostOS!=0)
|
||||
mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS);
|
||||
|
||||
mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo),
|
||||
Format==RARFMT15 ? L"3.0":L"5.0",hd.UnpVer,hd.Method,
|
||||
hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400,
|
||||
hd.WinSize>=0x100000 ? L"M":L"K");
|
||||
|
||||
if (hd.Solid || hd.Encrypted)
|
||||
{
|
||||
mprintf(L"\n%12ls: ",St(MListFlags));
|
||||
if (hd.Solid)
|
||||
mprintf(L"%ls ",St(MListSolid));
|
||||
if (hd.Encrypted)
|
||||
mprintf(L"%ls ",St(MListEnc));
|
||||
}
|
||||
|
||||
if (hd.Version)
|
||||
{
|
||||
uint Version=ParseVersionFileName(Name,false);
|
||||
if (Version!=0)
|
||||
mprintf(L"\n%12ls: %u",St(MListFileVer),Version);
|
||||
}
|
||||
|
||||
if (hd.UnixOwnerSet)
|
||||
{
|
||||
mprintf(L"\n%12ls: ",L"Unix owner");
|
||||
if (*hd.UnixOwnerName!=0)
|
||||
mprintf(L"%ls:",GetWide(hd.UnixOwnerName));
|
||||
if (*hd.UnixGroupName!=0)
|
||||
mprintf(L"%ls",GetWide(hd.UnixGroupName));
|
||||
if ((*hd.UnixOwnerName!=0 || *hd.UnixGroupName!=0) && (hd.UnixOwnerNumeric || hd.UnixGroupNumeric))
|
||||
mprintf(L" ");
|
||||
if (hd.UnixOwnerNumeric)
|
||||
mprintf(L"#%d:",hd.UnixOwnerID);
|
||||
if (hd.UnixGroupNumeric)
|
||||
mprintf(L"#%d:",hd.UnixGroupID);
|
||||
}
|
||||
|
||||
mprintf(L"\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mprintf(L"\n%c%10ls %9ls ",hd.Encrypted ? '*' : ' ',AttrStr,UnpSizeText);
|
||||
|
||||
if (Verbose)
|
||||
mprintf(L"%9ls %4ls ",PackSizeText,RatioStr);
|
||||
|
||||
mprintf(L" %ls ",DateStr);
|
||||
|
||||
if (Verbose)
|
||||
{
|
||||
if (hd.FileHash.Type==HASH_CRC32)
|
||||
mprintf(L"%8.8X ",hd.FileHash.CRC32);
|
||||
else
|
||||
if (hd.FileHash.Type==HASH_BLAKE2)
|
||||
{
|
||||
byte *S=hd.FileHash.Digest;
|
||||
mprintf(L"%02x%02x..%02x ",S[0],S[1],S[31]);
|
||||
}
|
||||
else
|
||||
mprintf(L"???????? ");
|
||||
}
|
||||
mprintf(L"%ls",Name);
|
||||
}
|
||||
|
||||
/*
|
||||
void ListSymLink(Archive &Arc)
|
||||
{
|
||||
if (Arc.FileHead.HSType==HSYS_UNIX && (Arc.FileHead.FileAttr & 0xF000)==0xA000)
|
||||
if (Arc.FileHead.Encrypted)
|
||||
{
|
||||
// Link data are encrypted. We would need to ask for password
|
||||
// and initialize decryption routine to display the link target.
|
||||
mprintf("\n%22s %s","-->","*<-?->");
|
||||
mprintf(L"\n%22ls %ls",L"-->",L"*<-?->");
|
||||
}
|
||||
else
|
||||
{
|
||||
char FileName[NM];
|
||||
uint DataSize=(uint)Min(Arc.FileHead.PackSize,sizeof(FileName)-1);
|
||||
Arc.Read(FileName,DataSize);
|
||||
FileName[DataSize]=0;
|
||||
mprintf(L"\n%22ls %ls",L"-->",GetWide(FileName));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void ListFileAttr(uint A,int HostOS)
|
||||
void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize)
|
||||
{
|
||||
switch(HostOS)
|
||||
switch(HostType)
|
||||
{
|
||||
case HOST_MSDOS:
|
||||
case HOST_OS2:
|
||||
case HOST_WIN32:
|
||||
case HOST_MACOS:
|
||||
mprintf(" %c%c%c%c%c%c%c ",
|
||||
(A & 0x08) ? 'V' : '.',
|
||||
(A & 0x10) ? 'D' : '.',
|
||||
(A & 0x01) ? 'R' : '.',
|
||||
(A & 0x02) ? 'H' : '.',
|
||||
(A & 0x04) ? 'S' : '.',
|
||||
(A & 0x20) ? 'A' : '.',
|
||||
(A & 0x800) ? 'C' : '.');
|
||||
case HSYS_WINDOWS:
|
||||
swprintf(AttrStr,AttrSize,L"%c%c%c%c%c%c%c",
|
||||
(A & 0x2000)!=0 ? 'I' : '.', // Not content indexed.
|
||||
(A & 0x0800)!=0 ? 'C' : '.', // Compressed.
|
||||
(A & 0x0020)!=0 ? 'A' : '.', // Archive.
|
||||
(A & 0x0010)!=0 ? 'D' : '.', // Directory.
|
||||
(A & 0x0004)!=0 ? 'S' : '.', // System.
|
||||
(A & 0x0002)!=0 ? 'H' : '.', // Hidden.
|
||||
(A & 0x0001)!=0 ? 'R' : '.'); // Read-only.
|
||||
break;
|
||||
case HOST_UNIX:
|
||||
case HOST_BEOS:
|
||||
case HSYS_UNIX:
|
||||
switch (A & 0xF000)
|
||||
{
|
||||
case 0x4000:
|
||||
mprintf("d");
|
||||
AttrStr[0]='d';
|
||||
break;
|
||||
case 0xA000:
|
||||
mprintf("l");
|
||||
AttrStr[0]='l';
|
||||
break;
|
||||
default:
|
||||
mprintf("-");
|
||||
AttrStr[0]='-';
|
||||
break;
|
||||
}
|
||||
mprintf("%c%c%c%c%c%c%c%c%c",
|
||||
swprintf(AttrStr+1,AttrSize-1,L"%c%c%c%c%c%c%c%c%c",
|
||||
(A & 0x0100) ? 'r' : '-',
|
||||
(A & 0x0080) ? 'w' : '-',
|
||||
(A & 0x0040) ? ((A & 0x0800) ? 's':'x'):((A & 0x0800) ? 'S':'-'),
|
||||
(A & 0x0040) ? ((A & 0x0800)!=0 ? 's':'x'):((A & 0x0800)!=0 ? 'S':'-'),
|
||||
(A & 0x0020) ? 'r' : '-',
|
||||
(A & 0x0010) ? 'w' : '-',
|
||||
(A & 0x0008) ? ((A & 0x0400) ? 's':'x'):((A & 0x0400) ? 'S':'-'),
|
||||
(A & 0x0008) ? ((A & 0x0400)!=0 ? 's':'x'):((A & 0x0400)!=0 ? 'S':'-'),
|
||||
(A & 0x0004) ? 'r' : '-',
|
||||
(A & 0x0002) ? 'w' : '-',
|
||||
(A & 0x0001) ? 'x' : '-');
|
||||
(A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-');
|
||||
break;
|
||||
case HSYS_UNKNOWN:
|
||||
wcscpy(AttrStr,L"?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void ListOldSubHeader(Archive &Arc)
|
||||
{
|
||||
switch(Arc.SubBlockHead.SubType)
|
||||
{
|
||||
case EA_HEAD:
|
||||
mprintf(St(MListEAHead));
|
||||
break;
|
||||
case UO_HEAD:
|
||||
mprintf(St(MListUOHead),Arc.UOHead.OwnerName,Arc.UOHead.GroupName);
|
||||
break;
|
||||
case MAC_HEAD:
|
||||
mprintf(St(MListMACHead1),Arc.MACHead.fileType>>24,Arc.MACHead.fileType>>16,Arc.MACHead.fileType>>8,Arc.MACHead.fileType);
|
||||
mprintf(St(MListMACHead2),Arc.MACHead.fileCreator>>24,Arc.MACHead.fileCreator>>16,Arc.MACHead.fileCreator>>8,Arc.MACHead.fileCreator);
|
||||
break;
|
||||
case BEEA_HEAD:
|
||||
mprintf(St(MListBeEAHead));
|
||||
break;
|
||||
case NTACL_HEAD:
|
||||
mprintf(St(MListNTACLHead));
|
||||
break;
|
||||
case STREAM_HEAD:
|
||||
mprintf(St(MListStrmHead),Arc.StreamHead.StreamName);
|
||||
break;
|
||||
default:
|
||||
mprintf(St(MListUnkHead),Arc.SubBlockHead.SubType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical)
|
||||
{
|
||||
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_CMT) &&
|
||||
(Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0 && !Cmd->DisableComment)
|
||||
{
|
||||
Array<byte> CmtData;
|
||||
size_t ReadSize=Arc.ReadCommentData(&CmtData,NULL);
|
||||
if (ReadSize!=0)
|
||||
{
|
||||
mprintf(St(MFileComment));
|
||||
OutComment((char *)&CmtData[0],ReadSize);
|
||||
}
|
||||
}
|
||||
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM) &&
|
||||
(Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0)
|
||||
{
|
||||
size_t DestSize=Arc.SubHead.SubData.Size()/2;
|
||||
wchar DestNameW[NM];
|
||||
char DestName[NM];
|
||||
if (DestSize<sizeof(DestName))
|
||||
{
|
||||
RawToWide(&Arc.SubHead.SubData[0],DestNameW,DestSize);
|
||||
DestNameW[DestSize]=0;
|
||||
WideToChar(DestNameW,DestName);
|
||||
mprintf("\n %s",DestName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,354 +1,381 @@
|
||||
#define MYesNo "_Yes_No"
|
||||
#define MYesNoAll "_Yes_No_All"
|
||||
#define MYesNoAllQ "_Yes_No_All_nEver_Quit"
|
||||
#define MYesNoAllRenQ "_Yes_No_All_nEver_Rename_Quit"
|
||||
#define MContinueQuit "_Continue_Quit"
|
||||
#define MRetryAbort "_Retry_Abort"
|
||||
#define MCopyright "\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d"
|
||||
#define MRegTo "\nRegistered to %s\n"
|
||||
#define MShare "\nShareware version Type RAR -? for help\n"
|
||||
#define MUCopyright "\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
|
||||
#define MBeta "beta"
|
||||
#define MMonthJan "Jan"
|
||||
#define MMonthFeb "Feb"
|
||||
#define MMonthMar "Mar"
|
||||
#define MMonthApr "Apr"
|
||||
#define MMonthMay "May"
|
||||
#define MMonthJun "Jun"
|
||||
#define MMonthJul "Jul"
|
||||
#define MMonthAug "Aug"
|
||||
#define MMonthSep "Sep"
|
||||
#define MMonthOct "Oct"
|
||||
#define MMonthNov "Nov"
|
||||
#define MMonthDec "Dec"
|
||||
#define MRARTitle1 "\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||
#define MUNRARTitle1 "\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||
#define MRARTitle2 "\n <@listfiles...> <path_to_extract\\>"
|
||||
#define MCHelpCmd "\n\n<Commands>"
|
||||
#define MCHelpCmdA "\n a Add files to archive"
|
||||
#define MCHelpCmdC "\n c Add archive comment"
|
||||
#define MCHelpCmdCF "\n cf Add files comment"
|
||||
#define MCHelpCmdCH "\n ch Change archive parameters"
|
||||
#define MCHelpCmdCW "\n cw Write archive comment to file"
|
||||
#define MCHelpCmdD "\n d Delete files from archive"
|
||||
#define MCHelpCmdE "\n e Extract files to current directory"
|
||||
#define MCHelpCmdF "\n f Freshen files in archive"
|
||||
#define MCHelpCmdI "\n i[par]=<str> Find string in archives"
|
||||
#define MCHelpCmdK "\n k Lock archive"
|
||||
#define MCHelpCmdL "\n l[t,b] List archive [technical, bare]"
|
||||
#define MCHelpCmdM "\n m[f] Move to archive [files only]"
|
||||
#define MCHelpCmdP "\n p Print file to stdout"
|
||||
#define MCHelpCmdR "\n r Repair archive"
|
||||
#define MCHelpCmdRC "\n rc Reconstruct missing volumes"
|
||||
#define MCHelpCmdRN "\n rn Rename archived files"
|
||||
#define MCHelpCmdRR "\n rr[N] Add data recovery record"
|
||||
#define MCHelpCmdRV "\n rv[N] Create recovery volumes"
|
||||
#define MCHelpCmdS "\n s[name|-] Convert archive to or from SFX"
|
||||
#define MCHelpCmdT "\n t Test archive files"
|
||||
#define MCHelpCmdU "\n u Update files in archive"
|
||||
#define MCHelpCmdV "\n v[t,b] Verbosely list archive [technical,bare]"
|
||||
#define MCHelpCmdX "\n x Extract files with full path"
|
||||
#define MCHelpSw "\n\n<Switches>"
|
||||
#define MCHelpSwm "\n - Stop switches scanning"
|
||||
#define MCHelpSwAC "\n ac Clear Archive attribute after compression or extraction"
|
||||
#define MCHelpSwAD "\n ad Append archive name to destination path"
|
||||
#define MCHelpSwAG "\n ag[format] Generate archive name using the current date"
|
||||
#define MCHelpSwAI "\n ai Ignore file attributes"
|
||||
#define MCHelpSwAO "\n ao Add files with Archive attribute set"
|
||||
#define MCHelpSwAP "\n ap<path> Set path inside archive"
|
||||
#define MCHelpSwAS "\n as Synchronize archive contents"
|
||||
#define MCHelpSwAV "\n av Put authenticity verification (registered versions only)"
|
||||
#define MCHelpSwAVm "\n av- Disable authenticity verification check"
|
||||
#define MCHelpSwCm "\n c- Disable comments show"
|
||||
#define MCHelpSwCFGm "\n cfg- Disable read configuration"
|
||||
#define MCHelpSwCL "\n cl Convert names to lower case"
|
||||
#define MCHelpSwCU "\n cu Convert names to upper case"
|
||||
#define MCHelpSwDF "\n df Delete files after archiving"
|
||||
#define MCHelpSwDH "\n dh Open shared files"
|
||||
#define MCHelpSwDR "\n dr Delete files to Recycle Bin"
|
||||
#define MCHelpSwDS "\n ds Disable name sort for solid archive"
|
||||
#define MCHelpSwDW "\n dw Wipe files after archiving"
|
||||
#define MCHelpSwEa "\n e[+]<attr> Set file exclude and include attributes"
|
||||
#define MCHelpSwED "\n ed Do not add empty directories"
|
||||
#define MCHelpSwEE "\n ee Do not save and extract extended attributes"
|
||||
#define MCHelpSwEN "\n en Do not put 'end of archive' block"
|
||||
#define MCHelpSwEP "\n ep Exclude paths from names"
|
||||
#define MCHelpSwEP1 "\n ep1 Exclude base directory from names"
|
||||
#define MCHelpSwEP2 "\n ep2 Expand paths to full"
|
||||
#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter"
|
||||
#define MCHelpSwF "\n f Freshen files"
|
||||
#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers"
|
||||
#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages"
|
||||
#define MCHelpSwIEML "\n ieml[addr] Send archive by email"
|
||||
#define MCHelpSwIERR "\n ierr Send all messages to stderr"
|
||||
#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)"
|
||||
#define MCHelpSwINUL "\n inul Disable all messages"
|
||||
#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation"
|
||||
#define MCHelpSwISND "\n isnd Enable sound"
|
||||
#define MCHelpSwK "\n k Lock archive"
|
||||
#define MCHelpSwKB "\n kb Keep broken extracted files"
|
||||
#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)"
|
||||
#define MCHelpSwMC "\n mc<par> Set advanced compression parameters"
|
||||
#define MCHelpSwMD "\n md<size> Dictionary size in KB (64,128,256,512,1024,2048,4096 or A-G)"
|
||||
#define MCHelpSwMS "\n ms[ext;ext] Specify file types to store"
|
||||
#define MCHelpSwMT "\n mt<threads> Set the number of threads"
|
||||
#define MCHelpSwN "\n n<file> Include only specified file"
|
||||
#define MCHelpSwNa "\n n@ Read file names to include from stdin"
|
||||
#define MCHelpSwNal "\n n@<list> Include files listed in specified list file"
|
||||
#define MCHelpSwO "\n o[+|-] Set the overwrite mode"
|
||||
#define MCHelpSwOC "\n oc Set NTFS Compressed attribute"
|
||||
#define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file"
|
||||
#define MCHelpSwOR "\n or Rename files automatically"
|
||||
#define MCHelpSwOS "\n os Save NTFS streams"
|
||||
#define MCHelpSwOW "\n ow Save or restore file owner and group"
|
||||
#define MCHelpSwP "\n p[password] Set password"
|
||||
#define MCHelpSwPm "\n p- Do not query password"
|
||||
#define MCHelpSwR "\n r Recurse subdirectories"
|
||||
#define MCHelpSwRm "\n r- Disable recursion"
|
||||
#define MCHelpSwR0 "\n r0 Recurse subdirectories for wildcard names only"
|
||||
#define MCHelpSwRI "\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms"
|
||||
#define MCHelpSwRR "\n rr[N] Add data recovery record"
|
||||
#define MCHelpSwRV "\n rv[N] Create recovery volumes"
|
||||
#define MCHelpSwS "\n s[<N>,v[-],e] Create solid archive"
|
||||
#define MCHelpSwSm "\n s- Disable solid archiving"
|
||||
#define MCHelpSwSC "\n sc<chr>[obj] Specify the character set"
|
||||
#define MCHelpSwSFX "\n sfx[name] Create SFX archive"
|
||||
#define MCHelpSwSI "\n si[name] Read data from standard input (stdin)"
|
||||
#define MCHelpSwSL "\n sl<size> Process files with size less than specified"
|
||||
#define MCHelpSwSM "\n sm<size> Process files with size more than specified"
|
||||
#define MCHelpSwT "\n t Test files after archiving"
|
||||
#define MCHelpSwTK "\n tk Keep original archive time"
|
||||
#define MCHelpSwTL "\n tl Set archive time to latest file"
|
||||
#define MCHelpSwTN "\n tn<time> Process files newer than <time>"
|
||||
#define MCHelpSwTO "\n to<time> Process files older than <time>"
|
||||
#define MCHelpSwTA "\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTB "\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTS "\n ts<m,c,a>[N] Save or restore file time (modification, creation, access)"
|
||||
#define MCHelpSwU "\n u Update files"
|
||||
#define MCHelpSwV "\n v Create volumes with size autodetection or list all volumes"
|
||||
#define MCHelpSwVUnr "\n v List all volumes"
|
||||
#define MCHelpSwVn "\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]"
|
||||
#define MCHelpSwVD "\n vd Erase disk contents before creating volume"
|
||||
#define MCHelpSwVER "\n ver[n] File version control"
|
||||
#define MCHelpSwVN "\n vn Use the old style volume naming scheme"
|
||||
#define MCHelpSwVP "\n vp Pause before each volume"
|
||||
#define MCHelpSwW "\n w<path> Assign work directory"
|
||||
#define MCHelpSwX "\n x<file> Exclude specified file"
|
||||
#define MCHelpSwXa "\n x@ Read file names to exclude from stdin"
|
||||
#define MCHelpSwXal "\n x@<list> Exclude files listed in specified list file"
|
||||
#define MCHelpSwY "\n y Assume Yes on all queries"
|
||||
#define MCHelpSwZ "\n z[file] Read archive comment from file"
|
||||
#define MBadArc "\nERROR: Bad archive %s\n"
|
||||
#define MAskPsw "Enter password (will not be echoed)"
|
||||
#define MAskPswEcho "Enter password"
|
||||
#define MReAskPsw "\nReenter password: "
|
||||
#define MFor " for "
|
||||
#define MNotMatchPsw "\nERROR: Passwords do not match\n"
|
||||
#define MErrWrite "Write error in the file %s"
|
||||
#define MErrRead "Read error in the file %s"
|
||||
#define MErrSeek "Seek error in the file %s"
|
||||
#define MErrFClose "Cannot close the file %s"
|
||||
#define MErrOutMem "Not enough memory"
|
||||
#define MErrBrokenArc "Corrupt archive - use 'Repair' command"
|
||||
#define MProgAborted "Program aborted"
|
||||
#define MErrRename "\nCannot rename %s to %s"
|
||||
#define MAbsNextVol "\nCannot find volume %s"
|
||||
#define MBreak "\nUser break\n"
|
||||
#define MAskCreatVol "\nCreate next volume ?"
|
||||
#define MAskNextDisk "\nDisk full. Insert next"
|
||||
#define MCreatVol "\n\nCreating %sarchive %s\n"
|
||||
#define MAskNextVol "\nInsert disk with %s"
|
||||
#define MTestVol "\n\nTesting archive %s\n"
|
||||
#define MExtrVol "\n\nExtracting from %s\n"
|
||||
#define MConverting "\nConverting %s"
|
||||
#define MCvtToSFX "\nConvert archives to SFX"
|
||||
#define MCvtFromSFX "\nRemoving SFX module"
|
||||
#define MNotSFX "\n%s is not SFX archive"
|
||||
#define MNotRAR "\n%s is not RAR archive"
|
||||
#define MNotFirstVol "\n%s is not the first volume"
|
||||
#define MCvtOldFormat "\n%s - cannot convert to SFX archive with old format"
|
||||
#define MCannotCreate "\nCannot create %s"
|
||||
#define MCannotOpen "\nCannot open %s"
|
||||
#define MUnknownMeth "\nUnknown method in %s"
|
||||
#define MVerRequired "\nYou need RAR %d.%d to unpack it"
|
||||
#define MOk " OK"
|
||||
#define MDone "\nDone"
|
||||
#define MLockingArc "\nLocking archive"
|
||||
#define MNotMdfOld "\n\nERROR: Cannot modify old format archive"
|
||||
#define MNotMdfLock "\n\nERROR: Locked archive"
|
||||
#define MNotMdfVol "\n\nERROR: Cannot modify volume"
|
||||
#define MVerifyAV "\nVerifying authenticity information ... "
|
||||
#define MFailedAV " Failed\n"
|
||||
#define MStrAV1 "\n\nArchive %s"
|
||||
#define MStrAV2 "\ncreated at %s"
|
||||
#define MStrAV3 "\nby %s\n"
|
||||
#define MLogFailedAV "Invalid authenticity information"
|
||||
#define MAddingAV "\nAdding authenticity verification "
|
||||
#define MAVOldStyle "\n\nOld style authenticity information"
|
||||
#define MPackAskReg "\nEvaluation copy. Please register.\n"
|
||||
#define MCreateArchive "\nCreating %sarchive %s\n"
|
||||
#define MUpdateArchive "\nUpdating %sarchive %s\n"
|
||||
#define MAddSolid "solid "
|
||||
#define MAddFile "\nAdding %-58s "
|
||||
#define MUpdFile "\nUpdating %-58s "
|
||||
#define MAddPoints "\n... %-58s "
|
||||
#define MCannotUpdPswSolid "\nERROR: Cannot update solid archives with password\n"
|
||||
#define MMoveDelFiles "\n\nDeleting files %s..."
|
||||
#define MMoveDelDirs "and directories"
|
||||
#define MMoveDelFile "\nDeleting %-30s"
|
||||
#define MMoveDeleted " deleted"
|
||||
#define MMoveNotDeleted " NOT DELETED"
|
||||
#define MClearAttrib "\n\nClearing attributes..."
|
||||
#define MMoveDelDir "\nDeleting directory %-30s"
|
||||
#define MWarErrFOpen "\nWARNING: Cannot open %d %s"
|
||||
#define MErrOpenFiles "files"
|
||||
#define MErrOpenFile "file"
|
||||
#define MAddNoFiles "\nWARNING: No files"
|
||||
#define MMdfEncrSol "\n%s: encrypted"
|
||||
#define MCannotMdfEncrSol "\nCannot modify solid archive containing encrypted files"
|
||||
#define MAddAnalyze "\nAnalyzing archived files: "
|
||||
#define MRepacking "\nRepacking archived files: "
|
||||
#define MCRCFailed "\n%-20s - CRC failed"
|
||||
#define MExtrTest "\n\nTesting archive %s\n"
|
||||
#define MExtracting "\n\nExtracting from %s\n"
|
||||
#define MUseCurPsw "\n%s - use current password ?"
|
||||
#define MCreatDir "\nCreating %-56s"
|
||||
#define MExtrSkipFile "\nSkipping %-56s"
|
||||
#define MExtrTestFile "\nTesting %-56s"
|
||||
#define MExtrFile "\nExtracting %-56s"
|
||||
#define MExtrPoints "\n... %-56s"
|
||||
#define MExtrErrMkDir "\nCannot create directory %s"
|
||||
#define MExtrPrinting "\n------ Printing %s\n\n"
|
||||
#define MEncrBadCRC "\nCRC failed in the encrypted file %s. Corrupt file or wrong password."
|
||||
#define MExtrNoFiles "\nNo files to extract"
|
||||
#define MExtrAllOk "\nAll OK"
|
||||
#define MExtrTotalErr "\nTotal errors: %ld"
|
||||
#define MFileExists "\n\n%s already exists. Overwrite it ?"
|
||||
#define MAskOverwrite "\nOverwrite %s ?"
|
||||
#define MAskNewName "\nEnter new name: "
|
||||
#define MLogMainHead "\nThe archive header is corrupt"
|
||||
#define MLogFileHead "\n%s - the file header is corrupt"
|
||||
#define MLogCommHead "\nThe comment header is corrupt\n"
|
||||
#define MLogProtectHead "The data recovery header is corrupt"
|
||||
#define MReadStdinCmt "\nReading comment from stdin\n"
|
||||
#define MReadCommFrom "\nReading comment from %s"
|
||||
#define MDelComment "\nDeleting comment from %s"
|
||||
#define MAddComment "\nAdding comment to %s"
|
||||
#define MFCommAdd "\nAdding file comments"
|
||||
#define MAskFComm "\n\nReading comment for %s : %s from stdin\n"
|
||||
#define MLogCommBrk "\nThe archive comment is corrupt"
|
||||
#define MCommAskCont "\nPress 'Enter' to continue or 'Q' to quit:"
|
||||
#define MLogBrokFCmt "\nThe file comment is corrupt"
|
||||
#define MWriteCommTo "\nWrite comment to %s"
|
||||
#define MCommNotPres "\nComment is not present"
|
||||
#define MDelFrom "\nDeleting from %s"
|
||||
#define MDeleting "\nDeleting %s"
|
||||
#define MEraseArc "\nErasing empty archive %s"
|
||||
#define MNoDelFiles "\nNo files to delete"
|
||||
#define MLogTitle "\n\n-------- %2d %s %d, archive %s\n"
|
||||
#define MPathTooLong "\nERROR: Path too long\n"
|
||||
#define MListSolid "Solid "
|
||||
#define MListSFX "SFX "
|
||||
#define MListVol1 "volume"
|
||||
#define MListVol2 "Volume"
|
||||
#define MListArc1 "archive"
|
||||
#define MListArc2 "Archive"
|
||||
#define MListRecRec "\nRecovery record is present\n"
|
||||
#define MListLock "\nLock is present\n"
|
||||
#define MListPathComm "\nPathname/Comment\n "
|
||||
#define MListName "\n Name "
|
||||
#define MListTitle " Size Packed Ratio Date Time Attr CRC Meth Ver\n"
|
||||
#define MListTechTitle " Host OS Solid Old\n"
|
||||
#define MListEAHead "\n OS/2 extended attributes"
|
||||
#define MListUOHead "\n Unix Owner/Group data: %-14s %-14s"
|
||||
#define MListBeEAHead "\n BeOS extended attributes"
|
||||
#define MListNTACLHead "\n NTFS security data"
|
||||
#define MListStrmHead "\n NTFS stream: %s"
|
||||
#define MListUnkHead "\n Unknown subheader type: 0x%04x"
|
||||
#define MFileComment "\nComment: "
|
||||
#define MYes "Yes"
|
||||
#define MNo "No"
|
||||
#define MListNoFiles " 0 files\n"
|
||||
#define MRprReconstr "\nReconstructing %s"
|
||||
#define MRprBuild "\nBuilding %s"
|
||||
#define MRprOldFormat "\nCannot repair archive with old format"
|
||||
#define MRprFind "\nFound %s"
|
||||
#define MRprAskIsSol "\nThe archive header is corrupt. Mark archive as solid ?"
|
||||
#define MRprNoFiles "\nNo files found"
|
||||
#define MRprSuspEntry "\n\nSuspicious entry %s"
|
||||
#define MRprDir "\nDirectory"
|
||||
#define MRprSuspSize "\nSize %ld Packed %ld"
|
||||
#define MRprSuspAdd "\nAdd it to archive ?"
|
||||
#define MLogUnexpEOF "\nUnexpected end of archive"
|
||||
#define MRepAskReconst "\nReconstruct archive structure ?"
|
||||
#define MRecScanning "\nScanning..."
|
||||
#define MRecRNotFound "\nData recovery record not found"
|
||||
#define MRecRFound "\nData recovery record found"
|
||||
#define MRecSecDamage "\nSector %ld (offsets %lX...%lX) damaged"
|
||||
#define MRecCorrected " - data recovered"
|
||||
#define MRecFailed " - cannot recover data"
|
||||
#define MAddRecRec "\nAdding data recovery record"
|
||||
#define MEraseForVolume "\n\nErasing contents of drive %c:\n"
|
||||
#define MGetOwnersError "\nWARNING: Cannot get %s owner and group\n"
|
||||
#define MErrGetOwnerID "\nWARNING: Cannot get owner %s ID\n"
|
||||
#define MErrGetGroupID "\nWARNING: Cannot get group %s ID\n"
|
||||
#define MOwnersBroken "\nERROR: %s group and owner data are corrupt\n"
|
||||
#define MSetOwnersError "\nWARNING: Cannot set %s owner and group\n"
|
||||
#define MErrLnkRead "\nWARNING: Cannot read symbolic link %s"
|
||||
#define MErrCreateLnk "\nWARNING: Cannot create link %s"
|
||||
#define MSymLinkExists "\nWARNING: Symbolic link %s already exists"
|
||||
#define MAskRetryCreate "\nCannot create %s. Retry ?"
|
||||
#define MListMACHead1 "\n Mac OS file type: %c%c%c%c ; "
|
||||
#define MListMACHead2 "file creator: %c%c%c%c\n"
|
||||
#define MDataBadCRC "\n%-20s : packed data CRC failed in volume %s"
|
||||
#define MFileRO "\n%s is read-only"
|
||||
#define MACLGetError "\nWARNING: Cannot get %s security data\n"
|
||||
#define MACLSetError "\nWARNING: Cannot set %s security data\n"
|
||||
#define MACLBroken "\nERROR: %s security data are corrupt\n"
|
||||
#define MACLUnknown "\nWARNING: Unknown format of %s security data\n"
|
||||
#define MStreamBroken "\nERROR: %s stream data are corrupt\n"
|
||||
#define MStreamUnknown "\nWARNING: Unknown format of %s stream data\n"
|
||||
#define MInvalidName "\nERROR: Invalid file name %s"
|
||||
#define MEABroken "\nERROR: %s extended attributes are corrupt\n"
|
||||
#define MEAUnknHeader "\nWARNING: %s - unknown format of extended attributes\n"
|
||||
#define MCannotSetEA "\nWARNING: cannot set extended attributes to %s\n"
|
||||
#define MCannotGetEA "\nERROR: Cannot get extended attributes of %s\n"
|
||||
#define MShowEA " (+EA)"
|
||||
#define MSkipEA "\n...skipping extended attributes"
|
||||
#define MProcessArc "\n\nProcessing archive %s"
|
||||
#define MSyncScanError "\nFile search errors, cannot synchronize archive"
|
||||
#define MCorrectingName "\nWARNING: Attempting to correct the invalid file name"
|
||||
#define MUnpCannotMerge "\nWARNING: You need to start extraction from a previous volume to unpack %s"
|
||||
#define MUnknownOption "\nERROR: Unknown option: %s"
|
||||
#define MSubHeadCorrupt "\nERROR: Corrupt data header found, ignored"
|
||||
#define MSubHeadUnknown "\nWARNING: Unknown data header format, ignored"
|
||||
#define MSubHeadDataCRC "\nERROR: Corrupt %s data block"
|
||||
#define MSubHeadType "\nData header type: %s"
|
||||
#define MScanError "\nCannot read contents of %s"
|
||||
#define MNotVolume "\n%s is not volume"
|
||||
#define MRecVolDiffSets "\nERROR: %s and %s belong to different sets"
|
||||
#define MRecVolMissing "\n%d volumes missing"
|
||||
#define MRecVolFound "\n%d recovery volumes found"
|
||||
#define MRecVolAllExist "\nNothing to reconstruct"
|
||||
#define MRecVolCannotFix "\nReconstruction impossible"
|
||||
#define MReconstructing "\nReconstructing..."
|
||||
#define MCreating "\nCreating %s"
|
||||
#define MRenaming "\nRenaming %s to %s"
|
||||
#define MNTFSRequired "\nWrite error: only NTFS file system supports files larger than 4 GB"
|
||||
#define MErrChangeAttr "\nWARNING: Cannot change attributes of %s"
|
||||
#define MWrongSFXVer "\nERROR: default SFX module does not support RAR %d.%d archives"
|
||||
#define MCannotEncName "\nCannot encrypt archive already contained encrypted files"
|
||||
#define MCannotEmail "\nCannot email the file %s"
|
||||
#define MCopyrightS "\nRAR SFX archive"
|
||||
#define MSHelpCmd "\n\n<Commands>"
|
||||
#define MSHelpCmdE "\n -x Extract from archive (default)"
|
||||
#define MSHelpCmdT "\n -t Test archive files"
|
||||
#define MSHelpCmdV "\n -v Verbosely list contents of archive"
|
||||
#define MMaxPathLimit "\nTotal path and file name length must not exceed %d characters"
|
||||
#define MRecVolLimit "\nTotal number of usual and recovery volumes must not exceed 255"
|
||||
#define MVolumeNumber "volume %d"
|
||||
#define MCannotDelete "\nCannot delete %s"
|
||||
#define MCalcCRC "\nCalculating the control sum"
|
||||
#define MTooLargeSFXArc "\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB."
|
||||
#define MCalcCRCAllVol "\nCalculating control sums of all volumes."
|
||||
#define MNotEnoughDisk "\nERROR: Not enough disk space for %s."
|
||||
#define MYesNo L"_Yes_No"
|
||||
#define MYesNoAll L"_Yes_No_All"
|
||||
#define MYesNoAllQ L"_Yes_No_All_nEver_Quit"
|
||||
#define MYesNoAllRenQ L"_Yes_No_All_nEver_Rename_Quit"
|
||||
#define MContinueQuit L"_Continue_Quit"
|
||||
#define MRetryAbort L"_Retry_Abort"
|
||||
#define MCopyright L"\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d"
|
||||
#define MRegTo L"\nRegistered to %s\n"
|
||||
#define MShare L"\nTrial version Type 'rar -?' for help\n"
|
||||
#define MRegKeyWarning L"\nAvailable license key is valid only for %s\n"
|
||||
#define MUCopyright L"\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
|
||||
#define MBeta L"beta"
|
||||
#define Mx86 L"x86"
|
||||
#define Mx64 L"x64"
|
||||
#define MMonthJan L"Jan"
|
||||
#define MMonthFeb L"Feb"
|
||||
#define MMonthMar L"Mar"
|
||||
#define MMonthApr L"Apr"
|
||||
#define MMonthMay L"May"
|
||||
#define MMonthJun L"Jun"
|
||||
#define MMonthJul L"Jul"
|
||||
#define MMonthAug L"Aug"
|
||||
#define MMonthSep L"Sep"
|
||||
#define MMonthOct L"Oct"
|
||||
#define MMonthNov L"Nov"
|
||||
#define MMonthDec L"Dec"
|
||||
#define MRARTitle1 L"\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||
#define MUNRARTitle1 L"\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||
#define MRARTitle2 L"\n <@listfiles...> <path_to_extract\\>"
|
||||
#define MCHelpCmd L"\n\n<Commands>"
|
||||
#define MCHelpCmdA L"\n a Add files to archive"
|
||||
#define MCHelpCmdC L"\n c Add archive comment"
|
||||
#define MCHelpCmdCH L"\n ch Change archive parameters"
|
||||
#define MCHelpCmdCW L"\n cw Write archive comment to file"
|
||||
#define MCHelpCmdD L"\n d Delete files from archive"
|
||||
#define MCHelpCmdE L"\n e Extract files without archived paths"
|
||||
#define MCHelpCmdF L"\n f Freshen files in archive"
|
||||
#define MCHelpCmdI L"\n i[par]=<str> Find string in archives"
|
||||
#define MCHelpCmdK L"\n k Lock archive"
|
||||
#define MCHelpCmdL L"\n l[t[a],b] List archive contents [technical[all], bare]"
|
||||
#define MCHelpCmdM L"\n m[f] Move to archive [files only]"
|
||||
#define MCHelpCmdP L"\n p Print file to stdout"
|
||||
#define MCHelpCmdR L"\n r Repair archive"
|
||||
#define MCHelpCmdRC L"\n rc Reconstruct missing volumes"
|
||||
#define MCHelpCmdRN L"\n rn Rename archived files"
|
||||
#define MCHelpCmdRR L"\n rr[N] Add data recovery record"
|
||||
#define MCHelpCmdRV L"\n rv[N] Create recovery volumes"
|
||||
#define MCHelpCmdS L"\n s[name|-] Convert archive to or from SFX"
|
||||
#define MCHelpCmdT L"\n t Test archive files"
|
||||
#define MCHelpCmdU L"\n u Update files in archive"
|
||||
#define MCHelpCmdV L"\n v[t[a],b] Verbosely list archive contents [technical[all],bare]"
|
||||
#define MCHelpCmdX L"\n x Extract files with full path"
|
||||
#define MCHelpSw L"\n\n<Switches>"
|
||||
#define MCHelpSwm L"\n - Stop switches scanning"
|
||||
#define MCHelpSwAT L"\n @[+] Disable [enable] file lists"
|
||||
#define MCHelpSwAC L"\n ac Clear Archive attribute after compression or extraction"
|
||||
#define MCHelpSwAD L"\n ad Append archive name to destination path"
|
||||
#define MCHelpSwAG L"\n ag[format] Generate archive name using the current date"
|
||||
#define MCHelpSwAI L"\n ai Ignore file attributes"
|
||||
#define MCHelpSwAO L"\n ao Add files with Archive attribute set"
|
||||
#define MCHelpSwAP L"\n ap<path> Set path inside archive"
|
||||
#define MCHelpSwAS L"\n as Synchronize archive contents"
|
||||
#define MCHelpSwCm L"\n c- Disable comments show"
|
||||
#define MCHelpSwCFGm L"\n cfg- Disable read configuration"
|
||||
#define MCHelpSwCL L"\n cl Convert names to lower case"
|
||||
#define MCHelpSwCU L"\n cu Convert names to upper case"
|
||||
#define MCHelpSwDF L"\n df Delete files after archiving"
|
||||
#define MCHelpSwDH L"\n dh Open shared files"
|
||||
#define MCHelpSwDR L"\n dr Delete files to Recycle Bin"
|
||||
#define MCHelpSwDS L"\n ds Disable name sort for solid archive"
|
||||
#define MCHelpSwDW L"\n dw Wipe files after archiving"
|
||||
#define MCHelpSwEa L"\n e[+]<attr> Set file exclude and include attributes"
|
||||
#define MCHelpSwED L"\n ed Do not add empty directories"
|
||||
#define MCHelpSwEN L"\n en Do not put 'end of archive' block"
|
||||
#define MCHelpSwEP L"\n ep Exclude paths from names"
|
||||
#define MCHelpSwEP1 L"\n ep1 Exclude base directory from names"
|
||||
#define MCHelpSwEP2 L"\n ep2 Expand paths to full"
|
||||
#define MCHelpSwEP3 L"\n ep3 Expand paths to full including the drive letter"
|
||||
#define MCHelpSwF L"\n f Freshen files"
|
||||
#define MCHelpSwHP L"\n hp[password] Encrypt both file data and headers"
|
||||
#define MCHelpSwHT L"\n ht[b|c] Select hash type [BLAKE2,CRC32] for file checksum"
|
||||
#define MCHelpSwIDP L"\n id[c,d,p,q] Disable messages"
|
||||
#define MCHelpSwIEML L"\n ieml[addr] Send archive by email"
|
||||
#define MCHelpSwIERR L"\n ierr Send all messages to stderr"
|
||||
#define MCHelpSwILOG L"\n ilog[name] Log errors to file (registered versions only)"
|
||||
#define MCHelpSwINUL L"\n inul Disable all messages"
|
||||
#define MCHelpSwIOFF L"\n ioff Turn PC off after completing an operation"
|
||||
#define MCHelpSwISND L"\n isnd Enable sound"
|
||||
#define MCHelpSwIVER L"\n iver Display the version number"
|
||||
#define MCHelpSwK L"\n k Lock archive"
|
||||
#define MCHelpSwKB L"\n kb Keep broken extracted files"
|
||||
#define MCHelpSwLog L"\n log[f][=name] Write names to log file"
|
||||
#define MCHelpSwMn L"\n m<0..5> Set compression level (0-store...3-default...5-maximal)"
|
||||
#define MCHelpSwMA L"\n ma[4|5] Specify a version of archiving format"
|
||||
#define MCHelpSwMC L"\n mc<par> Set advanced compression parameters"
|
||||
#define MCHelpSwMD L"\n md<n>[k,m,g] Dictionary size in KB, MB or GB"
|
||||
#define MCHelpSwMS L"\n ms[ext;ext] Specify file types to store"
|
||||
#define MCHelpSwMT L"\n mt<threads> Set the number of threads"
|
||||
#define MCHelpSwN L"\n n<file> Additionally filter included files"
|
||||
#define MCHelpSwNa L"\n n@ Read additional filter masks from stdin"
|
||||
#define MCHelpSwNal L"\n n@<list> Read additional filter masks from list file"
|
||||
#define MCHelpSwO L"\n o[+|-] Set the overwrite mode"
|
||||
#define MCHelpSwOC L"\n oc Set NTFS Compressed attribute"
|
||||
#define MCHelpSwOH L"\n oh Save hard links as the link instead of the file"
|
||||
#define MCHelpSwOI L"\n oi[0-4][:min] Save identical files as references"
|
||||
#define MCHelpSwOL L"\n ol[a] Process symbolic links as the link [absolute paths]"
|
||||
#define MCHelpSwONI L"\n oni Allow potentially incompatible names"
|
||||
#define MCHelpSwOR L"\n or Rename files automatically"
|
||||
#define MCHelpSwOS L"\n os Save NTFS streams"
|
||||
#define MCHelpSwOW L"\n ow Save or restore file owner and group"
|
||||
#define MCHelpSwP L"\n p[password] Set password"
|
||||
#define MCHelpSwPm L"\n p- Do not query password"
|
||||
#define MCHelpSwQO L"\n qo[-|+] Add quick open information [none|force]"
|
||||
#define MCHelpSwR L"\n r Recurse subdirectories"
|
||||
#define MCHelpSwRm L"\n r- Disable recursion"
|
||||
#define MCHelpSwR0 L"\n r0 Recurse subdirectories for wildcard names only"
|
||||
#define MCHelpSwRI L"\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms"
|
||||
#define MCHelpSwRR L"\n rr[N] Add data recovery record"
|
||||
#define MCHelpSwRV L"\n rv[N] Create recovery volumes"
|
||||
#define MCHelpSwS L"\n s[<N>,v[-],e] Create solid archive"
|
||||
#define MCHelpSwSm L"\n s- Disable solid archiving"
|
||||
#define MCHelpSwSC L"\n sc<chr>[obj] Specify the character set"
|
||||
#define MCHelpSwSFX L"\n sfx[name] Create SFX archive"
|
||||
#define MCHelpSwSI L"\n si[name] Read data from standard input (stdin)"
|
||||
#define MCHelpSwSL L"\n sl<size> Process files with size less than specified"
|
||||
#define MCHelpSwSM L"\n sm<size> Process files with size more than specified"
|
||||
#define MCHelpSwT L"\n t Test files after archiving"
|
||||
#define MCHelpSwTK L"\n tk Keep original archive time"
|
||||
#define MCHelpSwTL L"\n tl Set archive time to latest file"
|
||||
#define MCHelpSwTN L"\n tn<time> Process files newer than <time>"
|
||||
#define MCHelpSwTO L"\n to<time> Process files older than <time>"
|
||||
#define MCHelpSwTA L"\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTB L"\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTS L"\n ts[m|c|a] Save or restore file time (modification, creation, access)"
|
||||
#define MCHelpSwU L"\n u Update files"
|
||||
#define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes"
|
||||
#define MCHelpSwVUnr L"\n v List all volumes"
|
||||
#define MCHelpSwVn L"\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]"
|
||||
#define MCHelpSwVD L"\n vd Erase disk contents before creating volume"
|
||||
#define MCHelpSwVER L"\n ver[n] File version control"
|
||||
#define MCHelpSwVN L"\n vn Use the old style volume naming scheme"
|
||||
#define MCHelpSwVP L"\n vp Pause before each volume"
|
||||
#define MCHelpSwW L"\n w<path> Assign work directory"
|
||||
#define MCHelpSwX L"\n x<file> Exclude specified file"
|
||||
#define MCHelpSwXa L"\n x@ Read file names to exclude from stdin"
|
||||
#define MCHelpSwXal L"\n x@<list> Exclude files listed in specified list file"
|
||||
#define MCHelpSwY L"\n y Assume Yes on all queries"
|
||||
#define MCHelpSwZ L"\n z[file] Read archive comment from file"
|
||||
#define MBadArc L"\nERROR: Bad archive %s\n"
|
||||
#define MAskPsw L"Enter password (will not be echoed)"
|
||||
#define MAskPswFor L"\nEnter password (will not be echoed) for %s: "
|
||||
#define MReAskPsw L"\nReenter password: "
|
||||
#define MNotMatchPsw L"\nERROR: Passwords do not match\n"
|
||||
#define MErrWrite L"Write error in the file %s"
|
||||
#define MErrRead L"Read error in the file %s"
|
||||
#define MErrSeek L"Seek error in the file %s"
|
||||
#define MErrFClose L"Cannot close the file %s"
|
||||
#define MErrOutMem L"Not enough memory"
|
||||
#define MErrBrokenArc L"Corrupt archive - use 'Repair' command"
|
||||
#define MProgAborted L"Program aborted"
|
||||
#define MErrRename L"\nCannot rename %s to %s"
|
||||
#define MAbsNextVol L"\nCannot find volume %s"
|
||||
#define MBreak L"\nUser break\n"
|
||||
#define MAskCreatVol L"\nCreate next volume ?"
|
||||
#define MAskNextDisk L"\nDisk full. Insert next"
|
||||
#define MCreatVol L"\n\nCreating %sarchive %s\n"
|
||||
#define MAskNextVol L"\nInsert disk with %s"
|
||||
#define MTestVol L"\n\nTesting archive %s\n"
|
||||
#define MExtrVol L"\n\nExtracting from %s\n"
|
||||
#define MConverting L"\nConverting %s"
|
||||
#define MCvtToSFX L"\nConvert archives to SFX"
|
||||
#define MCvtFromSFX L"\nRemoving SFX module"
|
||||
#define MNotSFX L"\n%s is not SFX archive"
|
||||
#define MNotRAR L"\n%s is not RAR archive"
|
||||
#define MNotFirstVol L"\n%s is not the first volume"
|
||||
#define MCvtOldFormat L"\n%s - cannot convert to SFX archive with old format"
|
||||
#define MCannotCreate L"\nCannot create %s"
|
||||
#define MCannotOpen L"\nCannot open %s"
|
||||
#define MUnknownMeth L"\nUnknown method in %s"
|
||||
#define MNewRarFormat L"\nUnsupported archive format. Please update RAR to a newer version."
|
||||
#define MOk L" OK"
|
||||
#define MDone L"\nDone"
|
||||
#define MLockingArc L"\nLocking archive"
|
||||
#define MNotMdfOld L"\n\nERROR: Cannot modify old format archive"
|
||||
#define MNotMdfLock L"\n\nERROR: Locked archive"
|
||||
#define MNotMdfVol L"\n\nERROR: Cannot modify volume"
|
||||
#define MPackAskReg L"\nEvaluation copy. Please register.\n"
|
||||
#define MCreateArchive L"\nCreating %sarchive %s\n"
|
||||
#define MUpdateArchive L"\nUpdating %sarchive %s\n"
|
||||
#define MAddSolid L"solid "
|
||||
#define MAddFile L"\nAdding %-58s "
|
||||
#define MUpdFile L"\nUpdating %-58s "
|
||||
#define MAddPoints L"\n... %-58s "
|
||||
#define MMoveDelFiles L"\n\nDeleting files %s..."
|
||||
#define MMoveDelDirs L"and directories"
|
||||
#define MMoveDelFile L"\nDeleting %-30s"
|
||||
#define MMoveDeleted L" deleted"
|
||||
#define MMoveNotDeleted L" NOT DELETED"
|
||||
#define MClearAttrib L"\n\nClearing attributes..."
|
||||
#define MMoveDelDir L"\nDeleting directory %-30s"
|
||||
#define MWarErrFOpen L"\nWARNING: Cannot open %d %s"
|
||||
#define MErrOpenFiles L"files"
|
||||
#define MErrOpenFile L"file"
|
||||
#define MAddNoFiles L"\nWARNING: No files"
|
||||
#define MMdfEncrSol L"\n%s: encrypted"
|
||||
#define MCannotMdfEncrSol L"\nCannot modify solid archive containing encrypted files"
|
||||
#define MAddAnalyze L"\nAnalyzing archived files: "
|
||||
#define MRepacking L"\nRepacking archived files: "
|
||||
#define MCRCFailed L"\n%-20s - checksum error"
|
||||
#define MExtrTest L"\n\nTesting archive %s\n"
|
||||
#define MExtracting L"\n\nExtracting from %s\n"
|
||||
#define MUseCurPsw L"\n%s - use current password ?"
|
||||
#define MCreatDir L"\nCreating %-56s"
|
||||
#define MExtrSkipFile L"\nSkipping %-56s"
|
||||
#define MExtrTestFile L"\nTesting %-56s"
|
||||
#define MExtrFile L"\nExtracting %-56s"
|
||||
#define MExtrPoints L"\n... %-56s"
|
||||
#define MExtrErrMkDir L"\nCannot create directory %s"
|
||||
#define MExtrPrinting L"\n------ Printing %s\n\n"
|
||||
#define MEncrBadCRC L"\nChecksum error in the encrypted file %s. Corrupt file or wrong password."
|
||||
#define MExtrNoFiles L"\nNo files to extract"
|
||||
#define MExtrAllOk L"\nAll OK"
|
||||
#define MExtrTotalErr L"\nTotal errors: %ld"
|
||||
#define MAskReplace L"\n\nWould you like to replace the existing file %s\n%6s bytes, modified on %s\nwith a new one\n%6s bytes, modified on %s\n"
|
||||
#define MAskOverwrite L"\nOverwrite %s ?"
|
||||
#define MAskNewName L"\nEnter new name: "
|
||||
#define MHeaderBroken L"\nCorrupt header is found"
|
||||
#define MMainHeaderBroken L"\nMain archive header is corrupt"
|
||||
#define MLogFileHead L"\n%s - the file header is corrupt"
|
||||
#define MLogProtectHead L"The data recovery header is corrupt"
|
||||
#define MReadStdinCmt L"\nReading comment from stdin\n"
|
||||
#define MReadCommFrom L"\nReading comment from %s"
|
||||
#define MDelComment L"\nDeleting comment from %s"
|
||||
#define MAddComment L"\nAdding comment to %s"
|
||||
#define MFCommAdd L"\nAdding file comments"
|
||||
#define MAskFComm L"\n\nReading comment for %s : %s from stdin\n"
|
||||
#define MLogCommBrk L"\nThe archive comment is corrupt"
|
||||
#define MCommAskCont L"\nPress 'Enter' to continue or 'Q' to quit:"
|
||||
#define MWriteCommTo L"\nWrite comment to %s"
|
||||
#define MCommNotPres L"\nComment is not present"
|
||||
#define MDelFrom L"\nDeleting from %s"
|
||||
#define MDeleting L"\nDeleting %s"
|
||||
#define MEraseArc L"\nErasing empty archive %s"
|
||||
#define MNoDelFiles L"\nNo files to delete"
|
||||
#define MLogTitle L"-------- %2d %s %d, archive %s"
|
||||
#define MPathTooLong L"\nERROR: Path too long\n"
|
||||
#define MListArchive L"Archive"
|
||||
#define MListDetails L"Details"
|
||||
#define MListSolid L"solid"
|
||||
#define MListSFX L"SFX"
|
||||
#define MListVolume L"volume"
|
||||
#define MListRR L"recovery record"
|
||||
#define MListLock L"lock"
|
||||
#define MListEnc L"encrypted"
|
||||
#define MListEncHead L"encrypted headers"
|
||||
#define MListTitleL L" Attributes Size Date Time Name"
|
||||
#define MListTitleV L" Attributes Size Packed Ratio Date Time Checksum Name"
|
||||
#define MListName L"Name"
|
||||
#define MListType L"Type"
|
||||
#define MListFile L"File"
|
||||
#define MListDir L"Directory"
|
||||
#define MListUSymlink L"Unix symbolic link"
|
||||
#define MListWSymlink L"Windows symbolic link"
|
||||
#define MListJunction L"NTFS junction point"
|
||||
#define MListHardlink L"Hard link"
|
||||
#define MListCopy L"File reference"
|
||||
#define MListStream L"NTFS alternate data stream"
|
||||
#define MListTarget L"Target"
|
||||
#define MListSize L"Size"
|
||||
#define MListPacked L"Packed size"
|
||||
#define MListRatio L"Ratio"
|
||||
#define MListMtime L"mtime"
|
||||
#define MListCtime L"ctime"
|
||||
#define MListAtime L"atime"
|
||||
#define MListAttr L"Attributes"
|
||||
#define MListFlags L"Flags"
|
||||
#define MListCompInfo L"Compression"
|
||||
#define MListHostOS L"Host OS"
|
||||
#define MListFileVer L"File version"
|
||||
#define MListService L"Service"
|
||||
#define MListUOHead L"\n Unix Owner/Group data: %-14s %-14s"
|
||||
#define MListNTACLHead L"\n NTFS security data"
|
||||
#define MListStrmHead L"\n NTFS stream: %s"
|
||||
#define MListUnkHead L"\n Unknown subheader type: 0x%04x"
|
||||
#define MFileComment L"\nComment: "
|
||||
#define MYes L"Yes"
|
||||
#define MNo L"No"
|
||||
#define MListNoFiles L" 0 files\n"
|
||||
#define MRprReconstr L"\nReconstructing %s"
|
||||
#define MRprBuild L"\nBuilding %s"
|
||||
#define MRprOldFormat L"\nCannot repair archive with old format"
|
||||
#define MRprFind L"\nFound %s"
|
||||
#define MRprAskIsSol L"\nThe archive header is corrupt. Mark archive as solid ?"
|
||||
#define MRprNoFiles L"\nNo files found"
|
||||
#define MLogUnexpEOF L"\nUnexpected end of archive"
|
||||
#define MRepAskReconst L"\nReconstruct archive structure ?"
|
||||
#define MRecScanning L"\nScanning..."
|
||||
#define MRecRNotFound L"\nData recovery record not found"
|
||||
#define MRecRFound L"\nData recovery record found"
|
||||
#define MRecSecDamage L"\nSector %ld (offsets %lX...%lX) damaged"
|
||||
#define MRecCorrected L" - data recovered"
|
||||
#define MRecFailed L" - cannot recover data"
|
||||
#define MAddRecRec L"\nAdding data recovery record"
|
||||
#define MEraseForVolume L"\n\nErasing contents of drive %c:\n"
|
||||
#define MGetOwnersError L"\nWARNING: Cannot get %s owner and group\n"
|
||||
#define MErrGetOwnerID L"\nWARNING: Cannot get owner %s ID\n"
|
||||
#define MErrGetGroupID L"\nWARNING: Cannot get group %s ID\n"
|
||||
#define MOwnersBroken L"\nERROR: %s group and owner data are corrupt\n"
|
||||
#define MSetOwnersError L"\nWARNING: Cannot set %s owner and group\n"
|
||||
#define MErrLnkRead L"\nWARNING: Cannot read symbolic link %s"
|
||||
#define MSymLinkExists L"\nWARNING: Symbolic link %s already exists"
|
||||
#define MAskRetryCreate L"\nCannot create %s. Retry ?"
|
||||
#define MListMACHead1 L"\n Mac OS file type: %c%c%c%c ; "
|
||||
#define MListMACHead2 L"file creator: %c%c%c%c\n"
|
||||
#define MDataBadCRC L"\n%-20s : packed data checksum error in volume %s"
|
||||
#define MFileRO L"\n%s is read-only"
|
||||
#define MACLGetError L"\nWARNING: Cannot get %s security data\n"
|
||||
#define MACLSetError L"\nWARNING: Cannot set %s security data\n"
|
||||
#define MACLBroken L"\nERROR: %s security data are corrupt\n"
|
||||
#define MACLUnknown L"\nWARNING: Unknown format of %s security data\n"
|
||||
#define MStreamBroken L"\nERROR: %s stream data are corrupt\n"
|
||||
#define MStreamUnknown L"\nWARNING: Unknown format of %s stream data\n"
|
||||
#define MInvalidName L"\nERROR: Invalid file name %s"
|
||||
#define MProcessArc L"\n\nProcessing archive %s"
|
||||
#define MCorrectingName L"\nWARNING: Attempting to correct the invalid file name"
|
||||
#define MUnpCannotMerge L"\nWARNING: You need to start extraction from a previous volume to unpack %s"
|
||||
#define MUnknownOption L"\nERROR: Unknown option: %s"
|
||||
#define MSubHeadCorrupt L"\nERROR: Corrupt data header found, ignored"
|
||||
#define MSubHeadUnknown L"\nWARNING: Unknown data header format, ignored"
|
||||
#define MSubHeadDataCRC L"\nERROR: Corrupt %s data block"
|
||||
#define MSubHeadType L"\nData header type: %s"
|
||||
#define MScanError L"\nCannot read contents of %s"
|
||||
#define MNotVolume L"\n%s is not volume"
|
||||
#define MRecVolDiffSets L"\nERROR: %s and %s belong to different sets"
|
||||
#define MRecVolMissing L"\n%d volumes missing"
|
||||
#define MRecVolFound L"\n%d recovery volumes found"
|
||||
#define MRecVolAllExist L"\nNothing to reconstruct"
|
||||
#define MRecVolCannotFix L"\nReconstruction impossible"
|
||||
#define MReconstructing L"\nReconstructing..."
|
||||
#define MCreating L"\nCreating %s"
|
||||
#define MRenaming L"\nRenaming %s to %s"
|
||||
#define MNTFSRequired L"\nWrite error: only NTFS file system supports files larger than 4 GB"
|
||||
#define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files"
|
||||
#define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s"
|
||||
#define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives"
|
||||
#define MCannotEncName L"\nCannot encrypt archive already containing encrypted files"
|
||||
#define MCannotEmail L"\nCannot email the file %s"
|
||||
#define MCopyrightS L"\nRAR SFX archive"
|
||||
#define MSHelpCmd L"\n\n<Commands>"
|
||||
#define MSHelpCmdE L"\n -x Extract from archive (default)"
|
||||
#define MSHelpCmdT L"\n -t Test archive files"
|
||||
#define MSHelpCmdV L"\n -v Verbosely list contents of archive"
|
||||
#define MRecVolLimit L"\nTotal number of usual and recovery volumes must not exceed %d"
|
||||
#define MVolumeNumber L"volume %d"
|
||||
#define MCannotDelete L"\nCannot delete %s"
|
||||
#define MCalcCRC L"\nCalculating the checksum"
|
||||
#define MTooLargeSFXArc L"\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB."
|
||||
#define MCalcCRCAllVol L"\nCalculating checksums of all volumes."
|
||||
#define MNotEnoughDisk L"\nERROR: Not enough disk space for %s."
|
||||
#define MNewerRAR L"\nYou may need a newer version of RAR."
|
||||
#define MUnkEncMethod L"\nUnknown encryption method in %s"
|
||||
#define MWrongPassword L"\nThe specified password is incorrect."
|
||||
#define MRepairing L"\nRepairing"
|
||||
#define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x"
|
||||
#define MBlocksRecovered L"\n%d blocks recovered."
|
||||
#define MRRDamaged L"\nRecovery record is corrupt."
|
||||
#define MTestingRR L"\nTesting the recovery record"
|
||||
#define MFailed L"Failed"
|
||||
#define MIncompatSwitch L"\n%s switch is not supported for RAR %d.x archive format."
|
||||
#define MSearchDupFiles L"\nSearching for identical files"
|
||||
#define MNumFound L"%d found."
|
||||
#define MUnknownExtra L"\nUnknown extra field in %s."
|
||||
#define MCorruptExtra L"\nCorrupt %s extra field in %s."
|
||||
#define MCopyError L"\nCannot copy %s to %s."
|
||||
#define MCopyErrorHint L"\nYou need to unpack the entire archive to create file reference entries."
|
||||
#define MCopyingData L"\nCopying data"
|
||||
#define MErrCreateLnkS L"\nCannot create symbolic link %s"
|
||||
#define MErrCreateLnkH L"\nCannot create hard link %s"
|
||||
#define MNeedAdmin L"\nYou may need to run RAR as administrator"
|
||||
#define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB."
|
||||
#define MUseSmalllerDict L"\nPlease use a smaller compression dictionary."
|
||||
|
||||
@@ -1,23 +1,36 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
|
||||
static char LogName[NM];
|
||||
static wchar LogName[NM];
|
||||
static RAR_CHARSET LogCharset=RCH_DEFAULT;
|
||||
|
||||
void InitLogOptions(char *LogName)
|
||||
void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet)
|
||||
{
|
||||
strcpy(::LogName,LogName);
|
||||
wcsncpyz(LogName,LogFileName,ASIZE(LogName));
|
||||
LogCharset=CSet;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
void Log(const char *ArcName,const char *Format,...)
|
||||
void Log(const wchar *ArcName,const wchar *fmt,...)
|
||||
{
|
||||
safebuf char Msg[2*NM+1024];
|
||||
va_list ArgPtr;
|
||||
va_start(ArgPtr,Format);
|
||||
vsprintf(Msg,Format,ArgPtr);
|
||||
va_end(ArgPtr);
|
||||
eprintf("%s",Msg);
|
||||
// Preserve the error code for possible following system error message.
|
||||
int Code=ErrHandler.GetSystemErrorCode();
|
||||
|
||||
uiAlarm(UIALARM_ERROR);
|
||||
|
||||
// This buffer is for format string only, not for entire output,
|
||||
// so it can be short enough.
|
||||
wchar fmtw[1024];
|
||||
PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
|
||||
|
||||
safebuf wchar Msg[2*NM+1024];
|
||||
va_list arglist;
|
||||
va_start(arglist,fmt);
|
||||
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
|
||||
va_end(arglist);
|
||||
eprintf(L"%ls",Msg);
|
||||
ErrHandler.SetSystemErrorCode(Code);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
#ifndef _RAR_LOG_
|
||||
#define _RAR_LOG_
|
||||
|
||||
void InitLogOptions(char *LogName);
|
||||
|
||||
#ifndef SILENT
|
||||
void Log(const char *ArcName,const char *Format,...);
|
||||
#endif
|
||||
void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet);
|
||||
|
||||
#ifdef SILENT
|
||||
#ifdef __GNUC__
|
||||
#define Log(args...)
|
||||
inline void Log(const wchar *ArcName,const wchar *fmt,...) {}
|
||||
#else
|
||||
inline void Log(const char *a,const char *b,const char *c=NULL,const char *d=NULL) {}
|
||||
#endif
|
||||
void Log(const wchar *ArcName,const wchar *fmt,...);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
173
unrar/makefile
Normal file
173
unrar/makefile
Normal file
@@ -0,0 +1,173 @@
|
||||
#
|
||||
# Makefile for UNIX - unrar
|
||||
|
||||
# Linux using GCC
|
||||
CXX=c++
|
||||
CXXFLAGS=-O2
|
||||
LIBFLAGS=-fPIC
|
||||
DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
|
||||
STRIP=strip
|
||||
AR=ar
|
||||
LDFLAGS=-pthread
|
||||
DESTDIR=/usr
|
||||
|
||||
# Linux using LCC
|
||||
#CXX=lcc
|
||||
#CXXFLAGS=-O2
|
||||
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#DESTDIR=/usr
|
||||
|
||||
# CYGWIN using GCC
|
||||
#CXX=c++
|
||||
#CXXFLAGS=-O2
|
||||
#LIBFLAGS=
|
||||
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#LDFLAGS=-pthread
|
||||
#DESTDIR=/usr
|
||||
|
||||
# HP UX using aCC
|
||||
#CXX=aCC
|
||||
#CXXFLAGS=-AA +O2 +Onolimit
|
||||
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#DESTDIR=/usr
|
||||
|
||||
# IRIX using GCC
|
||||
#CXX=g++
|
||||
#CXXFLAGS=-O2
|
||||
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#DESTDIR=/usr
|
||||
|
||||
# IRIX using MIPSPro (experimental)
|
||||
#CXX=CC
|
||||
#CXXFLAGS=-O2 -mips3 -woff 1234,1156,3284 -LANG:std
|
||||
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -Dint64=int64_t
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#DESTDIR=/usr
|
||||
|
||||
# AIX using xlC (IBM VisualAge C++ 5.0)
|
||||
#CXX=xlC
|
||||
#CXXFLAGS=-O -qinline -qro -qroconst -qmaxmem=16384 -qcpluscmt
|
||||
#DEFINES=-D_LARGE_FILES -D_LARGE_FILE_API
|
||||
#LIBS=-lbsd
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#DESTDIR=/usr
|
||||
|
||||
# Solaris using CC
|
||||
#CXX=CC
|
||||
#CXXFLAGS=-fast -erroff=wvarhidemem
|
||||
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#DESTDIR=/usr
|
||||
|
||||
# Solaris using GCC (optimized for UltraSPARC 1 CPU)
|
||||
#CXX=g++
|
||||
#CXXFLAGS=-O3 -mcpu=v9 -mtune=ultrasparc -m32
|
||||
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
#STRIP=/usr/ccs/bin/strip
|
||||
#AR=/usr/ccs/bin/ar
|
||||
#DESTDIR=/usr
|
||||
|
||||
# Tru64 5.1B using GCC3
|
||||
#CXX=g++
|
||||
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_XOPEN_SOURCE=500
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#LDFLAGS=-rpath /usr/local/gcc/lib
|
||||
#DESTDIR=/usr
|
||||
|
||||
# Tru64 5.1B using DEC C++
|
||||
#CXX=cxx
|
||||
#CXXFLAGS=-O4 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Dint64=long
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#LDFLAGS=
|
||||
#DESTDIR=/usr
|
||||
|
||||
# QNX 6.x using GCC
|
||||
#CXX=g++
|
||||
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fexceptions
|
||||
#STRIP=strip
|
||||
#AR=ar
|
||||
#LDFLAGS=-fexceptions
|
||||
#DESTDIR=/usr
|
||||
|
||||
# Cross-compile
|
||||
# Linux using arm-linux-g++
|
||||
#CXX=arm-linux-g++
|
||||
#CXXFLAGS=-O2
|
||||
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
#STRIP=arm-linux-strip
|
||||
#AR=arm-linux-ar
|
||||
#LDFLAGS=-static
|
||||
#DESTDIR=/usr
|
||||
|
||||
##########################
|
||||
|
||||
COMPILE=$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES)
|
||||
LINK=$(CXX)
|
||||
|
||||
WHAT=UNRAR
|
||||
|
||||
UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o qopen.o
|
||||
LIB_OBJ=filestr.o scantree.o dll.o qopen.o
|
||||
|
||||
OBJECTS=rar.o strlist.o strfn.o pathfn.o smallfn.o global.o file.o filefn.o filcreat.o \
|
||||
archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
|
||||
resource.o match.o timefn.o rdwrfn.o consio.o options.o errhnd.o rarvm.o secpassword.o \
|
||||
rijndael.o getbits.o sha1.o sha256.o blake2s.o hash.o extinfo.o extract.o volume.o \
|
||||
list.o find.o unpack.o headers.o threadpool.o rs16.o cmddata.o ui.o
|
||||
|
||||
.cpp.o:
|
||||
$(COMPILE) -D$(WHAT) -c $<
|
||||
|
||||
all: unrar
|
||||
|
||||
install: install-unrar
|
||||
|
||||
uninstall: uninstall-unrar
|
||||
|
||||
clean:
|
||||
@rm -f *.o *.bak *~
|
||||
|
||||
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
|
||||
@rm -f unrar
|
||||
$(LINK) -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
|
||||
$(STRIP) unrar
|
||||
|
||||
sfx: WHAT=SFX_MODULE
|
||||
sfx: clean $(OBJECTS)
|
||||
@rm -f default.sfx
|
||||
$(LINK) -o default.sfx $(LDFLAGS) $(OBJECTS)
|
||||
$(STRIP) default.sfx
|
||||
|
||||
lib: WHAT=RARDLL
|
||||
lib: CXXFLAGS+=$(LIBFLAGS)
|
||||
lib: clean $(OBJECTS) $(LIB_OBJ)
|
||||
@rm -f libunrar.so
|
||||
@rm -f libunrar.a
|
||||
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
|
||||
$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
|
||||
|
||||
install-unrar:
|
||||
install -D unrar $(DESTDIR)/bin/unrar
|
||||
|
||||
uninstall-unrar:
|
||||
rm -f $(DESTDIR)/bin/unrar
|
||||
|
||||
install-lib:
|
||||
install libunrar.so $(DESTDIR)/lib
|
||||
install libunrar.a $(DESTDIR)/lib
|
||||
|
||||
uninstall-lib:
|
||||
rm -f $(DESTDIR)/lib/libunrar.so
|
||||
175
unrar/match.cpp
175
unrar/match.cpp
@@ -1,98 +1,21 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
static bool match(const char *pattern,const char *string,bool ForceCase);
|
||||
static bool match(const wchar *pattern,const wchar *string,bool ForceCase);
|
||||
|
||||
static int mstricompc(const char *Str1,const char *Str2,bool ForceCase);
|
||||
static int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase);
|
||||
static int mstrnicompc(const char *Str1,const char *Str2,size_t N,bool ForceCase);
|
||||
static int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase);
|
||||
|
||||
inline uint toupperc(byte ch,bool ForceCase)
|
||||
{
|
||||
if (ForceCase)
|
||||
return(ch);
|
||||
#ifdef _WIN_ALL
|
||||
return((uint)(LPARAM)CharUpper((LPTSTR)(ch)));
|
||||
#elif defined(_UNIX)
|
||||
return(ch);
|
||||
#else
|
||||
return(toupper(ch));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline uint touppercw(uint ch,bool ForceCase)
|
||||
{
|
||||
if (ForceCase)
|
||||
return(ch);
|
||||
return ch;
|
||||
#if defined(_UNIX)
|
||||
return(ch);
|
||||
return ch;
|
||||
#else
|
||||
return(toupperw(ch));
|
||||
return toupperw(ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CmpName(const char *Wildcard,const char *Name,int CmpMode)
|
||||
{
|
||||
bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0;
|
||||
|
||||
CmpMode&=MATCH_MODEMASK;
|
||||
|
||||
if (CmpMode!=MATCH_NAMES)
|
||||
{
|
||||
size_t WildLength=strlen(Wildcard);
|
||||
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH &&
|
||||
mstrnicompc(Wildcard,Name,WildLength,ForceCase)==0)
|
||||
{
|
||||
// For all modes except MATCH_NAMES, MATCH_EXACT and MATCH_EXACTPATH
|
||||
// "path1" mask must match "path1\path2\filename.ext" and "path1" names.
|
||||
char NextCh=Name[WildLength];
|
||||
if (NextCh=='\\' || NextCh=='/' || NextCh==0)
|
||||
return(true);
|
||||
}
|
||||
|
||||
// Nothing more to compare for MATCH_SUBPATHONLY.
|
||||
if (CmpMode==MATCH_SUBPATHONLY)
|
||||
return(false);
|
||||
|
||||
char Path1[NM],Path2[NM];
|
||||
GetFilePath(Wildcard,Path1,ASIZE(Path1));
|
||||
GetFilePath(Name,Path2,ASIZE(Path1));
|
||||
|
||||
if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
|
||||
mstricompc(Path1,Path2,ForceCase)!=0)
|
||||
return(false);
|
||||
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
|
||||
if (IsWildcard(Path1))
|
||||
return(match(Wildcard,Name,ForceCase));
|
||||
else
|
||||
if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard))
|
||||
{
|
||||
if (*Path1 && mstrnicompc(Path1,Path2,strlen(Path1),ForceCase)!=0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
if (mstricompc(Path1,Path2,ForceCase)!=0)
|
||||
return(false);
|
||||
}
|
||||
char *Name1=PointToName(Wildcard);
|
||||
char *Name2=PointToName(Name);
|
||||
|
||||
// Always return false for RAR temporary files to exclude them
|
||||
// from archiving operations.
|
||||
if (mstrnicompc("__rar_",Name2,6,false)==0)
|
||||
return(false);
|
||||
|
||||
if (CmpMode==MATCH_EXACT)
|
||||
return(mstricompc(Name1,Name2,ForceCase)==0);
|
||||
|
||||
return(match(Name1,Name2,ForceCase));
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||
{
|
||||
bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0;
|
||||
@@ -124,10 +47,10 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||
mwcsicompc(Path1,Path2,ForceCase)!=0)
|
||||
return(false);
|
||||
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
|
||||
if (IsWildcard(NULL,Path1))
|
||||
if (IsWildcard(Path1))
|
||||
return(match(Wildcard,Name,ForceCase));
|
||||
else
|
||||
if (CmpMode==MATCH_SUBPATH || IsWildcard(NULL,Wildcard))
|
||||
if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard))
|
||||
{
|
||||
if (*Path1 && mwcsnicompc(Path1,Path2,wcslen(Path1),ForceCase)!=0)
|
||||
return(false);
|
||||
@@ -149,61 +72,8 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||
|
||||
return(match(Name1,Name2,ForceCase));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool match(const char *pattern,const char *string,bool ForceCase)
|
||||
{
|
||||
for (;; ++string)
|
||||
{
|
||||
char stringc=toupperc(*string,ForceCase);
|
||||
char patternc=toupperc(*pattern++,ForceCase);
|
||||
switch (patternc)
|
||||
{
|
||||
case 0:
|
||||
return(stringc==0);
|
||||
case '?':
|
||||
if (stringc == 0)
|
||||
return(false);
|
||||
break;
|
||||
case '*':
|
||||
if (*pattern==0)
|
||||
return(true);
|
||||
if (*pattern=='.')
|
||||
{
|
||||
if (pattern[1]=='*' && pattern[2]==0)
|
||||
return(true);
|
||||
const char *dot=strchr(string,'.');
|
||||
if (pattern[1]==0)
|
||||
return (dot==NULL || dot[1]==0);
|
||||
if (dot!=NULL)
|
||||
{
|
||||
string=dot;
|
||||
if (strpbrk(pattern,"*?")==NULL && strchr(string+1,'.')==NULL)
|
||||
return(mstricompc(pattern+1,string+1,ForceCase)==0);
|
||||
}
|
||||
}
|
||||
|
||||
while (*string)
|
||||
if (match(pattern,string++,ForceCase))
|
||||
return(true);
|
||||
return(false);
|
||||
default:
|
||||
if (patternc != stringc)
|
||||
{
|
||||
// Allow "name." mask match "name" and "name.\" match "name\".
|
||||
if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.'))
|
||||
return(match(pattern,string,ForceCase));
|
||||
else
|
||||
return(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
bool match(const wchar *pattern,const wchar *string,bool ForceCase)
|
||||
{
|
||||
for (;; ++string)
|
||||
@@ -253,48 +123,23 @@ bool match(const wchar *pattern,const wchar *string,bool ForceCase)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int mstricompc(const char *Str1,const char *Str2,bool ForceCase)
|
||||
{
|
||||
if (ForceCase)
|
||||
return(strcmp(Str1,Str2));
|
||||
return(stricompc(Str1,Str2));
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase)
|
||||
{
|
||||
if (ForceCase)
|
||||
return(wcscmp(Str1,Str2));
|
||||
return(wcsicompc(Str1,Str2));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int mstrnicompc(const char *Str1,const char *Str2,size_t N,bool ForceCase)
|
||||
{
|
||||
if (ForceCase)
|
||||
return(strncmp(Str1,Str2,N));
|
||||
#if defined(_UNIX)
|
||||
return(strncmp(Str1,Str2,N));
|
||||
#else
|
||||
return(strnicomp(Str1,Str2,N));
|
||||
#endif
|
||||
return wcscmp(Str1,Str2);
|
||||
return wcsicompc(Str1,Str2);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase)
|
||||
{
|
||||
if (ForceCase)
|
||||
return(wcsncmp(Str1,Str2,N));
|
||||
return wcsncmp(Str1,Str2,N);
|
||||
#if defined(_UNIX)
|
||||
return(wcsncmp(Str1,Str2,N));
|
||||
return wcsncmp(Str1,Str2,N);
|
||||
#else
|
||||
return(wcsnicomp(Str1,Str2,N));
|
||||
return wcsnicomp(Str1,Str2,N);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,6 @@ enum {
|
||||
#define MATCH_MODEMASK 0x0000ffff
|
||||
#define MATCH_FORCECASESENSITIVE 0x80000000
|
||||
|
||||
bool CmpName(const char *Wildcard,const char *Name,int CmpMode);
|
||||
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,10 +5,17 @@
|
||||
* Contents: model description and encoding/decoding routines *
|
||||
****************************************************************************/
|
||||
|
||||
inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats,
|
||||
STATE& FirstState)
|
||||
static const int MAX_O=64; /* maximum allowed model order */
|
||||
const uint TOP=1 << 24, BOT=1 << 15;
|
||||
|
||||
template <class T>
|
||||
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
|
||||
|
||||
|
||||
inline RARPPM_CONTEXT* RARPPM_CONTEXT::createChild(ModelPPM *Model,RARPPM_STATE* pStats,
|
||||
RARPPM_STATE& FirstState)
|
||||
{
|
||||
PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext();
|
||||
RARPPM_CONTEXT* pc = (RARPPM_CONTEXT*) Model->SubAlloc.AllocContext();
|
||||
if ( pc )
|
||||
{
|
||||
pc->NumStats=1;
|
||||
@@ -34,11 +41,11 @@ void ModelPPM::RestartModelRare()
|
||||
memset(CharMask,0,sizeof(CharMask));
|
||||
SubAlloc.InitSubAllocator();
|
||||
InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
|
||||
MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext();
|
||||
MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext();
|
||||
MinContext->Suffix=NULL;
|
||||
OrderFall=MaxOrder;
|
||||
MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
|
||||
FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2);
|
||||
FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2);
|
||||
for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
|
||||
{
|
||||
MinContext->U.Stats[i].Symbol=i;
|
||||
@@ -105,10 +112,10 @@ void ModelPPM::StartModelRare(int MaxOrder)
|
||||
}
|
||||
|
||||
|
||||
void PPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
void RARPPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
{
|
||||
int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
|
||||
STATE* p1, * p;
|
||||
RARPPM_STATE* p1, * p;
|
||||
for (p=Model->FoundState;p != U.Stats;p--)
|
||||
_PPMD_SWAP(p[0],p[-1]);
|
||||
U.Stats->Freq += 4;
|
||||
@@ -122,7 +129,7 @@ void PPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
|
||||
if (p[0].Freq > p[-1].Freq)
|
||||
{
|
||||
STATE tmp=*(p1=p);
|
||||
RARPPM_STATE tmp=*(p1=p);
|
||||
do
|
||||
{
|
||||
p1[0]=p1[-1];
|
||||
@@ -139,7 +146,7 @@ void PPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
EscFreq += i;
|
||||
if ((NumStats -= i) == 1)
|
||||
{
|
||||
STATE tmp=*U.Stats;
|
||||
RARPPM_STATE tmp=*U.Stats;
|
||||
do
|
||||
{
|
||||
tmp.Freq-=(tmp.Freq >> 1);
|
||||
@@ -152,19 +159,19 @@ void PPM_CONTEXT::rescale(ModelPPM *Model)
|
||||
U.SummFreq += (EscFreq -= (EscFreq >> 1));
|
||||
int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
|
||||
if (n0 != n1)
|
||||
U.Stats = (STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
|
||||
U.Stats = (RARPPM_STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
|
||||
Model->FoundState=U.Stats;
|
||||
}
|
||||
|
||||
|
||||
inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1)
|
||||
inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1)
|
||||
{
|
||||
#ifdef __ICL
|
||||
static
|
||||
#endif
|
||||
STATE UpState;
|
||||
PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
|
||||
STATE * p, * ps[MAX_O], ** pps=ps;
|
||||
RARPPM_STATE UpState;
|
||||
RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
|
||||
RARPPM_STATE * p, * ps[MAX_O], ** pps=ps;
|
||||
if ( !Skip )
|
||||
{
|
||||
*pps++ = FoundState;
|
||||
@@ -202,7 +209,7 @@ NO_LOOP:
|
||||
if (pps == ps)
|
||||
return pc;
|
||||
UpState.Symbol=*(byte*) UpBranch;
|
||||
UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
|
||||
UpState.Successor=(RARPPM_CONTEXT*) (((byte*) UpBranch)+1);
|
||||
if (pc->NumStats != 1)
|
||||
{
|
||||
if ((byte*) pc <= SubAlloc.pText)
|
||||
@@ -230,8 +237,8 @@ NO_LOOP:
|
||||
|
||||
inline void ModelPPM::UpdateModel()
|
||||
{
|
||||
STATE fs = *FoundState, *p = NULL;
|
||||
PPM_CONTEXT *pc, *Successor;
|
||||
RARPPM_STATE fs = *FoundState, *p = NULL;
|
||||
RARPPM_CONTEXT *pc, *Successor;
|
||||
uint ns1, ns, cf, sf, s0;
|
||||
if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
|
||||
{
|
||||
@@ -269,7 +276,7 @@ inline void ModelPPM::UpdateModel()
|
||||
return;
|
||||
}
|
||||
*SubAlloc.pText++ = fs.Symbol;
|
||||
Successor = (PPM_CONTEXT*) SubAlloc.pText;
|
||||
Successor = (RARPPM_CONTEXT*) SubAlloc.pText;
|
||||
if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
|
||||
goto RESTART_MODEL;
|
||||
if ( fs.Successor )
|
||||
@@ -295,7 +302,7 @@ inline void ModelPPM::UpdateModel()
|
||||
{
|
||||
if ((ns1 & 1) == 0)
|
||||
{
|
||||
pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
|
||||
pc->U.Stats=(RARPPM_STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
|
||||
if ( !pc->U.Stats )
|
||||
goto RESTART_MODEL;
|
||||
}
|
||||
@@ -303,7 +310,7 @@ inline void ModelPPM::UpdateModel()
|
||||
}
|
||||
else
|
||||
{
|
||||
p=(STATE*) SubAlloc.AllocUnits(1);
|
||||
p=(RARPPM_STATE*) SubAlloc.AllocUnits(1);
|
||||
if ( !p )
|
||||
goto RESTART_MODEL;
|
||||
*p=pc->OneState;
|
||||
@@ -346,9 +353,9 @@ static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2,
|
||||
|
||||
|
||||
|
||||
inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
||||
inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
||||
{
|
||||
STATE& rs=OneState;
|
||||
RARPPM_STATE& rs=OneState;
|
||||
Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
|
||||
ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
|
||||
Model->NS2BSIndx[Suffix->NumStats-1]+
|
||||
@@ -360,14 +367,14 @@ inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
||||
rs.Freq += (rs.Freq < 128);
|
||||
Model->Coder.SubRange.LowCount=0;
|
||||
Model->Coder.SubRange.HighCount=bs;
|
||||
bs = SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
bs = GET_SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
Model->PrevSuccess=1;
|
||||
Model->RunLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Model->Coder.SubRange.LowCount=bs;
|
||||
bs = SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
bs = GET_SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
|
||||
Model->Coder.SubRange.HighCount=BIN_SCALE;
|
||||
Model->InitEsc=ExpEscape[bs >> 10];
|
||||
Model->NumMasked=1;
|
||||
@@ -378,7 +385,7 @@ inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
|
||||
}
|
||||
|
||||
|
||||
inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
|
||||
inline void RARPPM_CONTEXT::update1(ModelPPM *Model,RARPPM_STATE* p)
|
||||
{
|
||||
(Model->FoundState=p)->Freq += 4;
|
||||
U.SummFreq += 4;
|
||||
@@ -394,10 +401,10 @@ inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
|
||||
|
||||
|
||||
|
||||
inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
|
||||
inline bool RARPPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
|
||||
{
|
||||
Model->Coder.SubRange.scale=U.SummFreq;
|
||||
STATE* p=U.Stats;
|
||||
RARPPM_STATE* p=U.Stats;
|
||||
int i, HiCnt;
|
||||
int count=Model->Coder.GetCurrentCount();
|
||||
if (count>=(int)Model->Coder.SubRange.scale)
|
||||
@@ -439,7 +446,7 @@ inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
|
||||
}
|
||||
|
||||
|
||||
inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
|
||||
inline void RARPPM_CONTEXT::update2(ModelPPM *Model,RARPPM_STATE* p)
|
||||
{
|
||||
(Model->FoundState=p)->Freq += 4;
|
||||
U.SummFreq += 4;
|
||||
@@ -450,9 +457,9 @@ inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
|
||||
}
|
||||
|
||||
|
||||
inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
|
||||
inline RARPPM_SEE2_CONTEXT* RARPPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
|
||||
{
|
||||
SEE2_CONTEXT* psee2c;
|
||||
RARPPM_SEE2_CONTEXT* psee2c;
|
||||
if (NumStats != 256)
|
||||
{
|
||||
psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
|
||||
@@ -472,11 +479,11 @@ inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
|
||||
|
||||
|
||||
|
||||
inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||
inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||
{
|
||||
int count, HiCnt, i=NumStats-Model->NumMasked;
|
||||
SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
|
||||
STATE* ps[256], ** pps=ps, * p=U.Stats-1;
|
||||
RARPPM_SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
|
||||
RARPPM_STATE* ps[256], ** pps=ps, * p=U.Stats-1;
|
||||
HiCnt=0;
|
||||
do
|
||||
{
|
||||
|
||||
@@ -4,16 +4,17 @@
|
||||
#include "coder.hpp"
|
||||
#include "suballoc.hpp"
|
||||
|
||||
const int MAX_O=64; /* maximum allowed model order */
|
||||
|
||||
const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
|
||||
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
|
||||
|
||||
#ifndef STRICT_ALIGNMENT_REQUIRED
|
||||
#ifdef ALLOW_MISALIGNED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct SEE2_CONTEXT
|
||||
struct RARPPM_DEF
|
||||
{
|
||||
static const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
|
||||
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
|
||||
};
|
||||
|
||||
struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
|
||||
{ // SEE-contexts for PPM-contexts with masked symbols
|
||||
ushort Summ;
|
||||
byte Shift, Count;
|
||||
@@ -24,7 +25,7 @@ struct SEE2_CONTEXT
|
||||
}
|
||||
uint getMean()
|
||||
{
|
||||
uint RetVal=SHORT16(Summ) >> Shift;
|
||||
uint RetVal=GET_SHORT16(Summ) >> Shift;
|
||||
Summ -= RetVal;
|
||||
return RetVal+(RetVal == 0);
|
||||
}
|
||||
@@ -40,45 +41,47 @@ struct SEE2_CONTEXT
|
||||
|
||||
|
||||
class ModelPPM;
|
||||
struct PPM_CONTEXT;
|
||||
struct RARPPM_CONTEXT;
|
||||
|
||||
struct STATE
|
||||
struct RARPPM_STATE
|
||||
{
|
||||
byte Symbol;
|
||||
byte Freq;
|
||||
PPM_CONTEXT* Successor;
|
||||
RARPPM_CONTEXT* Successor;
|
||||
};
|
||||
|
||||
struct FreqData
|
||||
{
|
||||
ushort SummFreq;
|
||||
STATE _PACK_ATTR * Stats;
|
||||
};
|
||||
|
||||
struct PPM_CONTEXT
|
||||
struct RARPPM_CONTEXT : RARPPM_DEF
|
||||
{
|
||||
ushort NumStats;
|
||||
|
||||
struct FreqData
|
||||
{
|
||||
ushort SummFreq;
|
||||
RARPPM_STATE RARPPM_PACK_ATTR * Stats;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
FreqData U;
|
||||
STATE OneState;
|
||||
RARPPM_STATE OneState;
|
||||
};
|
||||
|
||||
PPM_CONTEXT* Suffix;
|
||||
RARPPM_CONTEXT* Suffix;
|
||||
inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
|
||||
inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
|
||||
inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
|
||||
inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
|
||||
inline bool decodeSymbol1(ModelPPM *Model); // other orders:
|
||||
inline bool decodeSymbol2(ModelPPM *Model); // BCD context
|
||||
inline void update1(ModelPPM *Model,STATE* p); // CD suffix
|
||||
inline void update2(ModelPPM *Model,STATE* p); // BCDE successor
|
||||
inline void update1(ModelPPM *Model,RARPPM_STATE* p); // CD suffix
|
||||
inline void update2(ModelPPM *Model,RARPPM_STATE* p); // BCDE successor
|
||||
void rescale(ModelPPM *Model);
|
||||
inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
|
||||
inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
|
||||
inline RARPPM_CONTEXT* createChild(ModelPPM *Model,RARPPM_STATE* pStats,RARPPM_STATE& FirstState);
|
||||
inline RARPPM_SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
|
||||
};
|
||||
|
||||
#ifndef STRICT_ALIGNMENT_REQUIRED
|
||||
#ifdef ALLOW_MISALIGNED
|
||||
#ifdef _AIX
|
||||
#pragma pack(pop)
|
||||
#else
|
||||
@@ -86,28 +89,15 @@ struct PPM_CONTEXT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK));
|
||||
const uint FIXED_UNIT_SIZE=12;
|
||||
|
||||
/*
|
||||
inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext):
|
||||
NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; }
|
||||
inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {}
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
|
||||
|
||||
|
||||
class ModelPPM
|
||||
class ModelPPM : RARPPM_DEF
|
||||
{
|
||||
private:
|
||||
friend struct PPM_CONTEXT;
|
||||
friend struct RARPPM_CONTEXT;
|
||||
|
||||
SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
|
||||
RARPPM_SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
|
||||
|
||||
struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
|
||||
STATE* FoundState; // found next state transition
|
||||
struct RARPPM_CONTEXT *MinContext, *MedContext, *MaxContext;
|
||||
RARPPM_STATE* FoundState; // found next state transition
|
||||
int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
|
||||
byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
||||
byte EscCount, PrevSuccess, HiBitsFlag;
|
||||
@@ -118,7 +108,7 @@ class ModelPPM
|
||||
|
||||
void RestartModelRare();
|
||||
void StartModelRare(int MaxOrder);
|
||||
inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);
|
||||
inline RARPPM_CONTEXT* CreateSuccessors(bool Skip,RARPPM_STATE* p1);
|
||||
|
||||
inline void UpdateModel();
|
||||
inline void ClearMask();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user