65 Commits

Author SHA1 Message Date
Gustavo Lopes
ece47716ab Merge pull request #2 from tony2001/master
v3.0.2 update
2013-10-11 01:53:56 -07:00
Antony Dovgal
388707153c version 3.0.2 is coming 2013-10-11 12:19:49 +04:00
Antony Dovgal
60cf649b85 allow rb mode for dirs, it won't hurt 2013-10-11 12:18:24 +04:00
Gustavo Lopes
881989bbac Allow 'rb' mode for opening rar entries 2013-04-28 21:13:34 +02:00
Gustavo Lopes
b1c3582301 Convert rar_navigation.c to unix line endings 2013-04-28 20:32:45 +02:00
Gustavo Lopes
1cfe9592c0 Remove trailing space 2013-04-28 20:32:45 +02:00
Antony Dovgal
c92f03f1e2 Use zend_read_property() to read object properties 2013-04-28 13:19:12 +02:00
Gustavo Lopes
430a8ba763 Merge branch 'unrar', with unrar 4.2.4.
Conflicts:
	unrar/dll.rc
	unrar/version.hpp
2012-12-16 18:11:42 +01:00
Gustavo Lopes
e2c046d88d Added unrar 4.2.4. 2012-12-16 17:39:34 +01:00
Gustavo Lopes
63d3b18405 Prepare for 3.0.1 release 2012-07-29 02:48:36 +00:00
Gustavo Lopes
6963ed8f43 Add .gitignore 2012-07-29 02:03:44 +00:00
Gustavo Lopes
0a57b9b313 Remove revision information 2012-07-29 02:02:35 +00:00
Gustavo Lopes
3b9dd4dd6e Added test for bug #59939 (can't reproduce) 2012-07-29 00:44:38 +00:00
Gustavo Lopes
28e2572026 Fix bad pointer in error message 2012-07-29 00:42:45 +00:00
Gustavo Lopes
21cba90843 Fix some tests for when TZ != 'Europe/Lisbon' 2012-07-29 00:28:32 +00:00
Gustavo Lopes
0473c464e1 Fix problem in PHP >= 5.3.11, 5.4.1
And not compiling in master.
2012-07-29 02:15:57 +02:00
Gustavo Lopes
9cd367de03 Use <> in standard includes 2012-07-28 23:13:30 +00:00
Gustavo Lopes
0ef63a5fbb Merge branch 'unrar', with unrar 4.2.2
Conflicts:
	unrar/UnRAR.vcproj
	unrar/UnRARDll.vcproj
	unrar/arcread.cpp
	unrar/cmddata.cpp
	unrar/dll.cpp
	unrar/dll.rc
	unrar/errhnd.hpp
	unrar/extract.cpp
	unrar/makefile.bcc
	unrar/makefile.dj
	unrar/makefile.dmc
	unrar/makefile.unix
	unrar/os.hpp
	unrar/unpack.hpp
	unrar/version.hpp
	unrar/volume.cpp
