mirror of
https://github.com/php-win-ext/php-rar.git
synced 2026-03-24 04:52:07 +01:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ece47716ab | ||
|
|
388707153c | ||
|
|
60cf649b85 | ||
|
|
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 |
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
*.o
|
||||
*.lo
|
||||
/tests/*.sh
|
||||
/tests/*.exp
|
||||
/tests/*.diff
|
||||
/tests/*.log
|
||||
/tests/*.php
|
||||
/tests/*.out
|
||||
/run-tests.php
|
||||
/modules
|
||||
/missing
|
||||
/.deps
|
||||
/.libs
|
||||
/Makefile
|
||||
/Makefile.fragments
|
||||
/Makefile.global
|
||||
/Makefile.objects
|
||||
/acinclude.m4
|
||||
/aclocal.m4
|
||||
/autom4te.cache
|
||||
/build
|
||||
/config.guess
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.nice
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/configure.in
|
||||
/install-sh
|
||||
/intl.la
|
||||
/libtool
|
||||
/mkinstalldirs
|
||||
/ltmain.sh
|
||||
/.cproject
|
||||
/.project
|
||||
/.settings
|
||||
@@ -18,14 +18,15 @@ unrar_sources="unrar/rar.cpp unrar/strlist.cpp unrar/strfn.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/scantree.cpp unrar/log.cpp unrar/extractchunk.cpp \
|
||||
unrar/secpassword.cpp"
|
||||
|
||||
if test "$PHP_RAR" != "no"; then
|
||||
PHP_REQUIRE_CXX
|
||||
AC_DEFINE(HAVE_RAR, 1, [Whether you have rar support])
|
||||
PHP_SUBST(RAR_SHARED_LIBADD)
|
||||
PHP_REQUIRE_CXX()
|
||||
PHP_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_NEW_EXTENSION(rar, rar.c rar_error.c rararch.c rarentry.c rar_stream.c rar_navigation.c $unrar_sources, $ext_shared,,-DRARDLL -DGUI -DSILENT -Wno-write-strings -Wno-logical-op-parentheses -I@ext_srcdir@/unrar)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
|
||||
fi
|
||||
|
||||
49
package.xml
49
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" />
|
||||
@@ -329,6 +318,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>
|
||||
|
||||
@@ -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 "3.0.2"
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define PHP_RAR_API __declspec(dllexport)
|
||||
@@ -288,8 +287,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 */
|
||||
|
||||
21
rar.c
21
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,7 +292,7 @@ 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)) {
|
||||
@@ -321,7 +321,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 +329,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 +451,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 +459,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 +698,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 +732,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
78
rar_stream.c
78
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,7 +264,7 @@ 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)
|
||||
ret = S_IFDIR;
|
||||
@@ -430,7 +431,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 +444,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 +452,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 +504,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 +522,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 +547,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 +587,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 +724,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 +750,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;
|
||||
}
|
||||
}
|
||||
@@ -842,10 +838,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 +866,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 +884,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 +981,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 +1052,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 +1072,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 +1113,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 +1163,7 @@ cleanup:
|
||||
*/
|
||||
if (flags & PHP_STREAM_URL_STAT_QUIET)
|
||||
_rar_stream_tidy_wrapper_error_log(wrapper TSRMLS_CC);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1189,10 +1195,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,7 +1222,7 @@ 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]) {
|
||||
@@ -1225,7 +1231,7 @@ static php_stream *php_stream_rar_dir_opener(php_stream_wrapper *wrapper,
|
||||
}
|
||||
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 */
|
||||
@@ -1236,7 +1242,7 @@ static php_stream *php_stream_rar_dir_opener(php_stream_wrapper *wrapper,
|
||||
if (!self->state->found || ((self->state->header->Flags &
|
||||
LHD_WINDOWMASK) != LHD_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)
|
||||
|
||||
46
rararch.c
46
rararch.c
@@ -130,7 +130,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 +138,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 +157,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
|
||||
@@ -268,7 +268,7 @@ static void rararch_ce_destroy_object(ze_rararch_object *object,
|
||||
|
||||
/* 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);
|
||||
}
|
||||
@@ -292,7 +292,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 +310,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 +374,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 +411,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 +540,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 +575,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 +611,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 +624,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 +662,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 +699,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 +760,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 +779,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 +859,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 +891,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);
|
||||
}
|
||||
|
||||
176
rarentry.c
176
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,14 +398,14 @@ 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));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -427,14 +413,14 @@ PHP_METHOD(rarentry, getHostOs)
|
||||
Return modification time of the entry */
|
||||
PHP_METHOD(rarentry, getFileTime)
|
||||
{
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
zval *entry_obj = getThis();
|
||||
|
||||
RAR_RETNULL_ON_ARGS();
|
||||
|
||||
|
||||
RAR_GET_PROPERTY(tmp, "file_time");
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
|
||||
|
||||
RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -442,14 +428,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 +443,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 +458,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 +473,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 +488,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 +497,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 +505,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 +516,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 +530,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);
|
||||
flags = Z_LVAL_P(tmp);
|
||||
is_dir = ((flags & LHD_WINDOWMASK) == LHD_DIRECTORY);
|
||||
|
||||
|
||||
RETURN_BOOL(is_dir);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -563,17 +549,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);
|
||||
flags = Z_LVAL_P(tmp);
|
||||
is_encrypted = (flags & 0x04);
|
||||
|
||||
|
||||
RETURN_BOOL(is_encrypted);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -582,9 +568,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 +581,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);
|
||||
flags = Z_LVAL_P(flags_zval);
|
||||
is_dir = ((flags & 0xE0) == 0xE0);
|
||||
|
||||
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 +599,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 +667,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);
|
||||
|
||||
@@ -3,6 +3,8 @@ RAR file stream stat
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded("rar")) die("skip");
|
||||
--ENV--
|
||||
TZ=Europe/Lisbon
|
||||
--FILE--
|
||||
<?php
|
||||
umask(0);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
BIN
tests/empty_file.rar
Normal file
BIN
tests/empty_file.rar
Normal file
Binary file not shown.
@@ -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
|
||||
|
||||
81
unrar/acknow.txt
Normal file
81
unrar/acknow.txt
Normal file
@@ -0,0 +1,81 @@
|
||||
ACKNOWLEDGMENTS
|
||||
|
||||
* 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.
|
||||
|
||||
* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
|
||||
to significantly improve RAR compression and speed.
|
||||
@@ -17,7 +17,7 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (NewMhd.Flags & MHD_COMMENT)
|
||||
if ((NewMhd.Flags & MHD_COMMENT)!=0)
|
||||
{
|
||||
// Old style (RAR 2.9) archive comment embedded into the main
|
||||
// archive header.
|
||||
@@ -43,18 +43,16 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
#endif
|
||||
}
|
||||
#ifndef SFX_MODULE
|
||||
if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT) || !OldFormat && CommHead.Method!=0x30)
|
||||
if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT)!=0 || !OldFormat && CommHead.Method!=0x30)
|
||||
{
|
||||
if (!OldFormat && (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER || CommHead.Method > 0x35))
|
||||
return(false);
|
||||
ComprDataIO DataIO;
|
||||
Unpack Unpack(&DataIO);
|
||||
Unpack.Init();
|
||||
DataIO.SetTestMode(true);
|
||||
uint UnpCmtLength;
|
||||
if (OldFormat)
|
||||
{
|
||||
#ifdef NOCRYPT
|
||||
#ifdef RAR_NOCRYPT
|
||||
return(false);
|
||||
#else
|
||||
UnpCmtLength=GetByte();
|
||||
@@ -68,6 +66,9 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
DataIO.SetFiles(this,NULL);
|
||||
DataIO.EnableShowProgress(false);
|
||||
DataIO.SetPackedSizeToRead(CmtLength);
|
||||
|
||||
Unpack Unpack(&DataIO);
|
||||
Unpack.Init();
|
||||
Unpack.SetDestSize(UnpCmtLength);
|
||||
Unpack.DoUnpack(CommHead.UnpVer,false);
|
||||
|
||||
@@ -110,8 +111,12 @@ bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
|
||||
if (CmtDataW!=NULL)
|
||||
{
|
||||
CmtDataW->Alloc(CmtSize+1);
|
||||
CmtData->Push(0);
|
||||
CharToWide(DataA,CmtDataW->Addr(),CmtSize+1);
|
||||
|
||||
// It can cause reallocation, so we should not use 'DataA' variable
|
||||
// with previosuly saved CmtData->Addr() after Push() call.
|
||||
CmtData->Push(0);
|
||||
|
||||
CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
|
||||
CmtData->Alloc(CmtSize);
|
||||
CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ Archive::Archive(RAROptions *InitCmd)
|
||||
VolWrite=0;
|
||||
AddingFilesSize=0;
|
||||
AddingHeadersSize=0;
|
||||
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
|
||||
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
|
||||
*HeadersSalt=0;
|
||||
*SubDataSalt=0;
|
||||
#endif
|
||||
@@ -52,13 +52,14 @@ Archive::Archive(RAROptions *InitCmd)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef SHELL_EXT
|
||||
void Archive::CheckArc(bool EnableBroken)
|
||||
{
|
||||
if (!IsArchive(EnableBroken))
|
||||
{
|
||||
Log(FileName,St(MBadArc),FileName);
|
||||
ErrHandler.Exit(FATAL_ERROR);
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -89,24 +90,23 @@ bool Archive::WCheckOpen(const char *Name,const wchar *NameW)
|
||||
}
|
||||
|
||||
|
||||
bool Archive::IsSignature(byte *D)
|
||||
ARCSIGN_TYPE Archive::IsSignature(const byte *D,size_t Size)
|
||||
{
|
||||
bool Valid=false;
|
||||
if (D[0]==0x52)
|
||||
ARCSIGN_TYPE Type=ARCSIGN_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=ARCSIGN_OLD;
|
||||
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 for non-zero last signature byte, so we can return
|
||||
// a sensible warning in case we'll want to change the archive
|
||||
// format sometimes in the future.
|
||||
Type=D[6]==0 ? ARCSIGN_CURRENT:ARCSIGN_FUTURE;
|
||||
}
|
||||
return(Valid);
|
||||
return Type;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,8 +125,11 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
|
||||
return(false);
|
||||
SFXSize=0;
|
||||
if (IsSignature(MarkHead.Mark))
|
||||
|
||||
ARCSIGN_TYPE Type;
|
||||
if ((Type=IsSignature(MarkHead.Mark,sizeof(MarkHead.Mark)))!=ARCSIGN_NONE)
|
||||
{
|
||||
OldFormat=(Type==ARCSIGN_OLD);
|
||||
if (OldFormat)
|
||||
Seek(0,SEEK_SET);
|
||||
}
|
||||
@@ -136,8 +139,9 @@ 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))!=ARCSIGN_NONE)
|
||||
{
|
||||
OldFormat=(Type==ARCSIGN_OLD);
|
||||
if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
|
||||
{
|
||||
char *D=&Buffer[28-CurPos];
|
||||
@@ -151,7 +155,14 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
break;
|
||||
}
|
||||
if (SFXSize==0)
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
if (Type==ARCSIGN_FUTURE)
|
||||
{
|
||||
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
|
||||
Log(FileName,St(MNewRarFormat));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
ReadHeader();
|
||||
SeekToNext();
|
||||
@@ -187,7 +198,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
#else
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
Log(FileName,St(MUnknownMeth),FileName);
|
||||
Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
|
||||
|
||||
@@ -5,10 +5,12 @@ class Pack;
|
||||
|
||||
enum {EN_LOCK=1,EN_VOL=2,EN_FIRSTVOL=4};
|
||||
|
||||
enum ARCSIGN_TYPE {ARCSIGN_NONE,ARCSIGN_OLD,ARCSIGN_CURRENT,ARCSIGN_FUTURE};
|
||||
|
||||
class Archive:public File
|
||||
{
|
||||
private:
|
||||
bool IsSignature(byte *D);
|
||||
ARCSIGN_TYPE IsSignature(const byte *D,size_t Size);
|
||||
void UpdateLatestTime(FileHeader *CurBlock);
|
||||
void ConvertNameCase(char *Name);
|
||||
void ConvertNameCase(wchar *Name);
|
||||
@@ -16,7 +18,7 @@ class Archive:public File
|
||||
size_t ReadOldHeader();
|
||||
void UnexpEndArcMsg();
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
|
||||
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
|
||||
CryptData HeadersCrypt;
|
||||
byte HeadersSalt[SALT_SIZE];
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,7 @@ void Archive::UnexpEndArcMsg()
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MLogUnexpEOF));
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ size_t Archive::ReadHeader()
|
||||
|
||||
if (Decrypt)
|
||||
{
|
||||
#if defined(SHELL_EXT) || defined(NOCRYPT)
|
||||
#if defined(SHELL_EXT) || defined(RAR_NOCRYPT)
|
||||
return(0);
|
||||
#else
|
||||
if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
|
||||
@@ -71,27 +71,42 @@ size_t Archive::ReadHeader()
|
||||
UnexpEndArcMsg();
|
||||
return(0);
|
||||
}
|
||||
if (*Cmd->Password==0)
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
#ifdef RARDLL
|
||||
char PasswordA[MAXPASSWORD];
|
||||
if (Cmd->Callback==NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
|
||||
if (Cmd->Callback!=NULL)
|
||||
{
|
||||
Close();
|
||||
//ErrHandler.Exit(USER_BREAK); original
|
||||
ErrHandler.Exit(NO_PASSWORD_ERROR);
|
||||
wchar PasswordW[MAXPASSWORD];
|
||||
*PasswordW=0;
|
||||
if (Cmd->Callback(UCM_NEEDPASSWORDW,Cmd->UserData,(LPARAM)PasswordW,ASIZE(PasswordW))==-1)
|
||||
*PasswordW=0;
|
||||
if (*PasswordW==0)
|
||||
{
|
||||
char PasswordA[MAXPASSWORD];
|
||||
*PasswordA=0;
|
||||
if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
|
||||
*PasswordA=0;
|
||||
GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW));
|
||||
cleandata(PasswordA,sizeof(PasswordA));
|
||||
}
|
||||
Cmd->Password.Set(PasswordW);
|
||||
cleandata(PasswordW,sizeof(PasswordW));
|
||||
}
|
||||
GetWideName(PasswordA,NULL,Cmd->Password,ASIZE(Cmd->Password));
|
||||
#else
|
||||
if (!GetPassword(PASSWORD_ARCHIVE,FileName,FileNameW,Cmd->Password,ASIZE(Cmd->Password)))
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
Close();
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
Cmd->DllError=ERAR_MISSING_PASSWORD;
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
#else
|
||||
if (!GetPassword(PASSWORD_ARCHIVE,FileName,FileNameW,&Cmd->Password))
|
||||
{
|
||||
Close();
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
|
||||
HeadersCrypt.SetCryptKeys(&Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
|
||||
Raw.SetCrypt(&HeadersCrypt);
|
||||
#endif
|
||||
}
|
||||
@@ -115,7 +130,7 @@ size_t Archive::ReadHeader()
|
||||
Log(FileName,St(MLogFileHead),"???");
|
||||
#endif
|
||||
BrokenFileHeader=true;
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -298,7 +313,7 @@ size_t Archive::ReadHeader()
|
||||
if (hd->HeadType==NEWSUB_HEAD && strlen(hd->FileName)<ASIZE(hd->FileName)-5)
|
||||
strcat(hd->FileName,"- ???");
|
||||
BrokenFileHeader=true;
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
|
||||
// If we have a broken encrypted header, we do not need to display
|
||||
// the error message here, because it will be displayed for such
|
||||
@@ -436,7 +451,7 @@ size_t Archive::ReadHeader()
|
||||
FailedHeaderDecryption=true;
|
||||
BrokenFileHeader=true;
|
||||
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
@@ -448,7 +463,7 @@ size_t Archive::ReadHeader()
|
||||
Log(FileName,St(MLogFileHead),"???");
|
||||
#endif
|
||||
BrokenFileHeader=true;
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return(0);
|
||||
}
|
||||
return(Raw.Size());
|
||||
@@ -691,7 +706,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MSubHeadCorrupt));
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return(false);
|
||||
}
|
||||
if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>/*PACK_VER*/36)
|
||||
@@ -715,8 +730,8 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
SubDataIO.SetUnpackToMemory(&(*UnpData)[0],SubHead.UnpSize);
|
||||
}
|
||||
if (SubHead.Flags & LHD_PASSWORD)
|
||||
if (*Cmd->Password!=0)
|
||||
SubDataIO.SetEncryption(SubHead.UnpVer,Cmd->Password,
|
||||
if (Cmd->Password.IsSet())
|
||||
SubDataIO.SetEncryption(SubHead.UnpVer,&Cmd->Password,
|
||||
(SubHead.Flags & LHD_SALT) ? SubHead.Salt:NULL,false,
|
||||
SubHead.UnpVer>=36);
|
||||
else
|
||||
@@ -737,7 +752,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||
#ifndef SHELL_EXT
|
||||
Log(FileName,St(MSubHeadDataCRC),SubHead.FileName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
if (UnpData!=NULL)
|
||||
UnpData->Reset();
|
||||
return(false);
|
||||
|
||||
@@ -19,6 +19,7 @@ template <class T> class Array
|
||||
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);}
|
||||
@@ -104,6 +105,14 @@ template <class T> void Array<T>::Reset()
|
||||
}
|
||||
|
||||
|
||||
// Reste 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();
|
||||
|
||||
@@ -5,7 +5,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
|
||||
@@ -29,14 +29,14 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
int fd = open(FileName,O_WRONLY);
|
||||
if (fd==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (NameSize>=sizeof(Name))
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
break;
|
||||
}
|
||||
memcpy(Name,CurItem+10,NameSize);
|
||||
@@ -59,7 +59,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
|
||||
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
break;
|
||||
}
|
||||
AttrPos+=10+NameSize+Size;
|
||||
@@ -79,7 +79,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
|
||||
if (fd==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
|
||||
if (NameSize>=sizeof(Name))
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
break;
|
||||
}
|
||||
memcpy(Name,CurItem+10,NameSize);
|
||||
@@ -102,7 +102,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
|
||||
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
break;
|
||||
}
|
||||
AttrPos+=10+NameSize+Size;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
|
||||
CommandData::CommandData()
|
||||
{
|
||||
FileArgs=ExclArgs=InclArgs=StoreArgs=ArcNames=NULL;
|
||||
@@ -15,6 +16,7 @@ CommandData::~CommandData()
|
||||
|
||||
void CommandData::Init()
|
||||
{
|
||||
RAROptions::Init();
|
||||
Close();
|
||||
|
||||
*Command=0;
|
||||
@@ -24,6 +26,9 @@ void CommandData::Init()
|
||||
FileLists=false;
|
||||
NoMoreSwitches=false;
|
||||
|
||||
ListMode=RCLM_AUTO;
|
||||
|
||||
|
||||
FileArgs=new StringList;
|
||||
ExclArgs=new StringList;
|
||||
InclArgs=new StringList;
|
||||
@@ -44,7 +49,92 @@ void CommandData::Close()
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SFX_MODULE)
|
||||
#ifdef CUSTOM_CMDLINE_PARSER
|
||||
// Return the pointer to next position in the string and store dynamically
|
||||
// allocated command line parameters in Unicode and ASCII in ParW and ParA.
|
||||
static const wchar *AllocCmdParam(const wchar *CmdLine,wchar **ParW,char **ParA)
|
||||
{
|
||||
const wchar *NextCmd=GetCmdParam(CmdLine,NULL,0);
|
||||
if (NextCmd==NULL)
|
||||
return NULL;
|
||||
size_t ParSize=NextCmd-CmdLine+2; // Parameter size including the trailing zero.
|
||||
*ParW=(wchar *)malloc(ParSize*sizeof(wchar));
|
||||
if (*ParW==NULL)
|
||||
return NULL;
|
||||
CmdLine=GetCmdParam(CmdLine,*ParW,ParSize);
|
||||
size_t ParSizeA=ParSize*2; // One Unicode char can be converted to several MBCS chars.
|
||||
*ParA=(char *)malloc(ParSizeA);
|
||||
if (*ParA==NULL)
|
||||
{
|
||||
free(*ParW);
|
||||
return NULL;
|
||||
}
|
||||
GetAsciiName(*ParW,*ParA,ParSizeA);
|
||||
return CmdLine;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void CommandData::PreprocessCommandLine(int argc, char *argv[])
|
||||
{
|
||||
#ifdef CUSTOM_CMDLINE_PARSER
|
||||
// In Windows we may prefer to implement our own command line parser
|
||||
// to avoid replacing \" by " in standard parser. Such replacing corrupts
|
||||
// destination paths like "dest path\" in extraction commands.
|
||||
const wchar *CmdLine=GetCommandLine();
|
||||
|
||||
wchar *ParW;
|
||||
char *ParA;
|
||||
for (bool FirstParam=true;;FirstParam=false)
|
||||
{
|
||||
if ((CmdLine=AllocCmdParam(CmdLine,&ParW,&ParA))==NULL)
|
||||
break;
|
||||
bool Code=FirstParam ? true:PreprocessSwitch(ParA);
|
||||
free(ParW);
|
||||
free(ParA);
|
||||
if (!Code)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
for (int I=1;I<argc;I++)
|
||||
if (!PreprocessSwitch(argv[I]))
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void CommandData::ParseCommandLine(int argc, char *argv[])
|
||||
{
|
||||
#ifdef CUSTOM_CMDLINE_PARSER
|
||||
// In Windows we may prefer to implement our own command line parser
|
||||
// to avoid replacing \" by " in standard parser. Such replacing corrupts
|
||||
// destination paths like "dest path\" in extraction commands.
|
||||
const wchar *CmdLine=GetCommandLine();
|
||||
|
||||
wchar *ParW;
|
||||
char *ParA;
|
||||
for (bool FirstParam=true;;FirstParam=false)
|
||||
{
|
||||
if ((CmdLine=AllocCmdParam(CmdLine,&ParW,&ParA))==NULL)
|
||||
break;
|
||||
if (!FirstParam) // First parameter is the executable name.
|
||||
ParseArg(ParA,ParW);
|
||||
free(ParW);
|
||||
free(ParA);
|
||||
}
|
||||
#else
|
||||
for (int I=1;I<argc;I++)
|
||||
ParseArg(argv[I],NULL);
|
||||
#endif
|
||||
ParseDone();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void CommandData::ParseArg(char *Arg,wchar *ArgW)
|
||||
{
|
||||
if (IsSwitch(*Arg) && !NoMoreSwitches)
|
||||
@@ -102,13 +192,14 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
|
||||
wcsncpyz(ExtrPathW,ArgW,ASIZE(ExtrPathW));
|
||||
}
|
||||
else
|
||||
if ((Add || CmdChar=='T') && *Arg!='@')
|
||||
if ((Add || CmdChar=='T') && (*Arg!='@' || ListMode==RCLM_REJECT_LISTS))
|
||||
FileArgs->AddString(Arg,ArgW);
|
||||
else
|
||||
{
|
||||
FindData FileData;
|
||||
bool Found=FindFile::FastFind(Arg,ArgW,&FileData);
|
||||
if (!Found && *Arg=='@' && !IsWildcard(Arg,ArgW))
|
||||
if ((!Found || ListMode==RCLM_ACCEPT_LISTS) &&
|
||||
ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg,ArgW))
|
||||
{
|
||||
FileLists=true;
|
||||
|
||||
@@ -161,47 +252,48 @@ void CommandData::ParseEnvVar()
|
||||
{
|
||||
char *EnvStr=getenv("RAR");
|
||||
if (EnvStr!=NULL)
|
||||
{
|
||||
ProcessSwitchesString(EnvStr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Return 'false' if -cfg- is present and preprocess switches
|
||||
// which must be processed before the rest of command line.
|
||||
#ifndef SFX_MODULE
|
||||
bool CommandData::IsConfigEnabled(int argc,char *argv[])
|
||||
// Preprocess those parameters, which must be processed before the rest of
|
||||
// command line. Return 'false' to stop further processing.
|
||||
bool CommandData::PreprocessSwitch(const char *Switch)
|
||||
{
|
||||
bool ConfigEnabled=true;
|
||||
for (int I=1;I<argc;I++)
|
||||
if (IsSwitch(*argv[I]))
|
||||
{
|
||||
if (stricomp(&argv[I][1],"-")==0)
|
||||
break;
|
||||
if (stricomp(&argv[I][1],"cfg-")==0)
|
||||
ConfigEnabled=false;
|
||||
if (IsSwitch(Switch[0]))
|
||||
{
|
||||
Switch++;
|
||||
if (stricomp(Switch,"-")==0) // Switch "--".
|
||||
return false;
|
||||
if (stricomp(Switch,"cfg-")==0)
|
||||
ConfigDisabled=true;
|
||||
#ifndef GUI
|
||||
if (strnicomp(&argv[I][1],"ilog",4)==0)
|
||||
{
|
||||
// Ensure that correct log file name is already set
|
||||
// if we need to report an error when processing the command line.
|
||||
ProcessSwitch(&argv[I][1]);
|
||||
InitLogOptions(LogName);
|
||||
}
|
||||
#endif
|
||||
if (strnicomp(&argv[I][1],"sc",2)==0)
|
||||
{
|
||||
// Process -sc before reading any file lists.
|
||||
ProcessSwitch(&argv[I][1]);
|
||||
}
|
||||
if (strnicomp(Switch,"ilog",4)==0)
|
||||
{
|
||||
// Ensure that correct log file name is already set
|
||||
// if we need to report an error when processing the command line.
|
||||
ProcessSwitch(Switch);
|
||||
InitLogOptions(LogName);
|
||||
}
|
||||
return(ConfigEnabled);
|
||||
#endif
|
||||
if (strnicomp(Switch,"sc",2)==0)
|
||||
{
|
||||
// Process -sc before reading any file lists.
|
||||
ProcessSwitch(Switch);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SFX_MODULE)
|
||||
void CommandData::ReadConfig(int argc,char *argv[])
|
||||
void CommandData::ReadConfig()
|
||||
{
|
||||
StringList List;
|
||||
if (ReadTextFile(DefConfigName,NULL,&List,true))
|
||||
@@ -242,13 +334,16 @@ void CommandData::ProcessSwitchesString(char *Str)
|
||||
|
||||
|
||||
#if !defined(SFX_MODULE)
|
||||
void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
void CommandData::ProcessSwitch(const char *Switch,const wchar *SwitchW)
|
||||
{
|
||||
|
||||
bool WidePresent=SwitchW!=NULL && *SwitchW!=0; // If 'true', SwitchW is not empty.
|
||||
|
||||
switch(etoupper(Switch[0]))
|
||||
{
|
||||
case '@':
|
||||
ListMode=Switch[1]=='+' ? RCLM_ACCEPT_LISTS:RCLM_REJECT_LISTS;
|
||||
break;
|
||||
case 'I':
|
||||
if (strnicomp(&Switch[1],"LOG",3)==0)
|
||||
{
|
||||
@@ -377,10 +472,21 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
case 'D':
|
||||
AppendArcNameToPath=true;
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case 'G':
|
||||
if (Switch[2]=='-' && Switch[3]==0)
|
||||
GenerateArcName=0;
|
||||
else
|
||||
{
|
||||
GenerateArcName=true;
|
||||
strncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'I':
|
||||
IgnoreGeneralAttr=true;
|
||||
break;
|
||||
case 'N': //reserved for archive name
|
||||
case 'N': // Reserved for archive name.
|
||||
break;
|
||||
case 'O':
|
||||
AddArcOnly=true;
|
||||
@@ -465,10 +571,14 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
case 'I':
|
||||
{
|
||||
Priority=atoi(Switch+2);
|
||||
char *ChPtr=strchr(Switch+2,':');
|
||||
if (Priority<0 || Priority>15)
|
||||
BadSwitch(Switch);
|
||||
const char *ChPtr=strchr(Switch+2,':');
|
||||
if (ChPtr!=NULL)
|
||||
{
|
||||
SleepTime=atoi(ChPtr+1);
|
||||
if (SleepTime>1000)
|
||||
BadSwitch(Switch);
|
||||
InitSystemOptions(SleepTime);
|
||||
}
|
||||
SetPriority(Priority);
|
||||
@@ -543,13 +653,16 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
case 'P':
|
||||
if (Switch[1]==0)
|
||||
{
|
||||
GetPassword(PASSWORD_GLOBAL,NULL,NULL,Password,ASIZE(Password));
|
||||
GetPassword(PASSWORD_GLOBAL,NULL,NULL,&Password);
|
||||
eprintf("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
CharToWide(Switch+1,Password,ASIZE(Password));
|
||||
Password[ASIZE(Password)-1]=0;
|
||||
wchar PlainPsw[MAXPASSWORD];
|
||||
CharToWide(Switch+1,PlainPsw,ASIZE(PlainPsw));
|
||||
PlainPsw[ASIZE(PlainPsw)-1]=0;
|
||||
Password.Set(PlainPsw);
|
||||
cleandata(PlainPsw,ASIZE(PlainPsw));
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
@@ -558,13 +671,16 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
EncryptHeaders=true;
|
||||
if (Switch[2]!=0)
|
||||
{
|
||||
CharToWide(Switch+2,Password,ASIZE(Password));
|
||||
Password[ASIZE(Password)-1]=0;
|
||||
wchar PlainPsw[MAXPASSWORD];
|
||||
CharToWide(Switch+2,PlainPsw,ASIZE(PlainPsw));
|
||||
PlainPsw[ASIZE(PlainPsw)-1]=0;
|
||||
Password.Set(PlainPsw);
|
||||
cleandata(PlainPsw,ASIZE(PlainPsw));
|
||||
}
|
||||
else
|
||||
if (*Password==0)
|
||||
if (!Password.IsSet())
|
||||
{
|
||||
GetPassword(PASSWORD_GLOBAL,NULL,NULL,Password,ASIZE(Password));
|
||||
GetPassword(PASSWORD_GLOBAL,NULL,NULL,&Password);
|
||||
eprintf("\n");
|
||||
}
|
||||
}
|
||||
@@ -572,21 +688,26 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
case 'Z':
|
||||
if (Switch[1]==0 && (!WidePresent || SwitchW[1]==0))
|
||||
{
|
||||
#ifndef GUI // stdin is not supported by WinRAR.
|
||||
// If comment file is not specified, we read data from stdin.
|
||||
strcpy(CommentFile,"stdin");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
|
||||
if (WidePresent)
|
||||
wcsncpyz(CommentFileW,SwitchW+1,ASIZE(CommentFileW));
|
||||
}
|
||||
strncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
|
||||
if (WidePresent)
|
||||
wcsncpyz(CommentFileW,SwitchW+1,ASIZE(CommentFileW));
|
||||
break;
|
||||
case 'M':
|
||||
switch(etoupper(Switch[1]))
|
||||
{
|
||||
case 'C':
|
||||
{
|
||||
char *Str=Switch+2;
|
||||
const char *Str=Switch+2;
|
||||
if (*Str=='-')
|
||||
for (int I=0;I<sizeof(FilterModes)/sizeof(FilterModes[0]);I++)
|
||||
for (uint I=0;I<ASIZE(FilterModes);I++)
|
||||
FilterModes[I].State=FILTER_DISABLE;
|
||||
else
|
||||
while (*Str)
|
||||
@@ -638,12 +759,9 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
char *Names=Switch+2,DefNames[512];
|
||||
if (*Names==0)
|
||||
{
|
||||
strcpy(DefNames,DefaultStoreList);
|
||||
Names=DefNames;
|
||||
}
|
||||
char StoreNames[1024];
|
||||
strncpyz(StoreNames,(Switch[2]==0 ? DefaultStoreList:Switch+2),ASIZE(StoreNames));
|
||||
char *Names=StoreNames;
|
||||
while (*Names!=0)
|
||||
{
|
||||
char *End=strchr(Names,';');
|
||||
@@ -663,10 +781,10 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef PACK_SMP
|
||||
#ifdef RAR_SMP
|
||||
case 'T':
|
||||
Threads=atoi(Switch+2);
|
||||
if (Threads>16)
|
||||
if (Threads>MaxPoolThreads || Threads<1)
|
||||
BadSwitch(Switch);
|
||||
else
|
||||
{
|
||||
@@ -697,64 +815,7 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
VolSize=0;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
int64 NewVolSize=atoil(&Switch[1]);
|
||||
|
||||
if (NewVolSize==0)
|
||||
NewVolSize=INT64NDF; // Autodetecting volume size.
|
||||
else
|
||||
switch (Switch[strlen(Switch)-1])
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
switch(NewVolSize)
|
||||
{
|
||||
case 360:
|
||||
NewVolSize=362496;
|
||||
break;
|
||||
case 720:
|
||||
NewVolSize=730112;
|
||||
break;
|
||||
case 1200:
|
||||
NewVolSize=1213952;
|
||||
break;
|
||||
case 1440:
|
||||
NewVolSize=1457664;
|
||||
break;
|
||||
case 2880:
|
||||
NewVolSize=2915328;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
NewVolSize*=1024;
|
||||
break;
|
||||
case 'm':
|
||||
NewVolSize*=1024*1024;
|
||||
break;
|
||||
case 'M':
|
||||
NewVolSize*=1000*1000;
|
||||
break;
|
||||
case 'g':
|
||||
NewVolSize*=1024*1024;
|
||||
NewVolSize*=1024;
|
||||
break;
|
||||
case 'G':
|
||||
NewVolSize*=1000*1000;
|
||||
NewVolSize*=1000;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
break;
|
||||
default:
|
||||
NewVolSize*=1000;
|
||||
break;
|
||||
}
|
||||
if (VolSize==0)
|
||||
VolSize=NewVolSize;
|
||||
else
|
||||
NextVolSizes.Push(NewVolSize);
|
||||
}
|
||||
VolSize=VOLSIZE_AUTO; // UnRAR -v switch for list command.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -879,7 +940,7 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
break;
|
||||
#ifndef GUI
|
||||
case '?' :
|
||||
OutHelp();
|
||||
OutHelp(RARX_SUCCESS);
|
||||
break;
|
||||
#endif
|
||||
default :
|
||||
@@ -891,10 +952,10 @@ void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void CommandData::BadSwitch(char *Switch)
|
||||
void CommandData::BadSwitch(const char *Switch)
|
||||
{
|
||||
mprintf(St(MUnknownOption),Switch);
|
||||
ErrHandler.Exit(USER_ERROR);
|
||||
ErrHandler.Exit(RARX_USERERROR);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -940,7 +1001,7 @@ inline bool CmpMSGID(MSGID i1,MSGID i2)
|
||||
#endif
|
||||
}
|
||||
|
||||
void CommandData::OutHelp()
|
||||
void CommandData::OutHelp(RAR_EXIT ExitCode)
|
||||
{
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
OutTitle();
|
||||
@@ -951,8 +1012,8 @@ void CommandData::OutHelp()
|
||||
#elif defined(UNRAR)
|
||||
// UnRAR switches definition.
|
||||
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
|
||||
MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,
|
||||
MCHelpSwm,MCHelpSwAC,MCHelpSwAD,MCHelpSwAI,MCHelpSwAP,
|
||||
MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,
|
||||
MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP,
|
||||
MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
|
||||
MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
|
||||
MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,
|
||||
@@ -1000,7 +1061,7 @@ void CommandData::OutHelp()
|
||||
if (CmpMSGID(Help[I],MCHelpSwOL))
|
||||
continue;
|
||||
#endif
|
||||
#ifndef PACK_SMP
|
||||
#ifndef RAR_SMP
|
||||
if (CmpMSGID(Help[I],MCHelpSwMT))
|
||||
continue;
|
||||
#endif
|
||||
@@ -1019,7 +1080,7 @@ void CommandData::OutHelp()
|
||||
mprintf(St(Help[I]));
|
||||
}
|
||||
mprintf("\n");
|
||||
ErrHandler.Exit(USER_ERROR);
|
||||
ErrHandler.Exit(ExitCode);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1086,7 +1147,7 @@ bool CommandData::ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool C
|
||||
if (CheckFullPath && IsFullPath(CurMask))
|
||||
{
|
||||
// We do not need to do the special "*\" processing here, because
|
||||
// onlike the "else" part of this "if", now we convert names to full
|
||||
// unlike the "else" part of this "if", now we convert names to full
|
||||
// format, so they all include the path, which is matched by "*\"
|
||||
// correctly. Moreover, removing "*\" from mask would break
|
||||
// the comparison, because now all names have the path.
|
||||
@@ -1235,18 +1296,21 @@ void CommandData::ProcessCommand()
|
||||
|
||||
const char *SingleCharCommands="FUADPXETK";
|
||||
if (Command[0]!=0 && Command[1]!=0 && strchr(SingleCharCommands,*Command)!=NULL || *ArcName==0)
|
||||
OutHelp();
|
||||
OutHelp(*Command==0 ? RARX_SUCCESS:RARX_USERERROR); // Return 'success' for 'rar' without parameters.
|
||||
|
||||
#ifdef _UNIX
|
||||
if (GetExt(ArcName)==NULL && (!FileExist(ArcName) || IsDir(GetFileAttr(ArcName))))
|
||||
strcat(ArcName,".rar");
|
||||
strncatz(ArcName,".rar",ASIZE(ArcName));
|
||||
#else
|
||||
if (GetExt(ArcName)==NULL)
|
||||
strcat(ArcName,".rar");
|
||||
strncatz(ArcName,".rar",ASIZE(ArcName));
|
||||
#endif
|
||||
|
||||
if (strchr("AFUMD",*Command)==NULL)
|
||||
{
|
||||
if (GenerateArcName)
|
||||
GenerateArchiveName(ArcName,ArcNameW,ASIZE(ArcName),GenerateMask,false);
|
||||
|
||||
StringList ArcMasks;
|
||||
ArcMasks.AddString(ArcName);
|
||||
ScanTree Scan(&ArcMasks,Recurse,SaveLinks,SCAN_SKIPDIRS);
|
||||
@@ -1276,7 +1340,7 @@ void CommandData::ProcessCommand()
|
||||
ListArchive(this);
|
||||
break;
|
||||
default:
|
||||
OutHelp();
|
||||
OutHelp(RARX_USERERROR);
|
||||
#endif
|
||||
}
|
||||
if (!BareOutput)
|
||||
@@ -1310,7 +1374,7 @@ bool CommandData::IsSwitch(int Ch)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint CommandData::GetExclAttr(char *Str)
|
||||
uint CommandData::GetExclAttr(const char *Str)
|
||||
{
|
||||
if (IsDigit(*Str))
|
||||
return(strtol(Str,NULL,0));
|
||||
|
||||
@@ -1,32 +1,39 @@
|
||||
#ifndef _RAR_CMDDATA_
|
||||
#define _RAR_CMDDATA_
|
||||
|
||||
|
||||
#define DefaultStoreList "7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;taz;tgz;z;zip"
|
||||
|
||||
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);
|
||||
void ProcessSwitch(const char *Switch,const wchar *SwitchW=NULL);
|
||||
void BadSwitch(const char *Switch);
|
||||
bool ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode);
|
||||
uint GetExclAttr(char *Str);
|
||||
uint GetExclAttr(const char *Str);
|
||||
|
||||
bool FileLists;
|
||||
bool NoMoreSwitches;
|
||||
RAR_CMD_LIST_MODE ListMode;
|
||||
bool BareOutput;
|
||||
public:
|
||||
CommandData();
|
||||
~CommandData();
|
||||
void Init();
|
||||
void Close();
|
||||
|
||||
void PreprocessCommandLine(int argc, char *argv[]);
|
||||
void ParseCommandLine(int argc, char *argv[]);
|
||||
void ParseArg(char *Arg,wchar *ArgW);
|
||||
void ParseDone();
|
||||
void ParseEnvVar();
|
||||
void ReadConfig(int argc,char *argv[]);
|
||||
bool IsConfigEnabled(int argc,char *argv[]);
|
||||
void ReadConfig();
|
||||
bool PreprocessSwitch(const char *Switch);
|
||||
void OutTitle();
|
||||
void OutHelp();
|
||||
void OutHelp(RAR_EXIT ExitCode);
|
||||
bool IsSwitch(int Ch);
|
||||
bool ExclCheck(char *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
|
||||
bool ExclDirByAttr(uint FileAttr);
|
||||
@@ -39,7 +46,7 @@ class CommandData:public RAROptions
|
||||
bool GetArcName(char *Name,wchar *NameW,int MaxSize);
|
||||
bool CheckWinSize();
|
||||
|
||||
int GetRecoverySize(char *Str,int DefSize);
|
||||
int GetRecoverySize(const char *Str,int DefSize);
|
||||
|
||||
char Command[NM+16];
|
||||
wchar CommandW[NM+16];
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
const uint TOP=1 << 24, BOT=1 << 15;
|
||||
|
||||
|
||||
class RangeCoder
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -6,7 +6,6 @@ class PackingFileTable;
|
||||
|
||||
#define MAX_LZ_MATCH 0x101
|
||||
|
||||
#define CODEBUFSIZE 0x4000
|
||||
#define MAXWINSIZE 0x400000
|
||||
#define MAXWINMASK (MAXWINSIZE-1)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ static int KbdAnsi(char *Addr,int Size);
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
|
||||
static uint GetKey();
|
||||
static byte GetKey();
|
||||
#endif
|
||||
|
||||
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
|
||||
@@ -26,10 +26,16 @@ void mprintf(const char *fmt,...)
|
||||
{
|
||||
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
|
||||
return;
|
||||
safebuf char Msg[MaxMsgSize];
|
||||
char Msg[MaxMsgSize];
|
||||
va_list argptr;
|
||||
va_start(argptr,fmt);
|
||||
vsprintf(Msg,fmt,argptr);
|
||||
vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
|
||||
|
||||
// Different vsnprintf implementation can return either -1 or >=MaxMsgSize
|
||||
// if string is truncated. So we do not check exit code and always zero
|
||||
// terminate the string for safety. It is faster than check for error.
|
||||
Msg[ASIZE(Msg)-1] = 0;
|
||||
|
||||
RawPrint(Msg,MsgStream);
|
||||
va_end(argptr);
|
||||
}
|
||||
@@ -44,7 +50,13 @@ void eprintf(const char *fmt,...)
|
||||
safebuf char Msg[MaxMsgSize];
|
||||
va_list argptr;
|
||||
va_start(argptr,fmt);
|
||||
vsprintf(Msg,fmt,argptr);
|
||||
vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
|
||||
|
||||
// Different vsnprintf implementation can return either -1 or >=MaxMsgSize
|
||||
// if string is truncated. So we do not check exit code and always zero
|
||||
// terminate the string for safety. It is faster than check for error.
|
||||
Msg[ASIZE(Msg)-1] = 0;
|
||||
|
||||
RawPrint(Msg,MSG_STDERR);
|
||||
va_end(argptr);
|
||||
}
|
||||
@@ -70,19 +82,21 @@ void RawPrint(char *Msg,MESSAGE_TYPE MessageType)
|
||||
#ifdef _WIN_ALL
|
||||
CharToOemA(Msg,Msg);
|
||||
|
||||
char OutMsg[MaxMsgSize],*OutPos=OutMsg;
|
||||
for (int I=0;Msg[I]!=0;I++)
|
||||
char OutMsg[MaxMsgSize];
|
||||
size_t OutPos=0;
|
||||
for (size_t I=0;Msg[I]!=0;I++)
|
||||
{
|
||||
if (Msg[I]=='\n' && (I==0 || Msg[I-1]!='\r'))
|
||||
*(OutPos++)='\r';
|
||||
*(OutPos++)=Msg[I];
|
||||
if (Msg[I]=='\n' && (I==0 || Msg[I-1]!='\r') && OutPos<ASIZE(OutMsg)-1)
|
||||
OutMsg[OutPos++]='\r';
|
||||
if (OutPos<ASIZE(OutMsg)-1)
|
||||
OutMsg[OutPos++]=Msg[I];
|
||||
}
|
||||
*OutPos=0;
|
||||
OutMsg[OutPos]=0;
|
||||
strcpy(Msg,OutMsg);
|
||||
#endif
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
char OutMsg[MaxMsgSize],*OutPos=OutMsg;
|
||||
for (int I=0;Msg[I]!=0;I++)
|
||||
for (size_t I=0;Msg[I]!=0;I++)
|
||||
if (Msg[I]!='\r')
|
||||
*(OutPos++)=Msg[I];
|
||||
*OutPos=0;
|
||||
@@ -133,6 +147,7 @@ void GetPasswordText(wchar *Str,uint MaxLength)
|
||||
strncpyz(StrA,getpass(""),ASIZE(StrA));
|
||||
#endif
|
||||
CharToWide(StrA,Str,MaxLength);
|
||||
cleandata(StrA,sizeof(StrA));
|
||||
#endif
|
||||
Str[MaxLength-1]=0;
|
||||
RemoveLF(Str);
|
||||
@@ -142,7 +157,8 @@ void GetPasswordText(wchar *Str,uint MaxLength)
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,wchar *Password,uint MaxLength)
|
||||
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,
|
||||
SecPassword *Password)
|
||||
{
|
||||
Alarm();
|
||||
while (true)
|
||||
@@ -161,23 +177,27 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,
|
||||
strcat(PromptStr,NameOnly);
|
||||
}
|
||||
eprintf("\n%s: ",PromptStr);
|
||||
GetPasswordText(Password,MaxLength);
|
||||
if (*Password==0 && Type==PASSWORD_GLOBAL)
|
||||
|
||||
wchar PlainPsw[MAXPASSWORD];
|
||||
GetPasswordText(PlainPsw,ASIZE(PlainPsw));
|
||||
if (*PlainPsw==0 && Type==PASSWORD_GLOBAL)
|
||||
return(false);
|
||||
if (Type==PASSWORD_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);
|
||||
@@ -186,7 +206,7 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,
|
||||
|
||||
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
uint GetKey()
|
||||
byte GetKey()
|
||||
{
|
||||
char Str[80];
|
||||
bool EndOfFile;
|
||||
@@ -201,9 +221,9 @@ uint GetKey()
|
||||
{
|
||||
// Looks like stdin is a null device. We can enter to infinite loop
|
||||
// calling Ask(), so let's better exit.
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
return(Str[0]);
|
||||
return (byte)Str[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -246,13 +266,13 @@ int Ask(const char *AskStr)
|
||||
eprintf("[%c]%s",Item[I][KeyPos],&Item[I][KeyPos+1]);
|
||||
}
|
||||
eprintf(" ");
|
||||
int Ch=GetKey();
|
||||
byte Ch=GetKey();
|
||||
#if defined(_WIN_ALL)
|
||||
OemToCharBuff((LPCSTR)&Ch,(LPTSTR)&Ch,1);
|
||||
OemToCharBuffA((LPCSTR)&Ch,(LPSTR)&Ch,1);
|
||||
#endif
|
||||
Ch=loctoupper(Ch);
|
||||
for (int I=0;I<NumItems;I++)
|
||||
if (Ch==Item[I][ItemKeyPos[I]])
|
||||
if (Ch==(byte)Item[I][ItemKeyPos[I]])
|
||||
return(I+1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound);
|
||||
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);
|
||||
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,SecPassword *Password);
|
||||
int Ask(const char *AskStr);
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,7 @@ void OutComment(char *Comment,size_t Size);
|
||||
#endif
|
||||
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 bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,SecPassword *Password) {return(false);}
|
||||
inline int Ask(const char *AskStr) {return(0);}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,16 +1,44 @@
|
||||
// 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"
|
||||
|
||||
// CRCTab duplicates crc_tables[0], but we still need it to decrypt
|
||||
// old version RAR archives. GUI code might use it for ZIP encryption.
|
||||
uint CRCTab[256];
|
||||
|
||||
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
|
||||
|
||||
void InitCRC()
|
||||
{
|
||||
for (int I=0;I<256;I++)
|
||||
for (uint I=0;I<256;I++) // Build the classic CRC32 lookup table.
|
||||
{
|
||||
uint C=I;
|
||||
for (int J=0;J<8;J++)
|
||||
for (uint J=0;J<8;J++)
|
||||
C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
|
||||
CRCTab[I]=C;
|
||||
CRCTab[I]=crc_tables[0][I]=C;
|
||||
}
|
||||
|
||||
for (uint I=0;I<=256;I++) // Build additional lookup tables.
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,36 +48,36 @@ uint CRC(uint StartCRC,const void *Addr,size_t Size)
|
||||
InitCRC();
|
||||
byte *Data=(byte *)Addr;
|
||||
|
||||
#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
|
||||
while (Size>0 && ((long)Data & 7))
|
||||
{
|
||||
StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
Size--;
|
||||
Data++;
|
||||
}
|
||||
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
|
||||
// Align Data to 8 for better performance.
|
||||
for (;Size>0 && ((long)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);
|
||||
#else
|
||||
StartCRC ^= *(uint32 *) Data;
|
||||
#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][Data[4]] ^
|
||||
crc_tables[2][Data[5]] ^
|
||||
crc_tables[1][Data[6]] ^
|
||||
crc_tables[0][Data[7]];
|
||||
}
|
||||
|
||||
for (;Size>0;Size--,Data++) // Process left data.
|
||||
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
|
||||
for (size_t I=0;I<Size;I++)
|
||||
StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
|
||||
return(StartCRC);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
// For RAR 1.4 archives in case somebody still has them.
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
byte *Data=(byte *)Addr;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef _RAR_CRC_
|
||||
#define _RAR_CRC_
|
||||
|
||||
extern uint CRCTab[256];
|
||||
|
||||
void InitCRC();
|
||||
uint CRC(uint StartCRC,const void *Addr,size_t Size);
|
||||
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size);
|
||||
|
||||
@@ -185,10 +185,12 @@ void CryptData::Swap(byte *Ch1,byte *Ch2)
|
||||
#endif
|
||||
|
||||
|
||||
void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
|
||||
void CryptData::SetCryptKeys(SecPassword *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
|
||||
{
|
||||
if (*Password==0)
|
||||
if (!Password->IsSet())
|
||||
return;
|
||||
wchar PlainPsw[MAXPASSWORD];
|
||||
Password->Get(PlainPsw,ASIZE(PlainPsw));
|
||||
if (OldOnly)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
@@ -198,7 +200,7 @@ void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt
|
||||
memset(Psw,0,sizeof(Psw));
|
||||
|
||||
// We need to use ASCII password for older encryption algorithms.
|
||||
WideToChar(Password,Psw,ASIZE(Psw));
|
||||
WideToChar(PlainPsw,Psw,ASIZE(Psw));
|
||||
Psw[ASIZE(Psw)-1]=0;
|
||||
|
||||
size_t PswLength=strlen(Psw);
|
||||
@@ -220,13 +222,15 @@ void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt
|
||||
}
|
||||
for (size_t I=0;I<PswLength;I+=16)
|
||||
EncryptBlock20((byte *)&Psw[I]);
|
||||
cleandata(Psw,sizeof(Psw));
|
||||
#endif
|
||||
cleandata(PlainPsw,sizeof(PlainPsw));
|
||||
return;
|
||||
}
|
||||
|
||||
bool Cached=false;
|
||||
for (uint I=0;I<ASIZE(Cache);I++)
|
||||
if (wcscmp(Cache[I].Password,Password)==0 &&
|
||||
if (Cache[I].Password==*Password &&
|
||||
(Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
|
||||
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&
|
||||
Cache[I].HandsOffHash==HandsOffHash)
|
||||
@@ -240,8 +244,8 @@ void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt
|
||||
if (!Cached)
|
||||
{
|
||||
byte RawPsw[2*MAXPASSWORD+SALT_SIZE];
|
||||
WideToRaw(Password,RawPsw);
|
||||
size_t RawLength=2*wcslen(Password);
|
||||
WideToRaw(PlainPsw,RawPsw);
|
||||
size_t RawLength=2*wcslen(PlainPsw);
|
||||
if (Salt!=NULL)
|
||||
{
|
||||
memcpy(RawPsw+RawLength,Salt,SALT_SIZE);
|
||||
@@ -273,15 +277,18 @@ void CryptData::SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt
|
||||
for (int J=0;J<4;J++)
|
||||
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
||||
|
||||
wcscpy(Cache[CachePos].Password,Password);
|
||||
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]));
|
||||
CachePos=(CachePos+1)%ASIZE(Cache);
|
||||
|
||||
cleandata(RawPsw,sizeof(RawPsw));
|
||||
}
|
||||
rin.init(Encrypt ? Rijndael::Encrypt : Rijndael::Decrypt,AESKey,AESInit);
|
||||
cleandata(PlainPsw,sizeof(PlainPsw));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,18 +9,18 @@ struct CryptKeyCacheItem
|
||||
#ifndef _SFX_RTL_
|
||||
CryptKeyCacheItem()
|
||||
{
|
||||
*Password=0;
|
||||
Password.Set(L"");
|
||||
}
|
||||
|
||||
~CryptKeyCacheItem()
|
||||
{
|
||||
memset(AESKey,0,sizeof(AESKey));
|
||||
memset(AESInit,0,sizeof(AESInit));
|
||||
memset(Password,0,sizeof(Password));
|
||||
memset(&Password,0,sizeof(Password));
|
||||
}
|
||||
#endif
|
||||
byte AESKey[16],AESInit[16];
|
||||
wchar Password[MAXPASSWORD];
|
||||
SecPassword Password;
|
||||
bool SaltPresent;
|
||||
byte Salt[SALT_SIZE];
|
||||
bool HandsOffHash;
|
||||
@@ -48,7 +48,7 @@ class CryptData
|
||||
static CryptKeyCacheItem Cache[4];
|
||||
static int CachePos;
|
||||
public:
|
||||
void SetCryptKeys(const wchar *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
|
||||
void SetCryptKeys(SecPassword *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
|
||||
void SetAV15Encryption();
|
||||
void SetCmt13Encryption();
|
||||
void EncryptBlock20(byte *Buf);
|
||||
|
||||
133
unrar/dll.cpp
133
unrar/dll.cpp
@@ -1,7 +1,7 @@
|
||||
#include "rar.hpp"
|
||||
#include "dll.hpp"
|
||||
|
||||
static int RarErrorToDll(int ErrCode);
|
||||
static int RarErrorToDll(RAR_EXIT ErrCode);
|
||||
|
||||
struct DataSet
|
||||
{
|
||||
@@ -33,10 +33,11 @@ HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
|
||||
|
||||
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("*");
|
||||
@@ -55,7 +56,7 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
Data->Cmd.Callback=r->Callback;
|
||||
Data->Cmd.UserData=r->UserData;
|
||||
|
||||
if (!Data->Arc.Open(r->ArcName,r->ArcNameW))
|
||||
if (!Data->Arc.Open(r->ArcName,r->ArcNameW,0))
|
||||
{
|
||||
r->OpenResult=ERAR_EOPEN;
|
||||
delete Data;
|
||||
@@ -86,11 +87,22 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||
Data->Extract.ExtractArchiveInit(&Data->Cmd,Data->Arc);
|
||||
return((HANDLE)Data);
|
||||
}
|
||||
catch (int ErrCode)
|
||||
catch (RAR_EXIT ErrCode)
|
||||
{
|
||||
r->OpenResult=RarErrorToDll(ErrCode);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,50 +117,26 @@ int PASCAL RARCloseArchive(HANDLE hArcData)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +159,7 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||
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))
|
||||
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)!=0)
|
||||
{
|
||||
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
|
||||
if (Code==0)
|
||||
@@ -218,9 +206,9 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||
Data->Arc.NewLhd.atime.GetLocal((RarLocalTime *) &D->atime);
|
||||
Data->Arc.NewLhd.arctime.GetLocal((RarLocalTime *) &D->arctime);
|
||||
}
|
||||
catch (int ErrCode)
|
||||
catch (RAR_EXIT ErrCode)
|
||||
{
|
||||
return(RarErrorToDll(ErrCode));
|
||||
return(Data->Cmd.DllError!=0 ? Data->Cmd.DllError:RarErrorToDll(ErrCode));
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -338,24 +326,31 @@ 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)
|
||||
while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 &&
|
||||
Data->Arc.GetHeaderType()==NEWSUB_HEAD)
|
||||
{
|
||||
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
|
||||
Data->Arc.SeekToNext();
|
||||
}
|
||||
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (int ErrCode)
|
||||
catch (RAR_EXIT ErrCode)
|
||||
{
|
||||
return(RarErrorToDll(ErrCode));
|
||||
return(Data->Cmd.DllError!=0 ? Data->Cmd.DllError:RarErrorToDll(ErrCode));
|
||||
}
|
||||
return(Data->Cmd.DllError);
|
||||
}
|
||||
@@ -419,11 +414,15 @@ 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
|
||||
|
||||
@@ -434,25 +433,23 @@ int PASCAL RARGetDllVersion()
|
||||
}
|
||||
|
||||
|
||||
static int RarErrorToDll(int ErrCode)
|
||||
static int RarErrorToDll(RAR_EXIT ErrCode)
|
||||
{
|
||||
switch(ErrCode)
|
||||
{
|
||||
case FATAL_ERROR:
|
||||
case RARX_FATAL:
|
||||
return(ERAR_EREAD);
|
||||
case CRC_ERROR:
|
||||
case RARX_CRC:
|
||||
return(ERAR_BAD_DATA);
|
||||
case WRITE_ERROR:
|
||||
case RARX_WRITE:
|
||||
return(ERAR_EWRITE);
|
||||
case OPEN_ERROR:
|
||||
case RARX_OPEN:
|
||||
return(ERAR_EOPEN);
|
||||
case CREATE_ERROR:
|
||||
case RARX_CREATE:
|
||||
return(ERAR_ECREATE);
|
||||
case MEMORY_ERROR:
|
||||
case RARX_MEMORY:
|
||||
return(ERAR_NO_MEMORY);
|
||||
case NO_PASSWORD_ERROR: //not in original
|
||||
return(ERAR_MISSING_PASSWORD);
|
||||
case SUCCESS:
|
||||
case RARX_SUCCESS:
|
||||
return(0);
|
||||
default:
|
||||
return(ERAR_UNKNOWN);
|
||||
|
||||
@@ -144,7 +144,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);
|
||||
|
||||
@@ -11,7 +11,7 @@ ErrorHandler::ErrorHandler()
|
||||
|
||||
void ErrorHandler::Clean()
|
||||
{
|
||||
ExitCode=SUCCESS;
|
||||
ExitCode=RARX_SUCCESS;
|
||||
ErrCount=0;
|
||||
EnableBreak=true;
|
||||
Silent=false;
|
||||
@@ -22,7 +22,7 @@ void ErrorHandler::Clean()
|
||||
void ErrorHandler::MemoryError()
|
||||
{
|
||||
MemoryErrorMsg();
|
||||
Throw(MEMORY_ERROR);
|
||||
Throw(RARX_MEMORY);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ void ErrorHandler::OpenError(const char *FileName,const wchar *FileNameW)
|
||||
{
|
||||
#ifndef SILENT
|
||||
OpenErrorMsg(FileName);
|
||||
Throw(OPEN_ERROR);
|
||||
Throw(RARX_OPEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void ErrorHandler::CloseError(const char *FileName,const wchar *FileNameW)
|
||||
}
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(FATAL_ERROR);
|
||||
Throw(RARX_FATAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ void ErrorHandler::ReadError(const char *FileName,const wchar *FileNameW)
|
||||
ReadErrorMsg(NULL,NULL,FileName,FileNameW);
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(FATAL_ERROR);
|
||||
Throw(RARX_FATAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ void ErrorHandler::WriteError(const char *ArcName,const wchar *ArcNameW,const ch
|
||||
WriteErrorMsg(ArcName,ArcNameW,FileName,FileNameW);
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(WRITE_ERROR);
|
||||
Throw(RARX_WRITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ void ErrorHandler::WriteErrorFAT(const char *FileName,const wchar *FileNameW)
|
||||
ErrMsg(NULL,St(MNTFSRequired),FileName);
|
||||
#endif
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
|
||||
Throw(WRITE_ERROR);
|
||||
Throw(RARX_WRITE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -126,7 +126,7 @@ void ErrorHandler::SeekError(const char *FileName,const wchar *FileNameW)
|
||||
}
|
||||
#endif
|
||||
#if !defined(SILENT) || defined(RARDLL)
|
||||
Throw(FATAL_ERROR);
|
||||
Throw(RARX_FATAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ void ErrorHandler::WriteErrorMsg(const char *ArcName,const wchar *ArcNameW,const
|
||||
}
|
||||
|
||||
|
||||
void ErrorHandler::Exit(int ExitCode)
|
||||
void ErrorHandler::Exit(RAR_EXIT ExitCode)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
Alarm();
|
||||
@@ -260,18 +260,18 @@ void ErrorHandler::ErrMsg(const char *ArcName,const char *fmt,...)
|
||||
#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_FATAL:
|
||||
if (ExitCode==RARX_SUCCESS || ExitCode==RARX_WARNING)
|
||||
ExitCode=RARX_FATAL;
|
||||
break;
|
||||
default:
|
||||
ExitCode=Code;
|
||||
@@ -308,7 +308,7 @@ void _stdfunction ProcessSignal(int SigType)
|
||||
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE) && !defined(RARDLL)
|
||||
ExtRes.UnloadDLL();
|
||||
#endif
|
||||
exit(USER_BREAK);
|
||||
exit(RARX_USERBREAK);
|
||||
#if defined(_WIN_ALL) && !defined(_MSC_VER)
|
||||
// never reached, just to avoid a compiler warning
|
||||
return(TRUE);
|
||||
@@ -332,9 +332,9 @@ void ErrorHandler::SetSignalHandlers(bool Enable)
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
@@ -389,9 +389,12 @@ 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)
|
||||
Log(NULL,"\n%s",err);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,34 @@
|
||||
#ifndef _RAR_ERRHANDLER_
|
||||
#define _RAR_ERRHANDLER_
|
||||
|
||||
#if (defined(GUI) || !defined(_WIN_ALL)) && !defined(SFX_MODULE) && !defined(_WIN_CE) || defined(RARDLL)
|
||||
#ifndef SFX_MODULE
|
||||
#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_USERBREAK = 255
|
||||
};
|
||||
|
||||
class ErrorHandler
|
||||
{
|
||||
private:
|
||||
void ErrMsg(const char *ArcName,const char *fmt,...);
|
||||
|
||||
int ExitCode;
|
||||
RAR_EXIT ExitCode;
|
||||
int ErrCount;
|
||||
bool EnableBreak;
|
||||
bool Silent;
|
||||
@@ -43,12 +54,12 @@ class ErrorHandler
|
||||
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);}
|
||||
void Exit(RAR_EXIT ExitCode);
|
||||
void SetErrorCode(RAR_EXIT Code);
|
||||
RAR_EXIT GetErrorCode() {return(ExitCode);}
|
||||
int 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();
|
||||
|
||||
@@ -2,20 +2,28 @@
|
||||
|
||||
CmdExtract::CmdExtract()
|
||||
{
|
||||
*ArcName=0;
|
||||
*ArcNameW=0;
|
||||
|
||||
*DestFileName=0;
|
||||
*DestFileNameW=0;
|
||||
|
||||
TotalFileCount=0;
|
||||
*Password=0;
|
||||
Password.Set(L"");
|
||||
|
||||
//next two lines added by me
|
||||
Buffer = NULL;
|
||||
BufferSize = 0;
|
||||
|
||||
Password.Set(L"");
|
||||
Unp=new Unpack(&DataIO);
|
||||
Unp->Init(NULL);
|
||||
Unp->Init();
|
||||
}
|
||||
|
||||
|
||||
CmdExtract::~CmdExtract()
|
||||
{
|
||||
delete Unp;
|
||||
memset(Password,0,sizeof(Password));
|
||||
}
|
||||
|
||||
|
||||
@@ -34,14 +42,14 @@ void CmdExtract::DoExtract(CommandData *Cmd)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
wchar PrevCmdPassword[MAXPASSWORD];
|
||||
wcscpy(PrevCmdPassword,Cmd->Password);
|
||||
SecPassword PrevCmdPassword;
|
||||
PrevCmdPassword=Cmd->Password;
|
||||
|
||||
EXTRACT_ARC_CODE Code=ExtractArchive(Cmd);
|
||||
|
||||
// Restore Cmd->Password, which could be changed in IsArchive() call
|
||||
// for next header encrypted archive.
|
||||
wcscpy(Cmd->Password,PrevCmdPassword);
|
||||
Cmd->Password=PrevCmdPassword;
|
||||
|
||||
if (Code!=EXTRACT_ARC_REPEAT)
|
||||
break;
|
||||
@@ -56,7 +64,7 @@ void CmdExtract::DoExtract(CommandData *Cmd)
|
||||
{
|
||||
mprintf(St(MExtrNoFiles));
|
||||
}
|
||||
ErrHandler.SetErrorCode(NO_FILES_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_NOFILES);
|
||||
}
|
||||
#ifndef GUI
|
||||
else
|
||||
@@ -82,9 +90,9 @@ void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc)
|
||||
FirstFile=true;
|
||||
#endif
|
||||
|
||||
if (*Cmd->Password!=0)
|
||||
wcscpy(Password,Cmd->Password);
|
||||
PasswordAll=(*Cmd->Password!=0);
|
||||
PasswordAll=(Cmd->Password.IsSet());
|
||||
if (PasswordAll)
|
||||
Password=Cmd->Password;
|
||||
|
||||
DataIO.UnpVolume=false;
|
||||
|
||||
@@ -103,7 +111,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
|
||||
Archive Arc(Cmd);
|
||||
if (!Arc.WOpen(ArcName,ArcNameW))
|
||||
{
|
||||
ErrHandler.SetErrorCode(OPEN_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_OPEN);
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
}
|
||||
|
||||
@@ -113,7 +121,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
|
||||
mprintf(St(MNotRAR),ArcName);
|
||||
#endif
|
||||
if (CmpExt(ArcName,"rar"))
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return(EXTRACT_ARC_NEXT);
|
||||
}
|
||||
|
||||
@@ -169,6 +177,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
|
||||
if (*Cmd->Command=='T' || *Cmd->Command=='I')
|
||||
Cmd->Test=true;
|
||||
|
||||
|
||||
#ifndef GUI
|
||||
if (*Cmd->Command=='I')
|
||||
Cmd->DisablePercentage=true;
|
||||
@@ -223,7 +232,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
#else
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return(false);
|
||||
}
|
||||
SignatureFound=false;
|
||||
@@ -255,7 +264,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
#ifndef NOVOLUME
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return(false);
|
||||
}
|
||||
SignatureFound=false;
|
||||
@@ -357,7 +366,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
|
||||
Arc.ConvertAttributes();
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
#if !defined(SFX_MODULE) && !defined(RARDLL)
|
||||
if ((Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 && FirstFile)
|
||||
{
|
||||
char CurVolName[NM];
|
||||
@@ -391,6 +400,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
strcpy(ArcName,CurVolName);
|
||||
}
|
||||
#endif
|
||||
|
||||
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0;
|
||||
DataIO.NextVolumeMissing=false;
|
||||
|
||||
@@ -409,7 +419,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_BAD_DATA;
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(OPEN_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_OPEN);
|
||||
}
|
||||
ExactMatch=false;
|
||||
}
|
||||
@@ -421,26 +431,40 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
{
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
|
||||
#ifndef RARDLL
|
||||
if (*Password==0)
|
||||
if (!Password.IsSet())
|
||||
#endif
|
||||
{
|
||||
#ifdef RARDLL
|
||||
if (*Cmd->Password==0)
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
char PasswordA[MAXPASSWORD];
|
||||
|
||||
if (Cmd->Callback==NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
|
||||
if (Cmd->Callback!=NULL)
|
||||
{
|
||||
wchar PasswordW[MAXPASSWORD];
|
||||
*PasswordW=0;
|
||||
if (Cmd->Callback(UCM_NEEDPASSWORDW,Cmd->UserData,(LPARAM)PasswordW,ASIZE(PasswordW))==-1)
|
||||
*PasswordW=0;
|
||||
if (*PasswordW==0)
|
||||
{
|
||||
char PasswordA[MAXPASSWORD];
|
||||
*PasswordA=0;
|
||||
if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
|
||||
*PasswordA=0;
|
||||
GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW));
|
||||
cleandata(PasswordA,sizeof(PasswordA));
|
||||
}
|
||||
Cmd->Password.Set(PasswordW);
|
||||
cleandata(PasswordW,sizeof(PasswordW));
|
||||
}
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
Cmd->DllError = ERAR_MISSING_PASSWORD; //added by me
|
||||
return(false);
|
||||
return false;
|
||||
}
|
||||
GetWideName(PasswordA,NULL,Cmd->Password,ASIZE(Cmd->Password));
|
||||
}
|
||||
wcscpy(Password,Cmd->Password);
|
||||
Password=Cmd->Password;
|
||||
|
||||
#else
|
||||
if (!GetPassword(PASSWORD_FILE,ArcFileName,ArcFileNameW,Password,ASIZE(Password)))
|
||||
if (!GetPassword(PASSWORD_FILE,ArcFileName,ArcFileNameW,&Password))
|
||||
{
|
||||
PasswordCancelled=true;
|
||||
return(false);
|
||||
@@ -455,9 +479,9 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll)))
|
||||
{
|
||||
case -1:
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
case 2:
|
||||
if (!GetPassword(PASSWORD_FILE,ArcFileName,ArcFileNameW,Password,ASIZE(Password)))
|
||||
if (!GetPassword(PASSWORD_FILE,ArcFileName,ArcFileNameW,&Password))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
@@ -614,9 +638,9 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
}
|
||||
|
||||
// Skip encrypted file if no password is specified.
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && *Password==0)
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && !Password.IsSet())
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_MISSING_PASSWORD;
|
||||
#endif
|
||||
@@ -654,7 +678,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
#endif
|
||||
#endif
|
||||
ExtrFile=false;
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
#endif
|
||||
@@ -690,12 +714,17 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
DirExist=FileExist(DestFileName,DestNameW);
|
||||
if (DirExist && !IsDir(GetFileAttr(DestFileName,DestNameW)))
|
||||
{
|
||||
// File with name same as this directory exists. Propose user
|
||||
// to overwrite it.
|
||||
bool UserReject;
|
||||
FileCreate(Cmd,NULL,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime);
|
||||
DirExist=false;
|
||||
}
|
||||
CreatePath(DestFileName,DestNameW,true);
|
||||
MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
|
||||
if (!DirExist)
|
||||
{
|
||||
CreatePath(DestFileName,DestNameW,true);
|
||||
MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
|
||||
}
|
||||
}
|
||||
if (MDCode==MKDIR_SUCCESS)
|
||||
{
|
||||
@@ -720,7 +749,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_ECREATE;
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
}
|
||||
if (PrevExtracted)
|
||||
{
|
||||
@@ -747,25 +776,33 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
if ((Command=='E' || Command=='X') && ExtrFile && !Cmd->Test)
|
||||
{
|
||||
bool UserReject;
|
||||
if (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime))
|
||||
// Specify "write only" mode to avoid OpenIndiana NAS problems
|
||||
// with SetFileTime and read+write files.
|
||||
if (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime,true))
|
||||
{
|
||||
ExtrFile=false;
|
||||
if (!UserReject)
|
||||
{
|
||||
ErrHandler.CreateErrorMsg(Arc.FileName,Arc.FileNameW,DestFileName,DestFileNameW);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_ECREATE;
|
||||
#endif
|
||||
if (!IsNameUsable(DestFileName))
|
||||
if (!IsNameUsable(DestFileName) && (!WideName || !IsNameUsable(DestNameW)))
|
||||
{
|
||||
Log(Arc.FileName,St(MCorrectingName));
|
||||
char OrigName[sizeof(DestFileName)];
|
||||
char OrigName[ASIZE(DestFileName)];
|
||||
wchar OrigNameW[ASIZE(DestFileNameW)];
|
||||
strncpyz(OrigName,DestFileName,ASIZE(OrigName));
|
||||
wcsncpyz(OrigNameW,NullToEmpty(DestNameW),ASIZE(OrigNameW));
|
||||
|
||||
MakeNameUsable(DestFileName,true);
|
||||
CreatePath(DestFileName,NULL,true);
|
||||
if (FileCreate(Cmd,&CurFile,DestFileName,NULL,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime))
|
||||
|
||||
if (WideName)
|
||||
MakeNameUsable(DestNameW,true);
|
||||
|
||||
CreatePath(DestFileName,DestNameW,true);
|
||||
if (FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime,true))
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
Log(Arc.FileName,St(MRenaming),OrigName,DestFileName);
|
||||
@@ -789,6 +826,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
}
|
||||
if (ExtrFile)
|
||||
{
|
||||
|
||||
if (!SkipSolid)
|
||||
{
|
||||
if (!TestMode && Command!='P' && CurFile.IsDevice())
|
||||
@@ -827,23 +865,29 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff;
|
||||
DataIO.PackedCRC=0xffffffff;
|
||||
|
||||
wchar FilePassword[MAXPASSWORD];
|
||||
SecPassword FilePassword;
|
||||
#ifdef _WIN_ALL
|
||||
if (Arc.NewLhd.HostOS==HOST_MSDOS/* && Arc.NewLhd.UnpVer<=25*/)
|
||||
{
|
||||
// We need the password in OEM encoding if file was encrypted by
|
||||
// native RAR/DOS (not extender based). Let's make the conversion.
|
||||
wchar PlainPsw[MAXPASSWORD];
|
||||
Password.Get(PlainPsw,ASIZE(PlainPsw));
|
||||
char PswA[MAXPASSWORD];
|
||||
CharToOemBuffW(Password,PswA,ASIZE(PswA));
|
||||
CharToWide(PswA,FilePassword,ASIZE(FilePassword));
|
||||
FilePassword[ASIZE(FilePassword)-1]=0;
|
||||
CharToOemBuffW(PlainPsw,PswA,ASIZE(PswA));
|
||||
PswA[ASIZE(PswA)-1]=0;
|
||||
CharToWide(PswA,PlainPsw,ASIZE(PlainPsw));
|
||||
PlainPsw[ASIZE(PlainPsw)-1]=0;
|
||||
FilePassword.Set(PlainPsw);
|
||||
cleandata(PlainPsw,sizeof(PlainPsw));
|
||||
cleandata(PswA,sizeof(PswA));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
wcscpy(FilePassword,Password);
|
||||
FilePassword=Password;
|
||||
|
||||
DataIO.SetEncryption(
|
||||
(Arc.NewLhd.Flags & LHD_PASSWORD)!=0 ? Arc.NewLhd.UnpVer:0,FilePassword,
|
||||
(Arc.NewLhd.Flags & LHD_PASSWORD)!=0 ? Arc.NewLhd.UnpVer:0,&FilePassword,
|
||||
(Arc.NewLhd.Flags & LHD_SALT)!=0 ? Arc.NewLhd.Salt:NULL,false,
|
||||
Arc.NewLhd.UnpVer>=36);
|
||||
DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
|
||||
@@ -880,8 +924,8 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
// if (Arc.IsOpened())
|
||||
Arc.SeekToNext();
|
||||
|
||||
bool ValidCRC=Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC) ||
|
||||
!Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff);
|
||||
bool ValidCRC=Arc.OldFormat && GET_UINT32(DataIO.UnpFileCRC)==GET_UINT32(Arc.NewLhd.FileCRC) ||
|
||||
!Arc.OldFormat && GET_UINT32(DataIO.UnpFileCRC)==GET_UINT32(Arc.NewLhd.FileCRC^0xffffffff);
|
||||
|
||||
// We set AnySolidDataUnpackedWell to true if we found at least one
|
||||
// valid non-zero solid file in preceding solid stream. If it is true
|
||||
@@ -914,9 +958,12 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderS
|
||||
Log(Arc.FileName,St(MCRCFailed),ArcFileName);
|
||||
}
|
||||
BrokenFile=true;
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
#ifdef RARDLL
|
||||
Cmd->DllError=ERAR_BAD_DATA;
|
||||
// If we already have ERAR_EOPEN as result of missing volume,
|
||||
// we should not replace it with less precise ERAR_BAD_DATA.
|
||||
if (Cmd->DllError!=ERAR_EOPEN)
|
||||
Cmd->DllError=ERAR_BAD_DATA;
|
||||
#endif
|
||||
Alarm();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class CmdExtract
|
||||
char ArcName[NM];
|
||||
wchar ArcNameW[NM];
|
||||
|
||||
wchar Password[MAXPASSWORD];
|
||||
SecPassword Password;
|
||||
bool PasswordAll;
|
||||
bool PrevExtracted;
|
||||
char DestFileName[NM];
|
||||
|
||||
@@ -21,7 +21,7 @@ bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
|
||||
#else
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command)) //command irrelevant
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return false;
|
||||
}
|
||||
SignatureFound=false;
|
||||
@@ -45,15 +45,21 @@ bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
|
||||
if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
|
||||
{
|
||||
char CurVolName[NM];
|
||||
/* are these first two needed? */
|
||||
wcsncpyz(ArcNameW, Arc.FileNameW, ASIZE(ArcNameW));
|
||||
strncpyz(ArcName, Arc.FileName, NM);
|
||||
strncpyz(CurVolName, ArcName, sizeof CurVolName);
|
||||
|
||||
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
|
||||
if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
||||
bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0;
|
||||
VolNameToFirstName(ArcName,ArcName,NewNumbering);
|
||||
if (*ArcNameW!=0)
|
||||
VolNameToFirstName(ArcNameW,ArcNameW,NewNumbering);
|
||||
|
||||
if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName,ArcNameW))
|
||||
{
|
||||
*ArcNameW=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;
|
||||
@@ -67,25 +73,38 @@ bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
|
||||
|
||||
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
|
||||
{
|
||||
if (*Cmd->Password==0)
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
char PasswordA[MAXPASSWORD];
|
||||
|
||||
if (Cmd->Callback==NULL ||
|
||||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
|
||||
if (Cmd->Callback!=NULL)
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
Cmd->DllError = ERAR_MISSING_PASSWORD;
|
||||
wchar PasswordW[MAXPASSWORD];
|
||||
*PasswordW=0;
|
||||
if (Cmd->Callback(UCM_NEEDPASSWORDW,Cmd->UserData,(LPARAM)PasswordW,ASIZE(PasswordW))==-1)
|
||||
*PasswordW=0;
|
||||
if (*PasswordW==0)
|
||||
{
|
||||
char PasswordA[MAXPASSWORD];
|
||||
*PasswordA=0;
|
||||
if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
|
||||
*PasswordA=0;
|
||||
GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW));
|
||||
cleandata(PasswordA,sizeof(PasswordA));
|
||||
}
|
||||
Cmd->Password.Set(PasswordW);
|
||||
cleandata(PasswordW,sizeof(PasswordW));
|
||||
}
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
Cmd->DllError = ERAR_MISSING_PASSWORD; //added by me
|
||||
return false;
|
||||
}
|
||||
GetWideName(PasswordA,NULL,Cmd->Password,ASIZE(Cmd->Password));
|
||||
}
|
||||
}
|
||||
wcscpy(Password,Cmd->Password);
|
||||
Password=Cmd->Password;
|
||||
}
|
||||
|
||||
if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
|
||||
{
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
|
||||
return false;
|
||||
}
|
||||
@@ -101,7 +120,7 @@ bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
|
||||
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_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);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize,
|
||||
uint FileTime)
|
||||
uint FileTime,bool WriteOnly)
|
||||
{
|
||||
if (UserReject!=NULL)
|
||||
*UserReject=false;
|
||||
@@ -121,14 +121,15 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
continue;
|
||||
}
|
||||
if (Choice==6)
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
}
|
||||
if (NewFile!=NULL && NewFile->Create(Name,NameW))
|
||||
uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
|
||||
if (NewFile!=NULL && NewFile->Create(Name,NameW,FileMode))
|
||||
return(true);
|
||||
PrepareToDelete(Name,NameW);
|
||||
CreatePath(Name,NameW,true);
|
||||
return(NewFile!=NULL ? NewFile->Create(Name,NameW):DelFile(Name,NameW));
|
||||
return(NewFile!=NULL ? NewFile->Create(Name,NameW,FileMode):DelFile(Name,NameW));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
|
||||
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize=INT64NDF,
|
||||
uint FileTime=0);
|
||||
uint FileTime=0,bool WriteOnly=false);
|
||||
bool GetAutoRenamedName(char *Name,wchar *NameW);
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE)
|
||||
|
||||
@@ -20,6 +20,7 @@ File::File()
|
||||
AllowExceptions=true;
|
||||
#ifdef _WIN_ALL
|
||||
NoSequentialRead=false;
|
||||
CreateMode=FMF_UNDEFINED;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -45,15 +46,16 @@ void File::operator = (File &SrcFile)
|
||||
}
|
||||
|
||||
|
||||
bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
|
||||
bool File::Open(const char *Name,const wchar *NameW,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;
|
||||
if (OpenShared)
|
||||
@@ -67,7 +69,7 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
|
||||
if (hNewFile==BAD_HANDLE && GetLastError()==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)
|
||||
@@ -85,14 +87,14 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,Update ? UPDATEBINARY:READBINARY);
|
||||
hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
|
||||
if (hNewFile==BAD_HANDLE && errno==ENOENT)
|
||||
ErrorType=FILE_NOTFOUND;
|
||||
#endif
|
||||
@@ -107,7 +109,7 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
|
||||
// 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).
|
||||
// FileName like Arc.Open(Arc.FileName,Arc.FileNameW,...).
|
||||
if (NameW!=NULL)
|
||||
memmove(FileNameW,NameW,(wcslen(NameW)+1)*sizeof(*NameW));
|
||||
else
|
||||
@@ -126,7 +128,7 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
|
||||
void File::TOpen(const char *Name,const wchar *NameW)
|
||||
{
|
||||
if (!WOpen(Name,NameW))
|
||||
ErrHandler.Exit(OPEN_ERROR);
|
||||
ErrHandler.Exit(RARX_OPEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -140,18 +142,24 @@ bool File::WOpen(const char *Name,const wchar *NameW)
|
||||
}
|
||||
|
||||
|
||||
bool File::Create(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
bool File::Create(const char *Name,const wchar *NameW,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;
|
||||
CreateMode=Mode;
|
||||
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ|GENERIC_WRITE;
|
||||
DWORD ShareMode=ShareRead ? FILE_SHARE_READ:0;
|
||||
if (WinNT() && NameW!=NULL && *NameW!=0)
|
||||
hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
|
||||
CREATE_ALWAYS,0,NULL);
|
||||
hFile=CreateFileW(NameW,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
|
||||
else
|
||||
hFile=CreateFileA(Name,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
|
||||
CREATE_ALWAYS,0,NULL);
|
||||
hFile=CreateFileA(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
|
||||
#else
|
||||
hFile=fopen(Name,CREATEBINARY);
|
||||
hFile=fopen(Name,WriteMode ? WRITEBINARY:CREATEBINARY);
|
||||
#endif
|
||||
NewFile=true;
|
||||
HandleType=FILE_HANDLENORMAL;
|
||||
@@ -182,19 +190,19 @@ void File::AddFileToList(FileHandle hFile)
|
||||
|
||||
|
||||
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
|
||||
void File::TCreate(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
void File::TCreate(const char *Name,const wchar *NameW,uint Mode)
|
||||
{
|
||||
if (!WCreate(Name,NameW,ShareRead))
|
||||
ErrHandler.Exit(FATAL_ERROR);
|
||||
if (!WCreate(Name,NameW,Mode))
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool File::WCreate(const char *Name,const wchar *NameW,bool ShareRead)
|
||||
bool File::WCreate(const char *Name,const wchar *NameW,uint Mode)
|
||||
{
|
||||
if (Create(Name,NameW,ShareRead))
|
||||
if (Create(Name,NameW,Mode))
|
||||
return(true);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
ErrHandler.CreateErrorMsg(Name,NameW);
|
||||
return(false);
|
||||
}
|
||||
@@ -498,6 +506,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 = fileno(hFile);
|
||||
if (fd >= 0)
|
||||
fallocate(fd, 0, 0, Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -528,6 +544,12 @@ 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();
|
||||
|
||||
@@ -24,6 +24,27 @@ struct FileStat
|
||||
};
|
||||
|
||||
|
||||
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,
|
||||
|
||||
// Provide read access to created file for other programs.
|
||||
FMF_SHAREREAD=8,
|
||||
|
||||
// Mode flags are not defined yet.
|
||||
FMF_UNDEFINED=256
|
||||
};
|
||||
|
||||
|
||||
class File
|
||||
{
|
||||
private:
|
||||
@@ -39,9 +60,10 @@ 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];
|
||||
@@ -53,12 +75,12 @@ class File
|
||||
File();
|
||||
virtual ~File();
|
||||
void operator = (File &SrcFile);
|
||||
bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false);
|
||||
bool Open(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_READ);
|
||||
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);
|
||||
bool Create(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||
void TCreate(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||
bool WCreate(const char *Name,const wchar *NameW=NULL,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
|
||||
bool Close();
|
||||
void Flush();
|
||||
bool Delete();
|
||||
|
||||
@@ -70,7 +70,9 @@ bool CreatePath(const char *Path,bool SkipLastName)
|
||||
if (s-Path>=NM)
|
||||
break;
|
||||
|
||||
if (*s==CPATHDIVIDER)
|
||||
// Process all kinds of path separators, so user can enter Unix style
|
||||
// path in Windows or Windows in Unix.
|
||||
if (IsPathDiv(*s))
|
||||
{
|
||||
char DirName[NM];
|
||||
strncpy(DirName,Path,s-Path);
|
||||
@@ -113,7 +115,9 @@ bool CreatePath(const wchar *Path,bool SkipLastName)
|
||||
if (s-Path>=NM)
|
||||
break;
|
||||
|
||||
if (*s==CPATHDIVIDER)
|
||||
// Process all kinds of path separators, so user can enter Unix style
|
||||
// path in Windows or Windows in Unix.
|
||||
if (IsPathDiv(*s))
|
||||
{
|
||||
wchar DirName[NM];
|
||||
wcsncpy(DirName,Path,s-Path);
|
||||
@@ -450,56 +454,6 @@ bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr)
|
||||
}
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
return(Name);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
wchar *MkTemp(wchar *Name)
|
||||
{
|
||||
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();
|
||||
|
||||
for (uint Attempt=0;;Attempt++)
|
||||
{
|
||||
sprintfw(Name+Length-6,7,L"%06u",(Random+Attempt)%1000000);
|
||||
Name[Length-4]='.';
|
||||
if (!FileExist(NULL,Name))
|
||||
break;
|
||||
if (Attempt==1000)
|
||||
return(NULL);
|
||||
}
|
||||
return(Name);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
@@ -579,6 +533,8 @@ bool DelFile(const char *Name,const wchar *NameW)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
|
||||
bool SetFileCompression(char *Name,wchar *NameW,bool State)
|
||||
{
|
||||
|
||||
@@ -28,8 +28,6 @@ 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);
|
||||
|
||||
enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL};
|
||||
uint CalcFileCRC(File *SrcFile,int64 Size=INT64NDF,CALCCRC_SHOWMODE ShowMode=CALCCRC_SHOWNONE);
|
||||
|
||||
@@ -35,12 +35,12 @@ bool ReadTextFile(
|
||||
File SrcFile;
|
||||
if (FileName!=NULL && *FileName!=0 || FileNameW!=NULL && *FileNameW!=0)
|
||||
{
|
||||
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName,FileNameW):SrcFile.Open(FileName,FileNameW);
|
||||
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName,FileNameW):SrcFile.Open(FileName,FileNameW,0);
|
||||
|
||||
if (!OpenCode)
|
||||
{
|
||||
if (AbortOnError)
|
||||
ErrHandler.Exit(OPEN_ERROR);
|
||||
ErrHandler.Exit(RARX_OPEN);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@ EXTVAR ErrorHandler ErrHandler;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
// 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
|
||||
// or other flags changing the size of main header. RAR expects the fixed
|
||||
// size of main header preceding the comment if MHD_COMMENT is found.
|
||||
#define MHD_COMMENT 0x0002U
|
||||
|
||||
@@ -69,15 +69,15 @@
|
||||
#define LHD_SALT 0x0400U
|
||||
#define LHD_VERSION 0x0800U
|
||||
#define LHD_EXTTIME 0x1000U
|
||||
#define LHD_EXTFLAGS 0x2000U
|
||||
#define LHD_EXTAREA 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,
|
||||
@@ -139,7 +139,7 @@ struct MarkHeader
|
||||
struct BaseBlock
|
||||
{
|
||||
ushort HeadCRC;
|
||||
HEADER_TYPE HeadType;//byte
|
||||
HEADER_TYPE HeadType; // 1 byte.
|
||||
ushort Flags;
|
||||
ushort HeadSize;
|
||||
|
||||
@@ -228,8 +228,15 @@ struct FileHeader:BlockHeader
|
||||
|
||||
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 if EARC_DATACRC flag is set.
|
||||
uint ArcDataCRC;
|
||||
|
||||
// Optional number of current volume.
|
||||
// Present if EARC_VOLNUMBER flag is set.
|
||||
ushort VolNumber;
|
||||
|
||||
// 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -38,11 +38,6 @@ void ListArchive(CommandData *Cmd)
|
||||
if (!Bare)
|
||||
{
|
||||
Arc.ViewComment();
|
||||
|
||||
// RAR can close a corrupt encrypted archive.
|
||||
// if (!Arc.IsOpened())
|
||||
// break;
|
||||
|
||||
mprintf("\n");
|
||||
if (Arc.Solid)
|
||||
mprintf(St(MListSolid));
|
||||
@@ -77,7 +72,7 @@ void ListArchive(CommandData *Cmd)
|
||||
case FILE_HEAD:
|
||||
IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName);
|
||||
FileMatched=Cmd->IsProcessFile(Arc.NewLhd)!=0;
|
||||
if (FileMatched)
|
||||
if (FileMatched)
|
||||
{
|
||||
ListFileHeader(Arc.NewLhd,Verbose,Technical,TitleShown,Bare);
|
||||
if (!(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#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 MShare "\nTrial version Type RAR -? for help\n"
|
||||
#define MUCopyright "\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
|
||||
#define MBeta "beta"
|
||||
#define MMonthJan "Jan"
|
||||
@@ -50,6 +50,7 @@
|
||||
#define MCHelpCmdX "\n x Extract files with full path"
|
||||
#define MCHelpSw "\n\n<Switches>"
|
||||
#define MCHelpSwm "\n - Stop switches scanning"
|
||||
#define MCHelpSwAT "\n @[+] Disable [enable] file lists"
|
||||
#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"
|
||||
@@ -87,6 +88,7 @@
|
||||
#define MCHelpSwISND "\n isnd Enable sound"
|
||||
#define MCHelpSwK "\n k Lock archive"
|
||||
#define MCHelpSwKB "\n kb Keep broken extracted files"
|
||||
#define MCHelpSwLog "\n log[f][=name] Write names to log file"
|
||||
#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)"
|
||||
@@ -171,6 +173,7 @@
|
||||
#define MCannotOpen "\nCannot open %s"
|
||||
#define MUnknownMeth "\nUnknown method in %s"
|
||||
#define MVerRequired "\nYou need RAR %d.%d to unpack it"
|
||||
#define MNewRarFormat "\nUnsupported archive format. Please update RAR to a newer version."
|
||||
#define MOk " OK"
|
||||
#define MDone "\nDone"
|
||||
#define MLockingArc "\nLocking archive"
|
||||
|
||||
@@ -360,14 +360,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;
|
||||
|
||||
@@ -24,7 +24,7 @@ struct SEE2_CONTEXT
|
||||
}
|
||||
uint getMean()
|
||||
{
|
||||
uint RetVal=SHORT16(Summ) >> Shift;
|
||||
uint RetVal=GET_SHORT16(Summ) >> Shift;
|
||||
Summ -= RetVal;
|
||||
return RetVal+(RetVal == 0);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#ifndef _RAR_OPTIONS_
|
||||
#define _RAR_OPTIONS_
|
||||
|
||||
#define DEFAULT_RECOVERY -1
|
||||
#define DEFAULT_RECOVERY -1
|
||||
|
||||
#define DEFAULT_RECVOLUMES -10
|
||||
|
||||
#define VOLSIZE_AUTO INT64NDF // Automatically detect the volume size.
|
||||
|
||||
enum PATH_EXCL_MODE {
|
||||
EXCL_UNCHANGED, // Process paths as is (default).
|
||||
EXCL_UNCHANGED=0, // Process paths as is (default).
|
||||
EXCL_SKIPWHOLEPATH, // -ep (exclude the path completely)
|
||||
EXCL_BASEPATH, // -ep1 (exclude the base part of path)
|
||||
EXCL_SAVEFULLPATH, // -ep2 (the full path without the disk letter)
|
||||
@@ -20,15 +22,15 @@ enum PATH_EXCL_MODE {
|
||||
enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
|
||||
SOLID_VOLUME_DEPENDENT=8,SOLID_VOLUME_INDEPENDENT=16};
|
||||
|
||||
enum {ARCTIME_NONE,ARCTIME_KEEP,ARCTIME_LATEST};
|
||||
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
|
||||
|
||||
enum EXTTIME_MODE {
|
||||
EXTTIME_NONE,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
|
||||
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
|
||||
};
|
||||
|
||||
enum {NAMES_ORIGINALCASE,NAMES_UPPERCASE,NAMES_LOWERCASE};
|
||||
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
|
||||
|
||||
enum MESSAGE_TYPE {MSG_STDOUT,MSG_STDERR,MSG_ERRONLY,MSG_NULL};
|
||||
enum MESSAGE_TYPE {MSG_STDOUT=0,MSG_STDERR,MSG_ERRONLY,MSG_NULL};
|
||||
|
||||
enum RECURSE_MODE
|
||||
{
|
||||
@@ -49,7 +51,7 @@ enum OVERWRITE_MODE
|
||||
|
||||
enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE };
|
||||
|
||||
#define MAX_FILTERS 16
|
||||
#define MAX_FILTER_TYPES 16
|
||||
enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE};
|
||||
|
||||
|
||||
@@ -60,6 +62,8 @@ struct FilterMode
|
||||
int Param2;
|
||||
};
|
||||
|
||||
#define MAX_GENERATE_MASK 128
|
||||
|
||||
|
||||
class RAROptions
|
||||
{
|
||||
@@ -73,6 +77,7 @@ class RAROptions
|
||||
bool InclAttrSet;
|
||||
uint WinSize;
|
||||
char TempPath[NM];
|
||||
bool ConfigDisabled; // Switch -cfg-.
|
||||
char ExtrPath[NM];
|
||||
wchar ExtrPathW[NM];
|
||||
char CommentFile[NM];
|
||||
@@ -81,7 +86,7 @@ class RAROptions
|
||||
RAR_CHARSET FilelistCharset;
|
||||
char ArcPath[NM];
|
||||
wchar ArcPathW[NM];
|
||||
wchar Password[MAXPASSWORD];
|
||||
SecPassword Password;
|
||||
bool EncryptHeaders;
|
||||
char LogName[NM];
|
||||
MESSAGE_TYPE MsgStream;
|
||||
@@ -118,6 +123,10 @@ class RAROptions
|
||||
bool KeepBroken;
|
||||
bool OpenShared;
|
||||
bool DeleteFiles;
|
||||
#ifndef SFX_MODULE
|
||||
bool GenerateArcName;
|
||||
char GenerateMask[MAX_GENERATE_MASK];
|
||||
#endif
|
||||
bool SyncFiles;
|
||||
bool ProcessEA;
|
||||
bool SaveStreams;
|
||||
@@ -131,7 +140,7 @@ class RAROptions
|
||||
bool Lock;
|
||||
bool Test;
|
||||
bool VolumePause;
|
||||
FilterMode FilterModes[MAX_FILTERS];
|
||||
FilterMode FilterModes[MAX_FILTER_TYPES];
|
||||
char EmailTo[NM];
|
||||
uint VersionControl;
|
||||
bool NoEndBlock;
|
||||
@@ -143,7 +152,7 @@ class RAROptions
|
||||
EXTTIME_MODE xarctime;
|
||||
char CompressStdin[NM];
|
||||
|
||||
#ifdef PACK_SMP
|
||||
#ifdef RAR_SMP
|
||||
uint Threads;
|
||||
#endif
|
||||
|
||||
|
||||
88
unrar/os.hpp
88
unrar/os.hpp
@@ -12,8 +12,10 @@
|
||||
#define SILENT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
#define ENABLE_BAD_ALLOC
|
||||
#define ENABLE_BAD_ALLOC // Undefine if std::bad_alloc is not supported.
|
||||
|
||||
#if defined(ENABLE_BAD_ALLOC) && defined(__cplusplus)
|
||||
#include <new>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -24,58 +26,43 @@
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(LEAN_RAR_INCLUDES)
|
||||
|
||||
#define STRICT
|
||||
#define UNICODE
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
#define WINVER 0x0500
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#define STRICT
|
||||
#define UNICODE
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <prsht.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
#ifndef _WIN_CE
|
||||
#include <shellapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
|
||||
#endif // _WIN_CE
|
||||
|
||||
|
||||
#endif // _WIN_ALL
|
||||
|
||||
#ifndef _WIN_CE
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dos.h>
|
||||
#endif // _WIN_CE
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dos.h>
|
||||
|
||||
#if !defined(_EMX) && !defined(_MSC_VER) && !defined(_WIN_CE)
|
||||
#if !defined(_EMX) && !defined(_MSC_VER)
|
||||
#include <dir.h>
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER<1500
|
||||
#define for if (0) ; else for
|
||||
#endif
|
||||
#ifndef _WIN_CE
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifndef _WIN_CE
|
||||
#include <share.h>
|
||||
#endif // _WIN_CE
|
||||
|
||||
#if defined(ENABLE_BAD_ALLOC) && !defined(_WIN_CE) && !defined(LEAN_RAR_INCLUDES)
|
||||
#include <new.h>
|
||||
#endif
|
||||
|
||||
#ifdef _EMX
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
@@ -88,14 +75,6 @@
|
||||
#include <sys/utime.h>
|
||||
#include <emx/syscalls.h>
|
||||
#endif
|
||||
#else
|
||||
#ifndef LEAN_RAR_INCLUDES
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__))
|
||||
#include <exception>
|
||||
#else
|
||||
#include <except.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef _WSTDIO_DEFINED
|
||||
@@ -104,19 +83,11 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifndef _WIN_CE
|
||||
#include <fcntl.h>
|
||||
#include <dos.h>
|
||||
#include <io.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifdef _WIN_ALL
|
||||
#pragma hdrstop
|
||||
#endif // _WIN_ALL
|
||||
*/
|
||||
#include <fcntl.h>
|
||||
#include <dos.h>
|
||||
#include <io.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define ENABLE_ACCESS
|
||||
|
||||
@@ -134,6 +105,7 @@
|
||||
#define READTEXT "rt"
|
||||
#define UPDATEBINARY "r+b"
|
||||
#define CREATEBINARY "w+b"
|
||||
#define WRITEBINARY "wb"
|
||||
#define APPENDTEXT "at"
|
||||
|
||||
#if defined(_WIN_ALL)
|
||||
@@ -174,6 +146,9 @@
|
||||
#if defined(__QNXNTO__)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#if defined(RAR_SMP) && defined(__APPLE__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__)
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
@@ -215,6 +190,7 @@
|
||||
#define READTEXT "r"
|
||||
#define UPDATEBINARY "r+"
|
||||
#define CREATEBINARY "w+"
|
||||
#define WRITEBINARY "w"
|
||||
#define APPENDTEXT "a"
|
||||
|
||||
#define _stdfunction
|
||||
@@ -266,13 +242,13 @@
|
||||
#endif
|
||||
|
||||
#if !defined(BIG_ENDIAN) && !defined(_WIN_CE) && defined(_WIN_ALL)
|
||||
/* allow not aligned integer access, increases speed in some operations */
|
||||
// Allow not aligned integer access, increases speed in some operations.
|
||||
#define ALLOW_NOT_ALIGNED_INT
|
||||
#endif
|
||||
|
||||
#if defined(__sparc) || defined(sparc) || defined(__sparcv9)
|
||||
/* prohibit not aligned access to data structures in text comression
|
||||
algorithm, increases memory requirements */
|
||||
// Prohibit not aligned access to data structures in text compression
|
||||
// algorithm, increases memory requirements
|
||||
#define STRICT_ALIGNMENT_REQUIRED
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,14 +13,14 @@ void ExtractOS2EA(Archive &Arc,char *FileName)
|
||||
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
|
||||
{
|
||||
Log(Arc.FileName,St(MEAUnknHeader),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ void ExtractOS2EA(Archive &Arc,char *FileName)
|
||||
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MEABroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ void ExtractOS2EA(Archive &Arc,char *FileName)
|
||||
if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
}
|
||||
File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
|
||||
mprintf(St(MShowEA));
|
||||
@@ -86,7 +86,7 @@ void ExtractOS2EANew(Archive &Arc,char *FileName)
|
||||
if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
|
||||
{
|
||||
Log(Arc.FileName,St(MCannotSetEA),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
}
|
||||
File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
|
||||
mprintf(St(MShowEA));
|
||||
|
||||
301
unrar/pathfn.cpp
301
unrar/pathfn.cpp
@@ -45,7 +45,7 @@ char* ConvertPath(const char *SrcPath,char *DestPath)
|
||||
if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
|
||||
DestPtr=s+4;
|
||||
|
||||
// Remove any sequence of . and \ in the beginning of path string.
|
||||
// Remove <d>:\ and any sequence of . and \ in the beginning of path string.
|
||||
while (*DestPtr!=0)
|
||||
{
|
||||
const char *s=DestPtr;
|
||||
@@ -94,7 +94,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
||||
if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
|
||||
DestPtr=s+4;
|
||||
|
||||
// Remove any sequence of . and \ in the beginning of path string.
|
||||
// Remove <d>:\ and any sequence of . and \ in the beginning of path string.
|
||||
while (*DestPtr!=0)
|
||||
{
|
||||
const wchar *s=DestPtr;
|
||||
@@ -323,7 +323,6 @@ void RemoveNameFromPath(char *Path)
|
||||
}
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
// Removes name and returns file path without the trailing
|
||||
// path separator symbol.
|
||||
void RemoveNameFromPath(wchar *Path)
|
||||
@@ -333,7 +332,6 @@ void RemoveNameFromPath(wchar *Path)
|
||||
Name--;
|
||||
*Name=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
|
||||
@@ -606,11 +604,11 @@ void NextVolumeName(char *ArcName,wchar *ArcNameW,uint MaxLength,bool OldNumberi
|
||||
char *ChPtr;
|
||||
if ((ChPtr=GetExt(ArcName))==NULL)
|
||||
{
|
||||
strcat(ArcName,".rar");
|
||||
strncatz(ArcName,".rar",MaxLength);
|
||||
ChPtr=GetExt(ArcName);
|
||||
}
|
||||
else
|
||||
if (ChPtr[1]==0 || stricomp(ChPtr+1,"exe")==0 || stricomp(ChPtr+1,"sfx")==0)
|
||||
if (ChPtr[1]==0 && strlen(ArcName)<MaxLength-3 || stricomp(ChPtr+1,"exe")==0 || stricomp(ChPtr+1,"sfx")==0)
|
||||
strcpy(ChPtr+1,"rar");
|
||||
if (!OldNumbering)
|
||||
{
|
||||
@@ -654,11 +652,11 @@ void NextVolumeName(char *ArcName,wchar *ArcNameW,uint MaxLength,bool OldNumberi
|
||||
wchar *ChPtr;
|
||||
if ((ChPtr=GetExt(ArcNameW))==NULL)
|
||||
{
|
||||
wcscat(ArcNameW,L".rar");
|
||||
wcsncatz(ArcNameW,L".rar",MaxLength);
|
||||
ChPtr=GetExt(ArcNameW);
|
||||
}
|
||||
else
|
||||
if (ChPtr[1]==0 || wcsicomp(ChPtr+1,L"exe")==0 || wcsicomp(ChPtr+1,L"sfx")==0)
|
||||
if (ChPtr[1]==0 && wcslen(ArcNameW)<MaxLength-3 || wcsicomp(ChPtr+1,L"exe")==0 || wcsicomp(ChPtr+1,L"sfx")==0)
|
||||
wcscpy(ChPtr+1,L"rar");
|
||||
if (!OldNumbering)
|
||||
{
|
||||
@@ -711,13 +709,49 @@ bool IsNameUsable(const char *Name)
|
||||
if (*s==' ' && IsPathDiv(s[1]))
|
||||
return(false);
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN_ALL
|
||||
// In Windows we need to check if all file name characters are defined
|
||||
// in current code page. For example, in Korean CP949 a lot of high ASCII
|
||||
// characters are not defined, cannot be used in file names, but cannot be
|
||||
// detected by other checks in this function.
|
||||
if (MultiByteToWideChar(CP_ACP,MB_ERR_INVALID_CHARS,Name,-1,NULL,0)==0 &&
|
||||
GetLastError()==ERROR_NO_UNICODE_TRANSLATION)
|
||||
return false;
|
||||
#endif
|
||||
return(*Name!=0 && strpbrk(Name,"?*<>|\"")==NULL);
|
||||
}
|
||||
|
||||
|
||||
bool IsNameUsable(const wchar *Name)
|
||||
{
|
||||
#ifndef _UNIX
|
||||
if (Name[0] && Name[1] && wcschr(Name+2,':')!=NULL)
|
||||
return(false);
|
||||
for (const wchar *s=Name;*s!=0;s++)
|
||||
{
|
||||
if ((uint)*s<32)
|
||||
return(false);
|
||||
if (*s==' ' && IsPathDiv(s[1]))
|
||||
return(false);
|
||||
}
|
||||
#endif
|
||||
return(*Name!=0 && wcspbrk(Name,L"?*<>|\"")==NULL);
|
||||
}
|
||||
|
||||
|
||||
void MakeNameUsable(char *Name,bool Extended)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// In Windows we also need to convert characters not defined in current
|
||||
// code page. This double conversion changes them to '?', which is
|
||||
// catched by code below.
|
||||
size_t NameLength=strlen(Name);
|
||||
wchar NameW[NM];
|
||||
CharToWide(Name,NameW,ASIZE(NameW));
|
||||
WideToChar(NameW,Name,NameLength+1);
|
||||
Name[NameLength]=0;
|
||||
#endif
|
||||
for (char *s=Name;*s!=0;s=charnext(s))
|
||||
{
|
||||
if (strchr(Extended ? "?*<>|\"":"?*",*s)!=NULL || Extended && (byte)*s<32)
|
||||
@@ -1069,7 +1103,7 @@ char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering)
|
||||
while (Find.Next(&FD))
|
||||
{
|
||||
Archive Arc;
|
||||
if (Arc.Open(FD.Name,FD.NameW) && Arc.IsArchive(true) && !Arc.NotFirstVolume)
|
||||
if (Arc.Open(FD.Name,FD.NameW,0) && Arc.IsArchive(true) && !Arc.NotFirstVolume)
|
||||
{
|
||||
strcpy(FirstName,FD.Name);
|
||||
break;
|
||||
@@ -1126,7 +1160,7 @@ wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,bool NewNumberin
|
||||
while (Find.Next(&FD))
|
||||
{
|
||||
Archive Arc;
|
||||
if (Arc.Open(FD.Name,FD.NameW) && Arc.IsArchive(true) && !Arc.NotFirstVolume)
|
||||
if (Arc.Open(FD.Name,FD.NameW,0) && Arc.IsArchive(true) && !Arc.NotFirstVolume)
|
||||
{
|
||||
wcscpy(FirstName,FD.NameW);
|
||||
break;
|
||||
@@ -1138,6 +1172,253 @@ wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,bool NewNumberin
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
static void GenArcName(char *ArcName,wchar *ArcNameW,char *GenerateMask,
|
||||
uint ArcNumber,bool &ArcNumPresent);
|
||||
|
||||
void GenerateArchiveName(char *ArcName,wchar *ArcNameW,size_t MaxSize,
|
||||
char *GenerateMask,bool Archiving)
|
||||
{
|
||||
// Must be enough space for archive name plus all stuff in mask plus
|
||||
// extra overhead produced by mask 'N' (archive number) characters.
|
||||
// One 'N' character can result in several numbers if we process more
|
||||
// than 9 archives.
|
||||
char NewName[NM+MAX_GENERATE_MASK+20];
|
||||
wchar NewNameW[NM+MAX_GENERATE_MASK+20];
|
||||
|
||||
uint ArcNumber=1;
|
||||
while (true) // Loop for 'N' (archive number) processing.
|
||||
{
|
||||
strncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
|
||||
wcsncpyz(NewNameW,NullToEmpty(ArcNameW),ASIZE(NewNameW));
|
||||
|
||||
bool ArcNumPresent=false;
|
||||
|
||||
GenArcName(NewName,NewNameW,GenerateMask,ArcNumber,ArcNumPresent);
|
||||
|
||||
if (!ArcNumPresent)
|
||||
break;
|
||||
if (!FileExist(NewName,NewNameW))
|
||||
{
|
||||
if (!Archiving && ArcNumber>1)
|
||||
{
|
||||
// If we perform non-archiving operation, we need to use the last
|
||||
// existing archive before the first unused name. So we generate
|
||||
// the name for (ArcNumber-1) below.
|
||||
strncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
|
||||
wcsncpyz(NewNameW,NullToEmpty(ArcNameW),ASIZE(NewNameW));
|
||||
GenArcName(NewName,NewNameW,GenerateMask,ArcNumber-1,ArcNumPresent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ArcNumber++;
|
||||
}
|
||||
if (ArcName!=NULL && *ArcName!=0)
|
||||
strncpyz(ArcName,NewName,MaxSize);
|
||||
if (ArcNameW!=NULL && *ArcNameW!=0)
|
||||
wcsncpyz(ArcNameW,NewNameW,MaxSize);
|
||||
}
|
||||
|
||||
|
||||
void GenArcName(char *ArcName,wchar *ArcNameW,char *GenerateMask,
|
||||
uint ArcNumber,bool &ArcNumPresent)
|
||||
{
|
||||
bool Prefix=false;
|
||||
if (*GenerateMask=='+')
|
||||
{
|
||||
Prefix=true; // Add the time string before the archive name.
|
||||
GenerateMask++; // Skip '+' in the beginning of time mask.
|
||||
}
|
||||
|
||||
char Mask[MAX_GENERATE_MASK];
|
||||
strncpyz(Mask,*GenerateMask ? GenerateMask:"yyyymmddhhmmss",ASIZE(Mask));
|
||||
|
||||
bool QuoteMode=false,Hours=false;
|
||||
for (uint I=0;Mask[I]!=0;I++)
|
||||
{
|
||||
if (Mask[I]=='{' || Mask[I]=='}')
|
||||
{
|
||||
QuoteMode=(Mask[I]=='{');
|
||||
continue;
|
||||
}
|
||||
if (QuoteMode)
|
||||
continue;
|
||||
int CurChar=etoupper(Mask[I]);
|
||||
if (CurChar=='H')
|
||||
Hours=true;
|
||||
|
||||
if (Hours && CurChar=='M')
|
||||
{
|
||||
// Replace minutes with 'I'. We use 'M' both for months and minutes,
|
||||
// so we treat as minutes only those 'M' which are found after hours.
|
||||
Mask[I]='I';
|
||||
}
|
||||
if (CurChar=='N')
|
||||
{
|
||||
uint Digits=GetDigits(ArcNumber);
|
||||
uint NCount=0;
|
||||
while (etoupper(Mask[I+NCount])=='N')
|
||||
NCount++;
|
||||
|
||||
// Here we ensure that we have enough 'N' characters to fit all digits
|
||||
// of archive number. We'll replace them by actual number later
|
||||
// in this function.
|
||||
if (NCount<Digits)
|
||||
{
|
||||
memmove(Mask+I+Digits,Mask+I+NCount,strlen(Mask+I+NCount)+1);
|
||||
memset(Mask+I,'N',Digits);
|
||||
}
|
||||
I+=Max(Digits,NCount)-1;
|
||||
ArcNumPresent=true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
RarTime CurTime;
|
||||
CurTime.SetCurrentTime();
|
||||
RarLocalTime rlt;
|
||||
CurTime.GetLocal(&rlt);
|
||||
|
||||
char Ext[NM];
|
||||
*Ext=0;
|
||||
if (ArcName!=NULL && *ArcName!=0)
|
||||
{
|
||||
char *Dot;
|
||||
if ((Dot=GetExt(ArcName))==NULL)
|
||||
strcpy(Ext,*PointToName(ArcName)==0 ? ".rar":"");
|
||||
else
|
||||
{
|
||||
strcpy(Ext,Dot);
|
||||
*Dot=0;
|
||||
}
|
||||
}
|
||||
|
||||
wchar ExtW[NM];
|
||||
*ExtW=0;
|
||||
if (ArcNameW!=NULL && *ArcNameW!=0)
|
||||
{
|
||||
wchar *DotW;
|
||||
if ((DotW=GetExt(ArcNameW))==NULL)
|
||||
wcscpy(ExtW,*PointToName(ArcNameW)==0 ? L".rar":L"");
|
||||
else
|
||||
{
|
||||
wcscpy(ExtW,DotW);
|
||||
*DotW=0;
|
||||
}
|
||||
}
|
||||
|
||||
int WeekDay=rlt.wDay==0 ? 6:rlt.wDay-1;
|
||||
int StartWeekDay=rlt.yDay-WeekDay;
|
||||
if (StartWeekDay<0)
|
||||
if (StartWeekDay<=-4)
|
||||
StartWeekDay+=IsLeapYear(rlt.Year-1) ? 366:365;
|
||||
else
|
||||
StartWeekDay=0;
|
||||
int CurWeek=StartWeekDay/7+1;
|
||||
if (StartWeekDay%7>=4)
|
||||
CurWeek++;
|
||||
|
||||
char Field[10][6];
|
||||
|
||||
sprintf(Field[0],"%04d",rlt.Year);
|
||||
sprintf(Field[1],"%02d",rlt.Month);
|
||||
sprintf(Field[2],"%02d",rlt.Day);
|
||||
sprintf(Field[3],"%02d",rlt.Hour);
|
||||
sprintf(Field[4],"%02d",rlt.Minute);
|
||||
sprintf(Field[5],"%02d",rlt.Second);
|
||||
sprintf(Field[6],"%02d",CurWeek);
|
||||
sprintf(Field[7],"%d",WeekDay+1);
|
||||
sprintf(Field[8],"%03d",rlt.yDay+1);
|
||||
sprintf(Field[9],"%05d",ArcNumber);
|
||||
|
||||
const char *MaskChars="YMDHISWAEN";
|
||||
|
||||
int CField[sizeof(Field)/sizeof(Field[0])];
|
||||
memset(CField,0,sizeof(CField));
|
||||
QuoteMode=false;
|
||||
for (int I=0;Mask[I]!=0;I++)
|
||||
{
|
||||
if (Mask[I]=='{' || Mask[I]=='}')
|
||||
{
|
||||
QuoteMode=(Mask[I]=='{');
|
||||
continue;
|
||||
}
|
||||
if (QuoteMode)
|
||||
continue;
|
||||
const char *Ch=strchr(MaskChars,etoupper(Mask[I]));
|
||||
if (Ch!=NULL)
|
||||
CField[Ch-MaskChars]++;
|
||||
}
|
||||
|
||||
char DateText[MAX_GENERATE_MASK];
|
||||
*DateText=0;
|
||||
QuoteMode=false;
|
||||
for (size_t I=0,J=0;Mask[I]!=0 && J<ASIZE(DateText)-1;I++)
|
||||
{
|
||||
if (Mask[I]=='{' || Mask[I]=='}')
|
||||
{
|
||||
QuoteMode=(Mask[I]=='{');
|
||||
continue;
|
||||
}
|
||||
const char *Ch=strchr(MaskChars,etoupper(Mask[I]));
|
||||
if (Ch==NULL || QuoteMode)
|
||||
DateText[J]=Mask[I];
|
||||
else
|
||||
{
|
||||
size_t FieldPos=Ch-MaskChars;
|
||||
int CharPos=(int)strlen(Field[FieldPos])-CField[FieldPos]--;
|
||||
if (FieldPos==1 && etoupper(Mask[I+1])=='M' && etoupper(Mask[I+2])=='M')
|
||||
{
|
||||
strncpyz(DateText+J,GetMonthName(rlt.Month-1),ASIZE(DateText)-J);
|
||||
J=strlen(DateText);
|
||||
I+=2;
|
||||
continue;
|
||||
}
|
||||
if (CharPos<0)
|
||||
DateText[J]=Mask[I];
|
||||
else
|
||||
DateText[J]=Field[FieldPos][CharPos];
|
||||
}
|
||||
DateText[++J]=0;
|
||||
}
|
||||
|
||||
wchar DateTextW[ASIZE(DateText)];
|
||||
CharToWide(DateText,DateTextW);
|
||||
|
||||
if (Prefix)
|
||||
{
|
||||
if (ArcName!=NULL && *ArcName!=0)
|
||||
{
|
||||
char NewName[NM];
|
||||
GetFilePath(ArcName,NewName,ASIZE(NewName));
|
||||
AddEndSlash(NewName);
|
||||
strcat(NewName,DateText);
|
||||
strcat(NewName,PointToName(ArcName));
|
||||
strcpy(ArcName,NewName);
|
||||
}
|
||||
if (ArcNameW!=NULL && *ArcNameW!=0)
|
||||
{
|
||||
wchar NewNameW[NM];
|
||||
GetFilePath(ArcNameW,NewNameW,ASIZE(NewNameW));
|
||||
AddEndSlash(NewNameW);
|
||||
wcscat(NewNameW,DateTextW);
|
||||
wcscat(NewNameW,PointToName(ArcNameW));
|
||||
wcscpy(ArcNameW,NewNameW);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ArcName!=NULL && *ArcName!=0)
|
||||
strcat(ArcName,DateText);
|
||||
if (ArcNameW!=NULL && *ArcNameW!=0)
|
||||
wcscat(ArcNameW,DateTextW);
|
||||
}
|
||||
if (ArcName!=NULL && *ArcName!=0)
|
||||
strcat(ArcName,Ext);
|
||||
if (ArcNameW!=NULL && *ArcNameW!=0)
|
||||
wcscat(ArcNameW,ExtW);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize)
|
||||
|
||||
@@ -38,6 +38,7 @@ char* GetVolNumPart(char *ArcName);
|
||||
wchar* GetVolNumPart(wchar *ArcName);
|
||||
void NextVolumeName(char *ArcName,wchar *ArcNameW,uint MaxLength,bool OldNumbering);
|
||||
bool IsNameUsable(const char *Name);
|
||||
bool IsNameUsable(const wchar *Name);
|
||||
void MakeNameUsable(char *Name,bool Extended);
|
||||
void MakeNameUsable(wchar *Name,bool Extended);
|
||||
char* UnixSlashToDos(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
|
||||
@@ -58,5 +59,8 @@ wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,bool NewNumberin
|
||||
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize);
|
||||
char* GetAsciiName(const wchar *NameW,char *Name,size_t DestSize);
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void GenerateArchiveName(char *ArcName,wchar *ArcNameW,size_t MaxSize,char *GenerateMask,bool Archiving);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -43,7 +43,9 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
|
||||
bool ShutdownOnClose;
|
||||
// Must be initialized, normal initialization can be skipped in case of
|
||||
// exception.
|
||||
bool ShutdownOnClose=false;
|
||||
#endif
|
||||
|
||||
#ifdef ALLOW_EXCEPTIONS
|
||||
@@ -78,21 +80,21 @@ int main(int argc, char *argv[])
|
||||
Cmd.Command[0]=UpperCmd;
|
||||
break;
|
||||
case '?':
|
||||
Cmd.OutHelp();
|
||||
Cmd.OutHelp(RARX_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Cmd.AddArcName(ModuleNameA,ModuleNameW);
|
||||
#else
|
||||
if (Cmd.IsConfigEnabled(argc,argv))
|
||||
Cmd.ParseDone();
|
||||
#else // !SFX_MODULE
|
||||
Cmd.PreprocessCommandLine(argc,argv);
|
||||
if (!Cmd.ConfigDisabled)
|
||||
{
|
||||
Cmd.ReadConfig(argc,argv);
|
||||
Cmd.ReadConfig();
|
||||
Cmd.ParseEnvVar();
|
||||
}
|
||||
for (int I=1;I<argc;I++)
|
||||
Cmd.ParseArg(argv[I],NULL);
|
||||
Cmd.ParseCommandLine(argc,argv);
|
||||
#endif
|
||||
Cmd.ParseDone();
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
|
||||
ShutdownOnClose=Cmd.Shutdown;
|
||||
@@ -107,21 +109,23 @@ int main(int argc, char *argv[])
|
||||
Cmd.ProcessCommand();
|
||||
}
|
||||
#ifdef ALLOW_EXCEPTIONS
|
||||
catch (int ErrCode)
|
||||
catch (RAR_EXIT ErrCode)
|
||||
{
|
||||
ErrHandler.SetErrorCode(ErrCode);
|
||||
}
|
||||
#ifdef ENABLE_BAD_ALLOC
|
||||
catch (bad_alloc)
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
ErrHandler.SetErrorCode(MEMORY_ERROR);
|
||||
ErrHandler.MemoryErrorMsg();
|
||||
ErrHandler.SetErrorCode(RARX_MEMORY);
|
||||
}
|
||||
#endif
|
||||
catch (...)
|
||||
{
|
||||
ErrHandler.SetErrorCode(FATAL_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_FATAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
File::RemoveCreated();
|
||||
#if defined(SFX_MODULE) && defined(_DJGPP)
|
||||
_chmod(ModuleNameA,1,0x20);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "errhnd.hpp"
|
||||
#include "array.hpp"
|
||||
#include "timefn.hpp"
|
||||
#include "secpassword.hpp"
|
||||
#include "options.hpp"
|
||||
#include "headers.hpp"
|
||||
#include "pathfn.hpp"
|
||||
@@ -51,14 +52,13 @@
|
||||
#include "resource.hpp"
|
||||
#include "compress.hpp"
|
||||
|
||||
|
||||
#include "rarvm.hpp"
|
||||
#include "model.hpp"
|
||||
|
||||
|
||||
#include "unpack.hpp"
|
||||
|
||||
|
||||
|
||||
#include "extinfo.hpp"
|
||||
#include "extract.hpp"
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
|
||||
#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
// MAXPASSWORD is expected to be multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE (16)
|
||||
// for CryptProtectMemory in SecPassword.
|
||||
#define MAXPASSWORD 128
|
||||
|
||||
#define MAXSFXSIZE 0x100000
|
||||
|
||||
#define DefSFXName "default.sfx"
|
||||
@@ -21,4 +24,5 @@
|
||||
#define FA_ARCH 0x20
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,10 +29,10 @@ typedef ushort wchar;
|
||||
#endif
|
||||
|
||||
// Get lowest 16 bits.
|
||||
#define SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
|
||||
#define GET_SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
|
||||
|
||||
// Get lowest 32 bits.
|
||||
#define UINT32(x) (sizeof(uint32)==4 ? (uint32)(x):((x)&0xffffffff))
|
||||
#define GET_UINT32(x) (sizeof(uint32)==4 ? (uint32)(x):((x)&0xffffffff))
|
||||
|
||||
// Make 64 bit integer from two 32 bit.
|
||||
#define INT32TO64(high,low) ((((uint64)(high))<<32)+((uint64)low))
|
||||
|
||||
@@ -47,12 +47,12 @@ inline uint RarVM::GetValue(bool ByteMode,uint *Addr)
|
||||
if (IS_VM_MEM(Addr))
|
||||
{
|
||||
byte *B=(byte *)Addr;
|
||||
return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
|
||||
return GET_UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
|
||||
}
|
||||
else
|
||||
return UINT32(*Addr);
|
||||
return GET_UINT32(*Addr);
|
||||
#else
|
||||
return UINT32(*Addr);
|
||||
return GET_UINT32(*Addr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ inline uint RarVM::GetValue(bool ByteMode,uint *Addr)
|
||||
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
|
||||
#define GET_VALUE(ByteMode,Addr) GetValue(ByteMode,(uint *)Addr)
|
||||
#else
|
||||
#define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):UINT32(*(uint *)(Addr)))
|
||||
#define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):GET_UINT32(*(uint *)(Addr)))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
case VM_CMP:
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
}
|
||||
break;
|
||||
@@ -212,14 +212,14 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
case VM_CMPB:
|
||||
{
|
||||
uint Value1=GET_VALUE(true,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(true,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(true,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
}
|
||||
break;
|
||||
case VM_CMPD:
|
||||
{
|
||||
uint Value1=GET_VALUE(false,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(false,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(false,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
}
|
||||
break;
|
||||
@@ -227,7 +227,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
case VM_ADD:
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
|
||||
if (Cmd->ByteMode)
|
||||
{
|
||||
Result&=0xff;
|
||||
@@ -249,7 +249,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
case VM_SUB:
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
@@ -278,7 +278,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
break;
|
||||
case VM_INC:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
|
||||
if (Cmd->ByteMode)
|
||||
Result&=0xff;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
@@ -295,7 +295,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
#endif
|
||||
case VM_DEC:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1);
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
}
|
||||
@@ -313,28 +313,28 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
continue;
|
||||
case VM_XOR:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
case VM_AND:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
case VM_OR:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
break;
|
||||
case VM_TEST:
|
||||
{
|
||||
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
|
||||
Flags=Result==0 ? VM_FZ:Result&VM_FS;
|
||||
}
|
||||
break;
|
||||
@@ -400,7 +400,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
|
||||
uint Result=UINT32(Value1<<Value2);
|
||||
uint Result=GET_UINT32(Value1<<Value2);
|
||||
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1<<(Value2-1))&0x80000000 ? VM_FC:0);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
@@ -409,7 +409,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
|
||||
uint Result=UINT32(Value1>>Value2);
|
||||
uint Result=GET_UINT32(Value1>>Value2);
|
||||
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
@@ -418,7 +418,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
|
||||
uint Result=UINT32(((int)Value1)>>Value2);
|
||||
uint Result=GET_UINT32(((int)Value1)>>Value2);
|
||||
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
@@ -427,7 +427,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
{
|
||||
// We use "0-value" expression to suppress "unary minus to unsigned"
|
||||
// compiler warning.
|
||||
uint Result=UINT32(0-GET_VALUE(Cmd->ByteMode,Op1));
|
||||
uint Result=GET_UINT32(0-GET_VALUE(Cmd->ByteMode,Op1));
|
||||
Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS);
|
||||
SET_VALUE(Cmd->ByteMode,Op1,Result);
|
||||
}
|
||||
@@ -496,7 +496,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint FC=(Flags&VM_FC);
|
||||
uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
|
||||
uint Result=GET_UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
|
||||
if (Cmd->ByteMode)
|
||||
Result&=0xff;
|
||||
Flags=(Result<Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
|
||||
@@ -507,7 +507,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
|
||||
{
|
||||
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
|
||||
uint FC=(Flags&VM_FC);
|
||||
uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
|
||||
uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
|
||||
if (Cmd->ByteMode)
|
||||
Result&=0xff;
|
||||
Flags=(Result>Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
|
||||
|
||||
@@ -13,7 +13,7 @@ RawRead::RawRead(File *SrcFile)
|
||||
|
||||
void RawRead::Read(size_t Size)
|
||||
{
|
||||
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
|
||||
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
|
||||
if (Crypt!=NULL)
|
||||
{
|
||||
size_t CurSize=Data.Size();
|
||||
|
||||
@@ -89,7 +89,7 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||
if (RetCode!=-1)
|
||||
{
|
||||
RetCode=TotalRead;
|
||||
#ifndef NOCRYPT
|
||||
#ifndef RAR_NOCRYPT
|
||||
if (Decryption)
|
||||
#ifndef SFX_MODULE
|
||||
if (Decryption<20)
|
||||
@@ -127,7 +127,7 @@ void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
|
||||
{
|
||||
if (Cmd->Callback!=NULL &&
|
||||
Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1)
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
if (Cmd->ProcessDataProc!=NULL)
|
||||
{
|
||||
// Here we preserve ESP value. It is necessary for those developers,
|
||||
@@ -153,7 +153,7 @@ void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
|
||||
_ESP=_EBX;
|
||||
#endif
|
||||
if (RetCode==0)
|
||||
ErrHandler.Exit(USER_BREAK);
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
}
|
||||
#endif // RARDLL
|
||||
@@ -249,26 +249,26 @@ void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size)
|
||||
}
|
||||
|
||||
|
||||
void ComprDataIO::SetEncryption(int Method,const wchar *Password,const byte *Salt,bool Encrypt,bool HandsOffHash)
|
||||
void ComprDataIO::SetEncryption(int Method,SecPassword *Password,const byte *Salt,bool Encrypt,bool HandsOffHash)
|
||||
{
|
||||
if (Encrypt)
|
||||
{
|
||||
Encryption=*Password ? Method:0;
|
||||
#ifndef NOCRYPT
|
||||
Encryption=Password->IsSet() ? Method:0;
|
||||
#ifndef RAR_NOCRYPT
|
||||
Crypt.SetCryptKeys(Password,Salt,Encrypt,false,HandsOffHash);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Decryption=*Password ? Method:0;
|
||||
#ifndef NOCRYPT
|
||||
Decryption=Password->IsSet() ? Method:0;
|
||||
#ifndef RAR_NOCRYPT
|
||||
Decrypt.SetCryptKeys(Password,Salt,Encrypt,Method<29,HandsOffHash);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SFX_MODULE) && !defined(NOCRYPT)
|
||||
#if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
|
||||
void ComprDataIO::SetAV15Encryption()
|
||||
{
|
||||
Decryption=15;
|
||||
@@ -277,7 +277,7 @@ void ComprDataIO::SetAV15Encryption()
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(SFX_MODULE) && !defined(NOCRYPT)
|
||||
#if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
|
||||
void ComprDataIO::SetCmt13Encryption()
|
||||
{
|
||||
Decryption=13;
|
||||
|
||||
@@ -37,7 +37,7 @@ class ComprDataIO
|
||||
FileHeader *SubHead;
|
||||
int64 *SubHeadPos;
|
||||
|
||||
#ifndef NOCRYPT
|
||||
#ifndef RAR_NOCRYPT
|
||||
CryptData Crypt;
|
||||
CryptData Decrypt;
|
||||
#endif
|
||||
@@ -61,7 +61,7 @@ class ComprDataIO
|
||||
void SetFiles(File *SrcFile,File *DestFile);
|
||||
void SetCommand(CmdAdd *Cmd) {Command=Cmd;}
|
||||
void SetSubHeader(FileHeader *hd,int64 *Pos) {SubHead=hd;SubHeadPos=Pos;}
|
||||
void SetEncryption(int Method,const wchar *Password,const byte *Salt,bool Encrypt,bool HandsOffHash);
|
||||
void SetEncryption(int Method,SecPassword *Password,const byte *Salt,bool Encrypt,bool HandsOffHash);
|
||||
void SetAV15Encryption();
|
||||
void SetCmt13Encryption();
|
||||
void SetUnpackToMemory(byte *Addr,size_t Size); //changed by me
|
||||
|
||||
142
unrar/recvol.cpp
142
unrar/recvol.cpp
@@ -3,6 +3,41 @@
|
||||
// Buffer size for all volumes involved.
|
||||
static const size_t TotalBufferSize=0x4000000;
|
||||
|
||||
class RSEncode // Encode or decode data area, one object per one thread.
|
||||
{
|
||||
private:
|
||||
RSCoder RSC;
|
||||
public:
|
||||
void EncodeBuf();
|
||||
void DecodeBuf();
|
||||
|
||||
void Init(int RecVolNumber) {RSC.Init(RecVolNumber);}
|
||||
byte *Buf;
|
||||
byte *OutBuf;
|
||||
int BufStart;
|
||||
int BufEnd;
|
||||
int FileNumber;
|
||||
int RecVolNumber;
|
||||
size_t RecBufferSize;
|
||||
int *Erasures;
|
||||
int EraSize;
|
||||
};
|
||||
|
||||
|
||||
#ifdef RAR_SMP
|
||||
THREAD_PROC(RSEncodeThread)
|
||||
{
|
||||
RSEncode *rs=(RSEncode *)Data;
|
||||
rs->EncodeBuf();
|
||||
}
|
||||
|
||||
THREAD_PROC(RSDecodeThread)
|
||||
{
|
||||
RSEncode *rs=(RSEncode *)Data;
|
||||
rs->DecodeBuf();
|
||||
}
|
||||
#endif
|
||||
|
||||
RecVolumes::RecVolumes()
|
||||
{
|
||||
Buf.Alloc(TotalBufferSize);
|
||||
@@ -12,13 +47,27 @@ RecVolumes::RecVolumes()
|
||||
|
||||
RecVolumes::~RecVolumes()
|
||||
{
|
||||
for (int I=0;I<sizeof(SrcFile)/sizeof(SrcFile[0]);I++)
|
||||
for (int I=0;I<ASIZE(SrcFile);I++)
|
||||
delete SrcFile[I];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RSEncode::EncodeBuf()
|
||||
{
|
||||
for (int BufPos=BufStart;BufPos<BufEnd;BufPos++)
|
||||
{
|
||||
byte Data[256],Code[256];
|
||||
for (int I=0;I<FileNumber;I++)
|
||||
Data[I]=Buf[I*RecBufferSize+BufPos];
|
||||
RSC.Encode(Data,FileNumber,Code);
|
||||
for (int I=0;I<RecVolNumber;I++)
|
||||
OutBuf[I*RecBufferSize+BufPos]=Code[I];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
const wchar *NameW,bool Silent)
|
||||
{
|
||||
@@ -175,6 +224,10 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
CalcCRCMessageDone=true;
|
||||
}
|
||||
|
||||
#ifndef SILENT
|
||||
mprintf("\r\n%s",CurName);
|
||||
#endif
|
||||
|
||||
File CurFile;
|
||||
CurFile.TOpen(CurName,CurNameW);
|
||||
CurFile.Seek(0,SEEK_END);
|
||||
@@ -265,6 +318,9 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
{
|
||||
if (NewFile->GetHeaderType()==ENDARC_HEAD)
|
||||
{
|
||||
#ifndef SILENT
|
||||
mprintf("\r\n%s",ArcName);
|
||||
#endif
|
||||
if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 &&
|
||||
NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos))
|
||||
{
|
||||
@@ -356,8 +412,6 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
mprintf(St(MReconstructing));
|
||||
#endif
|
||||
|
||||
RSCoder RSC(RecVolNumber);
|
||||
|
||||
int TotalFiles=FileNumber+RecVolNumber;
|
||||
int Erasures[256],EraSize=0;
|
||||
|
||||
@@ -375,6 +429,17 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
// Size of per file buffer.
|
||||
size_t RecBufferSize=TotalBufferSize/TotalFiles;
|
||||
|
||||
#ifdef RAR_SMP
|
||||
uint ThreadNumber=Cmd->Threads;
|
||||
RSEncode rse[MaxPoolThreads];
|
||||
uint WaitHandles[MaxPoolThreads];
|
||||
#else
|
||||
uint ThreadNumber=1;
|
||||
RSEncode rse[1];
|
||||
#endif
|
||||
for (uint I=0;I<ThreadNumber;I++)
|
||||
rse[I].Init(RecVolNumber);
|
||||
|
||||
while (true)
|
||||
{
|
||||
Wait();
|
||||
@@ -401,21 +466,50 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
}
|
||||
ProcessedSize+=MaxRead;
|
||||
#endif
|
||||
for (int BufPos=0;BufPos<MaxRead;BufPos++)
|
||||
|
||||
|
||||
int BlockStart=0;
|
||||
int BlockSize=MaxRead/ThreadNumber;
|
||||
if (BlockSize<0x100)
|
||||
BlockSize=MaxRead;
|
||||
uint CurThread=0;
|
||||
|
||||
while (BlockStart<MaxRead)
|
||||
{
|
||||
if ((BufPos&0xffff)==0)
|
||||
Wait();
|
||||
byte Data[256];
|
||||
for (int I=0;I<TotalFiles;I++)
|
||||
Data[I]=Buf[I*RecBufferSize+BufPos];
|
||||
RSC.Decode(Data,TotalFiles,Erasures,EraSize);
|
||||
for (int I=0;I<EraSize;I++)
|
||||
Buf[Erasures[I]*RecBufferSize+BufPos]=Data[Erasures[I]];
|
||||
/*
|
||||
for (int I=0;I<FileNumber;I++)
|
||||
Buf[I*RecBufferSize+BufPos]=Data[I];
|
||||
*/
|
||||
// Last thread processes all left data including increasement
|
||||
// from rounding error.
|
||||
if (CurThread==ThreadNumber-1)
|
||||
BlockSize=MaxRead-BlockStart;
|
||||
|
||||
RSEncode *curenc=rse+CurThread;
|
||||
curenc->Buf=&Buf[0];
|
||||
curenc->BufStart=BlockStart;
|
||||
curenc->BufEnd=BlockStart+BlockSize;
|
||||
curenc->FileNumber=TotalFiles;
|
||||
curenc->RecBufferSize=RecBufferSize;
|
||||
curenc->Erasures=Erasures;
|
||||
curenc->EraSize=EraSize;
|
||||
|
||||
#ifdef RAR_SMP
|
||||
if (ThreadNumber>1)
|
||||
{
|
||||
uint Handle=RSThreadPool.Start(RSDecodeThread,(void*)curenc);
|
||||
WaitHandles[CurThread++]=Handle;
|
||||
}
|
||||
else
|
||||
curenc->DecodeBuf();
|
||||
#else
|
||||
curenc->DecodeBuf();
|
||||
#endif
|
||||
|
||||
BlockStart+=BlockSize;
|
||||
}
|
||||
|
||||
#ifdef RAR_SMP
|
||||
if (CurThread>0)
|
||||
RSThreadPool.Wait(WaitHandles,CurThread);
|
||||
#endif // RAR_SMP
|
||||
|
||||
for (int I=0;I<FileNumber;I++)
|
||||
if (WriteFlags[I])
|
||||
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
|
||||
@@ -438,7 +532,7 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
{
|
||||
// Truncate the last volume to its real size.
|
||||
Archive Arc(Cmd);
|
||||
if (Arc.Open(LastVolName,LastVolNameW,false,true) && Arc.IsArchive(true) &&
|
||||
if (Arc.Open(LastVolName,LastVolNameW,FMF_UPDATE) && Arc.IsArchive(true) &&
|
||||
Arc.SearchBlock(ENDARC_HEAD))
|
||||
{
|
||||
Arc.Seek(Arc.NextBlockPos,SEEK_SET);
|
||||
@@ -462,3 +556,17 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
|
||||
#endif
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
void RSEncode::DecodeBuf()
|
||||
{
|
||||
for (int BufPos=BufStart;BufPos<BufEnd;BufPos++)
|
||||
{
|
||||
byte Data[256];
|
||||
for (int I=0;I<FileNumber;I++)
|
||||
Data[I]=Buf[I*RecBufferSize+BufPos];
|
||||
RSC.Decode(Data,FileNumber,Erasures,EraSize);
|
||||
for (int I=0;I<EraSize;I++)
|
||||
Buf[Erasures[I]*RecBufferSize+BufPos]=Data[Erasures[I]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ class RecVolumes
|
||||
private:
|
||||
File *SrcFile[256];
|
||||
Array<byte> Buf;
|
||||
|
||||
#ifdef RAR_SMP
|
||||
ThreadPool RSThreadPool;
|
||||
#endif
|
||||
public:
|
||||
RecVolumes();
|
||||
~RecVolumes();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#define Clean(D,S) {for (int I=0;I<(S);I++) (D)[I]=0;}
|
||||
|
||||
RSCoder::RSCoder(int ParSize)
|
||||
void RSCoder::Init(int ParSize)
|
||||
{
|
||||
RSCoder::ParSize=ParSize; // Store the number of recovery volumes.
|
||||
FirstBlockDone=false;
|
||||
|
||||
@@ -24,7 +24,7 @@ class RSCoder
|
||||
int ELPol[MAXPOL]; // Error locator polynomial.
|
||||
bool FirstBlockDone;
|
||||
public:
|
||||
RSCoder(int ParSize);
|
||||
void Init(int ParSize);
|
||||
void Encode(byte *Data,int DataSize,byte *DestData);
|
||||
bool Decode(byte *Data,int DataSize,int *EraLoc,int EraSize);
|
||||
};
|
||||
|
||||
@@ -117,7 +117,11 @@ bool ScanTree::GetNextMask()
|
||||
Depth=0;
|
||||
|
||||
strcpy(OrigCurMask,CurMask);
|
||||
wcscpy(OrigCurMaskW,CurMaskW);
|
||||
|
||||
// It is better to have non-empty OrigCurMaskW even if CurMaskW is empty.
|
||||
// We need OrigCurMaskW to process Unicode masks generated by FindProc
|
||||
// when encountering Unicode directory name.
|
||||
GetWideName(CurMask,CurMaskW,OrigCurMaskW,ASIZE(OrigCurMaskW));
|
||||
|
||||
return(true);
|
||||
}
|
||||
@@ -287,7 +291,19 @@ SCAN_CODE ScanTree::FindProc(FindData *FD)
|
||||
wchar Mask[NM];
|
||||
wcscpy(Mask,Slash);
|
||||
if (Depth<SetAllMaskDepth)
|
||||
{
|
||||
wcscpy(Mask+1,PointToName(OrigCurMaskW));
|
||||
|
||||
// FindProc function can generate Unicode CurMaskW when encountering
|
||||
// Unicode directory name even if Unicode mask was not specified.
|
||||
// But we must reset such temporary mask here if OrigCurMaskW is
|
||||
// empty, because we cannot shorten it correctly. It should not
|
||||
// happen normally though, because we attempt to ensure that
|
||||
// OrigCurMaskW is not empty. So it can happen only if converting
|
||||
// OrigCurMask to OrigCurMaskW has been failed.
|
||||
if (*OrigCurMaskW==0)
|
||||
*CurMaskW=Mask[0]=Mask[1]=0;
|
||||
}
|
||||
*Slash=0;
|
||||
wcscpy(DirNameW,CurMaskW);
|
||||
wchar *PrevSlash=wcsrchr(CurMaskW,CPATHDIVIDER);
|
||||
@@ -351,7 +367,7 @@ SCAN_CODE ScanTree::FindProc(FindData *FD)
|
||||
AddEndSlash(CurMask);
|
||||
strcat(CurMask,Mask);
|
||||
|
||||
if (*CurMaskW && *FD->NameW==0)
|
||||
if (*CurMaskW!=0 && *FD->NameW==0)
|
||||
CharToWide(FD->Name,FD->NameW);
|
||||
if (*FD->NameW!=0)
|
||||
{
|
||||
@@ -359,7 +375,7 @@ SCAN_CODE ScanTree::FindProc(FindData *FD)
|
||||
if (FastFindFile)
|
||||
wcscpy(Mask,MASKALLW);
|
||||
else
|
||||
if (*CurMaskW)
|
||||
if (*CurMaskW!=0)
|
||||
wcscpy(Mask,PointToName(CurMaskW));
|
||||
else
|
||||
CharToWide(PointToName(CurMask),Mask);
|
||||
|
||||
203
unrar/secpassword.cpp
Normal file
203
unrar/secpassword.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
typedef BOOL (WINAPI *CRYPTPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags);
|
||||
typedef BOOL (WINAPI *CRYPTUNPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags);
|
||||
|
||||
#ifndef CRYPTPROTECTMEMORY_BLOCK_SIZE
|
||||
#define CRYPTPROTECTMEMORY_BLOCK_SIZE 16
|
||||
#define CRYPTPROTECTMEMORY_SAME_PROCESS 0x00
|
||||
#endif
|
||||
|
||||
class CryptLoader
|
||||
{
|
||||
private:
|
||||
HMODULE hCrypt;
|
||||
bool LoadCalled;
|
||||
public:
|
||||
CryptLoader()
|
||||
{
|
||||
hCrypt=NULL;
|
||||
pCryptProtectMemory=NULL;
|
||||
pCryptUnprotectMemory=NULL;
|
||||
LoadCalled=false;
|
||||
}
|
||||
~CryptLoader()
|
||||
{
|
||||
if (hCrypt!=NULL)
|
||||
FreeLibrary(hCrypt);
|
||||
hCrypt=NULL;
|
||||
pCryptProtectMemory=NULL;
|
||||
pCryptUnprotectMemory=NULL;
|
||||
};
|
||||
void Load()
|
||||
{
|
||||
if (!LoadCalled)
|
||||
{
|
||||
hCrypt = LoadLibraryW(L"Crypt32.dll");
|
||||
if (hCrypt != NULL)
|
||||
{
|
||||
pCryptProtectMemory = (CRYPTPROTECTMEMORY)GetProcAddress(hCrypt, "CryptProtectMemory");
|
||||
pCryptUnprotectMemory = (CRYPTUNPROTECTMEMORY)GetProcAddress(hCrypt, "CryptUnprotectMemory");
|
||||
}
|
||||
LoadCalled=true;
|
||||
}
|
||||
}
|
||||
|
||||
CRYPTPROTECTMEMORY pCryptProtectMemory;
|
||||
CRYPTUNPROTECTMEMORY pCryptUnprotectMemory;
|
||||
};
|
||||
|
||||
// We want to call FreeLibrary when RAR is exiting.
|
||||
CryptLoader GlobalCryptLoader;
|
||||
#endif
|
||||
|
||||
SecPassword::SecPassword()
|
||||
{
|
||||
Set(L"");
|
||||
}
|
||||
|
||||
|
||||
SecPassword::~SecPassword()
|
||||
{
|
||||
Clean();
|
||||
}
|
||||
|
||||
|
||||
void SecPassword::Clean()
|
||||
{
|
||||
PasswordSet=false;
|
||||
cleandata(Password,sizeof(Password));
|
||||
}
|
||||
|
||||
|
||||
// When we call memset in end of function to clean local variables
|
||||
// for security reason, compiler optimizer can remove such call.
|
||||
// So we use our own function for this purpose.
|
||||
void cleandata(void *data,size_t size)
|
||||
{
|
||||
#if defined(_WIN_ALL) && defined(_MSC_VER)
|
||||
SecureZeroMemory(data,size);
|
||||
#else
|
||||
// 'volatile' is required. Otherwise optimizers can remove this function
|
||||
// if cleaning local variables, which are not used after that.
|
||||
volatile byte *d = (volatile byte *)data;
|
||||
for (size_t i=0;i<size;i++)
|
||||
d[i]=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// We got a complain from user that it is possible to create WinRAR dump
|
||||
// with "Create dump file" command in Windows Task Manager and then easily
|
||||
// locate Unicode password string in the dump. It is unsecure if several
|
||||
// people share the same computer and somebody left WinRAR copy with entered
|
||||
// password. So we decided to obfuscate the password to make it more difficult
|
||||
// to find it in dump.
|
||||
void SecPassword::Process(const wchar *Src,wchar *Dst,size_t MaxSize,bool Encode)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// Try to utilize the secure Crypt[Un]ProtectMemory if possible.
|
||||
if (GlobalCryptLoader.pCryptProtectMemory==NULL)
|
||||
GlobalCryptLoader.Load();
|
||||
if (Encode)
|
||||
{
|
||||
if (GlobalCryptLoader.pCryptProtectMemory!=NULL &&
|
||||
MaxSize%CRYPTPROTECTMEMORY_BLOCK_SIZE==0)
|
||||
{
|
||||
memcpy(Dst,Src,MaxSize*sizeof(*Dst));
|
||||
if (!GlobalCryptLoader.pCryptProtectMemory(Dst,DWORD(MaxSize*sizeof(*Dst)),
|
||||
CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
ErrHandler.GeneralErrMsg("CryptProtectMemory failed");
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL &&
|
||||
MaxSize%CRYPTPROTECTMEMORY_BLOCK_SIZE==0)
|
||||
{
|
||||
memcpy(Dst,Src,MaxSize*sizeof(*Dst));
|
||||
if (!GlobalCryptLoader.pCryptUnprotectMemory(Dst,DWORD(MaxSize*sizeof(*Dst)),
|
||||
CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
ErrHandler.GeneralErrMsg("CryptUnprotectMemory failed");
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// CryptProtectMemory is not available, so only slightly obfuscate data.
|
||||
uint Key;
|
||||
#ifdef _WIN_ALL
|
||||
Key=GetCurrentProcessId();
|
||||
#elif defined(_UNIX)
|
||||
Key=getpid();
|
||||
#else
|
||||
Key=10203040; // Just an arbitrary value.
|
||||
#endif
|
||||
|
||||
for (size_t I=0;I<MaxSize;I++)
|
||||
Dst[I]=wchar(Src[I]^(Key+I+75));
|
||||
}
|
||||
|
||||
|
||||
void SecPassword::Get(wchar *Psw,size_t MaxSize)
|
||||
{
|
||||
if (PasswordSet)
|
||||
{
|
||||
Process(Password,Psw,MaxSize,false);
|
||||
Psw[MaxSize-1]=0;
|
||||
}
|
||||
else
|
||||
*Psw=0;
|
||||
}
|
||||
|
||||
|
||||
void SecPassword::Set(const wchar *Psw)
|
||||
{
|
||||
if (*Psw==0)
|
||||
{
|
||||
PasswordSet=false;
|
||||
memset(Password,0,sizeof(Password));
|
||||
}
|
||||
else
|
||||
{
|
||||
PasswordSet=true;
|
||||
Process(Psw,Password,ASIZE(Password),true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t SecPassword::Length()
|
||||
{
|
||||
wchar Plain[MAXPASSWORD];
|
||||
Get(Plain,ASIZE(Plain));
|
||||
size_t Length=wcslen(Plain);
|
||||
cleandata(Plain,ASIZE(Plain));
|
||||
return Length;
|
||||
}
|
||||
|
||||
|
||||
bool SecPassword::operator == (SecPassword &psw)
|
||||
{
|
||||
// We cannot compare encoded data directly, because there is no guarantee
|
||||
// than encryption function will always produce the same result for same
|
||||
// data (salt?) and because we do not clean the rest of password buffer
|
||||
// after trailing zero before encoding password. So we decode first.
|
||||
wchar Plain1[MAXPASSWORD],Plain2[MAXPASSWORD];
|
||||
Get(Plain1,ASIZE(Plain1));
|
||||
psw.Get(Plain2,ASIZE(Plain2));
|
||||
bool Result=wcscmp(Plain1,Plain2)==0;
|
||||
cleandata(Plain1,ASIZE(Plain1));
|
||||
cleandata(Plain2,ASIZE(Plain2));
|
||||
return Result;
|
||||
}
|
||||
|
||||
30
unrar/secpassword.hpp
Normal file
30
unrar/secpassword.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef _RAR_SECURE_PASSWORD_
|
||||
#define _RAR_SECURE_PASSWORD_
|
||||
|
||||
// Store a password securely (if data encryption is provided by OS)
|
||||
// or obfuscated to make search for password in memory dump less trivial.
|
||||
class SecPassword
|
||||
{
|
||||
private:
|
||||
void Process(const wchar *Src,wchar *Dst,size_t MaxSize,bool Encode);
|
||||
|
||||
wchar Password[MAXPASSWORD];
|
||||
|
||||
// It is important to have this 'bool' value, so if our object is cleaned
|
||||
// with memset as a part of larger structure, it is handled correctly.
|
||||
bool PasswordSet;
|
||||
public:
|
||||
SecPassword();
|
||||
~SecPassword();
|
||||
void Clean();
|
||||
void Get(wchar *Psw,size_t MaxSize);
|
||||
void Set(const wchar *Psw);
|
||||
bool IsSet() {return PasswordSet;}
|
||||
size_t Length();
|
||||
bool operator == (SecPassword &psw);
|
||||
};
|
||||
|
||||
|
||||
void cleandata(void *data,size_t size);
|
||||
|
||||
#endif
|
||||
@@ -44,10 +44,22 @@ A million repetitions of "a"
|
||||
#define R3(v,w,x,y,z,i) {z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);}
|
||||
#define R4(v,w,x,y,z,i) {z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize( "", off )
|
||||
// We need to disable the optimization to really wipe these variables.
|
||||
#endif
|
||||
static void wipevars(uint32 &a,uint32 &b,uint32 &c,uint32 &d,uint32 &e)
|
||||
{
|
||||
// Wipe used variables for safety reason.
|
||||
a=b=c=d=e=0;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize( "", on )
|
||||
#endif
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(uint32 state[5], unsigned char buffer[64], bool handsoff)
|
||||
void SHA1Transform(uint32 state[5], unsigned char workspace[64], unsigned char buffer[64], bool handsoff)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
uint32 a, b, c, d, e;
|
||||
@@ -57,7 +69,6 @@ void SHA1Transform(uint32 state[5], unsigned char buffer[64], bool handsoff)
|
||||
uint32 l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
static unsigned char workspace[64];
|
||||
if (handsoff)
|
||||
{
|
||||
block = (CHAR64LONG16*)workspace;
|
||||
@@ -133,8 +144,11 @@ static unsigned char workspace[64];
|
||||
state[4] += e;
|
||||
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
memset(&a,0,sizeof(a));
|
||||
// Such wipe method does not work in optimizing compilers.
|
||||
// a = b = c = d = e = 0;
|
||||
// memset(&a,0,sizeof(a));
|
||||
|
||||
wipevars(a,b,c,d,e);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -165,14 +179,14 @@ uint blen = ((uint)len)<<3;
|
||||
context->count[1] += (uint32)(len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(context->state, context->buffer, handsoff);
|
||||
SHA1Transform(context->state, context->workspace, context->buffer, handsoff);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
#ifdef ALLOW_NOT_ALIGNED_INT
|
||||
SHA1Transform(context->state, &data[i], handsoff);
|
||||
SHA1Transform(context->state, context->workspace, &data[i], handsoff);
|
||||
#else
|
||||
unsigned char buffer[64];
|
||||
memcpy(buffer,data+i,sizeof(buffer));
|
||||
SHA1Transform(context->state, buffer, handsoff);
|
||||
SHA1Transform(context->state, context->workspace, buffer, handsoff);
|
||||
memcpy(data+i,buffer,sizeof(buffer));
|
||||
#endif
|
||||
#ifdef BIG_ENDIAN
|
||||
@@ -220,14 +234,15 @@ unsigned char finalcount[8];
|
||||
digest[i] = context->state[i] & 0xffffffff;
|
||||
}
|
||||
/* Wipe variables */
|
||||
memset(&i,0,sizeof(i));
|
||||
memset(&j,0,sizeof(j));
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(&finalcount, 0, 8);
|
||||
cleandata(&i,sizeof(i));
|
||||
cleandata(&j,sizeof(j));
|
||||
cleandata(context->buffer, 64);
|
||||
cleandata(context->state, 20);
|
||||
cleandata(context->count, 8);
|
||||
cleandata(&finalcount, 8);
|
||||
if (handsoff)
|
||||
SHA1Transform(context->state, context->buffer, true);
|
||||
memset(context->workspace,0,sizeof(context->workspace)); // Wipe the temporary buffer.
|
||||
// SHA1Transform(context->state, context->workspace, context->buffer, true); /* make SHA1Transform overwrite it's own static vars */
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ typedef struct {
|
||||
uint32 state[5];
|
||||
uint32 count[2];
|
||||
unsigned char buffer[64];
|
||||
|
||||
unsigned char workspace[64]; // Temporary buffer.
|
||||
} hash_context;
|
||||
|
||||
void hash_initial( hash_context * c );
|
||||
|
||||
@@ -7,7 +7,8 @@ int ToPercent(int64 N1,int64 N2)
|
||||
return(ToPercentUnlim(N1,N2));
|
||||
}
|
||||
|
||||
/* allows percent larger than 100 */
|
||||
|
||||
// Allows the percent larger than 100.
|
||||
int ToPercentUnlim(int64 N1,int64 N2)
|
||||
{
|
||||
if (N2==0)
|
||||
|
||||
@@ -12,6 +12,8 @@ const wchar *NullToEmpty(const wchar *Str)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char *IntNameToExt(const char *Name)
|
||||
{
|
||||
static char OutName[NM];
|
||||
@@ -22,7 +24,7 @@ char *IntNameToExt(const char *Name)
|
||||
|
||||
void ExtToInt(const char *Src,char *Dest)
|
||||
{
|
||||
#if defined(_WIN_ALL)
|
||||
#ifdef _WIN_ALL
|
||||
CharToOemA(Src,Dest);
|
||||
#else
|
||||
if (Dest!=Src)
|
||||
@@ -33,7 +35,7 @@ void ExtToInt(const char *Src,char *Dest)
|
||||
|
||||
void IntToExt(const char *Src,char *Dest)
|
||||
{
|
||||
#if defined(_WIN_ALL)
|
||||
#ifdef _WIN_ALL
|
||||
OemToCharA(Src,Dest);
|
||||
#else
|
||||
if (Dest!=Src)
|
||||
@@ -172,7 +174,7 @@ bool IsSpace(int ch)
|
||||
|
||||
|
||||
// We do not want to cast every signed char to unsigned when passing to
|
||||
// isspace, so we implement the replacement. Shall work for Unicode too.
|
||||
// isalpha, so we implement the replacement. Shall work for Unicode too.
|
||||
// If chars are signed, conversion from char to int could generate negative
|
||||
// values, resulting in undefined behavior in standard function.
|
||||
bool IsAlpha(int ch)
|
||||
@@ -183,6 +185,19 @@ bool IsAlpha(int ch)
|
||||
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint GetDigits(uint Number)
|
||||
{
|
||||
uint Digits=1;
|
||||
while (Number>=10)
|
||||
{
|
||||
Number/=10;
|
||||
Digits++;
|
||||
}
|
||||
return(Digits);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool LowAscii(const char *Str)
|
||||
{
|
||||
@@ -254,6 +269,30 @@ wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
||||
}
|
||||
|
||||
|
||||
// Safe strncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard strncat.
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = strlen(dest);
|
||||
if (Length + 1 < maxlen)
|
||||
strncat(dest, src, maxlen - Length - 1);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe wcsncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard wcsncat.
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = wcslen(dest);
|
||||
if (Length + 1 < maxlen)
|
||||
wcsncat(dest, src, maxlen - Length - 1);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
void itoa(int64 n,char *Str)
|
||||
{
|
||||
char NumStr[50];
|
||||
@@ -271,7 +310,8 @@ void itoa(int64 n,char *Str)
|
||||
}
|
||||
|
||||
|
||||
int64 atoil(char *Str)
|
||||
|
||||
int64 atoil(const char *Str)
|
||||
{
|
||||
int64 n=0;
|
||||
while (*Str>='0' && *Str<='9')
|
||||
@@ -300,7 +340,7 @@ void itoa(int64 n,wchar *Str)
|
||||
}
|
||||
|
||||
|
||||
int64 atoil(wchar *Str)
|
||||
int64 atoil(const wchar *Str)
|
||||
{
|
||||
int64 n=0;
|
||||
while (*Str>='0' && *Str<='9')
|
||||
@@ -324,3 +364,50 @@ const wchar* GetWide(const char *Src)
|
||||
Str[MaxLength-1]=0;
|
||||
return(Str);
|
||||
}
|
||||
|
||||
|
||||
const wchar* GetWide(const char *Src,const wchar *SrcW)
|
||||
{
|
||||
if (SrcW!=NULL && *SrcW!=0)
|
||||
return SrcW;
|
||||
return GetWide(Src);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
// Parse string containing parameters separated with spaces.
|
||||
// Support quote marks. Param can be NULL to return the pointer to next
|
||||
// parameter, which can be used to estimate the buffer size for Param.
|
||||
const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize)
|
||||
{
|
||||
while (IsSpace(*CmdLine))
|
||||
CmdLine++;
|
||||
if (*CmdLine==0)
|
||||
return NULL;
|
||||
|
||||
size_t ParamSize=0;
|
||||
bool Quote=false;
|
||||
while (*CmdLine!=0 && (Quote || !IsSpace(*CmdLine)))
|
||||
{
|
||||
if (*CmdLine=='\"')
|
||||
{
|
||||
if (CmdLine[1]=='\"')
|
||||
{
|
||||
// Insert the quote character instead of two adjoining quote characters.
|
||||
if (Param!=NULL && ParamSize<MaxSize-1)
|
||||
Param[ParamSize++]='\"';
|
||||
CmdLine++;
|
||||
}
|
||||
else
|
||||
Quote=!Quote;
|
||||
}
|
||||
else
|
||||
if (Param!=NULL && ParamSize<MaxSize-1)
|
||||
Param[ParamSize++]=*CmdLine;
|
||||
CmdLine++;
|
||||
}
|
||||
if (Param!=NULL)
|
||||
Param[ParamSize]=0;
|
||||
return CmdLine;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef _RAR_STRFN_
|
||||
#define _RAR_STRFN_
|
||||
|
||||
const char *NullToEmpty(const char *Str);
|
||||
const wchar *NullToEmpty(const wchar *Str);
|
||||
char *IntNameToExt(const char *Name);
|
||||
const char* NullToEmpty(const char *Str);
|
||||
const wchar* NullToEmpty(const wchar *Str);
|
||||
char* IntNameToExt(const char *Name);
|
||||
void ExtToInt(const char *Src,char *Dest);
|
||||
void IntToExt(const char *Src,char *Dest);
|
||||
char* strlower(char *Str);
|
||||
@@ -18,6 +18,8 @@ unsigned char loctoupper(unsigned char ch);
|
||||
|
||||
char* strncpyz(char *dest, const char *src, size_t maxlen);
|
||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen);
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||
|
||||
unsigned char etoupper(unsigned char ch);
|
||||
wchar etoupperw(wchar ch);
|
||||
@@ -27,6 +29,9 @@ bool IsSpace(int ch);
|
||||
bool IsAlpha(int ch);
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint GetDigits(uint Number);
|
||||
#endif
|
||||
|
||||
bool LowAscii(const char *Str);
|
||||
bool LowAscii(const wchar *Str);
|
||||
@@ -38,9 +43,11 @@ int wcsicompc(const wchar *Str1,const wchar *Str2);
|
||||
#endif
|
||||
|
||||
void itoa(int64 n,char *Str);
|
||||
int64 atoil(char *Str);
|
||||
int64 atoil(const char *Str);
|
||||
void itoa(int64 n,wchar *Str);
|
||||
int64 atoil(wchar *Str);
|
||||
int64 atoil(const wchar *Str);
|
||||
const wchar* GetWide(const char *Src);
|
||||
const wchar* GetWide(const char *Src,const wchar *SrcW);
|
||||
const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,6 +56,10 @@ void SetPriority(int Priority)
|
||||
SetPriorityClass(GetCurrentProcess(),PriorityClass);
|
||||
SetThreadPriority(GetCurrentThread(),PriorityLevel);
|
||||
|
||||
#ifdef RAR_SMP
|
||||
ThreadPool::SetPriority(PriorityLevel);
|
||||
#endif
|
||||
|
||||
// Background mode for Vista, too slow for real life use.
|
||||
// if (WinNT()>=WNT_VISTA && Priority==1)
|
||||
// SetPriorityClass(GetCurrentProcess(),PROCESS_MODE_BACKGROUND_BEGIN);
|
||||
|
||||
@@ -98,8 +98,8 @@ time_t RarTime::GetUnix()
|
||||
// since January 1, 1601 for Windows and since January 1, 1970 for Unix.
|
||||
// Actually we do not care since which date this time starts from
|
||||
// as long as this date is the same for GetRaw and SetRaw. We use the value
|
||||
// returned by GetRaw() for time comparisons and for relative operations
|
||||
// like SetRaw(GetRaw()-C).
|
||||
// returned by GetRaw() for time comparisons, for relative operations
|
||||
// like SetRaw(GetRaw()-C) and for compact time storage when necessary.
|
||||
int64 RarTime::GetRaw()
|
||||
{
|
||||
if (!IsSet())
|
||||
@@ -239,7 +239,7 @@ void RarTime::GetText(char *DateStr,bool FullYear)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void RarTime::SetIsoText(char *TimeText)
|
||||
void RarTime::SetIsoText(const char *TimeText)
|
||||
{
|
||||
int Field[6];
|
||||
memset(Field,0,sizeof(Field));
|
||||
@@ -263,7 +263,7 @@ void RarTime::SetIsoText(char *TimeText)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void RarTime::SetAgeText(char *TimeText)
|
||||
void RarTime::SetAgeText(const char *TimeText)
|
||||
{
|
||||
uint Seconds=0,Value=0;
|
||||
for (int I=0;TimeText[I]!=0;I++)
|
||||
|
||||
@@ -41,8 +41,8 @@ class RarTime
|
||||
uint GetDos();
|
||||
void SetDos(uint DosTime);
|
||||
void GetText(char *DateStr,bool FullYear);
|
||||
void SetIsoText(char *TimeText);
|
||||
void SetAgeText(char *TimeText);
|
||||
void SetIsoText(const char *TimeText);
|
||||
void SetAgeText(const char *TimeText);
|
||||
void SetCurrentTime();
|
||||
void Reset() {rlt.Year=0;}
|
||||
bool IsSet() {return(rlt.Year!=0);}
|
||||
|
||||
@@ -20,7 +20,7 @@ bool ExtractLink(ComprDataIO &DataIO,Archive &Arc,const char *LinkName,uint &Lin
|
||||
else
|
||||
{
|
||||
Log(Arc.FileName,St(MErrCreateLnk),LinkName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
}
|
||||
// We do not set time of created symlink, because utime changes
|
||||
// time of link target and lutimes is not available on all Linux
|
||||
|
||||
@@ -53,11 +53,12 @@ bool WideToChar(const wchar *Src,char *Dest,size_t DestSize)
|
||||
}
|
||||
#endif
|
||||
|
||||
// We tried to return the zero terminated string if conversion is failed,
|
||||
// We tried to return the empty string if conversion is failed,
|
||||
// but it does not work well. WideCharToMultiByte returns 'failed' code
|
||||
// even if we wanted to convert only a part of string and passed DestSize
|
||||
// smaller than required for fully converted string. Such call is the valid
|
||||
// behavior in RAR code and we do not expect the empty string in this case.
|
||||
// and partially converted string even if we wanted to convert only a part
|
||||
// of string and passed DestSize smaller than required for fully converted
|
||||
// string. Such call is the valid behavior in RAR code and we do not expect
|
||||
// the empty string in this case.
|
||||
|
||||
return(RetCode);
|
||||
}
|
||||
@@ -111,7 +112,7 @@ bool CharToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
}
|
||||
#endif
|
||||
|
||||
// We tried to return the zero terminated string if conversion is failed,
|
||||
// We tried to return the empty string if conversion is failed,
|
||||
// but it does not work well. MultiByteToWideChar returns 'failed' code
|
||||
// even if we wanted to convert only a part of string and passed DestSize
|
||||
// smaller than required for fully converted string. Such call is the valid
|
||||
@@ -121,6 +122,7 @@ bool CharToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
}
|
||||
|
||||
|
||||
// SrcSize is in wide characters, not in bytes.
|
||||
byte* WideToRaw(const wchar *Src,byte *Dest,size_t SrcSize)
|
||||
{
|
||||
for (size_t I=0;I<SrcSize;I++,Src++)
|
||||
@@ -178,8 +180,10 @@ void WideToUtf(const wchar *Src,char *Dest,size_t DestSize)
|
||||
}
|
||||
|
||||
|
||||
void UtfToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
// Dest can be NULL if we only need to check validity of Src.
|
||||
bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
{
|
||||
bool Success=true;
|
||||
long dsize=(long)DestSize;
|
||||
dsize--;
|
||||
while (*Src!=0)
|
||||
@@ -212,20 +216,37 @@ void UtfToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
Src+=3;
|
||||
}
|
||||
else
|
||||
break;
|
||||
if (--dsize<0)
|
||||
{
|
||||
// Skip bad character, but continue processing, so we can handle
|
||||
// archived UTF-8 file names even if one of characters is corrupt.
|
||||
Success=false;
|
||||
continue;
|
||||
}
|
||||
if (Dest!=NULL && --dsize<0)
|
||||
break;
|
||||
if (d>0xffff)
|
||||
{
|
||||
if (--dsize<0 || d>0x10ffff)
|
||||
if (Dest!=NULL && --dsize<0)
|
||||
break;
|
||||
*(Dest++)=((d-0x10000)>>10)+0xd800;
|
||||
*(Dest++)=(d&0x3ff)+0xdc00;
|
||||
if (d>0x10ffff)
|
||||
{
|
||||
// UTF-8 is restricted by RFC 3629 to end at 0x10ffff.
|
||||
Success=false;
|
||||
continue;
|
||||
}
|
||||
if (Dest!=NULL)
|
||||
{
|
||||
*(Dest++)=((d-0x10000)>>10)+0xd800;
|
||||
*(Dest++)=(d&0x3ff)+0xdc00;
|
||||
}
|
||||
}
|
||||
else
|
||||
*(Dest++)=d;
|
||||
if (Dest!=NULL)
|
||||
*(Dest++)=d;
|
||||
}
|
||||
*Dest=0;
|
||||
if (Dest!=NULL)
|
||||
*Dest=0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
||||
@@ -295,6 +316,16 @@ int toupperw(int ch)
|
||||
}
|
||||
|
||||
|
||||
int tolowerw(int ch)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
return((int)(LPARAM)CharLowerW((wchar *)(uint)ch));
|
||||
#else
|
||||
return((ch<128) ? loctolower(ch):ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int atoiw(const wchar *s)
|
||||
{
|
||||
int n=0;
|
||||
|
||||
@@ -40,7 +40,7 @@ bool CharToWide(const char *Src,wchar *Dest,size_t DestSize=0x1000000);
|
||||
byte* WideToRaw(const wchar *Src,byte *Dest,size_t SrcSize=0x1000000);
|
||||
wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize=0x1000000);
|
||||
void WideToUtf(const wchar *Src,char *Dest,size_t DestSize);
|
||||
void UtfToWide(const char *Src,wchar *Dest,size_t DestSize);
|
||||
bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize);
|
||||
bool UnicodeEnabled();
|
||||
|
||||
int wcsicomp(const wchar *s1,const wchar *s2);
|
||||
@@ -48,6 +48,7 @@ int wcsnicomp(const wchar *s1,const wchar *s2,size_t n);
|
||||
wchar* wcslower(wchar *Str);
|
||||
wchar* wcsupper(wchar *Str);
|
||||
int toupperw(int ch);
|
||||
int tolowerw(int ch);
|
||||
int atoiw(const wchar *s);
|
||||
|
||||
#ifdef DBCS_SUPPORTED
|
||||
|
||||
@@ -12,7 +12,6 @@ Unpack::Unpack(ComprDataIO *DataIO)
|
||||
{
|
||||
UnpIO=DataIO;
|
||||
Window=NULL;
|
||||
ExternalWindow=false;
|
||||
Suspended=false;
|
||||
UnpAllBuf=false;
|
||||
UnpSomeRead=false;
|
||||
@@ -21,31 +20,24 @@ Unpack::Unpack(ComprDataIO *DataIO)
|
||||
|
||||
Unpack::~Unpack()
|
||||
{
|
||||
if (Window!=NULL && !ExternalWindow)
|
||||
delete[] Window;
|
||||
delete[] Window;
|
||||
InitFilters();
|
||||
}
|
||||
|
||||
|
||||
void Unpack::Init(byte *Window)
|
||||
void Unpack::Init()
|
||||
{
|
||||
if (Window==NULL)
|
||||
{
|
||||
Unpack::Window=new byte[MAXWINSIZE];
|
||||
Window=new byte[MAXWINSIZE];
|
||||
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access to unused areas of sliding dictionary.
|
||||
memset(Unpack::Window,0,MAXWINSIZE);
|
||||
#ifndef ALLOW_EXCEPTIONS
|
||||
if (Unpack::Window==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
if (Window==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Unpack::Window=Window;
|
||||
ExternalWindow=true;
|
||||
}
|
||||
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access to unused areas of sliding dictionary.
|
||||
memset(Window,0,MAXWINSIZE);
|
||||
|
||||
UnpInitData(false);
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
@@ -86,13 +78,6 @@ inline void Unpack::InsertOldDist(unsigned int Distance)
|
||||
}
|
||||
|
||||
|
||||
inline void Unpack::InsertLastMatch(unsigned int Length,unsigned int Distance)
|
||||
{
|
||||
LastDist=Distance;
|
||||
LastLength=Length;
|
||||
}
|
||||
|
||||
|
||||
_forceinline void Unpack::CopyString(uint Length,uint Distance)
|
||||
{
|
||||
uint SrcPtr=UnpPtr-Distance;
|
||||
@@ -213,7 +198,7 @@ void Unpack::Unpack29(bool Solid,bool SuspendAfterInit)
|
||||
if (DDecode[1]==0)
|
||||
{
|
||||
int Dist=0,BitLength=0,Slot=0;
|
||||
for (int I=0;I<sizeof(DBitLengthCounts)/sizeof(DBitLengthCounts[0]);I++,BitLength++)
|
||||
for (int I=0;I<ASIZE(DBitLengthCounts);I++,BitLength++)
|
||||
for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
|
||||
{
|
||||
DDecode[Slot]=Dist;
|
||||
@@ -278,7 +263,7 @@ void Unpack::Unpack29(bool Solid,bool SuspendAfterInit)
|
||||
}
|
||||
if (NextCh==-1) // Corrupt PPM data found.
|
||||
break;
|
||||
if (NextCh==2) // End of file in PPM mode..
|
||||
if (NextCh==2) // End of file in PPM mode.
|
||||
break;
|
||||
if (NextCh==3) // Read VM code.
|
||||
{
|
||||
@@ -383,7 +368,7 @@ void Unpack::Unpack29(bool Solid,bool SuspendAfterInit)
|
||||
}
|
||||
|
||||
InsertOldDist(Distance);
|
||||
InsertLastMatch(Length,Distance);
|
||||
LastLength=Length;
|
||||
CopyString(Length,Distance);
|
||||
continue;
|
||||
}
|
||||
@@ -402,7 +387,7 @@ void Unpack::Unpack29(bool Solid,bool SuspendAfterInit)
|
||||
if (Number==258)
|
||||
{
|
||||
if (LastLength!=0)
|
||||
CopyString(LastLength,LastDist);
|
||||
CopyString(LastLength,OldDist[0]);
|
||||
continue;
|
||||
}
|
||||
if (Number<263)
|
||||
@@ -420,7 +405,7 @@ void Unpack::Unpack29(bool Solid,bool SuspendAfterInit)
|
||||
Length+=getbits()>>(16-Bits);
|
||||
addbits(Bits);
|
||||
}
|
||||
InsertLastMatch(Length,Distance);
|
||||
LastLength=Length;
|
||||
CopyString(Length,Distance);
|
||||
continue;
|
||||
}
|
||||
@@ -433,7 +418,7 @@ void Unpack::Unpack29(bool Solid,bool SuspendAfterInit)
|
||||
addbits(Bits);
|
||||
}
|
||||
InsertOldDist(Distance);
|
||||
InsertLastMatch(2,Distance);
|
||||
LastLength=2;
|
||||
CopyString(2,Distance);
|
||||
continue;
|
||||
}
|
||||
@@ -442,11 +427,17 @@ void Unpack::Unpack29(bool Solid,bool SuspendAfterInit)
|
||||
}
|
||||
|
||||
|
||||
// Return 'false' to quit unpacking the current file or 'true' to continue.
|
||||
bool Unpack::ReadEndOfBlock()
|
||||
{
|
||||
unsigned int BitField=getbits();
|
||||
bool NewTable,NewFile=false;
|
||||
if (BitField & 0x8000)
|
||||
|
||||
// "1" - no new file, new table just here.
|
||||
// "00" - new file, no new table.
|
||||
// "01" - new file, new table (in beginning of next file).
|
||||
|
||||
if ((BitField & 0x8000)!=0)
|
||||
{
|
||||
NewTable=true;
|
||||
addbits(1);
|
||||
@@ -458,12 +449,21 @@ bool Unpack::ReadEndOfBlock()
|
||||
addbits(2);
|
||||
}
|
||||
TablesRead=!NewTable;
|
||||
return !(NewFile || NewTable && !ReadTables());
|
||||
|
||||
// Quit immediately if "new file" flag is set. If "new table" flag
|
||||
// is present, we'll read the table in beginning of next file
|
||||
// based on 'TablesRead' 'false' value.
|
||||
if (NewFile)
|
||||
return false;
|
||||
return ReadTables(); // Quit only if we failed to read tables.
|
||||
}
|
||||
|
||||
|
||||
bool Unpack::ReadVMCode()
|
||||
{
|
||||
// Entire VM code is guaranteed to fully present in block defined
|
||||
// by current Huffman table. Compressor checks that VM code does not cross
|
||||
// Huffman block boundaries.
|
||||
unsigned int FirstByte=getbits()>>8;
|
||||
addbits(8);
|
||||
int Length=(FirstByte & 7)+1;
|
||||
@@ -557,7 +557,7 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
|
||||
if (NewFilter) // New filter code, never used before since VM reset.
|
||||
{
|
||||
// Too many different filters, corrupt archive.
|
||||
if (FiltPos>1024)
|
||||
if (FiltPos>MAX_FILTERS)
|
||||
{
|
||||
delete StackFilter;
|
||||
return false;
|
||||
@@ -839,6 +839,8 @@ void Unpack::UnpWriteBuf()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current filter intersects the window write border, so we adjust
|
||||
// the window border to process this filter next time, not now.
|
||||
for (size_t J=I;J<PrgStack.Size();J++)
|
||||
{
|
||||
UnpackFilter *flt=PrgStack[J];
|
||||
@@ -1115,7 +1117,7 @@ void Unpack::MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size)
|
||||
|
||||
// Prepare the decode table, so this position in code list will be
|
||||
// decoded to current alphabet item number.
|
||||
Dec->DecodeNum[LastPos]=I;
|
||||
Dec->DecodeNum[LastPos]=(ushort)I;
|
||||
|
||||
// We'll use next position number for this bit length next time.
|
||||
// So we pass through the entire range of positions available
|
||||
|
||||
@@ -6,6 +6,9 @@ enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
|
||||
// Maximum allowed number of compressed bits processed in quick mode.
|
||||
#define MAX_QUICK_DECODE_BITS 10
|
||||
|
||||
// Maximum number of filters per entire data block.
|
||||
#define MAX_FILTERS 1024
|
||||
|
||||
// Decode compressed bit fields to alphabet numbers.
|
||||
struct DecodeTable
|
||||
{
|
||||
@@ -33,7 +36,9 @@ struct DecodeTable
|
||||
|
||||
// Translates compressed bits (up to QuickBits length)
|
||||
// to position in alphabet in quick mode.
|
||||
uint QuickNum[1<<MAX_QUICK_DECODE_BITS];
|
||||
// 'ushort' saves some memory and even provides a little speed gain
|
||||
// comparting to 'uint' here.
|
||||
ushort QuickNum[1<<MAX_QUICK_DECODE_BITS];
|
||||
|
||||
// Translate the position in code list to position in alphabet.
|
||||
// We do not allocate it dynamically to avoid performance overhead
|
||||
@@ -41,7 +46,9 @@ struct DecodeTable
|
||||
// as array dimension. Real size of this array is defined in MaxNum.
|
||||
// We use this array if compressed bit field is too lengthy
|
||||
// for QuickLen based translation.
|
||||
uint DecodeNum[LARGEST_TABLE_SIZE];
|
||||
// 'ushort' saves some memory and even provides a little speed gain
|
||||
// comparting to 'uint' here.
|
||||
ushort DecodeNum[LARGEST_TABLE_SIZE];
|
||||
};
|
||||
|
||||
struct UnpackFilter
|
||||
@@ -73,7 +80,6 @@ struct AudioVariables // For RAR 2.0 archives only.
|
||||
class Unpack:private BitInput
|
||||
{
|
||||
private:
|
||||
friend class Pack;
|
||||
|
||||
void Unpack29(bool Solid,bool SuspendAfterInit=false);
|
||||
bool UnpReadBuf();
|
||||
@@ -87,7 +93,6 @@ class Unpack:private BitInput
|
||||
inline int SafePPMDecodeChar();
|
||||
void CopyString();
|
||||
inline void InsertOldDist(unsigned int Distance);
|
||||
inline void InsertLastMatch(unsigned int Length,unsigned int Distance);
|
||||
void UnpInitData(int Solid);
|
||||
_forceinline void CopyString(uint Length,uint Distance);
|
||||
bool ReadEndOfBlock();
|
||||
@@ -126,10 +131,14 @@ class Unpack:private BitInput
|
||||
DecodeTable DD; // Decode distances.
|
||||
DecodeTable LDD; // Decode lower bits of distances.
|
||||
DecodeTable RD; // Decode repeating distances.
|
||||
DecodeTable BD; // Decod bit lengths in Huffman table.
|
||||
DecodeTable BD; // Decode bit lengths in Huffman table.
|
||||
|
||||
unsigned int OldDist[4],OldDistPtr;
|
||||
unsigned int LastDist,LastLength;
|
||||
unsigned int LastLength;
|
||||
|
||||
// LastDist is necessary only for RAR2 and older with circular OldDist
|
||||
// array. In RAR3 last distance is always stored in OldDist[0].
|
||||
unsigned int LastDist;
|
||||
|
||||
unsigned int UnpPtr,WrPtr;
|
||||
|
||||
@@ -141,12 +150,11 @@ class Unpack:private BitInput
|
||||
// unless we are at the end of file.
|
||||
int ReadBorder;
|
||||
|
||||
unsigned char UnpOldTable[HUFF_TABLE_SIZE];
|
||||
byte UnpOldTable[HUFF_TABLE_SIZE];
|
||||
|
||||
int UnpBlockType;
|
||||
|
||||
byte *Window;
|
||||
bool ExternalWindow;
|
||||
|
||||
|
||||
int64 DestUnpSize;
|
||||
@@ -167,14 +175,13 @@ class Unpack:private BitInput
|
||||
void GetFlagsBuf();
|
||||
void OldUnpInitData(int Solid);
|
||||
void InitHuff();
|
||||
void CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace);
|
||||
void CorrHuff(ushort *CharSet,byte *NumToPlace);
|
||||
void OldCopyString(unsigned int Distance,unsigned int Length);
|
||||
uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab);
|
||||
void OldUnpWriteBuf();
|
||||
|
||||
unsigned int ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
|
||||
unsigned int Place[256],PlaceA[256],PlaceB[256],PlaceC[256];
|
||||
unsigned int NToPl[256],NToPlB[256],NToPlC[256];
|
||||
ushort ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
|
||||
byte NToPl[256],NToPlB[256],NToPlC[256];
|
||||
unsigned int FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
|
||||
int Buf60,NumHuf,StMode,LCount,FlagsCnt;
|
||||
unsigned int Nhfb,Nlzb,MaxDist3;
|
||||
@@ -198,7 +205,7 @@ class Unpack:private BitInput
|
||||
public:
|
||||
Unpack(ComprDataIO *DataIO);
|
||||
~Unpack();
|
||||
void Init(byte *Window=NULL);
|
||||
void Init();
|
||||
void DoUnpack(int Method,bool Solid,bool SuspendAfterInit=false);
|
||||
bool IsFileExtracted() {return(FileExtracted);}
|
||||
void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
|
||||
|
||||
@@ -242,9 +242,7 @@ void Unpack::ShortLZ()
|
||||
Distance=ChSetA[DistancePlace];
|
||||
if (--DistancePlace != -1)
|
||||
{
|
||||
PlaceA[Distance]--;
|
||||
LastDistance=ChSetA[DistancePlace];
|
||||
PlaceA[LastDistance]++;
|
||||
ChSetA[DistancePlace+1]=LastDistance;
|
||||
ChSetA[DistancePlace]=Distance;
|
||||
}
|
||||
@@ -468,8 +466,6 @@ void Unpack::InitHuff()
|
||||
{
|
||||
for (unsigned int I=0;I<256;I++)
|
||||
{
|
||||
Place[I]=PlaceA[I]=PlaceB[I]=I;
|
||||
PlaceC[I]=(~I+1) & 0xff;
|
||||
ChSet[I]=ChSetB[I]=I<<8;
|
||||
ChSetA[I]=I;
|
||||
ChSetC[I]=((~I+1) & 0xff)<<8;
|
||||
@@ -481,7 +477,7 @@ void Unpack::InitHuff()
|
||||
}
|
||||
|
||||
|
||||
void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace)
|
||||
void Unpack::CorrHuff(ushort *CharSet,byte *NumToPlace)
|
||||
{
|
||||
int I,J;
|
||||
for (I=7;I>=0;I--)
|
||||
|
||||
@@ -5,24 +5,28 @@ void ExtractUnixOwner(Archive &Arc,char *FileName)
|
||||
if (Arc.HeaderCRC!=Arc.UOHead.HeadCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MOwnersBroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
struct passwd *pw;
|
||||
errno=0; // Required by getpwnam specification if we need to check errno.
|
||||
if ((pw=getpwnam(Arc.UOHead.OwnerName))==NULL)
|
||||
{
|
||||
Log(Arc.FileName,St(MErrGetOwnerID),Arc.UOHead.OwnerName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return;
|
||||
}
|
||||
uid_t OwnerID=pw->pw_uid;
|
||||
|
||||
struct group *gr;
|
||||
errno=0; // Required by getgrnam specification if we need to check errno.
|
||||
if ((gr=getgrnam(Arc.UOHead.GroupName))==NULL)
|
||||
{
|
||||
Log(Arc.FileName,St(MErrGetGroupID),Arc.UOHead.GroupName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
uint Attr=GetFileAttr(FileName,NULL);
|
||||
@@ -34,7 +38,7 @@ void ExtractUnixOwner(Archive &Arc,char *FileName)
|
||||
#endif
|
||||
{
|
||||
Log(Arc.FileName,St(MSetOwnersError),FileName);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
}
|
||||
SetFileAttr(FileName,NULL,Attr);
|
||||
}
|
||||
@@ -53,7 +57,7 @@ void ExtractUnixOwnerNew(Archive &Arc,char *FileName)
|
||||
if ((pw=getpwnam(OwnerName))==NULL)
|
||||
{
|
||||
Log(Arc.FileName,St(MErrGetOwnerID),OwnerName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return;
|
||||
}
|
||||
uid_t OwnerID=pw->pw_uid;
|
||||
@@ -62,7 +66,7 @@ void ExtractUnixOwnerNew(Archive &Arc,char *FileName)
|
||||
if ((gr=getgrnam(GroupName))==NULL)
|
||||
{
|
||||
Log(Arc.FileName,St(MErrGetGroupID),GroupName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
uint Attr=GetFileAttr(FileName,NULL);
|
||||
@@ -74,7 +78,7 @@ void ExtractUnixOwnerNew(Archive &Arc,char *FileName)
|
||||
#endif
|
||||
{
|
||||
Log(Arc.FileName,St(MSetOwnersError),FileName);
|
||||
ErrHandler.SetErrorCode(CREATE_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
}
|
||||
SetFileAttr(FileName,NULL,Attr);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define RARVER_MAJOR 4
|
||||
#define RARVER_MINOR 0
|
||||
#define RARVER_MINOR 20
|
||||
#define RARVER_BETA 0
|
||||
#define RARVER_PATCH 1
|
||||
#define RARVER_DAY 12
|
||||
#define RARVER_MONTH 6
|
||||
#define RARVER_YEAR 2011
|
||||
#define RARVER_DAY 16
|
||||
#define RARVER_MONTH 12
|
||||
#define RARVER_YEAR 2012
|
||||
|
||||
174
unrar/volume.cpp
174
unrar/volume.cpp
@@ -43,58 +43,83 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman
|
||||
#endif
|
||||
bool FailedOpen=false,OldSchemeTested=false;
|
||||
|
||||
while (!Arc.Open(NextName,NextNameW))
|
||||
{
|
||||
// We need to open a new volume which size was not calculated
|
||||
// in total size before, so we cannot calculate the total progress
|
||||
// anymore. Let's reset the total size to zero and stop
|
||||
// the total progress.
|
||||
if (DataIO!=NULL)
|
||||
DataIO->TotalArcSize=0;
|
||||
#if !defined(GUI) && !defined(SILENT)
|
||||
// In -vp mode we force the pause before next volume even if it is present
|
||||
// and even if we are on the hard disk. It is important when user does not
|
||||
// want to process partially downloaded volumes preliminary.
|
||||
if (Cmd->VolumePause && !AskNextVol(NextName,NextNameW))
|
||||
FailedOpen=true;
|
||||
#endif
|
||||
|
||||
if (!OldSchemeTested)
|
||||
if (!FailedOpen)
|
||||
while (!Arc.Open(NextName,NextNameW,0))
|
||||
{
|
||||
// Checking for new style volumes renamed by user to old style
|
||||
// name format. Some users did it for unknown reason.
|
||||
char AltNextName[NM];
|
||||
wchar AltNextNameW[NM];
|
||||
strcpy(AltNextName,Arc.FileName);
|
||||
wcscpy(AltNextNameW,Arc.FileNameW);
|
||||
NextVolumeName(AltNextName,AltNextNameW,ASIZE(AltNextName),true);
|
||||
OldSchemeTested=true;
|
||||
if (Arc.Open(AltNextName,AltNextNameW))
|
||||
// We need to open a new volume which size was not calculated
|
||||
// in total size before, so we cannot calculate the total progress
|
||||
// anymore. Let's reset the total size to zero and stop
|
||||
// the total progress.
|
||||
if (DataIO!=NULL)
|
||||
DataIO->TotalArcSize=0;
|
||||
|
||||
if (!OldSchemeTested)
|
||||
{
|
||||
strcpy(NextName,AltNextName);
|
||||
wcscpy(NextNameW,AltNextNameW);
|
||||
break;
|
||||
// Checking for new style volumes renamed by user to old style
|
||||
// name format. Some users did it for unknown reason.
|
||||
char AltNextName[NM];
|
||||
wchar AltNextNameW[NM];
|
||||
strcpy(AltNextName,Arc.FileName);
|
||||
wcscpy(AltNextNameW,Arc.FileNameW);
|
||||
NextVolumeName(AltNextName,AltNextNameW,ASIZE(AltNextName),true);
|
||||
OldSchemeTested=true;
|
||||
if (Arc.Open(AltNextName,AltNextNameW,0))
|
||||
{
|
||||
strcpy(NextName,AltNextName);
|
||||
wcscpy(NextNameW,AltNextNameW);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef RARDLL
|
||||
//rar extension depends on NextName having size NM
|
||||
if (Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL ||
|
||||
Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1)
|
||||
{
|
||||
Cmd->DllError=ERAR_EOPEN;
|
||||
FailedOpen=true;
|
||||
break;
|
||||
}
|
||||
if (Cmd->ChangeVolProc!=NULL)
|
||||
{
|
||||
// Here we preserve ESP value. It is necessary for those developers,
|
||||
// who still define ChangeVolProc callback as "C" type function,
|
||||
// even though in year 2001 we announced in unrar.dll whatsnew.txt
|
||||
// that it will be PASCAL type (for compatibility with Visual Basic).
|
||||
//rar extension depends on NextName having size NM
|
||||
bool DllVolChanged=false;
|
||||
|
||||
if (Cmd->Callback!=NULL)
|
||||
{
|
||||
GetWideName(NextName,NextNameW,NextNameW,ASIZE(NextNameW));
|
||||
char CurName[ASIZE(NextName)];
|
||||
strcpy(CurName,NextName);
|
||||
wchar CurNameW[ASIZE(NextNameW)];
|
||||
wcscpy(CurNameW,NextNameW);
|
||||
if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextNameW,RAR_VOL_ASK)!=-1 &&
|
||||
wcscmp(CurNameW,NextNameW)!=0)
|
||||
{
|
||||
*NextName=0;
|
||||
DllVolChanged=true;
|
||||
}
|
||||
else
|
||||
if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)!=-1 &&
|
||||
strcmp(CurName,NextName)!=0)
|
||||
{
|
||||
*NextNameW=0;
|
||||
DllVolChanged=true;
|
||||
}
|
||||
}
|
||||
if (!DllVolChanged && Cmd->ChangeVolProc!=NULL)
|
||||
{
|
||||
// Here we preserve ESP value. It is necessary for those developers,
|
||||
// who still define ChangeVolProc callback as "C" type function,
|
||||
// even though in year 2001 we announced in unrar.dll whatsnew.txt
|
||||
// that it will be PASCAL type (for compatibility with Visual Basic).
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef _WIN_64
|
||||
__asm mov ebx,esp
|
||||
__asm mov ebx,esp
|
||||
#endif
|
||||
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||
_EBX=_ESP;
|
||||
_EBX=_ESP;
|
||||
#endif
|
||||
int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);
|
||||
int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);
|
||||
|
||||
// Restore ESP after ChangeVolProc with wrongly defined calling
|
||||
// convention broken it.
|
||||
// Restore ESP after ChangeVolProc with wrongly defined calling
|
||||
// convention broken it.
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef _WIN_64
|
||||
__asm mov esp,ebx
|
||||
@@ -102,56 +127,67 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman
|
||||
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||
_ESP=_EBX;
|
||||
#endif
|
||||
if (RetCode==0)
|
||||
if (RetCode!=0)
|
||||
{
|
||||
Cmd->DllError=ERAR_EOPEN;
|
||||
FailedOpen=true;
|
||||
break;
|
||||
*NextNameW=0;
|
||||
DllVolChanged=true;
|
||||
}
|
||||
}
|
||||
#else // RARDLL
|
||||
if (!DllVolChanged)
|
||||
{
|
||||
Cmd->DllError=ERAR_EOPEN;
|
||||
FailedOpen=true;
|
||||
break;
|
||||
}
|
||||
#else // !RARDLL
|
||||
|
||||
#if !defined(SFX_MODULE) && !defined(_WIN_CE)
|
||||
if (!RecoveryDone)
|
||||
{
|
||||
RecVolumes RecVol;
|
||||
RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true);
|
||||
RecoveryDone=true;
|
||||
continue;
|
||||
}
|
||||
if (!RecoveryDone)
|
||||
{
|
||||
RecVolumes RecVol;
|
||||
RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true);
|
||||
RecoveryDone=true;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef GUI
|
||||
if (!Cmd->VolumePause && !IsRemovable(NextName))
|
||||
{
|
||||
FailedOpen=true;
|
||||
break;
|
||||
}
|
||||
if (!Cmd->VolumePause && !IsRemovable(NextName))
|
||||
{
|
||||
FailedOpen=true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifndef SILENT
|
||||
if (Cmd->AllYes || !AskNextVol(NextName,NextNameW))
|
||||
if (Cmd->AllYes || !AskNextVol(NextName,NextNameW))
|
||||
#endif
|
||||
{
|
||||
FailedOpen=true;
|
||||
break;
|
||||
}
|
||||
{
|
||||
FailedOpen=true;
|
||||
break;
|
||||
}
|
||||
|
||||
#endif // RARDLL
|
||||
}
|
||||
}
|
||||
|
||||
if (FailedOpen)
|
||||
{
|
||||
#if !defined(SILENT) && !defined(_WIN_CE)
|
||||
Log(Arc.FileName,St(MAbsNextVol),NextName);
|
||||
#endif
|
||||
Arc.Open(Arc.FileName,Arc.FileNameW);
|
||||
Arc.Open(Arc.FileName,Arc.FileNameW,0);
|
||||
Arc.Seek(PosBeforeClose,SEEK_SET);
|
||||
return(false);
|
||||
}
|
||||
Arc.CheckArc(true);
|
||||
#ifdef RARDLL
|
||||
if (Cmd->Callback!=NULL &&
|
||||
Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1)
|
||||
return(false);
|
||||
if (Cmd->Callback!=NULL)
|
||||
{
|
||||
GetWideName(NextName,NextNameW,NextNameW,ASIZE(NextNameW));
|
||||
if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextNameW,RAR_VOL_NOTIFY)==-1)
|
||||
return(false);
|
||||
if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1)
|
||||
return(false);
|
||||
}
|
||||
if (Cmd->ChangeVolProc!=NULL)
|
||||
{
|
||||
#if defined(_WIN_ALL) && !defined(_MSC_VER) && !defined(__MINGW32__)
|
||||
@@ -168,6 +204,8 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman
|
||||
|
||||
if (Command=='T' || Command=='X' || Command=='E')
|
||||
mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);
|
||||
|
||||
|
||||
if (SplitHeader)
|
||||
Arc.SearchBlock(HeaderType);
|
||||
else
|
||||
|
||||
@@ -15,14 +15,14 @@ void ExtractACL(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MACLBroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
|
||||
{
|
||||
Log(Arc.FileName,St(MACLUnknown),FileName);
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ void ExtractACL(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
|
||||
{
|
||||
Log(Arc.FileName,St(MACLBroken),FileName);
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ void ExtractACL(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
{
|
||||
Log(Arc.FileName,St(MACLSetError),FileName);
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -94,7 +94,7 @@ void ExtractACLNew(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
{
|
||||
Log(Arc.FileName,St(MACLSetError),FileName);
|
||||
ErrHandler.SysErrMsg();
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ void ExtractStreams(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
#ifndef SILENT
|
||||
Log(Arc.FileName,St(MStreamBroken),FileName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ void ExtractStreams(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
#ifndef SILENT
|
||||
Log(Arc.FileName,St(MStreamUnknown),FileName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(WARNING);
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ void ExtractStreams(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
#ifndef SILENT
|
||||
Log(Arc.FileName,St(MStreamBroken),FileName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,13 +72,13 @@ void ExtractStreams(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
#ifndef SILENT
|
||||
Log(Arc.FileName,St(MStreamBroken),StreamName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
}
|
||||
else
|
||||
CurFile.Close();
|
||||
}
|
||||
File HostFile;
|
||||
if (Found && HostFile.Open(FileName,FileNameW,true,true))
|
||||
if (Found && HostFile.Open(FileName,FileNameW,FMF_OPENSHARED|FMF_UPDATE))
|
||||
SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
|
||||
&fd.ftLastWriteTime);
|
||||
if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
|
||||
@@ -115,7 +115,7 @@ void ExtractStreamsNew(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
Log(Arc.FileName,St(MStreamBroken),FileName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ void ExtractStreamsNew(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
#if !defined(SILENT) && !defined(SFX_MODULE)
|
||||
Log(Arc.FileName,St(MStreamBroken),FileName);
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(CRC_ERROR);
|
||||
ErrHandler.SetErrorCode(RARX_CRC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ void ExtractStreamsNew(Archive &Arc,char *FileName,wchar *FileNameW)
|
||||
if (CurFile.WCreate(StreamName,StreamNameW) && Arc.ReadSubData(NULL,&CurFile))
|
||||
CurFile.Close();
|
||||
File HostFile;
|
||||
if (Found && HostFile.Open(FileName,FileNameW,true,true))
|
||||
if (Found && HostFile.Open(FileName,FileNameW,FMF_OPENSHARED|FMF_UPDATE))
|
||||
SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
|
||||
&fd.ftLastWriteTime);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user