2012-07-29 00:53:30 +02:00
Gustavo Lopes
75486ffa92 Merge with strategy ours 1e542a4db.
This will allow to merge in new changes int he unrar lib without using
a temporary branch.
2012-07-28 16:26:51 +02:00
Gustavo Lopes
7d8ada6e1e Added unrar 4.2.2. 2012-07-28 01:40:45 +02:00
Gustavo Lopes
02e98e3188 Added unrar 4.2.2. 2012-07-28 01:40:10 +02:00
Gustavo Lopes
18a025c38d Added unrar 4.2.1. 2012-07-28 01:06:28 +02:00
Gustavo Lopes
3bd27b4b36 Added unrar 4.1.4. 2012-07-28 00:58:41 +02:00
Gustavo Lopes
5bb815b5db Added unrar 4.1.3. 2012-07-28 00:58:06 +02:00
Gustavo Lopes
e06c6250d0 Merged in changes in unrar 4.1.1 and 4.1.2. 2011-11-02 11:48:33 +00:00
Gustavo Lopes
1e542a4db3 Added unrar 4.1.2 2011-11-02 11:14:35 +00:00
Gustavo Lopes
6907905144 Added unrar 4.1.1 2011-11-02 11:14:22 +00:00
Gustavo Lopes
f8cb60259d Added unrar 4.0.7 2011-06-12 02:09:21 +01:00
Gustavo Lopes
1e2e912de2 Added unrar 4.0.6. 2011-02-17 19:07:06 +00:00
Gustavo Lopes
479c373f4d Added unrar 4.0.5 2011-01-24 04:22:35 +00:00
Gustavo Lopes
6c1dd8a81f Added unrar 4.0.4 2011-01-13 18:50:03 +00:00
Gustavo Lopes
b451c7c79b Added unrar 4.0.3 2011-01-13 18:49:58 +00:00
Gustavo Lopes
c915d361f4 Added unrar 4.0.2 2011-01-13 18:49:54 +00:00
Gustavo Lopes
15aa6f20d6 Added unrar 4.0.1 2011-01-13 18:49:44 +00:00
Gustavo Lopes
561966f23b Added unrar 3.9.10 2011-01-13 18:49:25 +00:00
Gustavo Lopes
80986445f5 Added unrar 3.9.9 2011-01-13 18:49:13 +00:00
Gustavo Lopes
446a2e8492 Added unrar 3.9.8 2011-01-13 18:49:00 +00:00
Gustavo Lopes
12719dce2c Added unrar 3.9.7 2011-01-13 18:48:55 +00:00
Gustavo Lopes
75c4bbc240 Added unrar 3.9.6 2011-01-13 18:48:50 +00:00
Gustavo Lopes
951ccf9767 Added unrar 3.9.5 2011-01-13 18:48:45 +00:00
Gustavo Lopes
2538d242ee Added unrar 3.9.4 2011-01-13 18:48:41 +00:00
Gustavo Lopes
e91808a5eb Added unrar 3.9.3 2011-01-13 18:48:36 +00:00
Gustavo Lopes
a9631cfddd Added unrar 3.9.2 2011-01-13 18:48:32 +00:00
Gustavo Lopes
89c4cbe487 Added unrar 3.9.1 2011-01-13 18:48:26 +00:00
Gustavo Lopes
876cb51c4c Added unrar 3.8.5 2011-01-13 18:47:51 +00:00
Gustavo Lopes
ad8e1e2a2b Added unrar 3.8.4 2011-01-13 18:47:45 +00:00
Gustavo Lopes
825de01ac1 Added unrar 3.8.3 2011-01-13 18:47:39 +00:00
Gustavo Lopes
7a8b0a7f59 Added unrar 3.8.2 2011-01-13 18:47:31 +00:00
Gustavo Lopes
35f7e43f2f Added unrar 3.8.1 2011-01-13 18:47:24 +00:00
Gustavo Lopes
3a535eba4e Added unrar 3.7.8 2011-01-13 18:47:06 +00:00
Gustavo Lopes
a16b24d665 Added unrar 3.7.7 2011-01-13 18:47:00 +00:00
Gustavo Lopes
9bd14a69e8 Added unrar 3.7.6 2011-01-13 18:46:54 +00:00
Gustavo Lopes
c093245020 Added unrar 3.7.5 2011-01-13 18:46:49 +00:00
Gustavo Lopes
f5ca2159f0 Added unrar 3.7.4 2011-01-13 18:46:44 +00:00
Gustavo Lopes
b8102334c6 Added unrar 3.7.3 2011-01-13 18:46:33 +00:00
Gustavo Lopes
eaffae90c0 Added unrar 3.7.2 2011-01-13 18:46:27 +00:00
Gustavo Lopes
2e18f53535 Added unrar 3.7.1 2011-01-13 18:46:22 +00:00
Gustavo Lopes
fff0c56e2e Added unrar 3.6.8 2011-01-13 18:46:12 +00:00
Gustavo Lopes
59a53d18ed Added unrar 3.6.7 2011-01-13 18:46:05 +00:00
Gustavo Lopes
e1490118df Added unrar 3.6.6 2011-01-13 18:46:00 +00:00
Gustavo Lopes
7bacdf6736 Added unrar 3.6.5 2011-01-13 18:45:55 +00:00
Gustavo Lopes
00a58e1934 Added unrar 3.6.4 2011-01-13 18:45:40 +00:00
Gustavo Lopes
55dd7388ab Added unrar 3.6.3 2011-01-13 18:44:53 +00:00
Gustavo Lopes
a18c3b7fdc Added unrar 3.6.2 2011-01-13 18:44:41 +00:00
Gustavo Lopes
c3cf0e0dd4 Added unrar 3.6.1 2011-01-13 18:44:23 +00:00
94 changed files with 2955 additions and 1682 deletions

38
.gitignore vendored Normal file
View 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

View File

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

View File

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

View File

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

@@ -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 = &params;
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,

View File

@@ -52,11 +52,11 @@ int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
if (err == NULL) {
return SUCCESS;
}
if (_rar_using_exceptions(TSRMLS_C)) {
zend_throw_exception_ex(rarexception_ce_ptr, errcode TSRMLS_CC,
"unRAR internal error: %s%s", preamble, err);
}
}
else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s", preamble, err);
}
@@ -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);
}
/* }}} */

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -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);
}

View File

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

View File

@@ -3,6 +3,8 @@ RAR file stream stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=Europe/Lisbon
--FILE--
<?php
umask(0);

View File

@@ -3,6 +3,8 @@ url stat test
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=Europe/Lisbon
--FILE--
<?php
umask(0);

View File

@@ -3,6 +3,8 @@ RAR directory stream stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=Europe/Lisbon
--FILE--
<?php
umask(0);

View File

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

Binary file not shown.

View File

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

View File

@@ -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()));
}

View File

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

View File

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

View File

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

View File

@@ -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();

View File

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

View File

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

View File

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

View File

@@ -4,6 +4,7 @@
const uint TOP=1 << 24, BOT=1 << 15;
class RangeCoder
{
public:

View File

@@ -6,7 +6,6 @@ class PackingFileTable;
#define MAX_LZ_MATCH 0x101
#define CODEBUFSIZE 0x4000
#define MAXWINSIZE 0x400000
#define MAXWINMASK (MAXWINSIZE-1)

View File

@@ -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);
}

View File

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

View File

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

View File

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

View File

@@ -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));
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -28,7 +28,7 @@ class CmdExtract
char ArcName[NM];
wchar ArcNameW[NM];
wchar Password[MAXPASSWORD];
SecPassword Password;
bool PasswordAll;
bool PrevExtracted;
char DestFileName[NM];

View File

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

View File

@@ -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));
}

View File

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

View File

@@ -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();

View File

@@ -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();

View File

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

View File

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

View File

@@ -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);
}
}

View File

@@ -11,4 +11,5 @@ EXTVAR ErrorHandler ErrHandler;
#endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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();

View File

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

View File

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

View File

@@ -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]];
}
}

View File

@@ -6,6 +6,10 @@ class RecVolumes
private:
File *SrcFile[256];
Array<byte> Buf;
#ifdef RAR_SMP
ThreadPool RSThreadPool;
#endif
public:
RecVolumes();
~RecVolumes();

View File

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

View File

@@ -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);
};

View File

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

View File

@@ -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 */
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);
}

View File

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

View File

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

View File

@@ -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);
}
}

View File

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