42 Commits

Author SHA1 Message Date
cvs2svn 9c3a779c58 This commit was manufactured by cvs2svn to create tag 'RELEASE_0_3_1'.
git-svn-id: http://svn.php.net/repository/pecl/rar/tags/RELEASE_0_3_1@218974 c90b9560-bf6c-de11-be94-00142212c4b1
2006-08-28 12:24:50 +00:00
tony2001 57f518d804 add tests
remove file missing in unrar 3.6.8


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@218973 c90b9560-bf6c-de11-be94-00142212c4b1
2006-08-28 12:24:49 +00:00
tony2001 0ed5106066 prepare for 0.3.1-beta
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@218972 c90b9560-bf6c-de11-be94-00142212c4b1
2006-08-28 12:21:16 +00:00
tony2001 473e865b38 update unrar to version 3.6.8
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@218970 c90b9560-bf6c-de11-be94-00142212c4b1
2006-08-28 12:19:04 +00:00
tony2001 b08d2ebc66 update changelog
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@216052 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-10 09:29:10 +00:00
tony2001 198fda108f fix PHP4 build
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@216051 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-10 09:03:48 +00:00
tony2001 a745071a2a update unrar to version 3.6.6
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@216048 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-10 08:38:22 +00:00
tony2001 6e5f90d038 prepare to 0.3.0
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@214300 c90b9560-bf6c-de11-be94-00142212c4b1
2006-06-06 08:07:44 +00:00
tony2001 45ac56f43b initialize internal structs
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212385 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 21:39:21 +00:00
tony2001 c3913f5ee9 prepare to 0.3
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212351 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 13:29:00 +00:00
tony2001 289e63250b add two more flags
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212350 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 13:27:36 +00:00
tony2001 9b7245f2ba update unrar to 3.6.2
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212349 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 13:26:34 +00:00
tony2001 a4f66e2dca fix/add .cvsignore files
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205800 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 14:01:22 +00:00
tony2001 5ec39978bc nuke unused vars
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205799 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 13:59:14 +00:00
tony2001 34652b09b2 don't use commandline when built as library
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205798 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 13:58:51 +00:00
tony2001 905a30a02d reorganize sources
one more attempt to fix win32 build


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205795 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 13:05:54 +00:00
fmk 355edc6bf5 Add missing list.cpp to source list
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@201052 c90b9560-bf6c-de11-be94-00142212c4b1
2005-11-22 17:33:42 +00:00
fmk 1ba294df92 Remove unused code blocks that breaks win32 builds
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@201051 c90b9560-bf6c-de11-be94-00142212c4b1
2005-11-22 17:33:11 +00:00
tony2001 c85047e54c update changelog
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@198129 c90b9560-bf6c-de11-be94-00142212c4b1
2005-10-10 19:27:33 +00:00
tony2001 5cbc4174f7 update bundled unrar to version 3.5.4
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@198128 c90b9560-bf6c-de11-be94-00142212c4b1
2005-10-10 19:26:35 +00:00
fmk c3d082f6b3 Make sure the config file is loaded so HAVE_RAR is defined before it's checked.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@187510 c90b9560-bf6c-de11-be94-00142212c4b1
2005-06-02 19:15:32 +00:00
wez 884f7db326 macro already includes these, maybe this will fix the rar dll?
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@187494 c90b9560-bf6c-de11-be94-00142212c4b1
2005-06-02 12:45:57 +00:00
tony2001 d5b4779393 *sigh*
I don't understand Windo$e..


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@183663 c90b9560-bf6c-de11-be94-00142212c4b1
2005-04-05 14:05:16 +00:00
tony2001 a0021aa3c2 fix build with HEAD
# why it worked nice before, I wonder?


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@180383 c90b9560-bf6c-de11-be94-00142212c4b1
2005-02-21 20:19:42 +00:00
fmk 80af4abe5a fix debug build on win32
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@174922 c90b9560-bf6c-de11-be94-00142212c4b1
2004-12-16 20:23:12 +00:00
tony2001 890f103f50 release 0.2
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@173958 c90b9560-bf6c-de11-be94-00142212c4b1
2004-12-02 13:06:58 +00:00
edink 101fddb80a Older nmake does't like double backslashed in the path
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@173404 c90b9560-bf6c-de11-be94-00142212c4b1
2004-11-23 20:48:08 +00:00
tony2001 8a59dd703c add .cvsignore
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@172293 c90b9560-bf6c-de11-be94-00142212c4b1
2004-11-08 21:34:45 +00:00
tony2001 7a18c6a556 fix small shared module build issue
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@167972 c90b9560-bf6c-de11-be94-00142212c4b1
2004-09-04 12:53:45 +00:00
tony2001 c1a3d3d0a7 add OS constants
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@167966 c90b9560-bf6c-de11-be94-00142212c4b1
2004-09-04 12:21:50 +00:00
tony2001 95146b812d add safe_mode checks
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@163348 c90b9560-bf6c-de11-be94-00142212c4b1
2004-07-15 06:43:07 +00:00
tony2001 9447de1436 dunno what's this, but it only produces warnings, so remove it
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161401 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-15 11:29:29 +00:00
tony2001 c594c7a9e1 remove extern C block to allow Win32 build finally (many thanks to Edin)
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161400 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-15 11:26:19 +00:00
tony2001 b474abaecf fix TS issues
yet another try to fix win32 build =)


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161392 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-15 07:25:07 +00:00
tony2001 652574e80f add config for Win32
hopefully this will allow Win32 build


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161076 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 08:36:14 +00:00
tony2001 42b0d2c57d fix example script
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161073 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 08:01:01 +00:00
tony2001 7d6d5a605b re-add as binary file
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161071 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 07:46:50 +00:00
tony2001 78f6dc0bda re-add it as binary
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161070 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 07:46:24 +00:00
tony2001 950825aa18 add open_basedir checks
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161069 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 07:43:48 +00:00
tony2001 cd443a6e7d add tests
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161067 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 07:41:04 +00:00
tony2001 604059cedf Initial import
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161063 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 06:29:43 +00:00
cvs2svn 1f63a42ba8 Standard project directories initialized by cvs2svn.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@161062 c90b9560-bf6c-de11-be94-00142212c4b1
2004-06-11 06:29:43 +00:00
179 changed files with 15243 additions and 22356 deletions
+1
View File
@@ -0,0 +1 @@
Antony Dovgal
View File
+31
View File
@@ -0,0 +1,31 @@
dnl $Id$
dnl config.m4 for extension rar
PHP_ARG_ENABLE(rar, whether to enable rar support,
[ --enable-rar Enable rar support])
unrar_sources="unrar/rar.cpp unrar/strlist.cpp unrar/strfn.cpp \
unrar/pathfn.cpp unrar/int64.cpp unrar/savepos.cpp \
unrar/global.cpp unrar/file.cpp unrar/filefn.cpp \
unrar/filcreat.cpp unrar/archive.cpp unrar/arcread.cpp \
unrar/unicode.cpp unrar/system.cpp unrar/isnt.cpp \
unrar/crypt.cpp unrar/crc.cpp unrar/rawread.cpp \
unrar/encname.cpp unrar/resource.cpp unrar/match.cpp \
unrar/timefn.cpp unrar/rdwrfn.cpp unrar/consio.cpp \
unrar/options.cpp unrar/ulinks.cpp unrar/errhnd.cpp \
unrar/rarvm.cpp unrar/rijndael.cpp unrar/getbits.cpp \
unrar/sha1.cpp unrar/extinfo.cpp unrar/extract.cpp \
unrar/volume.cpp unrar/find.cpp \
unrar/unpack.cpp unrar/cmddata.cpp unrar/dll.cpp \
unrar/filestr.cpp unrar/recvol.cpp unrar/rs.cpp \
unrar/scantree.cpp unrar/log.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_ADD_LIBRARY_WITH_PATH(stdc++, "", RAR_SHARED_LIBADD)
PHP_NEW_EXTENSION(rar, rar.cpp $unrar_sources, $ext_shared,,-DRARDLL -DGUI -DSILENT -I@ext_srcdir@/unrar)
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
fi
+28
View File
@@ -0,0 +1,28 @@
// $Id$
// vim:ft=javascript
ARG_ENABLE("rar", "Rar support", "no");
if (PHP_RAR != "no") {
EXTENSION("rar", "rar.cpp", PHP_RAR_SHARED, "-DRARDLL -DGUI -DSILENT");
ADD_SOURCES(configure_module_dirname + "/unrar", "rar.cpp \
strlist.cpp strfn.cpp pathfn.cpp int64.cpp \
savepos.cpp global.cpp file.cpp filefn.cpp \
filcreat.cpp archive.cpp arcread.cpp unicode.cpp \
system.cpp isnt.cpp crypt.cpp crc.cpp \
rawread.cpp encname.cpp resource.cpp match.cpp \
timefn.cpp rdwrfn.cpp consio.cpp options.cpp \
ulinks.cpp errhnd.cpp rarvm.cpp rijndael.cpp \
getbits.cpp sha1.cpp extinfo.cpp extract.cpp \
volume.cpp find.cpp unpack.cpp cmddata.cpp \
dll.cpp filestr.cpp recvol.cpp rs.cpp \
scantree.cpp list.cpp", "rar");
if (!PHP_RAR_SHARED) {
ADD_DEF_FILE(configure_module_dirname + "\\unrar\\dll.def");
}
AC_DEFINE("HAVE_RAR", 1, "Rar support");
}
+22
View File
@@ -0,0 +1,22 @@
<?
$archive_name = '/full/path/to/file.rar'
$entry_name = 'path/to/archive/entry.txt'; //notice: no slash at the beginning
$dir_to_extract_to = '/path/to/extract/dir';
$new_entry_name = 'some.txt';
$rar = rar_open($archive_name) OR die('failed to open ' . $archive_name);
$entry = rar_entry_get($rar, $entry_name) OR die('failed to find ' . $entry_name . ' in ' . $archive_name);
// this will create all necessary subdirs under $dir_to_extract_to
$entry->extract($dir_to_extract_to);
/* OR */
// this will create only one new file $new_entry_name in $dir_to_extract_to
$entry->extract('', $dir_to_extract_to.'/'.$new_entry_name);
// this line is really not necessary
rar_close($rar);
?>
+201
View File
@@ -0,0 +1,201 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<package>
<name>rar</name>
<summary>rar extension</summary>
<description>
Rar is a powerful and effective archiver, which was
created by Eugene Roshal and became rather popular quite fast.
This extension gives you possibility to read Rar archives.
</description>
<license>PHP License</license>
<maintainers>
<maintainer>
<user>tony2001</user>
<name>Antony Dovgal</name>
<email>tony2001@phpclub.net</email>
</maintainer>
</maintainers>
<release>
<version>0.3.1</version>
<date>2006-08-28</date>
<state>beta</state>
<notes>
- Updated bundled unrar to version 3.6.8.
- Fixed PHP4 compatibility.
</notes>
</release>
<changelog>
<release>
<version>0.3.0</version>
<date>2006-06-06</date>
<state>beta</state>
<notes>
- Updated bundled unrar to version 3.6.2 (fixes compile errors with GCC4).
- Several minor fixes.
</notes>
</release>
<release>
<version>0.2</version>
<date>2004-12-02</date>
<state>beta</state>
<notes>
1) Added open_basedir and safe_mode checks.
2) Fixed Win32 build issues (thanks to Edin).
Currently only 5.x builds are available.
3) Added OS constants.
4) Fixed 0 bugs. There are no bugs, wee =)
</notes>
</release>
<release>
<version>0.1</version>
<date>2004-06-11</date>
<state>alpha</state>
<notes>
1) Initial release
</notes>
</release>
</changelog>
<filelist>
<dir role="src" name="/">
<file role="doc">CREDITS</file>
<file role="doc">example.php</file>
<file role="src">config.m4</file>
<file role="src">php_rar.h</file>
<file role="src">rar.cpp</file>
<file role="test">tests/001.phpt</file>
<file role="test">tests/002.phpt</file>
<file role="test">tests/003.phpt</file>
<file role="test">tests/004.phpt</file>
<file role="test">tests/latest_winrar.rar</file>
<file role="test">tests/linux_rar.rar</file>
<dir role="src" name="/unrar/">
<file role="doc">LICENSE.txt</file>
<file role="doc">README.txt</file>
<file role="src">arccmt.cpp</file>
<file role="src">archive.cpp</file>
<file role="src">archive.hpp</file>
<file role="src">arcread.cpp</file>
<file role="src">array.hpp</file>
<file role="src">beosea.cpp</file>
<file role="src">cmddata.cpp</file>
<file role="src">cmddata.hpp</file>
<file role="src">coder.cpp</file>
<file role="src">coder.hpp</file>
<file role="src">compress.hpp</file>
<file role="src">consio.cpp</file>
<file role="src">consio.hpp</file>
<file role="src">crc.cpp</file>
<file role="src">crc.hpp</file>
<file role="src">crypt.cpp</file>
<file role="src">crypt.hpp</file>
<file role="src">dll.cpp</file>
<file role="src">dll.def</file>
<file role="src">dll.hpp</file>
<file role="src">encname.cpp</file>
<file role="src">encname.hpp</file>
<file role="src">errhnd.cpp</file>
<file role="src">errhnd.hpp</file>
<file role="src">extinfo.cpp</file>
<file role="src">extinfo.hpp</file>
<file role="src">extract.cpp</file>
<file role="src">extract.hpp</file>
<file role="src">filcreat.cpp</file>
<file role="src">filcreat.hpp</file>
<file role="src">file.cpp</file>
<file role="src">filefn.cpp</file>
<file role="src">filefn.hpp</file>
<file role="src">file.hpp</file>
<file role="src">filestr.cpp</file>
<file role="src">filestr.hpp</file>
<file role="src">find.cpp</file>
<file role="src">find.hpp</file>
<file role="src">getbits.cpp</file>
<file role="src">getbits.hpp</file>
<file role="src">global.cpp</file>
<file role="src">global.hpp</file>
<file role="src">headers.hpp</file>
<file role="src">int64.cpp</file>
<file role="src">int64.hpp</file>
<file role="src">isnt.cpp</file>
<file role="src">isnt.hpp</file>
<file role="src">list.cpp</file>
<file role="src">list.hpp</file>
<file role="src">loclang.hpp</file>
<file role="src">log.cpp</file>
<file role="src">log.hpp</file>
<file role="src">match.cpp</file>
<file role="src">match.hpp</file>
<file role="src">model.cpp</file>
<file role="src">model.hpp</file>
<file role="src">msc.dep</file>
<file role="src">options.cpp</file>
<file role="src">options.hpp</file>
<file role="src">os2ea.cpp</file>
<file role="src">os.hpp</file>
<file role="src">pathfn.cpp</file>
<file role="src">pathfn.hpp</file>
<file role="src">rar.cpp</file>
<file role="src">rardefs.hpp</file>
<file role="src">rarfn.hpp</file>
<file role="src">rar.hpp</file>
<file role="src">rarlang.hpp</file>
<file role="src">raros.hpp</file>
<file role="src">rartypes.hpp</file>
<file role="src">rarvm.cpp</file>
<file role="src">rarvm.hpp</file>
<file role="src">rarvmtbl.cpp</file>
<file role="src">rawread.cpp</file>
<file role="src">rawread.hpp</file>
<file role="src">rdwrfn.cpp</file>
<file role="src">rdwrfn.hpp</file>
<file role="src">recvol.cpp</file>
<file role="src">recvol.hpp</file>
<file role="src">resource.cpp</file>
<file role="src">resource.hpp</file>
<file role="src">rijndael.cpp</file>
<file role="src">rijndael.hpp</file>
<file role="src">rs.cpp</file>
<file role="src">rs.hpp</file>
<file role="src">savepos.cpp</file>
<file role="src">savepos.hpp</file>
<file role="src">scantree.cpp</file>
<file role="src">scantree.hpp</file>
<file role="src">sha1.cpp</file>
<file role="src">sha1.hpp</file>
<file role="src">smallfn.cpp</file>
<file role="src">smallfn.hpp</file>
<file role="src">strfn.cpp</file>
<file role="src">strfn.hpp</file>
<file role="src">strlist.cpp</file>
<file role="src">strlist.hpp</file>
<file role="src">suballoc.cpp</file>
<file role="src">suballoc.hpp</file>
<file role="src">system.cpp</file>
<file role="src">system.hpp</file>
<file role="src">timefn.cpp</file>
<file role="src">timefn.hpp</file>
<file role="src">ulinks.cpp</file>
<file role="src">ulinks.hpp</file>
<file role="src">unicode.cpp</file>
<file role="src">unicode.hpp</file>
<file role="src">unpack15.cpp</file>
<file role="src">unpack20.cpp</file>
<file role="src">unpack.cpp</file>
<file role="src">unpack.hpp</file>
<file role="src">uowners.cpp</file>
<file role="src">version.hpp</file>
<file role="src">volume.cpp</file>
<file role="src">volume.hpp</file>
<file role="src">win32acl.cpp</file>
<file role="src">win32stm.cpp</file>
</dir>
</dir>
</filelist>
</package>
<!--
vim:et:ts=1:sw=1
-->
+76
View File
@@ -0,0 +1,76 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| It's license states, that you MUST NOT use it's code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony2001@phpclub.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef PHP_RAR_H
#define PHP_RAR_H
extern zend_module_entry rar_module_entry;
#define phpext_rar_ptr &rar_module_entry
#ifdef PHP_WIN32
#define PHP_RAR_API __declspec(dllexport)
#else
#define PHP_RAR_API
#endif
#ifdef ZTS
#include "TSRM.h"
#endif
PHP_MINIT_FUNCTION(rar);
PHP_MSHUTDOWN_FUNCTION(rar);
PHP_RINIT_FUNCTION(rar);
PHP_RSHUTDOWN_FUNCTION(rar);
PHP_MINFO_FUNCTION(rar);
PHP_FUNCTION(rar_open);
PHP_FUNCTION(rar_list);
PHP_FUNCTION(rar_entry_get);
PHP_FUNCTION(rar_close);
typedef struct rar {
int id;
int entry_count;
struct RARHeaderData **entries;
struct RAROpenArchiveData *list_handle;
struct RAROpenArchiveData *extract_handle;
void *list_data;
char *password;
} rar_file_t;
#endif /* PHP_RAR_H */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
+725
View File
@@ -0,0 +1,725 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| It's license states, that you MUST NOT use it's code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony2001@phpclub.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef PHP_WIN32
# include <math.h>
#endif
extern "C" {
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
}
#if HAVE_RAR
#include "php_rar.h"
#include "unrar/rar.hpp"
/* PHP4 compat {{{ */
#ifndef PHP_METHOD
#define ZEND_MN(name) zim_##name
#define PHP_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name))
#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info},
#define PHP_ME(classname, name, arg_info, flags) ZEND_FENTRY(name, ZEND_MN(classname##_##name), arg_info, flags)
#endif
/* }}} */
static int le_rar_file;
#define le_rar_file_name "Rar"
static zend_class_entry *rar_class_entry_ptr;
/* {{{ internal functions protos */
static void _rar_file_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
static int _rar_list_files(rar_file_t * TSRMLS_DC);
static int _rar_handle_error(int TSRMLS_DC);
static void _rar_dos_date_to_text(int, char *);
static void _rar_entry_to_zval(struct RARHeaderData *, zval * TSRMLS_DC);
static zval **_rar_entry_get_property(zval *, char *, int TSRMLS_DC);
/* }}} */
/* <internal> */
static void _rar_file_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
{
rar_file_t *rar = (rar_file_t *)rsrc->ptr;
int i = 0;
if (rar->list_data) {
RARCloseArchive(rar->list_data);
}
if (rar->password) {
efree(rar->password);
}
if (rar->entries && rar->entry_count) {
for(i = 0; i < rar->entry_count; i++) {
efree(rar->entries[i]);
}
efree(rar->entries);
rar->entry_count = 0;
}
efree(rar->list_handle->ArcName);
efree(rar->list_handle);
efree(rar->extract_handle->ArcName);
efree(rar->extract_handle);
efree(rar);
}
/* }}} */
static int _rar_get_file_resource(zval **zval_file, rar_file_t **rar_file TSRMLS_DC) /* {{{ */
{
*rar_file = (rar_file_t *) zend_fetch_resource(zval_file TSRMLS_CC, -1, le_rar_file_name, NULL, 1, le_rar_file);
if (*rar_file) {
return 1;
}
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find Rar file resource");
return 0;
}
/* }}} */
static int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
{
int result = 0;
while (result == 0) {
struct RARHeaderData entry;
result = RARReadHeader(rar->list_data, &entry);
RARProcessFile(rar->list_data, RAR_OM_LIST, NULL, NULL);
if (result == 0) {
rar->entries = (struct RARHeaderData **)erealloc(rar->entries, sizeof(struct RARHeaderData *) * (rar->entry_count + 1));
if (!rar->entries) {
return FAILURE;
}
rar->entries[rar->entry_count] = (struct RARHeaderData *)emalloc(sizeof(struct RARHeaderData));
memcpy(rar->entries[rar->entry_count], &entry, sizeof(struct RARHeaderData));
rar->entry_count++;
}
}
return result;
}
/* }}} */
static int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
{
switch (errcode) {
case 0:
/* no error */
return SUCCESS;
break;
case ERAR_END_ARCHIVE:
/* no error */
return SUCCESS;
break;
case ERAR_NO_MEMORY:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_NO_MEMORY: not enough memory");
break;
case ERAR_BAD_DATA:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_DATA");
break;
case ERAR_BAD_ARCHIVE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_ARCHIVE");
break;
case ERAR_UNKNOWN_FORMAT:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN_FORMAT");
break;
case ERAR_EOPEN:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EOPEN");
break;
case ERAR_ECREATE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECREATE");
break;
case ERAR_ECLOSE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECLOSE");
break;
case ERAR_EREAD:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EREAD");
break;
case ERAR_EWRITE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EWRITE");
break;
case ERAR_SMALL_BUF:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_SMALL_BUF");
break;
case ERAR_UNKNOWN:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN: unknown RAR error");
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown RAR error");
break;
}
return FAILURE;
}
/* }}} */
static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
{
int second, minute, hour, day, month, year;
/* following lines were taken from timefn.cpp */
second = (dos_time & 0x1f)*2;
minute = (dos_time>>5) & 0x3f;
hour = (dos_time>>11) & 0x1f;
day = (dos_time>>16) & 0x1f;
month = (dos_time>>21) & 0x0f;
year = (dos_time>>25)+1980;
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
}
/* }}} */
static void _rar_entry_to_zval(struct RARHeaderData *entry, zval *object TSRMLS_DC) /* {{{ */
{
char tmp_s [MAX_LENGTH_OF_LONG + 1];
char time[50];
add_property_string(object, "name", entry->FileName, 1);
add_property_long(object, "unpacked_size", entry->UnpSize);
add_property_long(object, "packed_size", entry->PackSize);
add_property_long(object, "host_os", entry->HostOS);
_rar_dos_date_to_text(entry->FileTime, time);
add_property_string(object, "file_time", time, 1);
sprintf(tmp_s, "%lx", entry->FileCRC);
add_property_string(object, "crc", tmp_s, 1);
add_property_long(object, "attr", entry->FileAttr);
add_property_long(object, "version", entry->UnpVer);
add_property_long(object, "method", entry->Method);
}
/* }}} */
static zval **_rar_entry_get_property(zval *id, char *name, int namelen TSRMLS_DC) /* {{{ */
{
zval **tmp;
if (zend_hash_find(Z_OBJPROP_P(id), name, namelen, (void **)&tmp) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find property %s", name);
return NULL;
}
return tmp;
}
/* }}} */
/* </internal> */
#ifdef COMPILE_DL_RAR
BEGIN_EXTERN_C()
ZEND_GET_MODULE(rar)
END_EXTERN_C()
#endif
/* module functions */
/* {{{ proto rar_open(string filename [, string password])
Open Rar archive and return resource */
PHP_FUNCTION(rar_open)
{
zval **filename, **password;
rar_file_t *rar = NULL;
int ac = ZEND_NUM_ARGS(), result = 0;
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &filename, &password) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(filename);
if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
RETURN_FALSE;
}
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
RETURN_FALSE;
}
rar = (rar_file_t *) emalloc(sizeof(rar_file_t));
rar->list_handle = (RAROpenArchiveData *) ecalloc(1, sizeof(RAROpenArchiveData));
rar->list_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
rar->list_handle->OpenMode = RAR_OM_LIST;
rar->extract_handle = (RAROpenArchiveData *) ecalloc(1, sizeof(RAROpenArchiveData));
rar->extract_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
rar->extract_handle->OpenMode = RAR_OM_EXTRACT;
rar->password = NULL;
rar->entries = NULL;
rar->entry_count = 0;
rar->list_data = RAROpenArchive(rar->list_handle);
if (rar->list_data != NULL && rar->list_handle->OpenResult == 0) {
if (ac == 2) {
rar->password = estrndup(Z_STRVAL_PP(password), Z_STRLEN_PP(password));
}
rar->id = zend_list_insert(rar,le_rar_file);
RETURN_RESOURCE(rar->id);
}
else {
efree(rar->list_handle->ArcName);
efree(rar->list_handle);
efree(rar->extract_handle->ArcName);
efree(rar->extract_handle);
efree(rar);
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_list(resource rarfile)
Return entries from the rar archive */
PHP_FUNCTION(rar_list)
{
zval **file;
rar_file_t *rar = NULL;
int i = 0;
int ac = ZEND_NUM_ARGS(), result = 0;
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
array_init(return_value);
for (i = 0; i < rar->entry_count; i++) {
zval *tmp;
MAKE_STD_ZVAL(tmp);
object_init_ex(tmp, rar_class_entry_ptr);
add_property_resource(tmp, "rarfile", rar->id);
_rar_entry_to_zval(rar->entries[i], tmp TSRMLS_CC);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp, sizeof(zval*), NULL);
}
if (!return_value) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to list files from RAR archive");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_entry_get(resource rarfile, string filename)
Return entry from the rar archive */
PHP_FUNCTION(rar_entry_get)
{
zval **file, **filename;
rar_file_t *rar = NULL;
int result = 0, i = 0;
int ac = ZEND_NUM_ARGS();
if (ac < 2 || ac > 2 || zend_get_parameters_ex(ac, &file, &filename) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
for(i = 0; i < rar->entry_count; i++){
if (strcmp(rar->entries[i]->FileName, Z_STRVAL_PP(filename)) == 0) {
object_init_ex(return_value, rar_class_entry_ptr);
add_property_resource(return_value, "rarfile", rar->id);
_rar_entry_to_zval(rar->entries[i], return_value TSRMLS_CC);
break;
}
}
if (!return_value) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find such file in RAR archive");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_close(resource rarfile)
Close Rar archive and free all resources */
PHP_FUNCTION(rar_close)
{
zval **file;
rar_file_t *rar = NULL;
int file_counter = 0;
int ac = ZEND_NUM_ARGS();
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
RETURN_FALSE;
}
zend_list_delete(rar->id);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto RarEntry::extract(string path [, string filename ]);
Extract file from the archive */
PHP_METHOD(rarentry, extract)
{
zval **path, **filename, **tmp, **tmp_name;
rar_file_t *rar = NULL;
char *path_str = NULL, *extract_to_file = NULL;
int ac = ZEND_NUM_ARGS(), resource_type = 0, result = 0, process_result = 0;
zval *entry_obj = getThis();
struct RARHeaderData entry;
void *extract_data;
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &path, &filename) == FAILURE ) {
WRONG_PARAM_COUNT;
}
if ((tmp = _rar_entry_get_property(entry_obj, "rarfile", sizeof("rarfile") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
rar = (rar_file_t *) zend_list_find(Z_LVAL_PP(tmp), &resource_type);
convert_to_string_ex(path);
path_str = Z_STRVAL_PP(path);
if (Z_STRLEN_PP(path) && PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(path), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
RETURN_FALSE;
}
if (Z_STRLEN_PP(path) && php_check_open_basedir(Z_STRVAL_PP(path) TSRMLS_CC)) {
RETURN_FALSE;
}
if (ac == 2) {
convert_to_string_ex(filename);
extract_to_file = Z_STRVAL_PP(filename);
if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
RETURN_FALSE;
}
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
RETURN_FALSE;
}
}
if ((tmp_name = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
if (!rar || resource_type != le_rar_file) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Rar resource identifier not found");
RETURN_FALSE;
}
extract_data = RAROpenArchive(rar->extract_handle);
if (rar->extract_handle->OpenResult == 0 && extract_data != NULL) {
if (rar->password) {
RARSetPassword(extract_data, rar->password);
}
}
else {
_rar_handle_error(rar->extract_handle->OpenResult TSRMLS_CC);
RETURN_FALSE;
}
while ((result = RARReadHeader(extract_data, &entry)) == 0) {
if (strncmp(entry.FileName,Z_STRVAL_PP(tmp_name), sizeof(entry.FileName)) == 0) {
process_result = RARProcessFile(extract_data, RAR_EXTRACT, path_str, extract_to_file);
RETURN_TRUE;
}
else {
process_result = RARProcessFile(extract_data, RAR_SKIP, NULL, NULL);
}
if (_rar_handle_error(process_result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't find file %s in archive %s", Z_STRVAL_PP(tmp_name), rar->extract_handle->ArcName);
RETURN_FALSE;
}
/* }}} */
/* {{{ proto RarEntry::getName();
Return entry name */
PHP_METHOD(rarentry, getName)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getUnpackedSize();
Return unpacked size of the entry */
PHP_METHOD(rarentry, getUnpackedSize)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "unpacked_size", sizeof("unpacked_size") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getPackedSize();
Return packed size of the entry */
PHP_METHOD(rarentry, getPackedSize)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "packed_size", sizeof("packed_size") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getHostOs();
Return host OS of the entry */
PHP_METHOD(rarentry, getHostOs)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "host_os", sizeof("host_os") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getFileTime();
Return modification time of the entry */
PHP_METHOD(rarentry, getFileTime)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "file_time", sizeof("file_time") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getCrc();
Return CRC of the entry */
PHP_METHOD(rarentry, getCrc)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "crc", sizeof("crc") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getAttr();
Return attributes of the entry */
PHP_METHOD(rarentry, getAttr)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "attr", sizeof("attr") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getVersion();
Return version of the archiver, used to create this entry */
PHP_METHOD(rarentry, getVersion)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "version", sizeof("version") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getMethod();
Return packing method */
PHP_METHOD(rarentry, getMethod)
{
zval **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "method", sizeof("method") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ rar_functions[]
*
*/
function_entry rar_functions[] = {
PHP_FE(rar_open, NULL)
PHP_FE(rar_list, NULL)
PHP_FE(rar_entry_get, NULL)
PHP_FE(rar_close, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_rar_class_functions[] = {
PHP_ME(rarentry, extract, NULL, 0)
PHP_ME(rarentry, getName, NULL, 0)
PHP_ME(rarentry, getUnpackedSize, NULL, 0)
PHP_ME(rarentry, getPackedSize, NULL, 0)
PHP_ME(rarentry, getHostOs, NULL, 0)
PHP_ME(rarentry, getFileTime, NULL, 0)
PHP_ME(rarentry, getCrc, NULL, 0)
PHP_ME(rarentry, getAttr, NULL, 0)
PHP_ME(rarentry, getVersion, NULL, 0)
PHP_ME(rarentry, getMethod, NULL, 0)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(rar)
{
zend_class_entry rar_class_entry;
INIT_CLASS_ENTRY(rar_class_entry, "RarEntry", php_rar_class_functions);
rar_class_entry_ptr = zend_register_internal_class(&rar_class_entry TSRMLS_CC);
le_rar_file = zend_register_list_destructors_ex(_rar_file_list_dtor, NULL, le_rar_file_name, module_number);
REGISTER_LONG_CONSTANT("RAR_HOST_MSDOS", HOST_MSDOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_OS2", HOST_OS2, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_WIN32", HOST_WIN32, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_UNIX", HOST_UNIX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_MACOS", HOST_MACOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_BEOS", HOST_BEOS, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(rar)
{
php_info_print_table_start();
php_info_print_table_header(2, "Rar support", "enabled");
php_info_print_table_row(2, "Revision", "$Revision$");
php_info_print_table_end();
}
/* }}} */
/* {{{ rar_module_entry
*/
zend_module_entry rar_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"rar",
rar_functions,
PHP_MINIT(rar),
NULL,
NULL,
NULL,
PHP_MINFO(rar),
#if ZEND_MODULE_API_NO >= 20010901
"0.1", /* Replace with version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#endif /* HAVE_RAR */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
+18
View File
@@ -0,0 +1,18 @@
--TEST--
rar_open() function
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
var_dump($rar_file1);
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
var_dump($rar_file2);
?>
--EXPECTF--
resource(%d) of type (Rar)
resource(%d) of type (Rar)
+114
View File
@@ -0,0 +1,114 @@
--TEST--
rar_list() function
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
$list1 = rar_list($rar_file1);
var_dump($list1);
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$list2 = rar_list($rar_file2);
var_dump($list2);
?>
--EXPECTF--
array(2) {
[0]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
string(9) "plain.txt"
["unpacked_size"]=>
int(15)
["packed_size"]=>
int(25)
["host_os"]=>
int(3)
["file_time"]=>
string(19) "2004-06-11 11:01:24"
["crc"]=>
string(8) "7728b6fe"
["attr"]=>
int(33188)
["version"]=>
int(29)
["method"]=>
int(51)
}
[1]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
string(30) "test file with whitespaces.txt"
["unpacked_size"]=>
int(14)
["packed_size"]=>
int(20)
["host_os"]=>
int(3)
["file_time"]=>
string(19) "2004-06-11 11:01:32"
["crc"]=>
string(8) "21890dd9"
["attr"]=>
int(33188)
["version"]=>
int(29)
["method"]=>
int(51)
}
}
array(2) {
[0]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
string(5) "1.txt"
["unpacked_size"]=>
int(5)
["packed_size"]=>
int(17)
["host_os"]=>
int(2)
["file_time"]=>
string(19) "2004-06-11 10:07:18"
["crc"]=>
string(8) "a0de71c0"
["attr"]=>
int(32)
["version"]=>
int(29)
["method"]=>
int(53)
}
[1]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
string(5) "2.txt"
["unpacked_size"]=>
int(5)
["packed_size"]=>
int(16)
["host_os"]=>
int(2)
["file_time"]=>
string(19) "2004-06-11 10:07:26"
["crc"]=>
string(8) "45a918de"
["attr"]=>
int(32)
["version"]=>
int(29)
["method"]=>
int(53)
}
}
+64
View File
@@ -0,0 +1,64 @@
--TEST--
rar_entry_get() function
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
$entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
var_dump($entry1);
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entry2 = rar_entry_get($rar_file2, '2.txt');
var_dump($entry2);
?>
--EXPECTF--
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
string(30) "test file with whitespaces.txt"
["unpacked_size"]=>
int(14)
["packed_size"]=>
int(20)
["host_os"]=>
int(3)
["file_time"]=>
string(19) "2004-06-11 11:01:32"
["crc"]=>
string(8) "21890dd9"
["attr"]=>
int(33188)
["version"]=>
int(29)
["method"]=>
int(51)
}
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
string(5) "2.txt"
["unpacked_size"]=>
int(5)
["packed_size"]=>
int(16)
["host_os"]=>
int(2)
["file_time"]=>
string(19) "2004-06-11 10:07:26"
["crc"]=>
string(8) "45a918de"
["attr"]=>
int(32)
["version"]=>
int(29)
["method"]=>
int(53)
}
+40
View File
@@ -0,0 +1,40 @@
--TEST--
RarEntry::extract() method
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
$entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
$entry1->extract(dirname(__FILE__));
$contents11 = file_get_contents(dirname(__FILE__).'/test file with whitespaces.txt');
echo $contents11."\n";
$entry1->extract(false,dirname(__FILE__).'/1.txt');
$contents12 = file_get_contents(dirname(__FILE__).'/1.txt');
echo $contents12."\n";
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entry2 = rar_entry_get($rar_file2, '2.txt');
$entry2->extract(dirname(__FILE__));
$contents21 = file_get_contents(dirname(__FILE__).'/2.txt');
echo $contents21."\n";
$entry2->extract(false,dirname(__FILE__).'/some.txt');
$contents22 = file_get_contents(dirname(__FILE__).'/some.txt');
echo $contents22."\n";
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
@unlink(dirname(__FILE__).'/1.txt');
@unlink(dirname(__FILE__).'/2.txt');
@unlink(dirname(__FILE__).'/some.txt');
?>
--EXPECTF--
blah-blah-blah
blah-blah-blah
22222
22222
Binary file not shown.
Binary file not shown.
+41
View File
@@ -0,0 +1,41 @@
****** ***** ****** unRAR - free utility for RAR archives
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
****** ******* ****** License for use and distribution of
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** ** ** ** ** ** FREE portable version
~~~~~~~~~~~~~~~~~~~~~
The source code of unRAR utility is freeware. This means:
1. All copyrights to RAR and the utility unRAR are exclusively
owned by the author - Eugene 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.
3. The unRAR utility may be freely distributed. No person or company
may charge a fee for the distribution of unRAR without written
permission from the copyright holder.
4. THE RAR ARCHIVER AND THE UNRAR UTILITY ARE DISTRIBUTED "AS IS".
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
OR MISUSING THIS SOFTWARE.
5. Installing and using the unRAR utility signifies acceptance of
these terms and conditions of the license.
6. If you don't agree with terms of the license you must remove
unRAR files from your storage devices and cease to use the
utility.
Thank you for your interest in RAR and unRAR.
Eugene Roshal
+64
View File
@@ -0,0 +1,64 @@
Portable UnRAR version
1. General
This package includes freeware Unrar C++ source and a few makefiles
(makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source
is subset of RAR and generated from RAR source automatically,
by a small program removing blocks like '#ifndef UNRAR ... #endif'.
Such method is not perfect and you may find some RAR related
stuff unnecessary in Unrar, especially in header files.
If you wish to port Unrar to a new platform, you may need to edit
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
in rartypes.hpp.
It is important to provide 1 byte alignment for structures
in model.hpp. Now it contains '#pragma pack(1)' directive,
but your compiler may require something else. Though Unrar
should work with other model.hpp alignments, its memory
requirements may increase significantly. Alignment in other
modules is not important.
If you use Borland C++ makefile (makefile.bcc), you need to define
BASEPATHCC environment (or makefile) variable containing
the path to Borland C++ installation.
Makefile.unix contains both Linux and IRIX compiler option sets.
Linux is selected by default. If you need to compile Unrar for IRIX,
just uncomment corresponding lines.
2. Unrar binaries
If you compiled Unrar for OS, which is not present in "Downloads"
and "RAR extras" on www.rarlab.com, we will appreciate if you send
us the compiled executable to place it to our site.
3. Acknowledgements
This source includes parts of code written by the following authors:
Dmitry Shkarin PPMII text compression
Dmitry Subbotin Carryless rangecoder
Szymon Stefanek AES encryption
Brian Gladman AES encryption
Steve Reid SHA-1 hash function
Marcus Herbert makefile.unix file
Tomasz Klim fixes for libunrar.so
4. Legal stuff
Unrar source 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 source 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.
More detailed license text is available in license.txt.
-279
View File
@@ -1,279 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{95CC809B-03FC-4EDB-BB20-FD07A698C05F}</ProjectGuid>
<RootNamespace>UnRAR</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>build\unrar32\$(Configuration)\</OutDir>
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>build\unrar64\$(Configuration)\</OutDir>
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>build\unrar32\$(Configuration)\</OutDir>
<IntDir>build\unrar32\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>build\unrar64\$(Configuration)\</OutDir>
<IntDir>build\unrar64\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>Default</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Precise</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MinSpace</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>UNRAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>false</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="archive.cpp" />
<ClCompile Include="arcread.cpp" />
<ClCompile Include="blake2s.cpp" />
<ClCompile Include="cmddata.cpp" />
<ClCompile Include="consio.cpp" />
<ClCompile Include="crc.cpp" />
<ClCompile Include="crypt.cpp" />
<ClCompile Include="encname.cpp" />
<ClCompile Include="errhnd.cpp" />
<ClCompile Include="extinfo.cpp" />
<ClCompile Include="extract.cpp" />
<ClCompile Include="filcreat.cpp" />
<ClCompile Include="file.cpp" />
<ClCompile Include="filefn.cpp" />
<ClCompile Include="filestr.cpp" />
<ClCompile Include="find.cpp" />
<ClCompile Include="getbits.cpp" />
<ClCompile Include="global.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="hash.cpp" />
<ClCompile Include="headers.cpp" />
<ClCompile Include="isnt.cpp" />
<ClCompile Include="list.cpp" />
<ClCompile Include="match.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="pathfn.cpp" />
<ClCompile Include="qopen.cpp" />
<ClCompile Include="rar.cpp" />
<ClCompile Include="rarpch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="rarvm.cpp" />
<ClCompile Include="rawread.cpp" />
<ClCompile Include="rdwrfn.cpp" />
<ClCompile Include="recvol.cpp" />
<ClCompile Include="resource.cpp" />
<ClCompile Include="rijndael.cpp" />
<ClCompile Include="rs.cpp" />
<ClCompile Include="rs16.cpp" />
<ClCompile Include="scantree.cpp" />
<ClCompile Include="secpassword.cpp" />
<ClCompile Include="sha1.cpp" />
<ClCompile Include="sha256.cpp" />
<ClCompile Include="smallfn.cpp" />
<ClCompile Include="strfn.cpp" />
<ClCompile Include="strlist.cpp" />
<ClCompile Include="system.cpp" />
<ClCompile Include="threadpool.cpp" />
<ClCompile Include="timefn.cpp" />
<ClCompile Include="ui.cpp" />
<ClCompile Include="unicode.cpp" />
<ClCompile Include="unpack.cpp" />
<ClCompile Include="volume.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
-420
View File
@@ -1,420 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="release_nocrypt|Win32">
<Configuration>release_nocrypt</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="release_nocrypt|x64">
<Configuration>release_nocrypt</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>UnRAR</ProjectName>
<ProjectGuid>{E815C46C-36C4-499F-BBC2-E772C6B17971}</ProjectGuid>
<RootNamespace>UnRAR</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.24720.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
<LinkIncremental>true</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
<OutDir>build\unrardll32\$(Configuration)\</OutDir>
<IntDir>build\unrardll32\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
<OutDir>build\unrardll64\$(Configuration)\</OutDir>
<IntDir>build\unrardll64\$(Configuration)\obj\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Precise</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>false</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Precise</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>Cdecl</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalOptions>/SAFESEH %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>RARDLL;UNRAR;SILENT;RAR_NOCRYPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>false</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<DisableSpecificWarnings>4007;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<OutputFile>$(OutDir)unrar.dll</OutputFile>
<ModuleDefinitionFile>dll_nocrypt.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration />
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="archive.cpp" />
<ClCompile Include="arcread.cpp" />
<ClCompile Include="blake2s.cpp" />
<ClCompile Include="cmddata.cpp" />
<ClCompile Include="consio.cpp" />
<ClCompile Include="crc.cpp" />
<ClCompile Include="crypt.cpp" />
<ClCompile Include="dll.cpp" />
<ClCompile Include="encname.cpp" />
<ClCompile Include="errhnd.cpp" />
<ClCompile Include="extinfo.cpp" />
<ClCompile Include="extract.cpp" />
<ClCompile Include="filcreat.cpp" />
<ClCompile Include="file.cpp" />
<ClCompile Include="filefn.cpp" />
<ClCompile Include="filestr.cpp" />
<ClCompile Include="find.cpp" />
<ClCompile Include="getbits.cpp" />
<ClCompile Include="global.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">
</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="hash.cpp" />
<ClCompile Include="headers.cpp" />
<ClCompile Include="isnt.cpp" />
<ClCompile Include="match.cpp" />
<ClCompile Include="options.cpp" />
<ClCompile Include="pathfn.cpp" />
<ClCompile Include="qopen.cpp" />
<ClCompile Include="rar.cpp" />
<ClCompile Include="rarpch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release_nocrypt|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="rarvm.cpp" />
<ClCompile Include="rawread.cpp" />
<ClCompile Include="rdwrfn.cpp" />
<ClCompile Include="rijndael.cpp" />
<ClCompile Include="rs.cpp" />
<ClCompile Include="rs16.cpp" />
<ClCompile Include="scantree.cpp" />
<ClCompile Include="secpassword.cpp" />
<ClCompile Include="sha1.cpp" />
<ClCompile Include="sha256.cpp" />
<ClCompile Include="smallfn.cpp" />
<ClCompile Include="strfn.cpp" />
<ClCompile Include="strlist.cpp" />
<ClCompile Include="system.cpp" />
<ClCompile Include="threadpool.cpp" />
<ClCompile Include="timefn.cpp" />
<ClCompile Include="ui.cpp" />
<ClCompile Include="unicode.cpp" />
<ClCompile Include="unpack.cpp" />
<ClCompile Include="volume.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="rar.hpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="dll.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
-92
View File
@@ -1,92 +0,0 @@
ACKNOWLEDGMENTS
* We used "Screaming Fast Galois Field Arithmetic Using Intel
SIMD Instructions" paper by James S. Plank, Kevin M. Greenan
and Ethan L. Miller to improve Reed-Solomon coding performance.
Also we are grateful to Artem Drobanov and Bulat Ziganshin
for samples and ideas allowed to make Reed-Solomon coding
more efficient.
* RAR text compression algorithm is based on Dmitry Shkarin PPMII
and Dmitry Subbotin carryless rangecoder public domain source code.
You may find it in ftp.elf.stuba.sk/pub/pc/pack.
* RAR encryption includes parts of code from Szymon Stefanek
and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Source code of this package also as other cryptographic technology
and computing project related links are available on Brian Gladman's
web site: http://www.gladman.me.uk
* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
Original Intel Slicing-by-8 code is available here:
http://sourceforge.net/projects/slicing-by-8/
Original Intel Slicing-by-8 code is licensed under BSD License
available at http://www.opensource.org/licenses/bsd-license.html
Copyright (c) 2004-2006 Intel Corporation.
All Rights Reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with
the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
* RAR archives may optionally include BLAKE2sp hash ( https://blake2.net ),
designed by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn
and Christian Winnerlein.
* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
to significantly improve RAR compression and speed.
+143 -117
View File
@@ -1,185 +1,211 @@
static bool IsAnsiEscComment(const wchar *Data,size_t Size);
bool Archive::GetComment(Array<wchar> *CmtData)
bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
{
if (!MainComment)
return false;
int64 SavePos=Tell();
bool Success=DoGetComment(CmtData);
Seek(SavePos,SEEK_SET);
return Success;
}
return(false);
SaveFilePos SavePos(*this);
bool Archive::DoGetComment(Array<wchar> *CmtData)
{
ushort CmtLength;
#ifndef SFX_MODULE
uint CmtLength;
if (Format==RARFMT14)
if (OldFormat)
{
Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
CmtLength=GetByte();
CmtLength+=(GetByte()<<8);
Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET);
CmtLength=GetByte()+(GetByte()<<8);
}
else
#endif
{
if (MainHead.CommentInHeader)
if (NewMhd.Flags & MHD_COMMENT)
{
// Old style (RAR 2.9) archive comment embedded into the main
// archive header.
Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT)
return false;
Seek(SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD,SEEK_SET);
ReadHeader();
}
else
{
// Current (RAR 3.0+) version of archive comment.
Seek(GetStartPos(),SEEK_SET);
return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
Seek(SFXSize+SIZEOF_MARKHEAD+NewMhd.HeadSize,SEEK_SET);
return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData,CmtDataW)!=0);
}
#ifndef SFX_MODULE
// Old style (RAR 2.9) comment header embedded into the main
// archive header.
if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
if (CommHead.HeadCRC!=HeaderCRC)
{
uiMsg(UIERROR_CMTBROKEN,FileName);
return false;
Log(FileName,St(MLogCommHead));
Alarm();
return(false);
}
CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
#endif
}
#ifndef SFX_MODULE
if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT) || !OldFormat && CommHead.Method!=0x30)
{
if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
return false;
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 (Format==RARFMT14)
if (OldFormat)
{
#ifdef RAR_NOCRYPT
return false;
#else
UnpCmtLength=GetByte();
UnpCmtLength+=(GetByte()<<8);
if (CmtLength<2)
return false;
UnpCmtLength=GetByte()+(GetByte()<<8);
CmtLength-=2;
DataIO.SetCmt13Encryption();
CommHead.UnpVer=15;
#endif
}
else
UnpCmtLength=CommHead.UnpSize;
DataIO.SetFiles(this,NULL);
DataIO.EnableShowProgress(false);
DataIO.SetPackedSizeToRead(CmtLength);
DataIO.UnpHash.Init(HASH_CRC32,1);
DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet.
Unpack.SetDestSize(UnpCmtLength);
Unpack.DoUnpack(CommHead.UnpVer,false);
Unpack CmtUnpack(&DataIO);
CmtUnpack.Init(0x10000,false);
CmtUnpack.SetDestSize(UnpCmtLength);
CmtUnpack.DoUnpack(CommHead.UnpVer,false);
if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
if (!OldFormat && ((~DataIO.UnpFileCRC)&0xffff)!=CommHead.CommCRC)
{
uiMsg(UIERROR_CMTBROKEN,FileName);
return false;
Log(FileName,St(MLogCommBrk));
Alarm();
return(false);
}
else
{
byte *UnpData;
size_t UnpDataSize;
unsigned char *UnpData;
uint UnpDataSize;
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
if (UnpDataSize>0)
{
#ifdef _WIN_ALL
// If we ever decide to extend it to Android, we'll need to alloc
// 4x memory for OEM to UTF-8 output here.
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
#endif
CmtData->Alloc(UnpDataSize+1);
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
CmtData->Alloc(wcslen(CmtData->Addr(0)));
}
CmtData->Alloc(UnpDataSize);
memcpy(&((*CmtData)[0]),UnpData,UnpDataSize);
}
}
else
{
if (CmtLength==0)
return false;
Array<byte> CmtRaw(CmtLength);
int ReadSize=Read(&CmtRaw[0],CmtLength);
if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
CmtData->Alloc(CmtLength);
Read(&((*CmtData)[0]),CmtLength);
if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&((*CmtData)[0]),CmtLength)&0xffff))
{
CmtLength=ReadSize;
CmtRaw.Alloc(CmtLength);
Log(FileName,St(MLogCommBrk));
Alarm();
CmtData->Reset();
return(false);
}
if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
{
uiMsg(UIERROR_CMTBROKEN,FileName);
return false;
}
CmtData->Alloc(CmtLength+1);
CmtRaw.Push(0);
#ifdef _WIN_ALL
// If we ever decide to extend it to Android, we'll need to alloc
// 4x memory for OEM to UTF-8 output here.
OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
#endif
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
CmtData->Alloc(wcslen(CmtData->Addr(0)));
}
#endif
return CmtData->Size() > 0;
#if defined(_WIN_32) && !defined(_WIN_CE)
if (CmtData->Size()>0)
{
int CmtSize=CmtData->Size();
OemToCharBuff((char *)CmtData->Addr(),(char *)CmtData->Addr(),CmtSize);
if (CmtDataW!=NULL)
{
CmtDataW->Alloc(CmtSize+1);
CmtData->Push(0);
CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
CmtData->Alloc(CmtSize);
CmtDataW->Alloc(strlenw(CmtDataW->Addr()));
}
}
#endif
return(CmtData->Size()>0);
}
bool Archive::ReadCommentData(Array<wchar> *CmtData)
int Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
{
Array<byte> CmtRaw;
if (!ReadSubData(&CmtRaw,NULL,false))
return false;
size_t CmtSize=CmtRaw.Size();
CmtRaw.Push(0);
CmtData->Alloc(CmtSize+1);
if (Format==RARFMT50)
UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
if (!ReadSubData(CmtData,NULL))
return(0);
int CmtSize=CmtData->Size();
if (Unicode)
{
CmtSize/=2;
Array<wchar> DataW(CmtSize+1);
RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
DataW[CmtSize]=0;
int DestSize=CmtSize*4;
CmtData->Alloc(DestSize+1);
WideToChar(DataW.Addr(),(char *)CmtData->Addr(),DestSize);
(*CmtData)[DestSize]=0;
CmtSize=strlen((char *)CmtData->Addr());
CmtData->Alloc(CmtSize);
if (CmtDataW!=NULL)
{
*CmtDataW=DataW;
CmtDataW->Alloc(CmtSize);
}
}
else
if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
if (CmtDataW!=NULL)
{
RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
(*CmtData)[CmtSize/2]=0;
CmtData->Push(0);
CmtDataW->Alloc(CmtSize+1);
CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
CmtData->Alloc(CmtSize);
CmtDataW->Alloc(strlenw(CmtDataW->Addr()));
}
else
{
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
}
CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
return true;
return(CmtSize);
}
void Archive::ViewComment()
{
#ifndef GUI
if (Cmd->DisableComment)
return;
Array<wchar> CmtBuf;
if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
Array<byte> CmtBuf;
if (GetComment(&CmtBuf,NULL))
{
size_t CmtSize=CmtBuf.Size();
wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
int CmtSize=CmtBuf.Size();
char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize);
if (ChPtr!=NULL)
CmtSize=ChPtr-&CmtBuf[0];
mprintf(L"\n");
OutComment(&CmtBuf[0],CmtSize);
CmtSize=ChPtr-(char *)&CmtBuf[0];
mprintf("\n");
OutComment((char *)&CmtBuf[0],CmtSize);
}
#endif
}
#ifndef SFX_MODULE
void Archive::ViewFileComment()
{
if (!(NewLhd.Flags & LHD_COMMENT) || Cmd->DisableComment || OldFormat)
return;
#ifndef GUI
mprintf(St(MFileComment));
#endif
const int MaxSize=0x8000;
Array<char> CmtBuf(MaxSize);
SaveFilePos SavePos(*this);
Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
Int64 SaveCurBlockPos=CurBlockPos;
Int64 SaveNextBlockPos=NextBlockPos;
int Size=ReadHeader();
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
if (Size<7 || CommHead.HeadType!=COMM_HEAD)
return;
if (CommHead.HeadCRC!=HeaderCRC)
{
#ifndef GUI
Log(FileName,St(MLogCommHead));
#endif
return;
}
if (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER ||
CommHead.Method > 0x30 || CommHead.UnpSize > MaxSize)
return;
Read(&CmtBuf[0],CommHead.UnpSize);
if (CommHead.CommCRC!=((~CRC(0xffffffff,&CmtBuf[0],CommHead.UnpSize)&0xffff)))
{
Log(FileName,St(MLogBrokFCmt));
}
else
{
OutComment(&CmtBuf[0],CommHead.UnpSize);
#ifndef GUI
mprintf("\n");
#endif
}
}
#endif
+133 -214
View File
@@ -1,161 +1,143 @@
#include "rar.hpp"
#ifndef SHELL_EXT
#include "arccmt.cpp"
#endif
Archive::Archive(RAROptions *InitCmd)
{
Cmd=NULL; // Just in case we'll have an exception in 'new' below.
DummyCmd=(InitCmd==NULL);
Cmd=DummyCmd ? (new RAROptions):InitCmd;
Cmd=InitCmd==NULL ? &DummyCmd:InitCmd;
OpenShared=Cmd->OpenShared;
Format=RARFMT15;
OldFormat=false;
Solid=false;
Volume=false;
MainComment=false;
Locked=false;
Signed=false;
FirstVolume=false;
NewNumbering=false;
NotFirstVolume=false;
SFXSize=0;
LatestTime.Reset();
Protected=false;
Encrypted=false;
FailedHeaderDecryption=false;
BrokenHeader=false;
BrokenFileHeader=false;
LastReadBlock=0;
CurBlockPos=0;
NextBlockPos=0;
RecoveryPos=SIZEOF_MARKHEAD;
RecoverySectors=-1;
memset(&MainHead,0,sizeof(MainHead));
memset(&CryptHead,0,sizeof(CryptHead));
memset(&EndArcHead,0,sizeof(EndArcHead));
VolNumber=0;
memset(&NewMhd,0,sizeof(NewMhd));
NewMhd.HeadType=MAIN_HEAD;
NewMhd.HeadSize=SIZEOF_NEWMHD;
HeaderCRC=0;
VolWrite=0;
AddingFilesSize=0;
AddingHeadersSize=0;
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
*HeadersSalt=0;
*SubDataSalt=0;
#endif
*FirstVolumeName=0;
*FirstVolumeNameW=0;
Splitting=false;
NewArchive=false;
SilentOpen=false;
#ifdef USE_QOPEN
ProhibitQOpen=false;
#endif
}
Archive::~Archive()
{
if (DummyCmd)
delete Cmd;
}
#ifndef SHELL_EXT
void Archive::CheckArc(bool EnableBroken)
{
if (!IsArchive(EnableBroken))
{
// If FailedHeaderDecryption is set, we already reported that archive
// password is incorrect.
if (!FailedHeaderDecryption)
uiMsg(UIERROR_BADARCHIVE,FileName);
ErrHandler.Exit(RARX_FATAL);
Log(FileName,St(MBadArc),FileName);
ErrHandler.Exit(RAR_FATAL_ERROR);
}
}
#endif
#if !defined(SFX_MODULE)
void Archive::CheckOpen(const wchar *Name)
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
void Archive::CheckOpen(char *Name,wchar *NameW)
{
TOpen(Name);
TOpen(Name,NameW);
CheckArc(false);
}
#endif
bool Archive::WCheckOpen(const wchar *Name)
bool Archive::WCheckOpen(char *Name,wchar *NameW)
{
if (!WOpen(Name))
return false;
if (!WOpen(Name,NameW))
return(false);
if (!IsArchive(false))
{
uiMsg(UIERROR_BADARCHIVE,FileName);
#ifndef SHELL_EXT
Log(FileName,St(MNotRAR),FileName);
#endif
Close();
return false;
return(false);
}
return true;
return(true);
}
RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
bool Archive::IsSignature(byte *D)
{
RARFORMAT Type=RARFMT_NONE;
if (Size>=1 && D[0]==0x52)
bool Valid=false;
if (D[0]==0x52)
#ifndef SFX_MODULE
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
Type=RARFMT14;
if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
{
OldFormat=true;
Valid=true;
}
else
#endif
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00)
{
// We check the last signature byte, so we can return a sensible
// warning in case we'll want to change the archive format
// sometimes in the future.
if (D[6]==0)
Type=RARFMT15;
else
if (D[6]==1)
Type=RARFMT50;
else
if (D[6]>1 && D[6]<5)
Type=RARFMT_FUTURE;
OldFormat=false;
Valid=true;
}
return Type;
return(Valid);
}
bool Archive::IsArchive(bool EnableBroken)
{
Encrypted=false;
BrokenHeader=false; // Might be left from previous volume.
#ifndef SFX_MODULE
if (IsDevice())
{
uiMsg(UIERROR_INVALIDNAME,FileName,FileName);
return false;
#ifndef SHELL_EXT
Log(FileName,St(MInvalidName),FileName);
#endif
return(false);
}
#endif
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
return false;
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
return(false);
SFXSize=0;
RARFORMAT Type;
if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
if (IsSignature(MarkHead.Mark))
{
Format=Type;
if (Format==RARFMT14)
Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
if (OldFormat)
Seek(0,SEEK_SET);
}
else
{
Array<char> Buffer(MAXSFXSIZE);
long CurPos=(long)Tell();
long CurPos=int64to32(Tell());
int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
for (int I=0;I<ReadSize;I++)
if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE)
if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I]))
{
Format=Type;
if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31)
if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
{
char *D=&Buffer[28-CurPos];
if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
@@ -163,111 +145,88 @@ bool Archive::IsArchive(bool EnableBroken)
}
SFXSize=CurPos+I;
Seek(SFXSize,SEEK_SET);
if (Format==RARFMT15 || Format==RARFMT50)
Read(MarkHead.Mark,SIZEOF_MARKHEAD3);
if (!OldFormat)
Read(MarkHead.Mark,SIZEOF_MARKHEAD);
break;
}
if (SFXSize==0)
return false;
return(false);
}
if (Format==RARFMT_FUTURE)
ReadHeader();
SeekToNext();
#ifndef SFX_MODULE
if (OldFormat)
{
uiMsg(UIERROR_NEWRARFORMAT,FileName);
return false;
}
if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
{
if (Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1)!=1 || MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
return false;
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
NewMhd.Flags=OldMhd.Flags & 0x3f;
NewMhd.HeadSize=OldMhd.HeadSize;
}
else
MarkHead.HeadSize=SIZEOF_MARKHEAD3;
#ifdef RARDLL
// If callback function is not set, we cannot get the password,
// so we skip the initial header processing for encrypted header archive.
// It leads to skipped archive comment, but the rest of archive data
// is processed correctly.
if (Cmd->Callback==NULL)
SilentOpen=true;
#endif
bool HeadersLeft; // Any headers left to read.
bool StartFound=false; // Main or encryption headers found.
// Skip the archive encryption header if any and read the main header.
while ((HeadersLeft=(ReadHeader()!=0))==true) // Additional parentheses to silence Clang.
{
SeekToNext();
HEADER_TYPE Type=GetHeaderType();
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
// avoid the password prompt.
StartFound=Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT;
if (StartFound)
break;
}
// We should not do it for EnableBroken or we'll get 'not RAR archive'
// messages when extracting encrypted archives with wrong password.
if (FailedHeaderDecryption && !EnableBroken)
return false;
if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing.
{
if (!FailedHeaderDecryption) // If not reported a wrong password already.
uiMsg(UIERROR_MHEADERBROKEN,FileName);
if (!EnableBroken)
return false;
}
MainComment=MainHead.CommentInHeader;
// If we process non-encrypted archive or can request a password,
// we set 'first volume' flag based on file attributes below.
// It is necessary for RAR 2.x archives, which did not have 'first volume'
// flag in main header. Also for all RAR formats we need to scan until
// first file header to set "comment" flag when reading service header.
// Unless we are in silent mode, we need to know about presence of comment
// immediately after IsArchive call.
if (HeadersLeft && (!SilentOpen || !Encrypted))
{
int64 SavePos=Tell();
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
while (ReadHeader()!=0)
if (HeaderCRC!=NewMhd.HeadCRC)
{
HEADER_TYPE HeaderType=GetHeaderType();
if (HeaderType==HEAD_SERVICE)
#ifndef SHELL_EXT
Log(FileName,St(MLogMainHead));
#endif
Alarm();
if (!EnableBroken)
return(false);
}
}
Volume=(NewMhd.Flags & MHD_VOLUME);
Solid=(NewMhd.Flags & MHD_SOLID)!=0;
MainComment=(NewMhd.Flags & MHD_COMMENT)!=0;
Locked=(NewMhd.Flags & MHD_LOCK)!=0;
Signed=(NewMhd.PosAV!=0);
Protected=(NewMhd.Flags & MHD_PROTECT)!=0;
Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
if (NewMhd.EncryptVer>UNP_VER)
{
#ifdef RARDLL
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
#else
ErrHandler.SetErrorCode(RAR_WARNING);
#if !defined(SILENT) && !defined(SFX_MODULE)
Log(FileName,St(MUnknownMeth),FileName);
Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
#endif
#endif
return(false);
}
#ifdef RARDLL
SilentOpen=true;
#endif
if (!SilentOpen || !Encrypted)
{
SaveFilePos SavePos(*this);
Int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
NotFirstVolume=false;
while (ReadHeader())
{
int HeaderType=GetHeaderType();
if (HeaderType==NEWSUB_HEAD)
{
// If we have a split service headers, it surely indicates non-first
// volume. But not split service header does not guarantee the first
// volume, because we can have split file after non-split archive
// comment. So we do not quit from loop here.
FirstVolume=Volume && !SubHead.SplitBefore;
if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
MainComment=true;
if ((SubHead.Flags & LHD_SPLIT_BEFORE) ||
Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)
NotFirstVolume=true;
}
else
if (HeaderType==HEAD_FILE)
{
FirstVolume=Volume && !FileHead.SplitBefore;
break;
}
else
if (HeaderType==HEAD_ENDARC) // Might happen if archive contains only a split service header.
break;
{
if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 ||
Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
NotFirstVolume=true;
break;
}
SeekToNext();
}
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
CurHeaderType=SaveCurHeaderType;
Seek(SavePos,SEEK_SET);
}
if (!Volume || FirstVolume)
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
return true;
return(true);
}
@@ -279,60 +238,20 @@ void Archive::SeekToNext()
}
// Calculate the block size including encryption fields and padding if any.
uint Archive::FullHeaderSize(size_t Size)
#ifndef SFX_MODULE
int Archive::GetRecoverySize(bool Required)
{
if (Encrypted)
{
Size = ALIGN_VALUE(Size, CRYPT_BLOCK_SIZE); // Align to encryption block size.
if (Format == RARFMT50)
Size += SIZE_INITV;
else
Size += SIZE_SALT30;
}
return uint(Size);
}
#ifdef USE_QOPEN
bool Archive::Open(const wchar *Name,uint Mode)
{
// Important if we reuse Archive object and it has virtual QOpen
// file position not matching real. For example, for 'l -v volname'.
QOpen.Unload();
return File::Open(Name,Mode);
}
int Archive::Read(void *Data,size_t Size)
{
size_t Result;
if (QOpen.Read(Data,Size,Result))
return (int)Result;
return File::Read(Data,Size);
}
void Archive::Seek(int64 Offset,int Method)
{
if (!QOpen.Seek(Offset,Method))
File::Seek(Offset,Method);
}
int64 Archive::Tell()
{
int64 QPos;
if (QOpen.Tell(&QPos))
return QPos;
return File::Tell();
if (!Protected)
return(0);
if (RecoverySectors!=-1 || !Required)
return(RecoverySectors);
SaveFilePos SavePos(*this);
Seek(SFXSize,SEEK_SET);
SearchSubBlock(SUBHEAD_TYPE_RR);
return(RecoverySectors);
}
#endif
+69 -89
View File
@@ -1,148 +1,128 @@
#ifndef _RAR_ARCHIVE_
#define _RAR_ARCHIVE_
class PPack;
class RawRead;
class RawWrite;
class Pack;
enum NOMODIFY_FLAGS
{
NMDF_ALLOWLOCK=1,NMDF_ALLOWANYVOLUME=2,NMDF_ALLOWFIRSTVOLUME=4
};
enum RARFORMAT {RARFMT_NONE,RARFMT14,RARFMT15,RARFMT50,RARFMT_FUTURE};
enum ADDSUBDATA_FLAGS
{
ASDF_SPLIT = 1, // Allow to split archive just before header if necessary.
ASDF_COMPRESS = 2, // Allow to compress data following subheader.
ASDF_CRYPT = 4, // Encrypt data after subheader if password is set.
ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode.
};
// RAR5 headers must not exceed 2 MB.
#define MAX_HEADER_SIZE_RAR5 0x200000
enum {EN_LOCK=1,EN_VOL=2,EN_FIRSTVOL=4};
class Archive:public File
{
private:
bool IsSignature(byte *D);
void UpdateLatestTime(FileHeader *CurBlock);
void Protect(int RecSectors);
void ConvertNameCase(char *Name);
void ConvertNameCase(wchar *Name);
void ConvertFileHeader(FileHeader *hd);
size_t ReadHeader14();
size_t ReadHeader15();
size_t ReadHeader50();
void ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb);
void RequestArcPassword();
void UnexpEndArcMsg();
void BrokenHeaderMsg();
void UnkEncVerMsg(const wchar *Name,const wchar *Info);
bool DoGetComment(Array<wchar> *CmtData);
bool ReadCommentData(Array<wchar> *CmtData);
void ConvertUnknownHeader();
bool AddArcComment(char *NameToShow);
int ReadOldHeader();
void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array<byte> &TimeData);
#if !defined(RAR_NOCRYPT)
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
CryptData HeadersCrypt;
byte HeadersSalt[SALT_SIZE];
#endif
#ifndef SHELL_EXT
ComprDataIO SubDataIO;
bool DummyCmd;
RAROptions *Cmd;
byte SubDataSalt[SALT_SIZE];
#endif
RAROptions *Cmd,DummyCmd;
MarkHeader MarkHead;
OldMainHeader OldMhd;
int RecoverySectors;
Int64 RecoveryPos;
RarTime LatestTime;
int LastReadBlock;
HEADER_TYPE CurHeaderType;
int CurHeaderType;
bool SilentOpen;
#ifdef USE_QOPEN
QuickOpen QOpen;
bool ProhibitQOpen;
#endif
public:
Archive(RAROptions *InitCmd=NULL);
~Archive();
static RARFORMAT IsSignature(const byte *D,size_t Size);
bool IsArchive(bool EnableBroken);
size_t SearchBlock(HEADER_TYPE HeaderType);
size_t SearchSubBlock(const wchar *Type);
size_t SearchRR();
size_t ReadHeader();
int SearchBlock(int BlockType);
int SearchSubBlock(const char *Type);
int ReadBlock(int BlockType);
void WriteBlock(int BlockType,BaseBlock *wb=NULL);
int PrepareNamesToWrite(char *Name,wchar *NameW,char *DestName,byte *DestNameW);
void SetLhdSize();
int ReadHeader();
void CheckArc(bool EnableBroken);
void CheckOpen(const wchar *Name);
bool WCheckOpen(const wchar *Name);
bool GetComment(Array<wchar> *CmtData);
void CheckOpen(char *Name,wchar *NameW=NULL);
bool WCheckOpen(char *Name,wchar *NameW=NULL);
bool TestLock(int Mode);
void MakeTemp();
void CopyMainHeader(Archive &Src,bool CopySFX=true,char *NameToDisplay=NULL);
bool ProcessToFileHead(Archive &Src,bool LastBlockAdded,
Pack *Pack=NULL,const char *SkipName=NULL);
void TmpToArc(Archive &Src);
void CloseNew(int AdjustRecovery,bool CloseVolume);
void WriteEndBlock(bool CloseVolume);
void CopyFileRecord(Archive &Src);
void CopyArchiveData(Archive &Src);
bool GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW);
void ViewComment();
void ViewFileComment();
void SetLatestTime(RarTime *NewTime);
void SeekToNext();
bool CheckAccess();
bool IsArcDir();
bool IsArcLabel();
void ConvertAttributes();
void VolSubtractHeaderSize(size_t SubSize);
uint FullHeaderSize(size_t Size);
int64 GetStartPos();
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
const wchar *Name,uint Flags);
bool ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode);
HEADER_TYPE GetHeaderType() {return CurHeaderType;}
RAROptions* GetRAROptions() {return Cmd;}
int GetRecoverySize(bool Required);
void VolSubtractHeaderSize(int SubSize);
void AddSubData(byte *SrcData,int DataSize,File *SrcFile,char *Name,bool AllowSplit);
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
int GetHeaderType() {return(CurHeaderType);};
int ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW);
void WriteCommentData(byte *Data,int DataSize,bool FileComment);
RAROptions* GetRAROptions() {return(Cmd);}
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
#if 0
void GetRecoveryInfo(bool Required,int64 *Size,int *Percent);
#endif
#ifdef USE_QOPEN
bool Open(const wchar *Name,uint Mode=FMF_READ);
int Read(void *Data,size_t Size);
void Seek(int64 Offset,int Method);
int64 Tell();
void QOpenUnload() {QOpen.Unload();}
void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;}
#endif
BaseBlock ShortBlock;
MarkHeader MarkHead;
MainHeader MainHead;
CryptHeader CryptHead;
FileHeader FileHead;
MainHeader NewMhd;
FileHeader NewLhd;
EndArcHeader EndArcHead;
SubBlockHeader SubBlockHead;
FileHeader SubHead;
CommentHeader CommHead;
ProtectHeader ProtectHead;
AVHeader AVHead;
SignHeader SignHead;
UnixOwnersHeader UOHead;
MacFInfoHeader MACHead;
EAHeader EAHead;
StreamHeader StreamHead;
int64 CurBlockPos;
int64 NextBlockPos;
Int64 CurBlockPos;
Int64 NextBlockPos;
RARFORMAT Format;
bool OldFormat;
bool Solid;
bool Volume;
bool MainComment;
bool Locked;
bool Signed;
bool FirstVolume;
bool NewNumbering;
bool NotFirstVolume;
bool Protected;
bool Encrypted;
size_t SFXSize;
bool BrokenHeader;
bool FailedHeaderDecryption;
#if !defined(RAR_NOCRYPT)
byte ArcSalt[SIZE_SALT50];
#endif
uint SFXSize;
bool BrokenFileHeader;
bool Splitting;
uint VolNumber;
int64 VolWrite;
uint64 AddingFilesSize;
uint64 AddingHeadersSize;
ushort HeaderCRC;
Int64 VolWrite;
Int64 AddingFilesSize;
uint AddingHeadersSize;
bool NewArchive;
wchar FirstVolumeName[NM];
char FirstVolumeName[NM];
wchar FirstVolumeNameW[NM];
};
#endif
+442 -1273
View File
File diff suppressed because it is too large Load Diff
+26 -95
View File
@@ -7,41 +7,28 @@ template <class T> class Array
{
private:
T *Buffer;
size_t BufSize;
size_t AllocSize;
size_t MaxSize;
bool Secure; // Clean memory if true.
int BufSize;
int AllocSize;
public:
Array();
Array(size_t Size);
Array(const Array &Src); // Copy constructor.
Array(int Size);
~Array();
inline void CleanData();
inline T& operator [](size_t Item) const;
inline T* operator + (size_t Pos);
inline size_t Size(); // Returns the size in items, not in bytes.
void Add(size_t Items);
void Alloc(size_t Items);
inline T& operator [](int Item);
inline int Size();
void Add(int Items);
void Alloc(int Items);
void Reset();
void SoftReset();
void operator = (Array<T> &Src);
void Push(T Item);
void Append(T *Item,size_t Count);
T* Addr(size_t Item) {return Buffer+Item;}
void SetMaxSize(size_t Size) {MaxSize=Size;}
T* Begin() {return Buffer;}
T* End() {return Buffer==NULL ? NULL:Buffer+BufSize;}
void SetSecure() {Secure=true;}
T* Addr() {return(Buffer);}
};
template <class T> void Array<T>::CleanData()
{
Buffer=NULL;
BufSize=0;
AllocSize=0;
MaxSize=0;
Secure=false;
}
@@ -51,92 +38,52 @@ template <class T> Array<T>::Array()
}
template <class T> Array<T>::Array(size_t Size)
template <class T> Array<T>::Array(int Size)
{
CleanData();
Add(Size);
}
Buffer=(T *)rarmalloc(sizeof(T)*Size);
if (Buffer==NULL && Size!=0)
ErrHandler.MemoryError();
// Copy constructor in case we need to pass an object as value.
template <class T> Array<T>::Array(const Array &Src)
{
CleanData();
Alloc(Src.BufSize);
if (Src.BufSize!=0)
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
AllocSize=BufSize=Size;
}
template <class T> Array<T>::~Array()
{
if (Buffer!=NULL)
{
if (Secure)
cleandata(Buffer,AllocSize*sizeof(T));
free(Buffer);
}
rarfree(Buffer);
}
template <class T> inline T& Array<T>::operator [](size_t Item) const
template <class T> inline T& Array<T>::operator [](int Item)
{
return Buffer[Item];
return(Buffer[Item]);
}
template <class T> inline T* Array<T>::operator +(size_t Pos)
template <class T> inline int Array<T>::Size()
{
return Buffer+Pos;
return(BufSize);
}
template <class T> inline size_t Array<T>::Size()
{
return BufSize;
}
template <class T> void Array<T>::Add(size_t Items)
template <class T> void Array<T>::Add(int Items)
{
BufSize+=Items;
if (BufSize>AllocSize)
{
if (MaxSize!=0 && BufSize>MaxSize)
{
ErrHandler.GeneralErrMsg(L"Maximum allowed array size (%u) is exceeded",MaxSize);
int Suggested=AllocSize+AllocSize/4+32;
int NewSize=Max(BufSize,Suggested);
Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T));
if (Buffer==NULL)
ErrHandler.MemoryError();
}
size_t Suggested=AllocSize+AllocSize/4+32;
size_t NewSize=Max(BufSize,Suggested);
T *NewBuffer;
if (Secure)
{
NewBuffer=(T *)malloc(NewSize*sizeof(T));
if (NewBuffer==NULL)
ErrHandler.MemoryError();
if (Buffer!=NULL)
{
memcpy(NewBuffer,Buffer,AllocSize*sizeof(T));
cleandata(Buffer,AllocSize*sizeof(T));
free(Buffer);
}
}
else
{
NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T));
if (NewBuffer==NULL)
ErrHandler.MemoryError();
}
Buffer=NewBuffer;
AllocSize=NewSize;
}
}
template <class T> void Array<T>::Alloc(size_t Items)
template <class T> void Array<T>::Alloc(int Items)
{
if (Items>AllocSize)
Add(Items-BufSize);
@@ -149,7 +96,7 @@ template <class T> void Array<T>::Reset()
{
if (Buffer!=NULL)
{
free(Buffer);
rarfree(Buffer);
Buffer=NULL;
}
BufSize=0;
@@ -157,14 +104,6 @@ template <class T> void Array<T>::Reset()
}
// Reset buffer size, but preserve already allocated memory if any,
// so we can reuse it without wasting time to allocation.
template <class T> void Array<T>::SoftReset()
{
BufSize=0;
}
template <class T> void Array<T>::operator =(Array<T> &Src)
{
Reset();
@@ -180,12 +119,4 @@ template <class T> void Array<T>::Push(T Item)
(*this)[Size()-1]=Item;
}
template <class T> void Array<T>::Append(T *Items,size_t Count)
{
size_t CurSize=Size();
Add(Count);
memcpy(Buffer+CurSize,Items,Count*sizeof(T));
}
#endif
+113
View File
@@ -0,0 +1,113 @@
void ExtractBeEA(Archive &Arc,char *FileName)
{
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
return;
}
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
{
Log(Arc.FileName,St(MEAUnknHeader),FileName);
return;
}
ComprDataIO DataIO;
Unpack Unpack(&DataIO);
Unpack.Init();
Array<byte> UnpData(Arc.EAHead.UnpSize);
DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
DataIO.EnableShowProgress(false);
DataIO.SetFiles(&Arc,NULL);
Unpack.SetDestSize(Arc.EAHead.UnpSize);
Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
return;
}
int fd = open(FileName,O_WRONLY);
if (fd==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
return;
}
int AttrPos=0;
while (AttrPos<Arc.EAHead.UnpSize)
{
unsigned char *CurItem=&UnpData[AttrPos];
int NameSize=CurItem[0]+((int)CurItem[1]<<8);
int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
char Name[1024];
if (NameSize>=sizeof(Name))
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
break;
}
memcpy(Name,CurItem+10,NameSize);
Name[NameSize]=0;
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
break;
}
AttrPos+=10+NameSize+Size;
}
close(fd);
mprintf(St(MShowEA));
}
void ExtractBeEANew(Archive &Arc,char *FileName)
{
Array<byte> SubData;
if (!Arc.ReadSubData(&SubData,NULL))
return;
int fd = open(FileName,O_WRONLY);
if (fd==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
return;
}
int AttrPos=0;
while (AttrPos<Arc.EAHead.UnpSize)
{
unsigned char *CurItem=&SubData[AttrPos];
int NameSize=CurItem[0]+((int)CurItem[1]<<8);
int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
char Name[1024];
if (NameSize>=sizeof(Name))
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
break;
}
memcpy(Name,CurItem+10,NameSize);
Name[NameSize]=0;
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
break;
}
AttrPos+=10+NameSize+Size;
}
close(fd);
mprintf(St(MShowEA));
}
-183
View File
@@ -1,183 +0,0 @@
// Based on public domain code written in 2012 by Samuel Neves
#include "rar.hpp"
#ifdef USE_SSE
#include "blake2s_sse.cpp"
#endif
static void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth);
static void blake2s_update( blake2s_state *S, const byte *in, size_t inlen );
static void blake2s_final( blake2s_state *S, byte *digest );
#include "blake2sp.cpp"
static const uint32 blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const byte blake2s_sigma[10][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
};
static inline void blake2s_set_lastnode( blake2s_state *S )
{
S->f[1] = ~0U;
}
/* Some helper functions, not necessarily useful */
static inline void blake2s_set_lastblock( blake2s_state *S )
{
if( S->last_node ) blake2s_set_lastnode( S );
S->f[0] = ~0U;
}
static inline void blake2s_increment_counter( blake2s_state *S, const uint32 inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
}
/* init2 xors IV with input parameter block */
void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth)
{
#ifdef USE_SSE
if (_SSE_Version>=SSE_SSE2)
blake2s_init_sse();
#endif
S->init(); // Clean data.
for( int i = 0; i < 8; ++i )
S->h[i] = blake2s_IV[i];
S->h[0] ^= 0x02080020; // We use BLAKE2sp parameters block.
S->h[2] ^= node_offset;
S->h[3] ^= (node_depth<<16)|0x20000000;
}
#define G(r,i,m,a,b,c,d) \
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
d = rotr32(d ^ a, 16); \
c = c + d; \
b = rotr32(b ^ c, 12); \
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
d = rotr32(d ^ a, 8); \
c = c + d; \
b = rotr32(b ^ c, 7);
static void blake2s_compress( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
{
uint32 m[16];
uint32 v[16];
for( size_t i = 0; i < 16; ++i )
m[i] = RawGet4( block + i * 4 );
for( size_t i = 0; i < 8; ++i )
v[i] = S->h[i];
v[ 8] = blake2s_IV[0];
v[ 9] = blake2s_IV[1];
v[10] = blake2s_IV[2];
v[11] = blake2s_IV[3];
v[12] = S->t[0] ^ blake2s_IV[4];
v[13] = S->t[1] ^ blake2s_IV[5];
v[14] = S->f[0] ^ blake2s_IV[6];
v[15] = S->f[1] ^ blake2s_IV[7];
for ( uint r = 0; r <= 9; ++r ) // No gain on i7 if unrolled, but exe size grows.
{
G(r,0,m,v[ 0],v[ 4],v[ 8],v[12]);
G(r,1,m,v[ 1],v[ 5],v[ 9],v[13]);
G(r,2,m,v[ 2],v[ 6],v[10],v[14]);
G(r,3,m,v[ 3],v[ 7],v[11],v[15]);
G(r,4,m,v[ 0],v[ 5],v[10],v[15]);
G(r,5,m,v[ 1],v[ 6],v[11],v[12]);
G(r,6,m,v[ 2],v[ 7],v[ 8],v[13]);
G(r,7,m,v[ 3],v[ 4],v[ 9],v[14]);
}
for( size_t i = 0; i < 8; ++i )
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
void blake2s_update( blake2s_state *S, const byte *in, size_t inlen )
{
while( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
if( inlen > fill )
{
memcpy( S->buf + left, in, fill ); // Fill buffer
S->buflen += fill;
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
#ifdef USE_SSE
#ifdef _WIN_32 // We use SSSE3 _mm_shuffle_epi8 only in x64 mode.
if (_SSE_Version>=SSE_SSE2)
#else
if (_SSE_Version>=SSE_SSSE3)
#endif
blake2s_compress_sse( S, S->buf );
else
blake2s_compress( S, S->buf ); // Compress
#else
blake2s_compress( S, S->buf ); // Compress
#endif
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
S->buflen -= BLAKE2S_BLOCKBYTES;
in += fill;
inlen -= fill;
}
else // inlen <= fill
{
memcpy( S->buf + left, in, (size_t)inlen );
S->buflen += (size_t)inlen; // Be lazy, do not compress
in += inlen;
inlen = 0;
}
}
}
void blake2s_final( blake2s_state *S, byte *digest )
{
if( S->buflen > BLAKE2S_BLOCKBYTES )
{
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
blake2s_compress( S, S->buf );
S->buflen -= BLAKE2S_BLOCKBYTES;
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
}
blake2s_increment_counter( S, ( uint32 )S->buflen );
blake2s_set_lastblock( S );
memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
blake2s_compress( S, S->buf );
for( int i = 0; i < 8; ++i ) /* Output full hash */
RawPut4( S->h[i], digest + 4 * i );
}
-102
View File
@@ -1,102 +0,0 @@
// Based on public domain code written in 2012 by Samuel Neves
#ifndef _RAR_BLAKE2_
#define _RAR_BLAKE2_
#define BLAKE2_DIGEST_SIZE 32
#define BLAKE2_THREADS_NUMBER 8
enum blake2s_constant
{
BLAKE2S_BLOCKBYTES = 64,
BLAKE2S_OUTBYTES = 32
};
// Alignment to 64 improves performance of both SSE and non-SSE versions.
// Alignment to n*16 is required for SSE version, so we selected 64.
// We use the custom alignment scheme instead of __declspec(align(x)),
// because it is less compiler dependent. Also the compiler directive
// does not help if structure is a member of class allocated through
// 'new' operator.
struct blake2s_state
{
enum { BLAKE_ALIGNMENT = 64 };
// buffer and uint32 h[8], t[2], f[2];
enum { BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES };
byte ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT];
byte *buf; // byte buf[2 * BLAKE2S_BLOCKBYTES].
uint32 *h, *t, *f; // uint32 h[8], t[2], f[2].
size_t buflen;
byte last_node;
blake2s_state()
{
set_pointers();
}
// Required when we declare and assign in the same command.
blake2s_state(blake2s_state &st)
{
set_pointers();
*this=st;
}
void set_pointers()
{
// Set aligned pointers. Must be done in constructor, not in Init(),
// so assignments like 'blake2sp_state res=blake2ctx' work correctly
// even if blake2sp_init is not called for 'res'.
buf = (byte *) ALIGN_VALUE(ubuf, BLAKE_ALIGNMENT);
h = (uint32 *) (buf + 2 * BLAKE2S_BLOCKBYTES);
t = h + 8;
f = t + 2;
}
void init()
{
memset( ubuf, 0, sizeof( ubuf ) );
buflen = 0;
last_node = 0;
}
// Since we use pointers, the default = would work incorrectly.
blake2s_state& operator = (blake2s_state &st)
{
if (this != &st)
{
memcpy(buf, st.buf, BLAKE_DATA_SIZE);
buflen = st.buflen;
last_node = st.last_node;
}
return *this;
}
};
#ifdef RAR_SMP
class ThreadPool;
#endif
struct blake2sp_state
{
blake2s_state S[8];
blake2s_state R;
byte buf[8 * BLAKE2S_BLOCKBYTES];
size_t buflen;
#ifdef RAR_SMP
ThreadPool *ThPool;
uint MaxThreads;
#endif
};
void blake2sp_init( blake2sp_state *S );
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen );
void blake2sp_final( blake2sp_state *S, byte *digest );
#endif
-129
View File
@@ -1,129 +0,0 @@
// Based on public domain code written in 2012 by Samuel Neves
extern const byte blake2s_sigma[10][16];
// Initialization vector.
static __m128i blake2s_IV_0_3, blake2s_IV_4_7;
#ifdef _WIN_64
// Constants for cyclic rotation. Used in 64-bit mode in mm_rotr_epi32 macro.
static __m128i crotr8, crotr16;
#endif
static void blake2s_init_sse()
{
// We cannot initialize these 128 bit variables in place when declaring
// them globally, because global scope initialization is performed before
// our SSE check and it would make code incompatible with older non-SSE2
// CPUs. Also we cannot initialize them as static inside of function
// using these variables, because SSE static initialization is not thread
// safe: first thread starts initialization and sets "init done" flag even
// if it is not done yet, second thread can attempt to access half-init
// SSE data. So we moved init code here.
blake2s_IV_0_3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );
blake2s_IV_4_7 = _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 );
#ifdef _WIN_64
crotr8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 );
crotr16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 );
#endif
}
#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
#ifdef _WIN_32
// 32-bit mode has less SSE2 registers and in MSVC2008 it is more efficient
// to not use _mm_shuffle_epi8 here.
#define mm_rotr_epi32(r, c) ( \
_mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
#else
#define mm_rotr_epi32(r, c) ( \
c==8 ? _mm_shuffle_epi8(r,crotr8) \
: c==16 ? _mm_shuffle_epi8(r,crotr16) \
: _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
#endif
#define G1(row1,row2,row3,row4,buf) \
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
row4 = _mm_xor_si128( row4, row1 ); \
row4 = mm_rotr_epi32(row4, 16); \
row3 = _mm_add_epi32( row3, row4 ); \
row2 = _mm_xor_si128( row2, row3 ); \
row2 = mm_rotr_epi32(row2, 12);
#define G2(row1,row2,row3,row4,buf) \
row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
row4 = _mm_xor_si128( row4, row1 ); \
row4 = mm_rotr_epi32(row4, 8); \
row3 = _mm_add_epi32( row3, row4 ); \
row2 = _mm_xor_si128( row2, row3 ); \
row2 = mm_rotr_epi32(row2, 7);
#define DIAGONALIZE(row1,row2,row3,row4) \
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) );
#define UNDIAGONALIZE(row1,row2,row3,row4) \
row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \
row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) );
#ifdef _WIN_64
// MSVC 2008 in x64 mode expands _mm_set_epi32 to store to stack and load
// from stack operations, which are slower than this code.
#define _mm_set_epi32(i3,i2,i1,i0) \
_mm_unpacklo_epi32(_mm_unpacklo_epi32(_mm_cvtsi32_si128(i0),_mm_cvtsi32_si128(i2)), \
_mm_unpacklo_epi32(_mm_cvtsi32_si128(i1),_mm_cvtsi32_si128(i3)))
#endif
// Original BLAKE2 SSE4.1 message loading code was a little slower in x86 mode
// and about the same in x64 mode in our test. Perhaps depends on compiler.
// We also tried _mm_i32gather_epi32 and _mm256_i32gather_epi32 AVX2 gather
// instructions here, but they did not show any speed gain on i7-6700K.
#define SSE_ROUND(m,row,r) \
{ \
__m128i buf; \
buf=_mm_set_epi32(m[blake2s_sigma[r][6]],m[blake2s_sigma[r][4]],m[blake2s_sigma[r][2]],m[blake2s_sigma[r][0]]); \
G1(row[0],row[1],row[2],row[3],buf); \
buf=_mm_set_epi32(m[blake2s_sigma[r][7]],m[blake2s_sigma[r][5]],m[blake2s_sigma[r][3]],m[blake2s_sigma[r][1]]); \
G2(row[0],row[1],row[2],row[3],buf); \
DIAGONALIZE(row[0],row[1],row[2],row[3]); \
buf=_mm_set_epi32(m[blake2s_sigma[r][14]],m[blake2s_sigma[r][12]],m[blake2s_sigma[r][10]],m[blake2s_sigma[r][8]]); \
G1(row[0],row[1],row[2],row[3],buf); \
buf=_mm_set_epi32(m[blake2s_sigma[r][15]],m[blake2s_sigma[r][13]],m[blake2s_sigma[r][11]],m[blake2s_sigma[r][9]]); \
G2(row[0],row[1],row[2],row[3],buf); \
UNDIAGONALIZE(row[0],row[1],row[2],row[3]); \
}
static int blake2s_compress_sse( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
{
__m128i row[4];
__m128i ff0, ff1;
const uint32 *m = ( uint32 * )block;
row[0] = ff0 = LOAD( &S->h[0] );
row[1] = ff1 = LOAD( &S->h[4] );
row[2] = blake2s_IV_0_3;
row[3] = _mm_xor_si128( blake2s_IV_4_7, LOAD( &S->t[0] ) );
SSE_ROUND( m, row, 0 );
SSE_ROUND( m, row, 1 );
SSE_ROUND( m, row, 2 );
SSE_ROUND( m, row, 3 );
SSE_ROUND( m, row, 4 );
SSE_ROUND( m, row, 5 );
SSE_ROUND( m, row, 6 );
SSE_ROUND( m, row, 7 );
SSE_ROUND( m, row, 8 );
SSE_ROUND( m, row, 9 );
STORE( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row[0], row[2] ) ) );
STORE( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row[1], row[3] ) ) );
return 0;
}
-153
View File
@@ -1,153 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along with
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#define PARALLELISM_DEGREE 8
void blake2sp_init( blake2sp_state *S )
{
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
blake2s_init_param( &S->R, 0, 1 ); // Init root.
for( uint i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_init_param( &S->S[i], i, 0 ); // Init leaf.
S->R.last_node = 1;
S->S[PARALLELISM_DEGREE - 1].last_node = 1;
}
struct Blake2ThreadData
{
void Update();
blake2s_state *S;
const byte *in;
size_t inlen;
};
void Blake2ThreadData::Update()
{
size_t inlen__ = inlen;
const byte *in__ = ( const byte * )in;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
{
#ifdef USE_SSE
// We gain 5% in i7 SSE mode by prefetching next data block.
if (_SSE_Version>=SSE_SSE && inlen__ >= 2 * PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES)
_mm_prefetch((char*)(in__ + PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES), _MM_HINT_T0);
#endif
blake2s_update( S, in__, BLAKE2S_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
}
}
#ifdef RAR_SMP
THREAD_PROC(Blake2Thread)
{
Blake2ThreadData *td=(Blake2ThreadData *)Data;
td->Update();
}
#endif
void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen )
{
size_t left = S->buflen;
size_t fill = sizeof( S->buf ) - left;
if( left && inlen >= fill )
{
memcpy( S->buf + left, in, fill );
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
in += fill;
inlen -= fill;
left = 0;
}
Blake2ThreadData btd_array[PARALLELISM_DEGREE];
#ifdef RAR_SMP
uint ThreadNumber = inlen < 0x1000 ? 1 : S->MaxThreads;
if (ThreadNumber==6 || ThreadNumber==7) // 6 and 7 threads work slower than 4 here.
ThreadNumber=4;
#else
uint ThreadNumber=1;
#endif
for (size_t id__=0;id__<PARALLELISM_DEGREE;)
{
for (uint Thread=0;Thread<ThreadNumber && id__<PARALLELISM_DEGREE;Thread++)
{
Blake2ThreadData *btd=btd_array+Thread;
btd->inlen = inlen;
btd->in = in + id__ * BLAKE2S_BLOCKBYTES;
btd->S = &S->S[id__];
#ifdef RAR_SMP
if (ThreadNumber>1)
S->ThPool->AddTask(Blake2Thread,(void*)btd);
else
btd->Update();
#else
btd->Update();
#endif
id__++;
}
#ifdef RAR_SMP
if (S->ThPool!=NULL) // Can be NULL in -mt1 mode.
S->ThPool->WaitDone();
#endif // RAR_SMP
}
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
if( inlen > 0 )
memcpy( S->buf + left, in, (size_t)inlen );
S->buflen = left + (size_t)inlen;
}
void blake2sp_final( blake2sp_state *S, byte *digest )
{
byte hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
{
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
{
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
}
blake2s_final( &S->S[i], hash[i] );
}
for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( &S->R, hash[i], BLAKE2S_OUTBYTES );
blake2s_final( &S->R, digest );
}
+852 -721
View File
File diff suppressed because it is too large Load Diff
+30 -43
View File
@@ -1,70 +1,57 @@
#ifndef _RAR_CMDDATA_
#define _RAR_CMDDATA_
#define DefaultStoreList L"7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lz;lzh;mp3;rar;taz;tgz;xz;z;zip;zipx"
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
enum IS_PROCESS_FILE_FLAGS {IPFF_EXCLUDE_PARENT=1};
#define DefaultStoreList "7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;taz;tgz;z;zip"
class CommandData:public RAROptions
{
private:
void ProcessSwitchesString(const wchar *Str);
void ProcessSwitch(const wchar *Switch);
void BadSwitch(const wchar *Switch);
uint GetExclAttr(const wchar *Str,bool &Dir);
#if !defined(SFX_MODULE)
void SetTimeFilters(const wchar *Mod,bool Before,bool Age);
void SetStoreTimeMode(const wchar *S);
#endif
void ProcessSwitchesString(char *Str);
void ProcessSwitch(char *Switch);
void BadSwitch(char *Switch);
bool ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode);
uint GetExclAttr(char *Str);
bool FileLists;
bool NoMoreSwitches;
RAR_CMD_LIST_MODE ListMode;
bool TimeConverted;
bool BareOutput;
public:
CommandData();
~CommandData();
void Init();
void ParseCommandLine(bool Preprocess,int argc, char *argv[]);
void ParseArg(wchar *ArgW);
void Close();
void ParseArg(char *Arg,wchar *ArgW);
void ParseDone();
void ParseEnvVar();
void ReadConfig();
void PreprocessArg(const wchar *Arg);
void ReadConfig(int argc,char *argv[]);
bool IsConfigEnabled(int argc,char *argv[]);
void OutTitle();
void OutHelp(RAR_EXIT ExitCode);
void OutHelp();
bool IsSwitch(int Ch);
bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode);
bool ExclDirByAttr(uint FileAttr);
bool TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta);
bool SizeCheck(int64 Size);
bool AnyFiltersActive();
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
bool Flags,wchar *MatchedArg,uint MatchedArgSize);
bool ExclCheck(char *CheckName,bool CheckFullPath);
bool StoreCheck(char *CheckName);
bool TimeCheck(RarTime &ft);
bool SizeCheck(Int64 Size);
int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH);
void ProcessCommand();
void AddArcName(const wchar *Name);
bool GetArcName(wchar *Name,int MaxSize);
void AddArcName(char *Name,wchar *NameW);
bool GetArcName(char *Name,wchar *NameW,int MaxSize);
bool CheckWinSize();
int GetRecoverySize(const wchar *Str,int DefSize);
int GetRecoverySize(char *Str,int DefSize);
#ifndef SFX_MODULE
void ReportWrongSwitches(RARFORMAT Format);
#endif
char Command[NM+16];
wchar CommandW[NM+16];
wchar Command[NM+16];
char ArcName[NM];
wchar ArcNameW[NM];
wchar ArcName[NM];
StringList FileArgs;
StringList ExclArgs;
StringList InclArgs;
StringList ArcNames;
StringList StoreArgs;
StringList *FileArgs;
StringList *ExclArgs;
StringList *InclArgs;
StringList *ArcNames;
StringList *StoreArgs;
};
#endif
-352
View File
@@ -1,352 +0,0 @@
// Return 'true' if we need to exclude the file from processing as result
// of -x switch. If CheckInclList is true, we also check the file against
// the include list created with -n switch.
bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList)
{
if (CheckArgs(&ExclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
return true;
if (!CheckInclList || InclArgs.ItemsCount()==0)
return false;
if (CheckArgs(&InclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
return false;
return true;
}
bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode)
{
wchar *Name=ConvertPath(CheckName,NULL,0);
wchar FullName[NM];
wchar CurMask[NM];
*FullName=0;
Args->Rewind();
while (Args->GetString(CurMask,ASIZE(CurMask)))
{
wchar *LastMaskChar=PointToLastChar(CurMask);
bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only.
if (Dir)
{
// CheckName is a directory.
if (DirMask)
{
// We process the directory and have the directory exclusion mask.
// So let's convert "mask\" to "mask" and process it normally.
*LastMaskChar=0;
}
else
{
// REMOVED, we want -npath\* to match empty folders too.
// If mask has wildcards in name part and does not have the trailing
// '\' character, we cannot use it for directories.
// if (IsWildcard(PointToName(CurMask)))
// continue;
}
}
else
{
// If we process a file inside of directory excluded by "dirmask\".
// we want to exclude such file too. So we convert "dirmask\" to
// "dirmask\*". It is important for operations other than archiving
// with -x. When archiving with -x, directory matched by "dirmask\"
// is excluded from further scanning.
if (DirMask)
wcsncatz(CurMask,L"*",ASIZE(CurMask));
}
#ifndef SFX_MODULE
if (CheckFullPath && IsFullPath(CurMask))
{
// We do not need to do the special "*\" processing here, because
// 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.
if (*FullName==0)
ConvertNameToFull(CheckName,FullName,ASIZE(FullName));
if (CmpName(CurMask,FullName,MatchMode))
return true;
}
else
#endif
{
wchar NewName[NM+2],*CurName=Name;
// Important to convert before "*\" check below, so masks like
// d:*\something are processed properly.
wchar *CmpMask=ConvertPath(CurMask,NULL,0);
if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1]))
{
// We want "*\name" to match 'name' not only in subdirectories,
// but also in the current directory. We convert the name
// from 'name' to '.\name' to be matched by "*\" part even if it is
// in current directory.
NewName[0]='.';
NewName[1]=CPATHDIVIDER;
wcsncpyz(NewName+2,Name,ASIZE(NewName)-2);
CurName=NewName;
}
if (CmpName(CmpMask,CurName,MatchMode))
return true;
}
}
return false;
}
#ifndef SFX_MODULE
// Now this function performs only one task and only in Windows version:
// it skips symlinks to directories if -e1024 switch is specified.
// Symlinks are skipped in ScanTree class, so their entire contents
// is skipped too. Without this function we would check the attribute
// only directly before archiving, so we would skip the symlink record,
// but not the contents of symlinked directory.
bool CommandData::ExclDirByAttr(uint FileAttr)
{
#ifdef _WIN_ALL
if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 &&
(ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
return true;
#endif
return false;
}
#endif
#if !defined(SFX_MODULE)
void CommandData::SetTimeFilters(const wchar *Mod,bool Before,bool Age)
{
bool ModeOR=false,TimeMods=false;
const wchar *S=Mod;
// Check if any 'mca' modifiers are present, set OR mode if 'o' is present,
// skip modifiers and set S to beginning of time string. Be sure to check
// *S!=0, because termination 0 is a part of string for wcschr.
for (;*S!=0 && wcschr(L"MCAOmcao",*S)!=NULL;S++)
if (*S=='o' || *S=='O')
ModeOR=true;
else
TimeMods=true;
if (!TimeMods) // Assume 'm' if no modifiers are specified.
Mod=L"m";
// Set the specified time for every modifier. Be sure to check *Mod!=0,
// because termination 0 is a part of string for wcschr. This check is
// important when we set Mod to "m" above.
for (;*Mod!=0 && wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++)
switch(toupperw(*Mod))
{
case 'M':
if (Before)
{
Age ? FileMtimeBefore.SetAgeText(S):FileMtimeBefore.SetIsoText(S);
FileMtimeBeforeOR=ModeOR;
}
else
{
Age ? FileMtimeAfter.SetAgeText(S):FileMtimeAfter.SetIsoText(S);
FileMtimeAfterOR=ModeOR;
}
break;
case 'C':
if (Before)
{
Age ? FileCtimeBefore.SetAgeText(S):FileCtimeBefore.SetIsoText(S);
FileCtimeBeforeOR=ModeOR;
}
else
{
Age ? FileCtimeAfter.SetAgeText(S):FileCtimeAfter.SetIsoText(S);
FileCtimeAfterOR=ModeOR;
}
break;
case 'A':
if (Before)
{
Age ? FileAtimeBefore.SetAgeText(S):FileAtimeBefore.SetIsoText(S);
FileAtimeBeforeOR=ModeOR;
}
else
{
Age ? FileAtimeAfter.SetAgeText(S):FileAtimeAfter.SetIsoText(S);
FileAtimeAfterOR=ModeOR;
}
break;
}
}
#endif
#ifndef SFX_MODULE
// Return 'true' if we need to exclude the file from processing.
bool CommandData::TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta)
{
bool FilterOR=false;
if (FileMtimeBefore.IsSet()) // Filter present.
if (ftm>=FileMtimeBefore) // Condition not matched.
if (FileMtimeBeforeOR)
FilterOR=true; // Not matched OR filter is present.
else
return true; // Exclude file in AND mode.
else // Condition matched.
if (FileMtimeBeforeOR)
return false; // Include file in OR mode.
if (FileMtimeAfter.IsSet()) // Filter present.
if (ftm<FileMtimeAfter) // Condition not matched.
if (FileMtimeAfterOR)
FilterOR=true; // Not matched OR filter is present.
else
return true; // Exclude file in AND mode.
else // Condition matched.
if (FileMtimeAfterOR)
return false; // Include file in OR mode.
if (FileCtimeBefore.IsSet()) // Filter present.
if (ftc>=FileCtimeBefore) // Condition not matched.
if (FileCtimeBeforeOR)
FilterOR=true; // Not matched OR filter is present.
else
return true; // Exclude file in AND mode.
else // Condition matched.
if (FileCtimeBeforeOR)
return false; // Include file in OR mode.
if (FileCtimeAfter.IsSet()) // Filter present.
if (ftc<FileCtimeAfter) // Condition not matched.
if (FileCtimeAfterOR)
FilterOR=true; // Not matched OR filter is present.
else
return true; // Exclude file in AND mode.
else // Condition matched.
if (FileCtimeAfterOR)
return false; // Include file in OR mode.
if (FileAtimeBefore.IsSet()) // Filter present.
if (fta>=FileAtimeBefore) // Condition not matched.
if (FileAtimeBeforeOR)
FilterOR=true; // Not matched OR filter is present.
else
return true; // Exclude file in AND mode.
else // Condition matched.
if (FileAtimeBeforeOR)
return false; // Include file in OR mode.
if (FileAtimeAfter.IsSet()) // Filter present.
if (fta<FileAtimeAfter) // Condition not matched.
if (FileAtimeAfterOR)
FilterOR=true; // Not matched OR filter is present.
else
return true; // Exclude file in AND mode.
else // Condition matched.
if (FileAtimeAfterOR)
return false; // Include file in OR mode.
return FilterOR; // Exclude if all OR filters are not matched.
}
#endif
#ifndef SFX_MODULE
// Return 'true' if we need to exclude the file from processing.
bool CommandData::SizeCheck(int64 Size)
{
if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
return true;
if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
return true;
return false;
}
#endif
// Return 0 if file must not be processed or a number of matched parameter otherwise.
int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
bool Flags,wchar *MatchedArg,uint MatchedArgSize)
{
if (MatchedArg!=NULL && MatchedArgSize>0)
*MatchedArg=0;
bool Dir=FileHead.Dir;
if (ExclCheck(FileHead.FileName,Dir,false,true))
return 0;
#ifndef SFX_MODULE
if (TimeCheck(FileHead.mtime,FileHead.ctime,FileHead.atime))
return 0;
if ((FileHead.FileAttr & ExclFileAttr)!=0 || FileHead.Dir && ExclDir)
return 0;
if (InclAttrSet && (!FileHead.Dir && (FileHead.FileAttr & InclFileAttr)==0 ||
FileHead.Dir && !InclDir))
return 0;
if (!Dir && SizeCheck(FileHead.UnpSize))
return 0;
#endif
wchar *ArgName;
FileArgs.Rewind();
for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++)
if (CmpName(ArgName,FileHead.FileName,MatchType))
{
if (ExactMatch!=NULL)
*ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0;
if (MatchedArg!=NULL)
wcsncpyz(MatchedArg,ArgName,MatchedArgSize);
return StringCount;
}
return 0;
}
#if !defined(SFX_MODULE)
void CommandData::SetStoreTimeMode(const wchar *S)
{
if (*S==0 || IsDigit(*S) || *S=='-' || *S=='+')
{
// Apply -ts, -ts1, -ts-, -ts+ to all 3 times.
// Handle obsolete -ts[2,3,4] as ts+.
EXTTIME_MODE Mode=EXTTIME_MAX;
if (*S=='-')
Mode=EXTTIME_NONE;
if (*S=='1')
Mode=EXTTIME_1S;
xmtime=xctime=xatime=Mode;
S++;
}
while (*S!=0)
{
EXTTIME_MODE Mode=EXTTIME_MAX;
if (S[1]=='-')
Mode=EXTTIME_NONE;
if (S[1]=='1')
Mode=EXTTIME_1S;
switch(toupperw(*S))
{
case 'M':
xmtime=Mode;
break;
case 'C':
xctime=Mode;
break;
case 'A':
xatime=Mode;
break;
case 'P':
PreserveAtime=true;
break;
}
S++;
}
}
#endif
-118
View File
@@ -1,118 +0,0 @@
void CommandData::OutTitle()
{
if (BareOutput || DisableCopyright)
return;
#if defined(__GNUC__) && defined(SFX_MODULE)
mprintf(St(MCopyrightS));
#else
#ifndef SILENT
static bool TitleShown=false;
if (TitleShown)
return;
TitleShown=true;
wchar Version[80];
if (RARVER_BETA!=0)
swprintf(Version,ASIZE(Version),L"%d.%02d %ls %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA);
else
swprintf(Version,ASIZE(Version),L"%d.%02d",RARVER_MAJOR,RARVER_MINOR);
#if defined(_WIN_32) || defined(_WIN_64)
wcsncatz(Version,L" ",ASIZE(Version));
#endif
#ifdef _WIN_32
wcsncatz(Version,St(Mx86),ASIZE(Version));
#endif
#ifdef _WIN_64
wcsncatz(Version,St(Mx64),ASIZE(Version));
#endif
if (PrintVersion)
{
mprintf(L"%s",Version);
exit(0);
}
mprintf(St(MUCopyright),Version,RARVER_YEAR);
#endif
#endif
}
inline bool CmpMSGID(MSGID i1,MSGID i2)
{
#ifdef MSGID_INT
return i1==i2;
#else
// If MSGID is const char*, we cannot compare pointers only.
// Pointers to different instances of same string can differ,
// so we need to compare complete strings.
return wcscmp(i1,i2)==0;
#endif
}
void CommandData::OutHelp(RAR_EXIT ExitCode)
{
#if !defined(SILENT)
OutTitle();
static MSGID Help[]={
#ifdef SFX_MODULE
// Console SFX switches definition.
MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV
#else
// UnRAR switches definition.
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
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,
MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM,
MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,
MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,
MCHelpSwY
#endif
};
for (uint I=0;I<ASIZE(Help);I++)
{
#ifndef SFX_MODULE
if (CmpMSGID(Help[I],MCHelpSwV))
continue;
#ifndef _WIN_ALL
static MSGID Win32Only[]={
MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
MCHelpSwEP2,MCHelpSwOC,MCHelpSwONI,MCHelpSwDR,MCHelpSwRI
};
bool Found=false;
for (uint J=0;J<ASIZE(Win32Only);J++)
if (CmpMSGID(Help[I],Win32Only[J]))
{
Found=true;
break;
}
if (Found)
continue;
#endif
#if !defined(_UNIX) && !defined(_WIN_ALL)
if (CmpMSGID(Help[I],MCHelpSwOW))
continue;
#endif
#if !defined(_WIN_ALL) && !defined(_EMX)
if (CmpMSGID(Help[I],MCHelpSwAC))
continue;
#endif
#ifndef SAVE_LINKS
if (CmpMSGID(Help[I],MCHelpSwOL))
continue;
#endif
#ifndef RAR_SMP
if (CmpMSGID(Help[I],MCHelpSwMT))
continue;
#endif
#endif
mprintf(St(Help[I]));
}
mprintf(L"\n");
ErrHandler.Exit(ExitCode);
#endif
}
+1 -2
View File
@@ -17,10 +17,9 @@ void RangeCoder::InitDecoder(Unpack *UnpackRead)
}
// (int) cast before "low" added only to suppress compiler warnings.
#define ARI_DEC_NORMALIZE(code,low,range,read) \
{ \
while ((low^(low+range))<TOP || range<BOT && ((range=-(int)low&(BOT-1)),1)) \
while ((low^(low+range))<TOP || range<BOT && ((range=-low&(BOT-1)),1)) \
{ \
code=(code << 8) | read->GetChar(); \
range <<= 8; \
+1
View File
@@ -2,6 +2,7 @@
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
****************************************************************************/
const uint TOP=1 << 24, BOT=1 << 15;
class RangeCoder
{
+22 -45
View File
@@ -1,59 +1,36 @@
#ifndef _RAR_COMPRESS_
#define _RAR_COMPRESS_
// Combine pack and unpack constants to class to avoid polluting global
// namespace with numerous short names.
class PackDef
{
public:
// Maximum LZ match length we can encode even for short distances.
static const uint MAX_LZ_MATCH = 0x1001;
class ComprDataIO;
class PackingFileTable;
// We increment LZ match length for longer distances, because shortest
// matches are not allowed for them. Maximum length increment is 3
// for distances larger than 256KB (0x40000). Here we define the maximum
// incremented LZ match. Normally packer does not use it, but we must be
// ready to process it in corrupt archives.
static const uint MAX_INC_LZ_MATCH = MAX_LZ_MATCH + 3;
#define CODEBUFSIZE 0x4000
#define MAXWINSIZE 0x400000
#define MAXWINMASK (MAXWINSIZE-1)
static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
static const uint LOW_DIST_REP_COUNT = 16;
#define LOW_DIST_REP_COUNT 16
static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
static const uint DC = 64;
static const uint LDC = 16;
static const uint RC = 44;
static const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
static const uint BC = 20;
#define NC 299 /* alphabet = {0, 1, 2, ..., NC - 1} */
#define DC 60
#define LDC 17
#define RC 28
#define HUFF_TABLE_SIZE (NC+DC+RC+LDC)
#define BC 20
static const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
static const uint DC30 = 60;
static const uint LDC30 = 17;
static const uint RC30 = 28;
static const uint BC30 = 20;
static const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
#define DC20 48
#define RC20 28
#define BC20 19
#define MC20 257
static const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
static const uint DC20 = 48;
static const uint RC20 = 28;
static const uint BC20 = 19;
static const uint MC20 = 257;
// Largest alphabet size among all values listed above.
static const uint LARGEST_TABLE_SIZE = 306;
enum {
CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
};
};
enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA};
enum FilterType {
// These values must not be changed, because we use them directly
// in RAR5 compression and decompression code.
FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
FILTER_ITANIUM, FILTER_E8E9V2
};
#endif
+197 -261
View File
@@ -1,291 +1,219 @@
#include "rar.hpp"
#ifndef GUI
#include "log.cpp"
#endif
#if !defined(GUI) && !defined(SILENT)
static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
#endif
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
static RAR_CHARSET RedirectCharset=RCH_DEFAULT;
static bool Sound=false;
const int MaxMsgSize=2*NM+2048;
static bool StdoutRedirected=false,StderrRedirected=false,StdinRedirected=false;
#ifdef _WIN_ALL
static bool IsRedirected(DWORD nStdHandle)
{
HANDLE hStd=GetStdHandle(nStdHandle);
DWORD Mode;
return GetFileType(hStd)!=FILE_TYPE_CHAR || GetConsoleMode(hStd,&Mode)==0;
}
#endif
void InitConsole()
{
#ifdef _WIN_ALL
// We want messages like file names or progress percent to be printed
// immediately. Use only in Windows, in Unix they can cause wprintf %ls
// to fail with non-English strings.
setbuf(stdout,NULL);
setbuf(stderr,NULL);
// Detect if output is redirected and set output mode properly.
// We do not want to send Unicode output to files and especially to pipes
// like '|more', which cannot handle them correctly in Windows.
// In Unix console output is UTF-8 and it is handled correctly
// when redirecting, so no need to perform any adjustments.
StdoutRedirected=IsRedirected(STD_OUTPUT_HANDLE);
StderrRedirected=IsRedirected(STD_ERROR_HANDLE);
StdinRedirected=IsRedirected(STD_INPUT_HANDLE);
#ifdef _MSC_VER
if (!StdoutRedirected)
_setmode(_fileno(stdout), _O_U16TEXT);
if (!StderrRedirected)
_setmode(_fileno(stderr), _O_U16TEXT);
#endif
#elif defined(_UNIX)
StdoutRedirected=!isatty(fileno(stdout));
StderrRedirected=!isatty(fileno(stderr));
StdinRedirected=!isatty(fileno(stdin));
#endif
}
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream)
void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound)
{
::MsgStream=MsgStream;
::Sound=Sound;
}
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset)
{
::RedirectCharset=RedirectCharset;
}
#ifndef SILENT
static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist)
{
// This buffer is for format string only, not for entire output,
// so it can be short enough.
wchar fmtw[1024];
PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
#ifdef _WIN_ALL
safebuf wchar Msg[MaxMsgSize];
if (dest==stdout && StdoutRedirected || dest==stderr && StderrRedirected)
{
HANDLE hOut=GetStdHandle(dest==stdout ? STD_OUTPUT_HANDLE:STD_ERROR_HANDLE);
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
DWORD Written;
if (RedirectCharset==RCH_UNICODE)
WriteFile(hOut,Msg,(DWORD)wcslen(Msg)*sizeof(*Msg),&Written,NULL);
else
{
// Avoid Unicode for redirect in Windows, it does not work with pipes.
safebuf char MsgA[MaxMsgSize];
if (RedirectCharset==RCH_UTF8)
WideToUtf(Msg,MsgA,ASIZE(MsgA));
else
WideToChar(Msg,MsgA,ASIZE(MsgA));
if (RedirectCharset==RCH_DEFAULT || RedirectCharset==RCH_OEM)
CharToOemA(MsgA,MsgA); // Console tools like 'more' expect OEM encoding.
// We already converted \n to \r\n above, so we use WriteFile instead
// of C library to avoid unnecessary additional conversion.
WriteFile(hOut,MsgA,(DWORD)strlen(MsgA),&Written,NULL);
}
return;
}
// MSVC2008 vfwprintf writes every character to console separately
// and it is too slow. We use direct WriteConsole call instead.
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
HANDLE hOut=GetStdHandle(dest==stderr ? STD_ERROR_HANDLE:STD_OUTPUT_HANDLE);
DWORD Written;
WriteConsole(hOut,Msg,(DWORD)wcslen(Msg),&Written,NULL);
#else
vfwprintf(dest,fmtw,arglist);
// We do not use setbuf(NULL) in Unix (see comments in InitConsole).
fflush(dest);
#endif
}
void mprintf(const wchar *fmt,...)
#if !defined(GUI) && !defined(SILENT)
void mprintf(const char *fmt,...)
{
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
return;
fflush(stderr); // Ensure proper message order.
va_list arglist;
va_start(arglist,fmt);
FILE *dest=MsgStream==MSG_STDERR ? stderr:stdout;
cvt_wprintf(dest,fmt,arglist);
va_end(arglist);
safebuf char Msg[MaxMsgSize];
va_list argptr;
va_start(argptr,fmt);
vsprintf(Msg,fmt,argptr);
RawPrint(Msg,MsgStream);
va_end(argptr);
}
#endif
#ifndef SILENT
void eprintf(const wchar *fmt,...)
#if !defined(GUI) && !defined(SILENT)
void eprintf(const char *fmt,...)
{
if (MsgStream==MSG_NULL)
return;
safebuf char Msg[MaxMsgSize];
va_list argptr;
va_start(argptr,fmt);
vsprintf(Msg,fmt,argptr);
RawPrint(Msg,MSG_STDERR);
va_end(argptr);
}
#endif
fflush(stdout); // Ensure proper message order.
va_list arglist;
va_start(arglist,fmt);
cvt_wprintf(stderr,fmt,arglist);
va_end(arglist);
#if !defined(GUI) && !defined(SILENT)
void RawPrint(char *Msg,MESSAGE_TYPE MessageType)
{
File OutFile;
switch(MessageType)
{
case MSG_STDOUT:
OutFile.SetHandleType(FILE_HANDLESTD);
break;
case MSG_STDERR:
case MSG_ERRONLY:
OutFile.SetHandleType(FILE_HANDLEERR);
break;
default:
return;
}
#ifdef _WIN_32
CharToOem(Msg,Msg);
char OutMsg[MaxMsgSize],*OutPos=OutMsg;
for (int I=0;Msg[I]!=0;I++)
{
if (Msg[I]=='\n' && (I==0 || Msg[I-1]!='\r'))
*(OutPos++)='\r';
*(OutPos++)=Msg[I];
}
*OutPos=0;
strcpy(Msg,OutMsg);
#endif
#if defined(_UNIX) || defined(_EMX)
char OutMsg[MaxMsgSize],*OutPos=OutMsg;
for (int I=0;Msg[I]!=0;I++)
if (Msg[I]!='\r')
*(OutPos++)=Msg[I];
*OutPos=0;
strcpy(Msg,OutMsg);
#endif
OutFile.Write(Msg,strlen(Msg));
// OutFile.Flush();
}
#endif
#ifndef SILENT
static void GetPasswordText(wchar *Str,uint MaxLength)
void Alarm()
{
if (MaxLength==0)
return;
if (StdinRedirected)
getwstr(Str,MaxLength); // Read from pipe or redirected file.
else
{
#ifdef _WIN_ALL
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
DWORD ConInMode,ConOutMode;
DWORD Read=0;
GetConsoleMode(hConIn,&ConInMode);
GetConsoleMode(hConOut,&ConOutMode);
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
#ifndef SFX_MODULE
if (Sound)
putchar('\007');
#endif
}
#endif
ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL);
Str[Read]=0;
SetConsoleMode(hConIn,ConInMode);
SetConsoleMode(hConOut,ConOutMode);
#ifndef SILENT
#ifndef GUI
void GetPasswordText(char *Str,int MaxLength)
{
#ifdef _WIN_32
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
DWORD ConInMode,ConOutMode;
DWORD Read=0;
GetConsoleMode(hConIn,&ConInMode);
GetConsoleMode(hConOut,&ConOutMode);
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL);
Str[Read]=0;
OemToChar(Str,Str);
SetConsoleMode(hConIn,ConInMode);
SetConsoleMode(hConOut,ConOutMode);
#elif defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
fgets(Str,MaxLength-1,stdin);
#else
char StrA[MAXPASSWORD];
#if defined(_EMX) || defined (__VMS)
fgets(StrA,ASIZE(StrA)-1,stdin);
#elif defined(__sun)
strncpyz(StrA,getpassphrase(""),ASIZE(StrA));
#else
strncpyz(StrA,getpass(""),ASIZE(StrA));
strncpy(Str,getpass(""),MaxLength-1);
#endif
CharToWide(StrA,Str,MaxLength);
cleandata(StrA,sizeof(StrA));
#endif
}
Str[MaxLength-1]=0;
RemoveLF(Str);
}
#endif
#endif
#if !defined(GUI) && !defined(SILENT)
unsigned int GetKey()
{
#ifdef SILENT
return(0);
#else
char Str[80];
#ifdef __GNUC__
fgets(Str,sizeof(Str),stdin);
return(Str[0]);
#else
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
SrcFile.Read(Str,sizeof(Str));
return(Str[0]);
#endif
#endif
}
#endif
#ifndef SILENT
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength)
{
if (!StdinRedirected)
uiAlarm(UIALARM_QUESTION);
Alarm();
while (true)
{
if (!StdinRedirected)
if (Type==UIPASSWORD_GLOBAL)
eprintf(L"\n%s: ",St(MAskPsw));
else
eprintf(St(MAskPswFor),FileName);
wchar PlainPsw[MAXPASSWORD];
GetPasswordText(PlainPsw,ASIZE(PlainPsw));
if (*PlainPsw==0 && Type==UIPASSWORD_GLOBAL)
return false;
if (!StdinRedirected && Type==UIPASSWORD_GLOBAL)
char PromptStr[256];
#if defined(_EMX) || defined(_BEOS)
strcpy(PromptStr,St(MAskPswEcho));
#else
strcpy(PromptStr,St(MAskPsw));
#endif
if (Type!=PASSWORD_GLOBAL)
{
eprintf(St(MReAskPsw));
wchar CmpStr[MAXPASSWORD];
GetPasswordText(CmpStr,ASIZE(CmpStr));
if (*CmpStr==0 || wcscmp(PlainPsw,CmpStr)!=0)
strcat(PromptStr,St(MFor));
strcat(PromptStr,PointToName(FileName));
}
eprintf("\n%s: ",PromptStr);
GetPasswordText(Password,MaxLength);
if (*Password==0 && Type==PASSWORD_GLOBAL)
return(false);
if (Type==PASSWORD_GLOBAL)
{
strcpy(PromptStr,St(MReAskPsw));
eprintf(PromptStr);
char CmpStr[256];
GetPasswordText(CmpStr,sizeof(CmpStr));
if (*CmpStr==0 || strcmp(Password,CmpStr)!=0)
{
eprintf(St(MNotMatchPsw));
cleandata(PlainPsw,sizeof(PlainPsw));
cleandata(CmpStr,sizeof(CmpStr));
strcpy(PromptStr,St(MNotMatchPsw));
/*
#ifdef _WIN_32
CharToOem(PromptStr,PromptStr);
#endif
*/
eprintf(PromptStr);
memset(Password,0,MaxLength);
memset(CmpStr,0,sizeof(CmpStr));
continue;
}
cleandata(CmpStr,sizeof(CmpStr));
memset(CmpStr,0,sizeof(CmpStr));
}
Password->Set(PlainPsw);
cleandata(PlainPsw,sizeof(PlainPsw));
break;
}
return true;
return(true);
}
#endif
#ifndef SILENT
bool getwstr(wchar *str,size_t n)
#if !defined(GUI) && !defined(SILENT)
int Ask(const char *AskStr)
{
// Print buffered prompt title function before waiting for input.
fflush(stderr);
*str=0;
#if defined(_WIN_ALL)
// fgetws does not work well with non-English text in Windows,
// so we do not use it.
if (StdinRedirected) // ReadConsole does not work if redirected.
{
// fgets does not work well with pipes in Windows in our test.
// Let's use files.
Array<char> StrA(n*4); // Up to 4 UTF-8 characters per wchar_t.
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
int ReadSize=SrcFile.Read(&StrA[0],StrA.Size()-1);
if (ReadSize<=0)
{
// Looks like stdin is a null device. We can enter to infinite loop
// calling Ask(), so let's better exit.
ErrHandler.Exit(RARX_USERBREAK);
}
StrA[ReadSize]=0;
CharToWide(&StrA[0],str,n);
cleandata(&StrA[0],StrA.Size()); // We can use this function to enter passwords.
}
else
{
DWORD ReadSize=0;
if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),str,DWORD(n-1),&ReadSize,NULL)==0)
return false;
str[ReadSize]=0;
}
#else
if (fgetws(str,n,stdin)==NULL)
ErrHandler.Exit(RARX_USERBREAK); // Avoid infinite Ask() loop.
#endif
RemoveLF(str);
return true;
}
#endif
#ifndef SILENT
// We allow this function to return 0 in case of invalid input,
// because it might be convenient to press Enter to some not dangerous
// prompts like "insert disk with next volume". We should call this function
// again in case of 0 in dangerous prompt such as overwriting file.
int Ask(const wchar *AskStr)
{
uiAlarm(UIALARM_QUESTION);
const int MaxItems=10;
wchar Item[MaxItems][40];
char Item[MaxItems][40];
int ItemKeyPos[MaxItems],NumItems=0;
for (const wchar *NextItem=AskStr;NextItem!=NULL;NextItem=wcschr(NextItem+1,'_'))
for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
{
wchar *CurItem=Item[NumItems];
wcsncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
wchar *EndItem=wcschr(CurItem,'_');
char *CurItem=Item[NumItems];
strncpy(CurItem,NextItem+1,sizeof(Item[0]));
char *EndItem=strchr(CurItem,'_');
if (EndItem!=NULL)
*EndItem=0;
int KeyPos=0,CurKey;
@@ -293,7 +221,7 @@ int Ask(const wchar *AskStr)
{
bool Found=false;
for (int I=0;I<NumItems && !Found;I++)
if (toupperw(Item[I][ItemKeyPos[I]])==toupperw(CurKey))
if (loctoupper(Item[I][ItemKeyPos[I]])==loctoupper(CurKey))
Found=true;
if (!Found && CurKey!=' ')
break;
@@ -305,53 +233,61 @@ int Ask(const wchar *AskStr)
for (int I=0;I<NumItems;I++)
{
eprintf(I==0 ? (NumItems>4 ? L"\n":L" "):L", ");
eprintf(I==0 ? (NumItems>4 ? "\n":" "):", ");
int KeyPos=ItemKeyPos[I];
for (int J=0;J<KeyPos;J++)
eprintf(L"%c",Item[I][J]);
eprintf(L"[%c]%ls",Item[I][KeyPos],&Item[I][KeyPos+1]);
eprintf("%c",Item[I][J]);
eprintf("[%c]%s",Item[I][KeyPos],&Item[I][KeyPos+1]);
}
eprintf(L" ");
wchar Str[50];
getwstr(Str,ASIZE(Str));
wchar Ch=toupperw(Str[0]);
eprintf(" ");
int Ch=GetKey();
#if defined(_WIN_32)
OemToCharBuff((LPCSTR)&Ch,(LPTSTR)&Ch,1);
#endif
Ch=loctoupper(Ch);
for (int I=0;I<NumItems;I++)
if (Ch==Item[I][ItemKeyPos[I]])
return I+1;
return 0;
return(I+1);
return(0);
}
#endif
static bool IsCommentUnsafe(const wchar *Data,size_t Size)
int KbdAnsi(char *Addr,int Size)
{
for (size_t I=0;I<Size;I++)
if (Data[I]==27 && Data[I+1]=='[')
for (size_t J=I+2;J<Size;J++)
int RetCode=0;
#ifndef GUI
for (int I=0;I<Size;I++)
if (Addr[I]==27 && Addr[I+1]=='[')
{
for (int J=I+2;J<Size;J++)
{
// Return true for <ESC>[{key};"{string}"p used to redefine
// a keyboard key on some terminals.
if (Data[J]=='\"')
return true;
if (!IsDigit(Data[J]) && Data[J]!=';')
if (Addr[J]=='\"')
return(2);
if (!isdigit(Addr[J]) && Addr[J]!=';')
break;
}
return false;
RetCode=1;
}
#endif
return(RetCode);
}
void OutComment(const wchar *Comment,size_t Size)
void OutComment(char *Comment,int Size)
{
if (IsCommentUnsafe(Comment,Size))
#ifndef GUI
if (KbdAnsi(Comment,Size)==2)
return;
const size_t MaxOutSize=0x400;
for (size_t I=0;I<Size;I+=MaxOutSize)
const int MaxOutSize=0x400;
for (int I=0;I<Size;I+=MaxOutSize)
{
wchar Msg[MaxOutSize+1];
size_t CopySize=Min(MaxOutSize,Size-I);
wcsncpy(Msg,Comment+I,CopySize);
char Msg[MaxOutSize+1];
int CopySize=Min(MaxOutSize,Size-I);
strncpy(Msg,Comment+I,CopySize);
Msg[CopySize]=0;
mprintf(L"%s",Msg);
mprintf("%s",Msg);
}
mprintf(L"\n");
mprintf("\n");
#endif
}
+34 -15
View File
@@ -1,27 +1,46 @@
#ifndef _RAR_CONSIO_
#define _RAR_CONSIO_
void InitConsole();
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream);
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset);
void OutComment(const wchar *Comment,size_t Size);
enum {ALARM_SOUND,ERROR_SOUND,QUESTION_SOUND};
enum PASSWORD_TYPE {PASSWORD_GLOBAL,PASSWORD_FILE,PASSWORD_ARCHIVE};
void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound);
#ifndef SILENT
bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password);
void mprintf(const char *fmt,...);
void eprintf(const char *fmt,...);
void Alarm();
void GetPasswordText(char *Str,int MaxLength);
unsigned int GetKey();
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength);
int Ask(const char *AskStr);
#endif
int KbdAnsi(char *Addr,int Size);
void OutComment(char *Comment,int Size);
#ifdef SILENT
inline void mprintf(const wchar *fmt,...) {}
inline void eprintf(const wchar *fmt,...) {}
inline void Alarm() {}
inline int Ask(const wchar *AskStr) {return 0;}
inline bool getwstr(wchar *str,size_t n) {return false;}
#ifdef __GNUC__
#define mprintf(args...)
#define eprintf(args...)
#else
void mprintf(const wchar *fmt,...);
void eprintf(const wchar *fmt,...);
void Alarm();
int Ask(const wchar *AskStr);
bool getwstr(wchar *str,size_t n);
#ifdef _MSC_VER
inline void mprintf(const char *fmt,...) {}
#else
inline void mprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
#endif
inline void eprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
inline void mprintf(const char *fmt,int b) {}
inline void eprintf(const char *fmt,int b) {}
inline void mprintf(const char *fmt,const char *a,int b) {}
inline void eprintf(const char *fmt,const char *a,int b) {}
#endif
inline void Alarm() {}
inline void GetPasswordText(char *Str,int MaxLength) {}
inline unsigned int GetKey() {return(0);}
inline bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength) {return(false);}
inline int Ask(const char *AskStr) {return(0);}
#endif
#endif
+35 -76
View File
@@ -1,102 +1,61 @@
// 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"
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
uint CRCTab[256];
// Build the classic CRC32 lookup table.
// We also provide this function to legacy RAR and ZIP decryption code.
void InitCRC32(uint *CRCTab)
void InitCRC()
{
if (CRCTab[1]!=0)
return;
for (uint I=0;I<256;I++)
for (int I=0;I<256;I++)
{
uint C=I;
for (uint J=0;J<8;J++)
C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
for (int J=0;J<8;J++)
C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
CRCTab[I]=C;
}
}
static void InitTables()
{
InitCRC32(crc_tables[0]);
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;
}
}
}
struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32;
uint CRC32(uint StartCRC,const void *Addr,size_t Size)
uint CRC(uint StartCRC,const void *Addr,uint Size)
{
if (CRCTab[1]==0)
InitCRC();
byte *Data=(byte *)Addr;
// Align Data to 8 for better performance.
for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
for (;Size>=8;Size-=8,Data+=8)
#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
while (Size>0 && ((long)Data & 7))
{
#ifdef BIG_ENDIAN
StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
#else
StartCRC ^= *(uint32 *) Data;
uint NextData = *(uint32 *) (Data+4);
#endif
StartCRC = crc_tables[7][(byte) StartCRC ] ^
crc_tables[6][(byte)(StartCRC >> 8) ] ^
crc_tables[5][(byte)(StartCRC >> 16)] ^
crc_tables[4][(byte)(StartCRC >> 24)] ^
crc_tables[3][(byte) NextData ] ^
crc_tables[2][(byte)(NextData >> 8) ] ^
crc_tables[1][(byte)(NextData >> 16)] ^
crc_tables[0][(byte)(NextData >> 24)];
StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8);
Size--;
Data++;
}
for (;Size>0;Size--,Data++) // Process left data.
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
return StartCRC;
while (Size>=8)
{
StartCRC^=*(uint32 *)Data;
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
StartCRC^=*(uint32 *)(Data+4);
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
Data+=8;
Size-=8;
}
#endif
for (int 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 Checksum14(ushort StartCRC,const void *Addr,size_t Size)
ushort OldCRC(ushort StartCRC,const void *Addr,uint Size)
{
byte *Data=(byte *)Addr;
for (size_t I=0;I<Size;I++)
for (int I=0;I<Size;I++)
{
StartCRC=(StartCRC+Data[I])&0xffff;
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
}
return StartCRC;
return(StartCRC);
}
#endif
+4 -9
View File
@@ -1,15 +1,10 @@
#ifndef _RAR_CRC_
#define _RAR_CRC_
// This function is only to intialize external CRC tables. We do not need to
// call it before calculating CRC32.
void InitCRC32(uint *CRCTab);
uint CRC32(uint StartCRC,const void *Addr,size_t Size);
#ifndef SFX_MODULE
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size);
#endif
extern uint CRCTab[256];
void InitCRC();
uint CRC(uint StartCRC,const void *Addr,uint Size);
ushort OldCRC(ushort StartCRC,const void *Addr,uint Size);
#endif
+350 -103
View File
@@ -1,134 +1,381 @@
#include "rar.hpp"
#ifndef SFX_MODULE
#include "crypt1.cpp"
#include "crypt2.cpp"
extern uint CRCTab[256];
#endif
#include "crypt3.cpp"
#include "crypt5.cpp"
#define NROUNDS 32
#define rol(x,n,xsize) (((x)<<(n)) | ((x)>>(xsize-(n))))
#define ror(x,n,xsize) (((x)>>(n)) | ((x)<<(xsize-(n))))
#define substLong(t) ( (uint)SubstTable[(uint)t&255] | \
((uint)SubstTable[(int)(t>> 8)&255]<< 8) | \
((uint)SubstTable[(int)(t>>16)&255]<<16) | \
((uint)SubstTable[(int)(t>>24)&255]<<24) )
CryptKeyCacheItem CryptData::Cache[4];
int CryptData::CachePos=0;
CryptData::CryptData()
#ifndef SFX_MODULE
static byte InitSubstTable[256]={
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
};
#endif
void CryptData::DecryptBlock(byte *Buf,int Size)
{
Method=CRYPT_NONE;
memset(KDF3Cache,0,sizeof(KDF3Cache));
memset(KDF5Cache,0,sizeof(KDF5Cache));
KDF3CachePos=0;
KDF5CachePos=0;
memset(CRCTab,0,sizeof(CRCTab));
rin.blockDecrypt(Buf,Size,Buf);
}
CryptData::~CryptData()
#ifndef SFX_MODULE
void CryptData::EncryptBlock20(byte *Buf)
{
cleandata(KDF3Cache,sizeof(KDF3Cache));
cleandata(KDF5Cache,sizeof(KDF5Cache));
uint A,B,C,D,T,TA,TB;
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0];
B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1];
C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2];
D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3];
#else
uint32 *BufPtr=(uint32 *)Buf;
A=BufPtr[0]^Key[0];
B=BufPtr[1]^Key[1];
C=BufPtr[2]^Key[2];
D=BufPtr[3]^Key[3];
#endif
for(int I=0;I<NROUNDS;I++)
{
T=((C+rol(D,11,32))^Key[I&3]);
TA=A^substLong(T);
T=((D^rol(C,17,32))+Key[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
C^=Key[0];
Buf[0]=(byte)C;
Buf[1]=(byte)(C>>8);
Buf[2]=(byte)(C>>16);
Buf[3]=(byte)(C>>24);
D^=Key[1];
Buf[4]=(byte)D;
Buf[5]=(byte)(D>>8);
Buf[6]=(byte)(D>>16);
Buf[7]=(byte)(D>>24);
A^=Key[2];
Buf[8]=(byte)A;
Buf[9]=(byte)(A>>8);
Buf[10]=(byte)(A>>16);
Buf[11]=(byte)(A>>24);
B^=Key[3];
Buf[12]=(byte)B;
Buf[13]=(byte)(B>>8);
Buf[14]=(byte)(B>>16);
Buf[15]=(byte)(B>>24);
#else
BufPtr[0]=C^Key[0];
BufPtr[1]=D^Key[1];
BufPtr[2]=A^Key[2];
BufPtr[3]=B^Key[3];
#endif
UpdKeys(Buf);
}
void CryptData::DecryptBlock(byte *Buf,size_t Size)
void CryptData::DecryptBlock20(byte *Buf)
{
switch(Method)
byte InBuf[16];
uint A,B,C,D,T,TA,TB;
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0];
B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1];
C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2];
D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3];
#else
uint32 *BufPtr=(uint32 *)Buf;
A=BufPtr[0]^Key[0];
B=BufPtr[1]^Key[1];
C=BufPtr[2]^Key[2];
D=BufPtr[3]^Key[3];
#endif
memcpy(InBuf,Buf,sizeof(InBuf));
for(int I=NROUNDS-1;I>=0;I--)
{
T=((C+rol(D,11,32))^Key[I&3]);
TA=A^substLong(T);
T=((D^rol(C,17,32))+Key[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
C^=Key[0];
Buf[0]=(byte)C;
Buf[1]=(byte)(C>>8);
Buf[2]=(byte)(C>>16);
Buf[3]=(byte)(C>>24);
D^=Key[1];
Buf[4]=(byte)D;
Buf[5]=(byte)(D>>8);
Buf[6]=(byte)(D>>16);
Buf[7]=(byte)(D>>24);
A^=Key[2];
Buf[8]=(byte)A;
Buf[9]=(byte)(A>>8);
Buf[10]=(byte)(A>>16);
Buf[11]=(byte)(A>>24);
B^=Key[3];
Buf[12]=(byte)B;
Buf[13]=(byte)(B>>8);
Buf[14]=(byte)(B>>16);
Buf[15]=(byte)(B>>24);
#else
BufPtr[0]=C^Key[0];
BufPtr[1]=D^Key[1];
BufPtr[2]=A^Key[2];
BufPtr[3]=B^Key[3];
#endif
UpdKeys(InBuf);
}
void CryptData::UpdKeys(byte *Buf)
{
for (int I=0;I<16;I+=4)
{
Key[0]^=CRCTab[Buf[I]];
Key[1]^=CRCTab[Buf[I+1]];
Key[2]^=CRCTab[Buf[I+2]];
Key[3]^=CRCTab[Buf[I+3]];
}
}
void CryptData::Swap(byte *Ch1,byte *Ch2)
{
byte Ch=*Ch1;
*Ch1=*Ch2;
*Ch2=Ch;
}
#endif
void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
{
if (*Password==0)
return;
if (OldOnly)
{
#ifndef SFX_MODULE
case CRYPT_RAR13:
Decrypt13(Buf,Size);
break;
case CRYPT_RAR15:
Crypt15(Buf,Size);
break;
case CRYPT_RAR20:
for (size_t I=0;I<Size;I+=CRYPT_BLOCK_SIZE)
DecryptBlock20(Buf+I);
break;
if (CRCTab[1]==0)
InitCRC();
byte Psw[MAXPASSWORD];
SetOldKeys(Password);
Key[0]=0xD3A3B879L;
Key[1]=0x3F6D12F7L;
Key[2]=0x7515A235L;
Key[3]=0xA4E7F123L;
memset(Psw,0,sizeof(Psw));
#if defined(_WIN_32) && !defined(GUI)
CharToOemBuff(Password,(char*)Psw,strlen(Password));
#else
strncpy((char *)Psw,Password,MAXPASSWORD-1);
#endif
case CRYPT_RAR30:
case CRYPT_RAR50:
rin.blockDecrypt(Buf,Size,Buf);
break;
int PswLength=strlen(Password);
memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
for (int J=0;J<256;J++)
for (int I=0;I<PswLength;I+=2)
{
uint N1=(byte)CRCTab[(Psw[I]-J)&0xff];
uint N2=(byte)CRCTab[(Psw[I+1]+J)&0xff];
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]);
}
for (int I=0;I<PswLength;I+=16)
EncryptBlock20(&Psw[I]);
#endif
return;
}
bool Cached=false;
for (int I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++)
if (strcmp(Cache[I].Password,Password)==0 &&
(Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&
Cache[I].HandsOffHash==HandsOffHash)
{
memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey));
memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit));
Cached=true;
break;
}
if (!Cached)
{
wchar PswW[MAXPASSWORD];
CharToWide(Password,PswW,MAXPASSWORD-1);
PswW[MAXPASSWORD-1]=0;
byte RawPsw[2*MAXPASSWORD+SALT_SIZE];
WideToRaw(PswW,RawPsw);
int RawLength=2*strlenw(PswW);
if (Salt!=NULL)
{
memcpy(RawPsw+RawLength,Salt,SALT_SIZE);
RawLength+=SALT_SIZE;
}
hash_context c;
hash_initial(&c);
const int HashRounds=0x40000;
for (int I=0;I<HashRounds;I++)
{
hash_process( &c, RawPsw, RawLength, HandsOffHash);
byte PswNum[3];
PswNum[0]=(byte)I;
PswNum[1]=(byte)(I>>8);
PswNum[2]=(byte)(I>>16);
hash_process( &c, PswNum, 3, HandsOffHash);
if (I%(HashRounds/16)==0)
{
hash_context tempc=c;
uint32 digest[5];
hash_final( &tempc, digest, HandsOffHash);
AESInit[I/(HashRounds/16)]=(byte)digest[4];
}
}
uint32 digest[5];
hash_final( &c, digest, HandsOffHash);
for (int I=0;I<4;I++)
for (int J=0;J<4;J++)
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
strcpy(Cache[CachePos].Password,Password);
if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true)
memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE);
Cache[CachePos].HandsOffHash=HandsOffHash;
memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey));
memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit));
CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0]));
}
rin.init(Encrypt ? Rijndael::Encrypt : Rijndael::Decrypt,AESKey,AESInit);
}
bool CryptData::SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,
SecPassword *Password,const byte *Salt,
const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck)
{
if (!Password->IsSet() || Method==CRYPT_NONE)
return false;
CryptData::Method=Method;
wchar PwdW[MAXPASSWORD];
Password->Get(PwdW,ASIZE(PwdW));
char PwdA[MAXPASSWORD];
WideToChar(PwdW,PwdA,ASIZE(PwdA));
switch(Method)
{
#ifndef SFX_MODULE
case CRYPT_RAR13:
SetKey13(PwdA);
break;
case CRYPT_RAR15:
SetKey15(PwdA);
break;
case CRYPT_RAR20:
SetKey20(PwdA);
break;
#endif
case CRYPT_RAR30:
SetKey30(Encrypt,Password,PwdW,Salt);
break;
case CRYPT_RAR50:
SetKey50(Encrypt,Password,PwdW,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
break;
}
cleandata(PwdA,sizeof(PwdA));
cleandata(PwdW,sizeof(PwdW));
return true;
}
// Use the current system time to additionally randomize data.
static void TimeRandomize(byte *RndBuf,size_t BufSize)
void CryptData::SetOldKeys(char *Password)
{
static uint Count=0;
RarTime CurTime;
CurTime.SetCurrentTime();
uint64 Random=CurTime.GetWin()+clock();
for (size_t I=0;I<BufSize;I++)
uint PswCRC=CRC(0xffffffff,Password,strlen(Password));
OldKey[0]=PswCRC&0xffff;
OldKey[1]=(PswCRC>>16)&0xffff;
OldKey[2]=OldKey[3]=0;
PN1=PN2=PN3=0;
byte Ch;
while ((Ch=*Password)!=0)
{
byte RndByte = byte (Random >> ( (I & 7) * 8 ));
RndBuf[I]=byte( (RndByte ^ I) + Count++);
PN1+=Ch;
PN2^=Ch;
PN3+=Ch;
PN3=(byte)rol(PN3,1,8);
OldKey[2]^=Ch^CRCTab[Ch];
OldKey[3]+=Ch+(CRCTab[Ch]>>16);
Password++;
}
}
// Fill buffer with random data.
void GetRnd(byte *RndBuf,size_t BufSize)
void CryptData::SetAV15Encryption()
{
bool Success=false;
#if defined(_WIN_ALL)
HCRYPTPROV hProvider = 0;
if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
{
Success=CryptGenRandom(hProvider, (DWORD)BufSize, RndBuf) == TRUE;
CryptReleaseContext(hProvider, 0);
}
#elif defined(_UNIX)
FILE *rndf = fopen("/dev/urandom", "r");
if (rndf!=NULL)
{
Success=fread(RndBuf, BufSize, 1, rndf) == BufSize;
fclose(rndf);
}
#endif
// We use this code only as the last resort if code above failed.
if (!Success)
TimeRandomize(RndBuf,BufSize);
OldKey[0]=0x4765;
OldKey[1]=0x9021;
OldKey[2]=0x7382;
OldKey[3]=0x5215;
}
void CryptData::SetCmt13Encryption()
{
PN1=0;
PN2=7;
PN3=77;
}
void CryptData::Crypt(byte *Data,uint Count,int Method)
{
if (Method==OLD_DECODE)
Decode13(Data,Count);
else
if (Method==OLD_ENCODE)
Encode13(Data,Count);
else
Crypt15(Data,Count);
}
void CryptData::Encode13(byte *Data,uint Count)
{
while (Count--)
{
PN2+=PN3;
PN1+=PN2;
*Data+=PN1;
Data++;
}
}
void CryptData::Decode13(byte *Data,uint Count)
{
while (Count--)
{
PN2+=PN3;
PN1+=PN2;
*Data-=PN1;
Data++;
}
}
void CryptData::Crypt15(byte *Data,uint Count)
{
while (Count--)
{
OldKey[0]+=0x1234;
OldKey[1]^=CRCTab[(OldKey[0] & 0x1fe)>>1];
OldKey[2]-=CRCTab[(OldKey[0] & 0x1fe)>>1]>>16;
OldKey[0]^=OldKey[2];
OldKey[3]=ror(OldKey[3]&0xffff,1,16)^OldKey[1];
OldKey[3]=ror(OldKey[3]&0xffff,1,16);
OldKey[0]^=OldKey[3];
*Data^=(byte)(OldKey[0]>>8);
Data++;
}
}
#endif
+43 -82
View File
@@ -1,101 +1,62 @@
#ifndef _RAR_CRYPT_
#define _RAR_CRYPT_
enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
enum CRYPT_METHOD {
CRYPT_NONE,CRYPT_RAR13,CRYPT_RAR15,CRYPT_RAR20,CRYPT_RAR30,CRYPT_RAR50
struct CryptKeyCacheItem
{
#ifndef _SFX_RTL_
CryptKeyCacheItem()
{
*Password=0;
}
~CryptKeyCacheItem()
{
memset(AESKey,0,sizeof(AESKey));
memset(AESInit,0,sizeof(AESInit));
memset(Password,0,sizeof(Password));
}
#endif
byte AESKey[16],AESInit[16];
char Password[MAXPASSWORD];
bool SaltPresent;
byte Salt[SALT_SIZE];
bool HandsOffHash;
};
#define SIZE_SALT50 16
#define SIZE_SALT30 8
#define SIZE_INITV 16
#define SIZE_PSWCHECK 8
#define SIZE_PSWCHECK_CSUM 4
#define CRYPT_BLOCK_SIZE 16
#define CRYPT_BLOCK_MASK (CRYPT_BLOCK_SIZE-1) // 0xf
#define CRYPT5_KDF_LG2_COUNT 15 // LOG2 of PDKDF2 iteration count.
#define CRYPT5_KDF_LG2_COUNT_MAX 24 // LOG2 of maximum accepted iteration count.
#define CRYPT_VERSION 0 // Supported encryption version.
class CryptData
{
struct KDF5CacheItem
{
SecPassword Pwd;
byte Salt[SIZE_SALT50];
byte Key[32];
uint Lg2Count; // Log2 of PBKDF2 repetition count.
byte PswCheckValue[SHA256_DIGEST_SIZE];
byte HashKeyValue[SHA256_DIGEST_SIZE];
};
struct KDF3CacheItem
{
SecPassword Pwd;
byte Salt[SIZE_SALT30];
byte Key[16];
byte Init[16];
bool SaltPresent;
};
private:
void SetKey13(const char *Password);
void Decrypt13(byte *Data,size_t Count);
void SetKey15(const char *Password);
void Crypt15(byte *Data,size_t Count);
void SetKey20(const char *Password);
void Swap20(byte *Ch1,byte *Ch2);
void UpdKeys20(byte *Buf);
void EncryptBlock20(byte *Buf);
void DecryptBlock20(byte *Buf);
void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt);
void SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck);
KDF3CacheItem KDF3Cache[4];
uint KDF3CachePos;
KDF5CacheItem KDF5Cache[4];
uint KDF5CachePos;
CRYPT_METHOD Method;
void Encode13(byte *Data,uint Count);
void Decode13(byte *Data,uint Count);
void Crypt15(byte *Data,uint Count);
void UpdKeys(byte *Buf);
void Swap(byte *Ch1,byte *Ch2);
void SetOldKeys(char *Password);
Rijndael rin;
uint CRCTab[256]; // For RAR 1.5 and RAR 2.0 encryption.
byte SubstTable20[256];
uint Key20[4];
byte SubstTable[256];
uint Key[4];
ushort OldKey[4];
byte PN1,PN2,PN3;
byte Key13[3];
ushort Key15[4];
byte AESKey[16],AESInit[16];
static CryptKeyCacheItem Cache[4];
static int CachePos;
public:
CryptData();
~CryptData();
bool SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
const byte *Salt,const byte *InitV,uint Lg2Cnt,
byte *HashKey,byte *PswCheck);
void SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
void SetAV15Encryption();
void SetCmt13Encryption();
void EncryptBlock(byte *Buf,size_t Size);
void DecryptBlock(byte *Buf,size_t Size);
static void SetSalt(byte *Salt,size_t SaltSize);
void EncryptBlock20(byte *Buf);
void DecryptBlock20(byte *Buf);
void EncryptBlock(byte *Buf,int Size);
void DecryptBlock(byte *Buf,int Size);
void Crypt(byte *Data,uint Count,int Method);
static void SetSalt(byte *Salt,int SaltSize);
};
void GetRnd(byte *RndBuf,size_t BufSize);
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
size_t DataLength,byte *ResDigest);
void pbkdf2(const byte *pass, size_t pass_len, const byte *salt,
size_t salt_len,byte *key, byte *Value1, byte *Value2,
uint rounds);
void ConvertHashToMAC(HashValue *Value,byte *Key);
#endif
-79
View File
@@ -1,79 +0,0 @@
extern uint CRCTab[256];
void CryptData::SetKey13(const char *Password)
{
Key13[0]=Key13[1]=Key13[2]=0;
for (size_t I=0;Password[I]!=0;I++)
{
byte P=Password[I];
Key13[0]+=P;
Key13[1]^=P;
Key13[2]+=P;
Key13[2]=(byte)rotls(Key13[2],1,8);
}
}
void CryptData::SetKey15(const char *Password)
{
InitCRC32(CRCTab);
uint PswCRC=CRC32(0xffffffff,Password,strlen(Password));
Key15[0]=PswCRC&0xffff;
Key15[1]=(PswCRC>>16)&0xffff;
Key15[2]=Key15[3]=0;
for (size_t I=0;Password[I]!=0;I++)
{
byte P=Password[I];
Key15[2]^=P^CRCTab[P];
Key15[3]+=P+(CRCTab[P]>>16);
}
}
void CryptData::SetAV15Encryption()
{
InitCRC32(CRCTab);
Method=CRYPT_RAR15;
Key15[0]=0x4765;
Key15[1]=0x9021;
Key15[2]=0x7382;
Key15[3]=0x5215;
}
void CryptData::SetCmt13Encryption()
{
Method=CRYPT_RAR13;
Key13[0]=0;
Key13[1]=7;
Key13[2]=77;
}
void CryptData::Decrypt13(byte *Data,size_t Count)
{
while (Count--)
{
Key13[1]+=Key13[2];
Key13[0]+=Key13[1];
*Data-=Key13[0];
Data++;
}
}
void CryptData::Crypt15(byte *Data,size_t Count)
{
while (Count--)
{
Key15[0]+=0x1234;
Key15[1]^=CRCTab[(Key15[0] & 0x1fe)>>1];
Key15[2]-=CRCTab[(Key15[0] & 0x1fe)>>1]>>16;
Key15[0]^=Key15[2];
Key15[3]=rotrs(Key15[3]&0xffff,1,16)^Key15[1];
Key15[3]=rotrs(Key15[3]&0xffff,1,16);
Key15[0]^=Key15[3];
*Data^=(byte)(Key15[0]>>8);
Data++;
}
}
-133
View File
@@ -1,133 +0,0 @@
#define NROUNDS 32
#define substLong(t) ( (uint)SubstTable20[(uint)t&255] | \
((uint)SubstTable20[(int)(t>> 8)&255]<< 8) | \
((uint)SubstTable20[(int)(t>>16)&255]<<16) | \
((uint)SubstTable20[(int)(t>>24)&255]<<24) )
static byte InitSubstTable20[256]={
215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42,
232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,
255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6,
71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,
107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,
158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,
97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,
164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,
207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7,
122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,
131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,
224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,
118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108,
161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,
0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52,
116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
};
void CryptData::SetKey20(const char *Password)
{
InitCRC32(CRCTab);
char Psw[MAXPASSWORD];
strncpyz(Psw,Password,ASIZE(Psw)); // We'll need to modify it below.
size_t PswLength=strlen(Psw);
Key20[0]=0xD3A3B879L;
Key20[1]=0x3F6D12F7L;
Key20[2]=0x7515A235L;
Key20[3]=0xA4E7F123L;
memcpy(SubstTable20,InitSubstTable20,sizeof(SubstTable20));
for (uint J=0;J<256;J++)
for (size_t I=0;I<PswLength;I+=2)
{
uint N1=(byte)CRCTab [ (byte(Password[I]) - J) &0xff];
uint N2=(byte)CRCTab [ (byte(Password[I+1]) + J) &0xff];
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
Swap20(&SubstTable20[N1],&SubstTable20[(N1+I+K)&0xff]);
}
// Incomplete last block of password must be zero padded.
if ((PswLength & CRYPT_BLOCK_MASK)!=0)
for (size_t I=PswLength;I<=(PswLength|CRYPT_BLOCK_MASK);I++)
Psw[I]=0;
for (size_t I=0;I<PswLength;I+=CRYPT_BLOCK_SIZE)
EncryptBlock20((byte *)Psw+I);
}
void CryptData::EncryptBlock20(byte *Buf)
{
uint A,B,C,D,T,TA,TB;
A=RawGet4(Buf+0)^Key20[0];
B=RawGet4(Buf+4)^Key20[1];
C=RawGet4(Buf+8)^Key20[2];
D=RawGet4(Buf+12)^Key20[3];
for(int I=0;I<NROUNDS;I++)
{
T=((C+rotls(D,11,32))^Key20[I&3]);
TA=A^substLong(T);
T=((D^rotls(C,17,32))+Key20[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
RawPut4(C^Key20[0],Buf+0);
RawPut4(D^Key20[1],Buf+4);
RawPut4(A^Key20[2],Buf+8);
RawPut4(B^Key20[3],Buf+12);
UpdKeys20(Buf);
}
void CryptData::DecryptBlock20(byte *Buf)
{
byte InBuf[16];
uint A,B,C,D,T,TA,TB;
A=RawGet4(Buf+0)^Key20[0];
B=RawGet4(Buf+4)^Key20[1];
C=RawGet4(Buf+8)^Key20[2];
D=RawGet4(Buf+12)^Key20[3];
memcpy(InBuf,Buf,sizeof(InBuf));
for(int I=NROUNDS-1;I>=0;I--)
{
T=((C+rotls(D,11,32))^Key20[I&3]);
TA=A^substLong(T);
T=((D^rotls(C,17,32))+Key20[I&3]);
TB=B^substLong(T);
A=C;
B=D;
C=TA;
D=TB;
}
RawPut4(C^Key20[0],Buf+0);
RawPut4(D^Key20[1],Buf+4);
RawPut4(A^Key20[2],Buf+8);
RawPut4(B^Key20[3],Buf+12);
UpdKeys20(InBuf);
}
void CryptData::UpdKeys20(byte *Buf)
{
for (int I=0;I<16;I+=4)
{
Key20[0]^=CRCTab[Buf[I]];
Key20[1]^=CRCTab[Buf[I+1]];
Key20[2]^=CRCTab[Buf[I+2]];
Key20[3]^=CRCTab[Buf[I+3]];
}
}
void CryptData::Swap20(byte *Ch1,byte *Ch2)
{
byte Ch=*Ch1;
*Ch1=*Ch2;
*Ch2=Ch;
}
-68
View File
@@ -1,68 +0,0 @@
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt)
{
byte AESKey[16],AESInit[16];
bool Cached=false;
for (uint I=0;I<ASIZE(KDF3Cache);I++)
if (KDF3Cache[I].Pwd==*Password &&
(Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL &&
KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0))
{
memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey));
SecHideData(AESKey,sizeof(AESKey),false,false);
memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit));
Cached=true;
break;
}
if (!Cached)
{
byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
WideToRaw(PwdW,RawPsw,ASIZE(RawPsw));
size_t RawLength=2*wcslen(PwdW);
if (Salt!=NULL)
{
memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
RawLength+=SIZE_SALT30;
}
sha1_context c;
sha1_init(&c);
const uint HashRounds=0x40000;
for (uint I=0;I<HashRounds;I++)
{
sha1_process_rar29( &c, RawPsw, RawLength );
byte PswNum[3];
PswNum[0]=(byte)I;
PswNum[1]=(byte)(I>>8);
PswNum[2]=(byte)(I>>16);
sha1_process(&c, PswNum, 3);
if (I%(HashRounds/16)==0)
{
sha1_context tempc=c;
uint32 digest[5];
sha1_done( &tempc, digest );
AESInit[I/(HashRounds/16)]=(byte)digest[4];
}
}
uint32 digest[5];
sha1_done( &c, digest );
for (uint I=0;I<4;I++)
for (uint J=0;J<4;J++)
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
KDF3Cache[KDF3CachePos].Pwd=*Password;
if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true)
memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30);
memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey));
SecHideData(KDF3Cache[KDF3CachePos].Key,sizeof(KDF3Cache[KDF3CachePos].Key),true,false);
memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit));
KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache);
cleandata(RawPsw,sizeof(RawPsw));
}
rin.Init(Encrypt, AESKey, 128, AESInit);
cleandata(AESKey,sizeof(AESKey));
cleandata(AESInit,sizeof(AESInit));
}
-233
View File
@@ -1,233 +0,0 @@
static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
size_t DataLength,byte *ResDigest,
sha256_context *ICtxOpt,bool *SetIOpt,
sha256_context *RCtxOpt,bool *SetROpt)
{
const size_t Sha256BlockSize=64; // As defined in RFC 4868.
byte KeyHash[SHA256_DIGEST_SIZE];
if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash.
{
sha256_context KCtx;
sha256_init(&KCtx);
sha256_process(&KCtx, Key, KeyLength);
sha256_done(&KCtx, KeyHash);
Key = KeyHash;
KeyLength = SHA256_DIGEST_SIZE;
}
byte KeyBuf[Sha256BlockSize]; // Store the padded key here.
sha256_context ICtx;
if (ICtxOpt!=NULL && *SetIOpt)
ICtx=*ICtxOpt; // Use already calculated first block context.
else
{
// This calculation is the same for all iterations with same password.
// So for PBKDF2 we can calculate it only for first block and then reuse
// to improve performance.
for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest.
KeyBuf[I] = Key[I] ^ 0x36;
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
KeyBuf[I] = 0x36;
sha256_init(&ICtx);
sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key.
}
if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse.
{
*ICtxOpt=ICtx;
*SetIOpt=true;
}
sha256_process(&ICtx, Data, DataLength); // Hash data.
byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data.
sha256_done(&ICtx, IDig);
sha256_context RCtx;
if (RCtxOpt!=NULL && *SetROpt)
RCtx=*RCtxOpt; // Use already calculated first block context.
else
{
// This calculation is the same for all iterations with same password.
// So for PBKDF2 we can calculate it only for first block and then reuse
// to improve performance.
for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding.
KeyBuf[I] = Key[I] ^ 0x5c;
for (size_t I = KeyLength; I < Sha256BlockSize; I++)
KeyBuf[I] = 0x5c;
sha256_init(&RCtx);
sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key.
}
if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse.
{
*RCtxOpt=RCtx;
*SetROpt=true;
}
sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest.
sha256_done(&RCtx, ResDigest);
}
// PBKDF2 for 32 byte key length. We generate the key for specified number
// of iteration count also as two supplementary values (key for checksums
// and password verification) for iterations+16 and iterations+32.
void pbkdf2(const byte *Pwd, size_t PwdLength,
const byte *Salt, size_t SaltLength,
byte *Key, byte *V1, byte *V2, uint Count)
{
const size_t MaxSalt=64;
byte SaltData[MaxSalt+4];
memcpy(SaltData, Salt, Min(SaltLength,MaxSalt));
SaltData[SaltLength + 0] = 0; // Salt concatenated to 1.
SaltData[SaltLength + 1] = 0;
SaltData[SaltLength + 2] = 0;
SaltData[SaltLength + 3] = 1;
// First iteration: HMAC of password, salt and block index (1).
byte U1[SHA256_DIGEST_SIZE];
hmac_sha256(Pwd, PwdLength, SaltData, SaltLength + 4, U1, NULL, NULL, NULL, NULL);
byte Fn[SHA256_DIGEST_SIZE]; // Current function value.
memcpy(Fn, U1, sizeof(Fn)); // Function at first iteration.
uint CurCount[] = { Count-1, 16, 16 };
byte *CurValue[] = { Key , V1, V2 };
sha256_context ICtxOpt,RCtxOpt;
bool SetIOpt=false,SetROpt=false;
byte U2[SHA256_DIGEST_SIZE];
for (uint I = 0; I < 3; I++) // For output key and 2 supplementary values.
{
for (uint J = 0; J < CurCount[I]; J++)
{
// U2 = PRF (P, U1).
hmac_sha256(Pwd, PwdLength, U1, sizeof(U1), U2, &ICtxOpt, &SetIOpt, &RCtxOpt, &SetROpt);
memcpy(U1, U2, sizeof(U1));
for (uint K = 0; K < sizeof(Fn); K++) // Function ^= U.
Fn[K] ^= U1[K];
}
memcpy(CurValue[I], Fn, SHA256_DIGEST_SIZE);
}
cleandata(SaltData, sizeof(SaltData));
cleandata(Fn, sizeof(Fn));
cleandata(U1, sizeof(U1));
cleandata(U2, sizeof(U2));
}
void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,
const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,
byte *PswCheck)
{
if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX)
return;
byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE];
bool Found=false;
for (uint I=0;I<ASIZE(KDF5Cache);I++)
{
KDF5CacheItem *Item=KDF5Cache+I;
if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password &&
memcmp(Item->Salt,Salt,SIZE_SALT50)==0)
{
memcpy(Key,Item->Key,sizeof(Key));
SecHideData(Key,sizeof(Key),false,false);
memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue));
memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue));
Found=true;
break;
}
}
if (!Found)
{
char PwdUtf[MAXPASSWORD*4];
WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf));
pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt));
cleandata(PwdUtf,sizeof(PwdUtf));
KDF5CacheItem *Item=KDF5Cache+(KDF5CachePos++ % ASIZE(KDF5Cache));
Item->Lg2Count=Lg2Cnt;
Item->Pwd=*Password;
memcpy(Item->Salt,Salt,SIZE_SALT50);
memcpy(Item->Key,Key,sizeof(Item->Key));
memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue));
memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue));
SecHideData(Item->Key,sizeof(Item->Key),true,false);
}
if (HashKey!=NULL)
memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE);
if (PswCheck!=NULL)
{
memset(PswCheck,0,SIZE_PSWCHECK);
for (uint I=0;I<SHA256_DIGEST_SIZE;I++)
PswCheck[I%SIZE_PSWCHECK]^=PswCheckValue[I];
cleandata(PswCheckValue,sizeof(PswCheckValue));
}
// NULL initialization vector is possible if we only need the password
// check value for archive encryption header.
if (InitV!=NULL)
rin.Init(Encrypt, Key, 256, InitV);
cleandata(Key,sizeof(Key));
}
void ConvertHashToMAC(HashValue *Value,byte *Key)
{
if (Value->Type==HASH_CRC32)
{
byte RawCRC[4];
RawPut4(Value->CRC32,RawCRC);
byte Digest[SHA256_DIGEST_SIZE];
hmac_sha256(Key,SHA256_DIGEST_SIZE,RawCRC,sizeof(RawCRC),Digest,NULL,NULL,NULL,NULL);
Value->CRC32=0;
for (uint I=0;I<ASIZE(Digest);I++)
Value->CRC32^=Digest[I] << ((I & 3) * 8);
}
if (Value->Type==HASH_BLAKE2)
{
byte Digest[BLAKE2_DIGEST_SIZE];
hmac_sha256(Key,BLAKE2_DIGEST_SIZE,Value->Digest,sizeof(Value->Digest),Digest,NULL,NULL,NULL,NULL);
memcpy(Value->Digest,Digest,sizeof(Value->Digest));
}
}
#if 0
static void TestPBKDF2();
struct TestKDF {TestKDF() {TestPBKDF2();exit(0);}} GlobalTestKDF;
void TestPBKDF2() // Test PBKDF2 HMAC-SHA256
{
byte Key[32],V1[32],V2[32];
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 1);
byte Res1[32]={0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, 0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48, 0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b };
mprintf(L"\nPBKDF2 test1: %s", memcmp(Key,Res1,32)==0 ? L"OK":L"Failed");
pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 4096);
byte Res2[32]={0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, 0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11, 0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a };
mprintf(L"\nPBKDF2 test2: %s", memcmp(Key,Res2,32)==0 ? L"OK":L"Failed");
pbkdf2((byte *)"just some long string pretending to be a password", 49, (byte *)"salt, salt, salt, a lot of salt", 31, Key, V1, V2, 65536);
byte Res3[32]={0x08, 0x0f, 0xa3, 0x1d, 0x42, 0x2d, 0xb0, 0x47, 0x83, 0x9b, 0xce, 0x3a, 0x3b, 0xce, 0x49, 0x51, 0xe2, 0x62, 0xb9, 0xff, 0x76, 0x2f, 0x57, 0xe9, 0xc4, 0x71, 0x96, 0xce, 0x4b, 0x6b, 0x6e, 0xbf};
mprintf(L"\nPBKDF2 test3: %s", memcmp(Key,Res3,32)==0 ? L"OK":L"Failed");
}
#endif
+178 -312
View File
@@ -1,16 +1,17 @@
#include "rar.hpp"
#include "dll.hpp"
static int RarErrorToDll(RAR_EXIT ErrCode);
static int RarErrorToDll(int ErrCode);
struct DataSet
{
CommandData Cmd;
Archive Arc;
CmdExtract Extract;
Archive Arc;
int OpenMode;
int HeaderSize;
DataSet():Arc(&Cmd),Extract(&Cmd) {};
DataSet():Arc(&Cmd) {};
};
@@ -26,183 +27,123 @@ HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
r->OpenResult=rx.OpenResult;
r->CmtSize=rx.CmtSize;
r->CmtState=rx.CmtState;
return hArc;
return(hArc);
}
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
{
DataSet *Data=NULL;
try
{
ErrHandler.Clean();
r->OpenResult=0;
Data=new DataSet;
DataSet *Data=new DataSet;
Data->Cmd.DllError=0;
Data->OpenMode=r->OpenMode;
Data->Cmd.FileArgs.AddString(L"*");
Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0;
Data->Cmd.FileArgs->AddString("*");
char AnsiArcName[NM];
*AnsiArcName=0;
if (r->ArcName!=NULL)
char an[NM];
if (r->ArcName==NULL && r->ArcNameW!=NULL)
{
strncpyz(AnsiArcName,r->ArcName,ASIZE(AnsiArcName));
#ifdef _WIN_ALL
if (!AreFileApisANSI())
{
OemToCharBuffA(r->ArcName,AnsiArcName,ASIZE(AnsiArcName));
AnsiArcName[ASIZE(AnsiArcName)-1]=0;
}
#endif
WideToChar(r->ArcNameW,an,NM);
r->ArcName=an;
}
wchar ArcName[NM];
GetWideName(AnsiArcName,r->ArcNameW,ArcName,ASIZE(ArcName));
Data->Cmd.AddArcName(ArcName);
Data->Cmd.AddArcName(r->ArcName,r->ArcNameW);
Data->Cmd.Overwrite=OVERWRITE_ALL;
Data->Cmd.VersionControl=1;
Data->Cmd.Callback=r->Callback;
Data->Cmd.UserData=r->UserData;
// Open shared mode is added by request of dll users, who need to
// browse and unpack archives while downloading.
Data->Cmd.OpenShared = true;
if (!Data->Arc.Open(ArcName,FMF_OPENSHARED))
if (!Data->Arc.Open(r->ArcName,r->ArcNameW))
{
r->OpenResult=ERAR_EOPEN;
delete Data;
return NULL;
return(NULL);
}
if (!Data->Arc.IsArchive(true))
if (!Data->Arc.IsArchive(false))
{
if (Data->Cmd.DllError!=0)
r->OpenResult=Data->Cmd.DllError;
else
{
RAR_EXIT ErrCode=ErrHandler.GetErrorCode();
if (ErrCode!=RARX_SUCCESS && ErrCode!=RARX_WARNING)
r->OpenResult=RarErrorToDll(ErrCode);
else
r->OpenResult=ERAR_BAD_ARCHIVE;
}
r->OpenResult=Data->Cmd.DllError!=0 ? Data->Cmd.DllError:ERAR_BAD_ARCHIVE;
delete Data;
return NULL;
return(NULL);
}
r->Flags=0;
if (Data->Arc.Volume)
r->Flags|=ROADF_VOLUME;
if (Data->Arc.MainComment)
r->Flags|=ROADF_COMMENT;
if (Data->Arc.Locked)
r->Flags|=ROADF_LOCK;
if (Data->Arc.Solid)
r->Flags|=ROADF_SOLID;
if (Data->Arc.NewNumbering)
r->Flags|=ROADF_NEWNUMBERING;
if (Data->Arc.Signed)
r->Flags|=ROADF_SIGNED;
if (Data->Arc.Protected)
r->Flags|=ROADF_RECOVERY;
if (Data->Arc.Encrypted)
r->Flags|=ROADF_ENCHEADERS;
if (Data->Arc.FirstVolume)
r->Flags|=ROADF_FIRSTVOLUME;
Array<wchar> CmtDataW;
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
r->Flags=Data->Arc.NewMhd.Flags;
Array<byte> CmtData;
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
{
if (r->CmtBufW!=NULL)
{
CmtDataW.Push(0);
size_t Size=wcslen(&CmtDataW[0])+1;
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW));
r->CmtBufW[r->CmtSize-1]=0;
}
else
if (r->CmtBuf!=NULL)
{
Array<char> CmtData(CmtDataW.Size()*4+1);
memset(&CmtData[0],0,CmtData.Size());
WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
size_t Size=strlen(&CmtData[0])+1;
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
r->CmtBuf[r->CmtSize-1]=0;
}
r->Flags|=2;
int Size=CmtData.Size()+1;
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
r->CmtSize=Min(Size,r->CmtBufSize);
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
if (Size<=r->CmtBufSize)
r->CmtBuf[r->CmtSize-1]=0;
}
else
r->CmtState=r->CmtSize=0;
Data->Extract.ExtractArchiveInit(Data->Arc);
return (HANDLE)Data;
if (Data->Arc.Signed)
r->Flags|=0x20;
Data->Extract.ExtractArchiveInit(&Data->Cmd,Data->Arc);
return((HANDLE)Data);
}
catch (RAR_EXIT ErrCode)
catch (int 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;
r->OpenResult=RarErrorToDll(ErrCode);
return(NULL);
}
catch (std::bad_alloc&) // Catch 'new' exception.
{
r->OpenResult=ERAR_NO_MEMORY;
if (Data != NULL)
delete Data;
}
return NULL; // To make compilers happy.
}
int PASCAL RARCloseArchive(HANDLE hArcData)
{
DataSet *Data=(DataSet *)hArcData;
try
{
bool Success=Data==NULL ? false:Data->Arc.Close();
delete Data;
return Success ? ERAR_SUCCESS : ERAR_ECLOSE;
}
catch (RAR_EXIT ErrCode)
{
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
}
bool Success=Data==NULL ? false:Data->Arc.Close();
delete Data;
return(Success ? 0:ERAR_ECLOSE);
}
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
{
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;
DataSet *Data=(DataSet *)hArcData;
try
{
if ((Data->HeaderSize=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->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);
}
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(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);
}
@@ -211,114 +152,64 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
DataSet *Data=(DataSet *)hArcData;
try
{
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(HEAD_FILE))<=0)
if ((Data->HeaderSize=Data->Arc.SearchBlock(FILE_HEAD))<=0)
{
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_ENDARC &&
Data->Arc.EndArcHead.NextVolume)
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return RARReadHeaderEx(hArcData,D);
return(RARReadHeaderEx(hArcData,D));
}
else
return ERAR_EOPEN;
if (Data->Arc.BrokenHeader)
return ERAR_BAD_DATA;
// Might be necessary if RARSetPassword is still called instead of
// open callback for RAR5 archives and if password is invalid.
if (Data->Arc.FailedHeaderDecryption)
return ERAR_BAD_PASSWORD;
return ERAR_END_ARCHIVE;
return(ERAR_EOPEN);
return(Data->Arc.BrokenFileHeader ? ERAR_BAD_DATA:ERAR_END_ARCHIVE);
}
FileHeader *hd=&Data->Arc.FileHead;
if (Data->OpenMode==RAR_OM_LIST && hd->SplitBefore)
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 RARReadHeaderEx(hArcData,D);
return(RARReadHeaderEx(hArcData,D));
else
return Code;
return(Code);
}
wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName));
wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName));
#ifdef _WIN_ALL
CharToOemA(D->FileName,D->FileName);
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
if (*Data->Arc.FileNameW)
strncpyw(D->ArcNameW,Data->Arc.FileNameW,sizeof(D->ArcNameW));
else
CharToWide(Data->Arc.FileName,D->ArcNameW);
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(D->FileName));
if (*Data->Arc.NewLhd.FileNameW)
strncpyw(D->FileNameW,Data->Arc.NewLhd.FileNameW,sizeof(D->FileNameW));
else
{
#ifdef _WIN_32
char AnsiName[NM];
OemToChar(Data->Arc.NewLhd.FileName,AnsiName);
CharToWide(AnsiName,D->FileNameW);
#else
CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW);
#endif
D->Flags=0;
if (hd->SplitBefore)
D->Flags|=RHDF_SPLITBEFORE;
if (hd->SplitAfter)
D->Flags|=RHDF_SPLITAFTER;
if (hd->Encrypted)
D->Flags|=RHDF_ENCRYPTED;
if (hd->Solid)
D->Flags|=RHDF_SOLID;
if (hd->Dir)
D->Flags|=RHDF_DIRECTORY;
D->PackSize=uint(hd->PackSize & 0xffffffff);
D->PackSizeHigh=uint(hd->PackSize>>32);
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
D->UnpSizeHigh=uint(hd->UnpSize>>32);
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
D->UnpVer=Data->Arc.FileHead.UnpVer;
D->FileCRC=hd->FileHash.CRC32;
D->FileTime=hd->mtime.GetDos();
uint64 MRaw=hd->mtime.GetWin();
D->MtimeLow=(uint)MRaw;
D->MtimeHigh=(uint)(MRaw>>32);
uint64 CRaw=hd->ctime.GetWin();
D->CtimeLow=(uint)CRaw;
D->CtimeHigh=(uint)(CRaw>>32);
uint64 ARaw=hd->atime.GetWin();
D->AtimeLow=(uint)ARaw;
D->AtimeHigh=(uint)(ARaw>>32);
D->Method=hd->Method+0x30;
D->FileAttr=hd->FileAttr;
}
D->Flags=Data->Arc.NewLhd.Flags;
D->PackSize=Data->Arc.NewLhd.PackSize;
D->PackSizeHigh=Data->Arc.NewLhd.HighPackSize;
D->UnpSize=Data->Arc.NewLhd.UnpSize;
D->UnpSizeHigh=Data->Arc.NewLhd.HighUnpSize;
D->HostOS=Data->Arc.NewLhd.HostOS;
D->FileCRC=Data->Arc.NewLhd.FileCRC;
D->FileTime=Data->Arc.NewLhd.FileTime;
D->UnpVer=Data->Arc.NewLhd.UnpVer;
D->Method=Data->Arc.NewLhd.Method;
D->FileAttr=Data->Arc.NewLhd.FileAttr;
D->CmtSize=0;
D->CmtState=0;
D->DictSize=uint(hd->WinSize/1024);
switch (hd->FileHash.Type)
{
case HASH_RAR14:
case HASH_CRC32:
D->HashType=RAR_HASH_CRC32;
break;
case HASH_BLAKE2:
D->HashType=RAR_HASH_BLAKE2;
memcpy(D->Hash,hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
break;
default:
D->HashType=RAR_HASH_NONE;
break;
}
D->RedirType=hd->RedirType;
// RedirNameSize sanity check is useful in case some developer
// did not initialize Reserved area with 0 as required in docs.
// We have taken 'Redir*' fields from Reserved area. We may remove
// this RedirNameSize check sometimes later.
if (hd->RedirType!=FSREDIR_NONE && D->RedirName!=NULL &&
D->RedirNameSize>0 && D->RedirNameSize<100000)
wcsncpyz(D->RedirName,hd->RedirName,D->RedirNameSize);
D->DirTarget=hd->DirTarget;
}
catch (RAR_EXIT ErrCode)
catch (int ErrCode)
{
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
return(RarErrorToDll(ErrCode));
}
return ERAR_SUCCESS;
return(0);
}
@@ -328,104 +219,86 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
try
{
Data->Cmd.DllError=0;
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
Operation==RAR_SKIP && !Data->Arc.Solid)
if (Data->OpenMode==RAR_OM_LIST || Operation==RAR_SKIP && !Data->Arc.Solid)
{
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_FILE &&
Data->Arc.FileHead.SplitAfter)
if (/*Data->OpenMode==RAR_OM_LIST && */Data->Arc.Volume &&
Data->Arc.GetHeaderType()==FILE_HEAD &&
(Data->Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0)
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return ERAR_SUCCESS;
return(0);
}
else
return ERAR_EOPEN;
return(ERAR_EOPEN);
Data->Arc.SeekToNext();
}
else
{
Data->Cmd.DllOpMode=Operation;
*Data->Cmd.ExtrPath=0;
*Data->Cmd.DllDestName=0;
if (DestPath!=NULL)
if (DestPath!=NULL || DestName!=NULL)
{
char ExtrPathA[NM];
strncpyz(ExtrPathA,DestPath,ASIZE(ExtrPathA)-2);
#ifdef _WIN_ALL
// We must not apply OemToCharBuffA directly to DestPath,
// because we do not know DestPath length and OemToCharBuffA
// does not stop at 0.
OemToCharA(ExtrPathA,ExtrPathA);
#ifdef _WIN_32
OemToChar(NullToEmpty(DestPath),Data->Cmd.ExtrPath);
#else
strcpy(Data->Cmd.ExtrPath,NullToEmpty(DestPath));
#endif
CharToWide(ExtrPathA,Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
}
if (DestName!=NULL)
{
char DestNameA[NM];
strncpyz(DestNameA,DestName,ASIZE(DestNameA)-2);
#ifdef _WIN_ALL
// We must not apply OemToCharBuffA directly to DestName,
// because we do not know DestName length and OemToCharBuffA
// does not stop at 0.
OemToCharA(DestNameA,DestNameA);
AddEndSlash(Data->Cmd.ExtrPath);
#ifdef _WIN_32
OemToChar(NullToEmpty(DestName),Data->Cmd.DllDestName);
#else
strcpy(Data->Cmd.DllDestName,NullToEmpty(DestName));
#endif
CharToWide(DestNameA,Data->Cmd.DllDestName,ASIZE(Data->Cmd.DllDestName));
}
if (DestPathW!=NULL)
else
{
wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
*Data->Cmd.ExtrPath=0;
*Data->Cmd.DllDestName=0;
}
if (DestNameW!=NULL)
wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
if (DestPathW!=NULL || DestNameW!=NULL)
{
strncpyw(Data->Cmd.ExtrPathW,NullToEmpty(DestPathW),NM-2);
AddEndSlash(Data->Cmd.ExtrPathW);
strncpyw(Data->Cmd.DllDestNameW,NullToEmpty(DestNameW),NM-1);
}
else
{
*Data->Cmd.ExtrPathW=0;
*Data->Cmd.DllDestNameW=0;
}
wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command));
strcpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? "X":"T");
Data->Cmd.Test=Operation!=RAR_EXTRACT;
bool Repeat=false;
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
// 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.
while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 &&
Data->Arc.GetHeaderType()==HEAD_SERVICE)
while (Data->Arc.ReadHeader()!=0 && Data->Arc.GetHeaderType()==NEWSUB_HEAD)
{
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
Data->Arc.SeekToNext();
}
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
}
}
catch (std::bad_alloc&)
catch (int ErrCode)
{
return ERAR_NO_MEMORY;
return(RarErrorToDll(ErrCode));
}
catch (RAR_EXIT ErrCode)
{
return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
}
return Data->Cmd.DllError;
return(Data->Cmd.DllError);
}
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
{
return ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL);
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL));
}
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
{
return ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName);
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName));
}
@@ -436,7 +309,7 @@ void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
}
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.Callback=Callback;
@@ -453,43 +326,36 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
{
#ifndef RAR_NOCRYPT
DataSet *Data=(DataSet *)hArcData;
wchar PasswordW[MAXPASSWORD];
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
Data->Cmd.Password.Set(PasswordW);
cleandata(PasswordW,sizeof(PasswordW));
#endif
strncpy(Data->Cmd.Password,Password,sizeof(Data->Cmd.Password));
}
int PASCAL RARGetDllVersion()
{
return RAR_DLL_VERSION;
return(RAR_DLL_VERSION);
}
static int RarErrorToDll(RAR_EXIT ErrCode)
static int RarErrorToDll(int ErrCode)
{
switch(ErrCode)
{
case RARX_FATAL:
return ERAR_EREAD;
case RARX_CRC:
return ERAR_BAD_DATA;
case RARX_WRITE:
return ERAR_EWRITE;
case RARX_OPEN:
return ERAR_EOPEN;
case RARX_CREATE:
return ERAR_ECREATE;
case RARX_MEMORY:
return ERAR_NO_MEMORY;
case RARX_BADPWD:
return ERAR_BAD_PASSWORD;
case RARX_SUCCESS:
return ERAR_SUCCESS; // 0.
case RAR_FATAL_ERROR:
return(ERAR_EREAD);
case RAR_CRC_ERROR:
return(ERAR_BAD_DATA);
case RAR_WRITE_ERROR:
return(ERAR_EWRITE);
case RAR_OPEN_ERROR:
return(ERAR_EOPEN);
case RAR_CREATE_ERROR:
return(ERAR_ECREATE);
case RAR_MEMORY_ERROR:
return(ERAR_NO_MEMORY);
case RAR_SUCCESS:
return(0);
default:
return ERAR_UNKNOWN;
return(ERAR_UNKNOWN);
}
}
+12 -13
View File
@@ -1,13 +1,12 @@
EXPORTS
RAROpenArchive
RAROpenArchiveEx
RARCloseArchive
RARReadHeader
RARReadHeaderEx
RARProcessFile
RARProcessFileW
RARSetCallback
RARSetChangeVolProc
RARSetProcessDataProc
RARSetPassword
RARGetDllVersion
EXPORTS
RAROpenArchive
RAROpenArchiveEx
RARCloseArchive
RARReadHeader
RARReadHeaderEx
RARProcessFile
RARSetCallback
RARSetChangeVolProc
RARSetProcessDataProc
RARSetPassword
RARGetDllVersion
+27 -79
View File
@@ -1,28 +1,21 @@
#ifndef _UNRAR_DLL_
#define _UNRAR_DLL_
#pragma pack(push, 1)
#define ERAR_END_ARCHIVE 10
#define ERAR_NO_MEMORY 11
#define ERAR_BAD_DATA 12
#define ERAR_BAD_ARCHIVE 13
#define ERAR_UNKNOWN_FORMAT 14
#define ERAR_EOPEN 15
#define ERAR_ECREATE 16
#define ERAR_ECLOSE 17
#define ERAR_EREAD 18
#define ERAR_EWRITE 19
#define ERAR_SMALL_BUF 20
#define ERAR_UNKNOWN 21
#define ERAR_SUCCESS 0
#define ERAR_END_ARCHIVE 10
#define ERAR_NO_MEMORY 11
#define ERAR_BAD_DATA 12
#define ERAR_BAD_ARCHIVE 13
#define ERAR_UNKNOWN_FORMAT 14
#define ERAR_EOPEN 15
#define ERAR_ECREATE 16
#define ERAR_ECLOSE 17
#define ERAR_EREAD 18
#define ERAR_EWRITE 19
#define ERAR_SMALL_BUF 20
#define ERAR_UNKNOWN 21
#define ERAR_MISSING_PASSWORD 22
#define ERAR_EREFERENCE 23
#define ERAR_BAD_PASSWORD 24
#define RAR_OM_LIST 0
#define RAR_OM_EXTRACT 1
#define RAR_OM_LIST_INCSPLIT 2
#define RAR_OM_LIST 0
#define RAR_OM_EXTRACT 1
#define RAR_SKIP 0
#define RAR_TEST 1
@@ -31,29 +24,16 @@
#define RAR_VOL_ASK 0
#define RAR_VOL_NOTIFY 1
#define RAR_DLL_VERSION 8
#define RAR_HASH_NONE 0
#define RAR_HASH_CRC32 1
#define RAR_HASH_BLAKE2 2
#define RAR_DLL_VERSION 4
#ifdef _UNIX
#define CALLBACK
#define PASCAL
#define LONG long
#define HANDLE void *
#define LPARAM long
#define UINT unsigned int
#endif
#define RHDF_SPLITBEFORE 0x01
#define RHDF_SPLITAFTER 0x02
#define RHDF_ENCRYPTED 0x04
#define RHDF_SOLID 0x10
#define RHDF_DIRECTORY 0x20
struct RARHeaderData
{
char ArcName[260];
@@ -95,20 +75,7 @@ struct RARHeaderDataEx
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int DictSize;
unsigned int HashType;
char Hash[32];
unsigned int RedirType;
wchar_t *RedirName;
unsigned int RedirNameSize;
unsigned int DirTarget;
unsigned int MtimeLow;
unsigned int MtimeHigh;
unsigned int CtimeLow;
unsigned int CtimeHigh;
unsigned int AtimeLow;
unsigned int AtimeHigh;
unsigned int Reserved[988];
unsigned int Reserved[1024];
};
@@ -123,43 +90,26 @@ struct RAROpenArchiveData
unsigned int CmtState;
};
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
#define ROADF_VOLUME 0x0001
#define ROADF_COMMENT 0x0002
#define ROADF_LOCK 0x0004
#define ROADF_SOLID 0x0008
#define ROADF_NEWNUMBERING 0x0010
#define ROADF_SIGNED 0x0020
#define ROADF_RECOVERY 0x0040
#define ROADF_ENCHEADERS 0x0080
#define ROADF_FIRSTVOLUME 0x0100
#define ROADOF_KEEPBROKEN 0x0001
struct RAROpenArchiveDataEx
{
char *ArcName;
wchar_t *ArcNameW;
unsigned int OpenMode;
unsigned int OpenResult;
unsigned int OpenMode;
unsigned int OpenResult;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int Flags;
UNRARCALLBACK Callback;
LPARAM UserData;
unsigned int OpFlags;
wchar_t *CmtBufW;
unsigned int Reserved[25];
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int Flags;
unsigned int Reserved[32];
};
enum UNRARCALLBACK_MESSAGES {
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD,UCM_CHANGEVOLUMEW,
UCM_NEEDPASSWORDW
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD
};
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LONG UserData,LONG P1,LONG P2);
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
@@ -174,7 +124,7 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName);
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData);
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
void PASCAL RARSetPassword(HANDLE hArcData,char *Password);
@@ -184,6 +134,4 @@ int PASCAL RARGetDllVersion();
}
#endif
#pragma pack(pop)
#endif
-28
View File
@@ -1,28 +0,0 @@
#include <windows.h>
#include <commctrl.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION 5, 91, 100, 3470
PRODUCTVERSION 5, 91, 100, 3470
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "CompanyName", "Alexander Roshal\0"
VALUE "ProductName", "RAR decompression library\0"
VALUE "FileDescription", "RAR decompression library\0"
VALUE "FileVersion", "5.91.0\0"
VALUE "ProductVersion", "5.91.0\0"
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2020\0"
VALUE "OriginalFilename", "Unrar.dll\0"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 0x04E4
}
}
-13
View File
@@ -1,13 +0,0 @@
EXPORTS
RAROpenArchive
RAROpenArchiveEx
RARCloseArchive
RARReadHeader
RARReadHeaderEx
RARProcessFile
RARProcessFileW
RARSetCallback
RARSetChangeVolProc
RARSetProcessDataProc
; RARSetPassword
RARGetDllVersion
+7 -19
View File
@@ -11,53 +11,41 @@ EncodeFileName::EncodeFileName()
void EncodeFileName::Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize,
wchar *NameW,size_t MaxDecSize)
void EncodeFileName::Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,
int MaxDecSize)
{
size_t EncPos=0,DecPos=0;
byte HighByte=EncPos<EncSize ? EncName[EncPos++] : 0;
int EncPos=0,DecPos=0;
byte HighByte=EncName[EncPos++];
while (EncPos<EncSize && DecPos<MaxDecSize)
{
if (FlagBits==0)
{
if (EncPos>=EncSize)
break;
Flags=EncName[EncPos++];
FlagBits=8;
}
switch(Flags>>6)
{
case 0:
if (EncPos>=EncSize)
break;
NameW[DecPos++]=EncName[EncPos++];
break;
case 1:
if (EncPos>=EncSize)
break;
NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8);
break;
case 2:
if (EncPos+1>=EncSize)
break;
NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8);
EncPos+=2;
break;
case 3:
{
if (EncPos>=EncSize)
break;
int Length=EncName[EncPos++];
if ((Length & 0x80)!=0)
if (Length & 0x80)
{
if (EncPos>=EncSize)
break;
byte Correction=EncName[EncPos++];
for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize && DecPos<NameSize;Length--,DecPos++)
for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
NameW[DecPos]=((Name[DecPos]+Correction)&0xff)+(HighByte<<8);
}
else
for (Length+=2;Length>0 && DecPos<MaxDecSize && DecPos<NameSize;Length--,DecPos++)
for (Length+=2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
NameW[DecPos]=Name[DecPos];
}
break;
+5 -5
View File
@@ -8,13 +8,13 @@ class EncodeFileName
byte *EncName;
byte Flags;
uint FlagBits;
size_t FlagsPos;
size_t DestSize;
int FlagBits;
int FlagsPos;
int DestSize;
public:
EncodeFileName();
size_t Encode(char *Name,wchar *NameW,byte *EncName);
void Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
int Encode(char *Name,wchar *NameW,byte *EncName);
void Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,int MaxDecSize);
};
#endif
+188 -223
View File
@@ -1,5 +1,8 @@
#include "rar.hpp"
static bool UserBreak;
ErrorHandler::ErrorHandler()
{
Clean();
@@ -8,243 +11,250 @@ ErrorHandler::ErrorHandler()
void ErrorHandler::Clean()
{
ExitCode=RARX_SUCCESS;
ExitCode=RAR_SUCCESS;
ErrCount=0;
EnableBreak=true;
Silent=false;
UserBreak=false;
MainExit=false;
DisableShutdown=false;
DoShutdown=false;
}
void ErrorHandler::MemoryError()
{
MemoryErrorMsg();
Exit(RARX_MEMORY);
Throw(RAR_MEMORY_ERROR);
}
void ErrorHandler::OpenError(const wchar *FileName)
void ErrorHandler::OpenError(const char *FileName)
{
#ifndef SILENT
OpenErrorMsg(FileName);
Exit(RARX_OPEN);
Throw(RAR_OPEN_ERROR);
#endif
}
void ErrorHandler::CloseError(const wchar *FileName)
{
if (!UserBreak)
{
uiMsg(UIERROR_FILECLOSE,FileName);
SysErrMsg();
}
// We must not call Exit and throw an exception here, because this function
// is called from File object destructor and can be invoked when stack
// unwinding while handling another exception. Throwing a new exception
// when stack unwinding is prohibited and terminates a program.
// If necessary, we can check std::uncaught_exception() before throw.
SetErrorCode(RARX_FATAL);
}
void ErrorHandler::ReadError(const wchar *FileName)
void ErrorHandler::CloseError(const char *FileName)
{
#ifndef SILENT
ReadErrorMsg(FileName);
#endif
#if !defined(SILENT) || defined(RARDLL)
Exit(RARX_FATAL);
#endif
}
bool ErrorHandler::AskRepeatRead(const wchar *FileName)
{
#if !defined(SILENT) && !defined(SFX_MODULE)
if (!Silent)
if (!UserBreak)
{
ErrMsg(NULL,St(MErrFClose),FileName);
SysErrMsg();
bool Repeat=uiAskRepeatRead(FileName);
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
DisableShutdown=true;
return Repeat;
}
#endif
return false;
#if !defined(SILENT) || defined(RARDLL)
Throw(RAR_FATAL_ERROR);
#endif
}
void ErrorHandler::WriteError(const wchar *ArcName,const wchar *FileName)
void ErrorHandler::ReadError(const char *FileName)
{
#ifndef SILENT
ReadErrorMsg(NULL,FileName);
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RAR_FATAL_ERROR);
#endif
}
bool ErrorHandler::AskRepeatRead(const char *FileName)
{
#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE)
if (!Silent)
{
mprintf("\n");
Log(NULL,St(MErrRead),FileName);
return(Ask(St(MRetryAbort))==1);
}
#endif
return(false);
}
void ErrorHandler::WriteError(const char *ArcName,const char *FileName)
{
#ifndef SILENT
WriteErrorMsg(ArcName,FileName);
#endif
#if !defined(SILENT) || defined(RARDLL)
Exit(RARX_WRITE);
Throw(RAR_WRITE_ERROR);
#endif
}
#ifdef _WIN_ALL
void ErrorHandler::WriteErrorFAT(const wchar *FileName)
#ifdef _WIN_32
void ErrorHandler::WriteErrorFAT(const char *FileName)
{
#if !defined(SILENT) && !defined(SFX_MODULE)
SysErrMsg();
uiMsg(UIERROR_NTFSREQUIRED,FileName);
ErrMsg(NULL,St(MNTFSRequired),FileName);
#endif
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
Exit(RARX_WRITE);
Throw(RAR_WRITE_ERROR);
#endif
}
#endif
bool ErrorHandler::AskRepeatWrite(const wchar *FileName,bool DiskFull)
bool ErrorHandler::AskRepeatWrite(const char *FileName)
{
#ifndef SILENT
#if !defined(SILENT) && !defined(_WIN_CE)
if (!Silent)
{
// We do not display "repeat write" prompt in Android, so we do not
// need the matching system error message.
SysErrMsg();
bool Repeat=uiAskRepeatWrite(FileName,DiskFull);
if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog.
DisableShutdown=true;
return Repeat;
mprintf("\n");
Log(NULL,St(MErrWrite),FileName);
return(Ask(St(MRetryAbort))==1);
}
#endif
return false;
return(false);
}
void ErrorHandler::SeekError(const wchar *FileName)
void ErrorHandler::SeekError(const char *FileName)
{
#ifndef SILENT
if (!UserBreak)
{
uiMsg(UIERROR_FILESEEK,FileName);
ErrMsg(NULL,St(MErrSeek),FileName);
SysErrMsg();
}
#endif
#if !defined(SILENT) || defined(RARDLL)
Exit(RARX_FATAL);
Throw(RAR_FATAL_ERROR);
#endif
}
void ErrorHandler::GeneralErrMsg(const wchar *fmt,...)
void ErrorHandler::GeneralErrMsg(const char *Msg)
{
va_list arglist;
va_start(arglist,fmt);
wchar Msg[1024];
vswprintf(Msg,ASIZE(Msg),fmt,arglist);
uiMsg(UIERROR_GENERALERRMSG,Msg);
#ifndef SILENT
Log(NULL,"%s",Msg);
SysErrMsg();
va_end(arglist);
#endif
}
void ErrorHandler::MemoryErrorMsg()
{
uiMsg(UIERROR_MEMORY);
SetErrorCode(RARX_MEMORY);
#ifndef SILENT
ErrMsg(NULL,St(MErrOutMem));
#endif
}
void ErrorHandler::OpenErrorMsg(const wchar *FileName)
void ErrorHandler::OpenErrorMsg(const char *FileName)
{
OpenErrorMsg(NULL,FileName);
}
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
void ErrorHandler::OpenErrorMsg(const char *ArcName,const char *FileName)
{
Wait(); // Keep GUI responsive if many files cannot be opened when archiving.
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
#ifndef SILENT
Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotOpen),FileName);
Alarm();
SysErrMsg();
SetErrorCode(RARX_OPEN);
#endif
}
void ErrorHandler::CreateErrorMsg(const wchar *FileName)
void ErrorHandler::CreateErrorMsg(const char *FileName)
{
CreateErrorMsg(NULL,FileName);
}
void ErrorHandler::CreateErrorMsg(const wchar *ArcName,const wchar *FileName)
void ErrorHandler::CreateErrorMsg(const char *ArcName,const char *FileName)
{
uiMsg(UIERROR_FILECREATE,ArcName,FileName);
#ifndef SILENT
Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotCreate),FileName);
Alarm();
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAXPATH)
if (GetLastError()==ERROR_PATH_NOT_FOUND)
{
int NameLength=strlen(FileName);
if (!IsFullPath(FileName))
{
char CurDir[NM];
GetCurrentDirectory(sizeof(CurDir),CurDir);
NameLength+=strlen(CurDir)+1;
}
if (NameLength>MAXPATH)
{
Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAXPATH);
}
}
#endif
SysErrMsg();
SetErrorCode(RARX_CREATE);
#endif
}
void ErrorHandler::ReadErrorMsg(const wchar *FileName)
void ErrorHandler::ReadErrorMsg(const char *ArcName,const char *FileName)
{
ReadErrorMsg(NULL,FileName);
}
void ErrorHandler::ReadErrorMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_FILEREAD,ArcName,FileName);
#ifndef SILENT
ErrMsg(ArcName,St(MErrRead),FileName);
SysErrMsg();
SetErrorCode(RARX_FATAL);
#endif
}
void ErrorHandler::WriteErrorMsg(const wchar *ArcName,const wchar *FileName)
void ErrorHandler::WriteErrorMsg(const char *ArcName,const char *FileName)
{
uiMsg(UIERROR_FILEWRITE,ArcName,FileName);
#ifndef SILENT
ErrMsg(ArcName,St(MErrWrite),FileName);
SysErrMsg();
SetErrorCode(RARX_WRITE);
#endif
}
void ErrorHandler::ArcBrokenMsg(const wchar *ArcName)
void ErrorHandler::Exit(int ExitCode)
{
uiMsg(UIERROR_ARCBROKEN,ArcName);
SetErrorCode(RARX_CRC);
}
void ErrorHandler::ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_CHECKSUM,ArcName,FileName);
SetErrorCode(RARX_CRC);
}
void ErrorHandler::UnknownMethodMsg(const wchar *ArcName,const wchar *FileName)
{
uiMsg(UIERROR_UNKNOWNMETHOD,ArcName,FileName);
ErrHandler.SetErrorCode(RARX_FATAL);
}
void ErrorHandler::Exit(RAR_EXIT ExitCode)
{
uiAlarm(UIALARM_ERROR);
#ifndef SFX_MODULE
Alarm();
#endif
Throw(ExitCode);
}
void ErrorHandler::SetErrorCode(RAR_EXIT Code)
#ifndef GUI
void ErrorHandler::ErrMsg(const char *ArcName,const char *fmt,...)
{
safebuf char Msg[NM+1024];
va_list argptr;
va_start(argptr,fmt);
vsprintf(Msg,fmt,argptr);
va_end(argptr);
#ifdef _WIN_32
if (UserBreak)
Sleep(5000);
#endif
Alarm();
if (*Msg)
{
Log(ArcName,"\n%s",Msg);
mprintf("\n%s\n",St(MProgAborted));
}
}
#endif
void ErrorHandler::SetErrorCode(int Code)
{
switch(Code)
{
case RARX_WARNING:
case RARX_USERBREAK:
if (ExitCode==RARX_SUCCESS)
case RAR_WARNING:
case RAR_USER_BREAK:
if (ExitCode==RAR_SUCCESS)
ExitCode=Code;
break;
case RARX_CRC:
if (ExitCode!=RARX_BADPWD)
ExitCode=Code;
break;
case RARX_FATAL:
if (ExitCode==RARX_SUCCESS || ExitCode==RARX_WARNING)
ExitCode=RARX_FATAL;
case RAR_FATAL_ERROR:
if (ExitCode==RAR_SUCCESS || ExitCode==RAR_WARNING)
ExitCode=RAR_FATAL_ERROR;
break;
default:
ExitCode=Code;
@@ -254,7 +264,8 @@ void ErrorHandler::SetErrorCode(RAR_EXIT Code)
}
#ifdef _WIN_ALL
#if !defined(GUI) && !defined(_SFX_RTL_)
#ifdef _WIN_32
BOOL __stdcall ProcessSignal(DWORD SigType)
#else
#if defined(__sun)
@@ -263,147 +274,101 @@ extern "C"
void _stdfunction ProcessSignal(int SigType)
#endif
{
#ifdef _WIN_ALL
// When a console application is run as a service, this allows the service
// to continue running after the user logs off.
#ifdef _WIN_32
if (SigType==CTRL_LOGOFF_EVENT)
return TRUE;
return(TRUE);
#endif
ErrHandler.UserBreak=true;
ErrHandler.SetDisableShutdown();
UserBreak=true;
mprintf(St(MBreak));
#ifdef _WIN_ALL
// Let the main thread to handle 'throw' and destroy file objects.
for (uint I=0;!ErrHandler.MainExit && I<50;I++)
for (int I=0;!File::RemoveCreated() && I<3;I++)
{
#ifdef _WIN_32
Sleep(100);
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(RARDLL)
#endif
}
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE)
ExtRes.UnloadDLL();
#endif
exit(RARX_USERBREAK);
#endif
#ifdef _UNIX
static uint BreakCount=0;
// User continues to press Ctrl+C, exit immediately without cleanup.
if (++BreakCount>1)
exit(RARX_USERBREAK);
// Otherwise return from signal handler and let Wait() function to close
// files and quit. We cannot use the same approach as in Windows,
// because Unix signal handler can block execution of our main code.
#endif
#if defined(_WIN_ALL) && !defined(_MSC_VER)
// Never reached, just to avoid a compiler warning
return TRUE;
exit(RAR_USER_BREAK);
#ifdef _WIN_32
return(TRUE);
#endif
}
#endif
void ErrorHandler::SetSignalHandlers(bool Enable)
{
EnableBreak=Enable;
#ifdef _WIN_ALL
#if !defined(GUI) && !defined(_SFX_RTL_)
#ifdef _WIN_32
SetConsoleCtrlHandler(Enable ? ProcessSignal:NULL,TRUE);
// signal(SIGBREAK,Enable ? ProcessSignal:SIG_IGN);
#else
signal(SIGINT,Enable ? ProcessSignal:SIG_IGN);
signal(SIGTERM,Enable ? ProcessSignal:SIG_IGN);
#endif
#endif
}
void ErrorHandler::Throw(RAR_EXIT Code)
void ErrorHandler::Throw(int Code)
{
if (Code==RARX_USERBREAK && !EnableBreak)
if (Code==RAR_USER_BREAK && !EnableBreak)
return;
#if !defined(SILENT)
// Do not write "aborted" when just displaying online help.
if (Code!=RARX_SUCCESS && Code!=RARX_USERERROR)
mprintf(L"\n%s\n",St(MProgAborted));
#endif
SetErrorCode(Code);
ErrHandler.SetErrorCode(Code);
#ifdef ALLOW_EXCEPTIONS
throw Code;
}
bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
{
#ifndef SILENT
#ifdef _WIN_ALL
int ErrType=GetLastError();
if (ErrType!=0)
return FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,ErrType,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
Msg,(DWORD)Size,NULL)!=0;
#else
File::RemoveCreated();
exit(Code);
#endif
#if defined(_UNIX) || defined(_EMX)
if (errno!=0)
{
char *err=strerror(errno);
if (err!=NULL)
{
CharToWide(err,Msg,Size);
return true;
}
}
#endif
#endif
return false;
}
void ErrorHandler::SysErrMsg()
{
#if !defined(SFX_MODULE) && !defined(SILENT)
wchar Msg[1024];
if (!GetSysErrMsg(Msg,ASIZE(Msg)))
return;
#ifdef _WIN_ALL
wchar *CurMsg=Msg;
while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines.
#ifdef _WIN_32
#define STRCHR strchr
#define ERRCHAR char
ERRCHAR *lpMsgBuf=NULL;
int ErrType=GetLastError();
if (ErrType!=0 && FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,ErrType,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,0,NULL))
{
while (*CurMsg=='\r' || *CurMsg=='\n')
CurMsg++;
if (*CurMsg==0)
break;
wchar *EndMsg=wcschr(CurMsg,'\r');
if (EndMsg==NULL)
EndMsg=wcschr(CurMsg,'\n');
if (EndMsg!=NULL)
ERRCHAR *CurMsg=lpMsgBuf;
while (CurMsg!=NULL)
{
*EndMsg=0;
EndMsg++;
while (*CurMsg=='\r' || *CurMsg=='\n')
CurMsg++;
if (*CurMsg==0)
break;
ERRCHAR *EndMsg=STRCHR(CurMsg,'\r');
if (EndMsg==NULL)
EndMsg=STRCHR(CurMsg,'\n');
if (EndMsg!=NULL)
{
*EndMsg=0;
EndMsg++;
}
Log(NULL,"\n%s",CurMsg);
CurMsg=EndMsg;
}
uiMsg(UIERROR_SYSERRMSG,CurMsg);
CurMsg=EndMsg;
}
LocalFree( lpMsgBuf );
#endif
#if defined(_UNIX) || defined(_EMX)
uiMsg(UIERROR_SYSERRMSG,Msg);
char *err=strerror(errno);
if (err!=NULL)
Log(NULL,"\n%s",err);
#endif
#endif
}
int ErrorHandler::GetSystemErrorCode()
{
#ifdef _WIN_ALL
return GetLastError();
#else
return errno;
#endif
}
void ErrorHandler::SetSystemErrorCode(int Code)
{
#ifdef _WIN_ALL
SetLastError(Code);
#else
errno=Code;
#endif
}
+43 -53
View File
@@ -1,72 +1,62 @@
#ifndef _RAR_ERRHANDLER_
#define _RAR_ERRHANDLER_
enum RAR_EXIT // RAR exit code.
{
RARX_SUCCESS = 0,
RARX_WARNING = 1,
RARX_FATAL = 2,
RARX_CRC = 3,
RARX_LOCK = 4,
RARX_WRITE = 5,
RARX_OPEN = 6,
RARX_USERERROR = 7,
RARX_MEMORY = 8,
RARX_CREATE = 9,
RARX_NOFILES = 10,
RARX_BADPWD = 11,
RARX_USERBREAK = 255
};
#if (defined(GUI) || !defined(_WIN_32)) && !defined(SFX_MODULE) && !defined(_WIN_CE) || defined(RARDLL)
#define ALLOW_EXCEPTIONS
#endif
#define rarmalloc malloc
#define rarcalloc calloc
#define rarrealloc realloc
#define rarfree free
#define rarstrdup strdup
enum { RAR_SUCCESS,RAR_WARNING,RAR_FATAL_ERROR,RAR_CRC_ERROR,RAR_LOCK_ERROR,RAR_WRITE_ERROR,
RAR_OPEN_ERROR,RAR_USER_ERROR,RAR_MEMORY_ERROR,RAR_CREATE_ERROR,RAR_USER_BREAK=255};
class ErrorHandler
{
private:
RAR_EXIT ExitCode;
uint ErrCount;
void ErrMsg(const char *ArcName,const char *fmt,...);
int ExitCode;
int ErrCount;
bool EnableBreak;
bool Silent;
bool DisableShutdown; // Shutdown is not suitable after last error.
bool DoShutdown;
public:
ErrorHandler();
void Clean();
void MemoryError();
void OpenError(const wchar *FileName);
void CloseError(const wchar *FileName);
void ReadError(const wchar *FileName);
bool AskRepeatRead(const wchar *FileName);
void WriteError(const wchar *ArcName,const wchar *FileName);
void WriteErrorFAT(const wchar *FileName);
bool AskRepeatWrite(const wchar *FileName,bool DiskFull);
void SeekError(const wchar *FileName);
void GeneralErrMsg(const wchar *fmt,...);
void OpenError(const char *FileName);
void CloseError(const char *FileName);
void ReadError(const char *FileName);
bool AskRepeatRead(const char *FileName);
void WriteError(const char *ArcName,const char *FileName);
void WriteErrorFAT(const char *FileName);
bool AskRepeatWrite(const char *FileName);
void SeekError(const char *FileName);
void GeneralErrMsg(const char *Msg);
void MemoryErrorMsg();
void OpenErrorMsg(const wchar *FileName);
void OpenErrorMsg(const wchar *ArcName,const wchar *FileName);
void CreateErrorMsg(const wchar *FileName);
void CreateErrorMsg(const wchar *ArcName,const wchar *FileName);
void ReadErrorMsg(const wchar *FileName);
void ReadErrorMsg(const wchar *ArcName,const wchar *FileName);
void WriteErrorMsg(const wchar *ArcName,const wchar *FileName);
void ArcBrokenMsg(const wchar *ArcName);
void ChecksumFailedMsg(const wchar *ArcName,const wchar *FileName);
void UnknownMethodMsg(const wchar *ArcName,const wchar *FileName);
void Exit(RAR_EXIT ExitCode);
void SetErrorCode(RAR_EXIT Code);
RAR_EXIT GetErrorCode() {return ExitCode;}
uint GetErrorCount() {return ErrCount;}
void OpenErrorMsg(const char *FileName);
void OpenErrorMsg(const char *ArcName,const char *FileName);
void CreateErrorMsg(const char *FileName);
void CreateErrorMsg(const char *ArcName,const char *FileName);
void ReadErrorMsg(const char *ArcName,const char *FileName);
void WriteErrorMsg(const char *ArcName,const char *FileName);
void Exit(int ExitCode);
void SetErrorCode(int Code);
int GetErrorCode() {return(ExitCode);}
int GetErrorCount() {return(ErrCount);}
void SetSignalHandlers(bool Enable);
void Throw(RAR_EXIT Code);
void SetSilent(bool Mode) {Silent=Mode;}
bool GetSysErrMsg(wchar *Msg,size_t Size);
void Throw(int Code);
void SetSilent(bool Mode) {Silent=Mode;};
void SetShutdown(bool Mode) {DoShutdown=Mode;};
void SysErrMsg();
int GetSystemErrorCode();
void SetSystemErrorCode(int Code);
void SetDisableShutdown() {DisableShutdown=true;}
bool IsShutdownEnabled() {return !DisableShutdown;}
bool UserBreak; // Ctrl+Break is pressed.
bool MainExit; // main() is completed.
};
#endif
+41 -143
View File
@@ -1,43 +1,51 @@
#include "rar.hpp"
#include "hardlinks.cpp"
#include "win32stm.cpp"
#ifdef _WIN_ALL
#ifdef _WIN_32
#include "win32acl.cpp"
#include "win32lnk.cpp"
#include "win32stm.cpp"
#endif
#ifdef _BEOS
#include "beosea.cpp"
#endif
#if defined(_EMX) && !defined(_DJGPP)
#include "os2ea.cpp"
#endif
#ifdef _UNIX
#include "uowners.cpp"
#ifdef SAVE_LINKS
#include "ulinks.cpp"
#endif
#endif
// RAR2 service header extra records.
#ifndef SFX_MODULE
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name)
void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW)
{
if (Cmd->Test)
return;
switch(Arc.SubBlockHead.SubType)
{
#if defined(_EMX) && !defined(_DJGPP)
case EA_HEAD:
if (Cmd->ProcessEA)
ExtractOS2EA(Arc,Name);
break;
#endif
#ifdef _UNIX
case UO_HEAD:
if (Cmd->ProcessOwners)
ExtractUnixOwner20(Arc,Name);
ExtractUnixOwner(Arc,Name);
break;
#endif
#ifdef _WIN_ALL
#ifdef _BEOS
case BEEA_HEAD:
if (Cmd->ProcessEA)
ExtractBeEA(Arc,Name);
break;
#endif
#ifdef _WIN_32
case NTACL_HEAD:
if (Cmd->ProcessOwners)
ExtractACL20(Arc,Name);
ExtractACL(Arc,Name,NameW);
break;
case STREAM_HEAD:
ExtractStreams20(Arc,Name);
ExtractStreams(Arc,Name,NameW);
break;
#endif
}
@@ -45,134 +53,24 @@ void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name)
#endif
// RAR3 and RAR5 service header extra records.
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name)
void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW)
{
#ifdef _UNIX
if (!Cmd->Test && Cmd->ProcessOwners && Arc.Format==RARFMT15 &&
Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
ExtractUnixOwner30(Arc,Name);
#if defined(_EMX) && !defined(_DJGPP)
if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_OS2EA))
ExtractOS2EANew(Arc,Name);
#endif
#ifdef _WIN_ALL
if (!Cmd->Test && Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
ExtractACL(Arc,Name);
#ifdef _UNIX
if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
ExtractUnixOwnerNew(Arc,Name);
#endif
#ifdef _BEOS
if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
ExtractUnixOwnerNew(Arc,Name);
#endif
#ifdef _WIN_32
if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
ExtractACLNew(Arc,Name,NameW);
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
ExtractStreams(Arc,Name,Cmd->Test);
ExtractStreamsNew(Arc,Name,NameW);
#endif
}
// Extra data stored directly in file header.
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name)
{
#ifdef _UNIX
if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet)
SetUnixOwner(Arc,Name);
#endif
}
// Calculate a number of path components except \. and \..
static int CalcAllowedDepth(const wchar *Name)
{
int AllowedDepth=0;
while (*Name!=0)
{
if (IsPathDiv(Name[0]) && Name[1]!=0 && !IsPathDiv(Name[1]))
{
bool Dot=Name[1]=='.' && (IsPathDiv(Name[2]) || Name[2]==0);
bool Dot2=Name[1]=='.' && Name[2]=='.' && (IsPathDiv(Name[3]) || Name[3]==0);
if (!Dot && !Dot2)
AllowedDepth++;
}
Name++;
}
return AllowedDepth;
}
// Check if all existing path components are directories and not links.
static bool LinkInPath(const wchar *Name)
{
wchar Path[NM];
if (wcslen(Name)>=ASIZE(Path))
return true; // It should not be that long, skip.
wcsncpyz(Path,Name,ASIZE(Path));
for (wchar *s=Path+wcslen(Path)-1;s>Path;s--)
if (IsPathDiv(*s))
{
*s=0;
FindData FD;
if (FindFile::FastFind(Path,&FD,true) && (FD.IsLink || !FD.IsDir))
return true;
}
return false;
}
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
{
// Catch root dir based /path/file paths also as stuff like \\?\.
// Do not check PrepSrcName here, it can be root based if destination path
// is a root based.
if (IsFullRootPath(SrcName) || IsFullRootPath(TargetName))
return false;
// Number of ".." in link target.
int UpLevels=0;
for (int Pos=0;*TargetName!=0;Pos++)
{
bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' &&
(IsPathDiv(TargetName[2]) || TargetName[2]==0) &&
(Pos==0 || IsPathDiv(*(TargetName-1)));
if (Dot2)
UpLevels++;
TargetName++;
}
// If link target includes "..", it must not have another links
// in the path, because they can bypass our safety check. For example,
// suppose we extracted "lnk1" -> "." first and "lnk1/lnk2" -> ".." next
// or "dir/lnk1" -> ".." first and "dir/lnk1/lnk2" -> ".." next.
if (UpLevels>0 && LinkInPath(PrepSrcName))
return false;
// We could check just prepared src name, but for extra safety
// we check both original (as from archive header) and prepared
// (after applying the destination path and -ep switches) names.
int AllowedDepth=CalcAllowedDepth(SrcName); // Original name depth.
// Remove the destination path from prepared name if any. We should not
// count the destination path depth, because the link target must point
// inside of this path, not outside of it.
size_t ExtrPathLength=wcslen(Cmd->ExtrPath);
if (ExtrPathLength>0 && wcsncmp(PrepSrcName,Cmd->ExtrPath,ExtrPathLength)==0)
{
PrepSrcName+=ExtrPathLength;
while (IsPathDiv(*PrepSrcName))
PrepSrcName++;
}
int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName);
return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels;
}
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName)
{
#if defined(SAVE_LINKS) && defined(_UNIX)
// For RAR 3.x archives we process links even in test mode to skip link data.
if (Arc.Format==RARFMT15)
return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName);
if (Arc.Format==RARFMT50)
return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead);
#elif defined _WIN_ALL
// RAR 5.0 archives store link information in file header, so there is
// no need to additionally test it if we do not create a file.
if (Arc.Format==RARFMT50)
return CreateReparsePoint(Cmd,LinkName,&Arc.FileHead);
#endif
return false;
}
+2 -17
View File
@@ -1,23 +1,8 @@
#ifndef _RAR_EXTINFO_
#define _RAR_EXTINFO_
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName);
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName);
#ifdef _UNIX
void SetUnixOwner(Archive &Arc,const wchar *FileName);
#endif
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
void GetStreamNameNTFS(Archive &Arc,wchar *StreamName,size_t MaxSize);
#ifdef _WIN_ALL
bool SetPrivilege(LPCTSTR PrivName);
#endif
void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name);
void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name);
void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name);
void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW);
void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW);
#endif
+578 -922
View File
File diff suppressed because it is too large Load Diff
+18 -39
View File
@@ -6,57 +6,36 @@ enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
class CmdExtract
{
private:
EXTRACT_ARC_CODE ExtractArchive();
bool ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
void ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize);
#ifdef RARDLL
bool ExtrDllGetPassword();
#else
bool ExtrGetPassword(Archive &Arc,const wchar *ArcFileName);
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
void ConvertDosPassword(Archive &Arc,SecPassword &DestPwd);
#endif
void ExtrCreateDir(Archive &Arc,const wchar *ArcFileName);
bool ExtrCreateFile(Archive &Arc,File &CurFile);
bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName);
RarTime StartTime; // time when extraction started
CommandData *Cmd;
EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
ComprDataIO DataIO;
Unpack *Unp;
unsigned long TotalFileCount;
long TotalFileCount;
unsigned long FileCount;
unsigned long MatchedArgs;
long FileCount;
long MatchedArgs;
bool FirstFile;
bool AllMatchesExact;
bool ReconstructDone;
// If any non-zero solid file was successfully unpacked before current.
// If true and if current encrypted file is broken, obviously
// the password is correct and we can report broken CRC without
// any wrong password hints.
bool AnySolidDataUnpackedWell;
char ArcName[NM];
wchar ArcNameW[NM];
wchar ArcName[NM];
bool GlobalPassword;
bool PrevProcessed; // If previous file was successfully extracted or tested.
wchar DestFileName[NM];
char Password[MAXPASSWORD];
bool PasswordAll;
bool PrevExtracted;
bool SignatureFound;
char DestFileName[NM];
wchar DestFileNameW[NM];
bool PasswordCancelled;
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
bool Fat32,NotFat32;
#endif
public:
CmdExtract(CommandData *Cmd);
CmdExtract();
~CmdExtract();
void DoExtract();
void ExtractArchiveInit(Archive &Arc);
bool ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat);
static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize);
void DoExtract(CommandData *Cmd);
void ExtractArchiveInit(CommandData *Cmd,Archive &Arc);
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,
bool &Repeat);
static void UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize);
};
#endif
+189 -113
View File
@@ -1,163 +1,239 @@
#include "rar.hpp"
// If NewFile==NULL, we delete created file after user confirmation.
// It is useful we we need to overwrite an existing folder or file,
// but need user confirmation for that.
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
bool *UserReject,int64 FileSize,RarTime *FileTime,bool WriteOnly)
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize,
uint FileTime)
{
if (UserReject!=NULL)
*UserReject=false;
#ifdef _WIN_ALL
#if defined(_WIN_32) && !defined(_WIN_CE)
bool ShortNameChanged=false;
#endif
while (FileExist(Name))
while (FileExist(Name,NameW))
{
#if defined(_WIN_ALL)
#if defined(_WIN_32) && !defined(_WIN_CE)
if (!ShortNameChanged)
{
// Avoid the infinite loop if UpdateExistingShortName returns
// the same name.
ShortNameChanged=true;
// Maybe our long name matches the short name of existing file.
// Let's check if we can change the short name.
if (UpdateExistingShortName(Name))
if (UpdateExistingShortName(Name,NameW))
continue;
}
// Allow short name check again. It is necessary, because rename and
// autorename below can change the name, so we need to check it again.
ShortNameChanged=false;
#endif
UIASKREP_RESULT Choice=uiAskReplaceEx(Cmd,Name,MaxNameSize,FileSize,FileTime,(NewFile==NULL ? UIASKREP_F_NORENAME:0));
if (Choice==UIASKREP_R_REPLACE)
break;
if (Choice==UIASKREP_R_SKIP)
if (Mode==OVERWRITE_NONE)
{
if (UserReject!=NULL)
*UserReject=true;
return false;
return(false);
}
#ifdef SILENT
Mode=OVERWRITE_ALL;
#endif
if (Cmd->AllYes || Mode==OVERWRITE_ALL)
break;
if (Mode==OVERWRITE_ASK)
{
eprintf(St(MFileExists),Name);
int Choice=Ask(St(MYesNoAllRenQ));
if (Choice==1)
break;
if (Choice==2)
{
if (UserReject!=NULL)
*UserReject=true;
return(false);
}
if (Choice==3)
{
Cmd->Overwrite=OVERWRITE_ALL;
break;
}
if (Choice==4)
{
if (UserReject!=NULL)
*UserReject=true;
Cmd->Overwrite=OVERWRITE_NONE;
return(false);
}
if (Choice==5)
{
mprintf(St(MAskNewName));
char NewName[NM];
#ifdef _WIN_32
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
int Size=SrcFile.Read(NewName,sizeof(NewName)-1);
NewName[Size]=0;
OemToChar(NewName,NewName);
#else
fgets(NewName,sizeof(NewName),stdin);
#endif
RemoveLF(NewName);
if (PointToName(NewName)==NewName)
strcpy(PointToName(Name),NewName);
else
strcpy(Name,NewName);
if (NameW!=NULL)
*NameW=0;
continue;
}
if (Choice==6)
ErrHandler.Exit(RAR_USER_BREAK);
}
if (Mode==OVERWRITE_AUTORENAME)
{
if (GetAutoRenamedName(Name))
{
if (NameW!=NULL)
*NameW=0;
}
else
Mode=OVERWRITE_ASK;
continue;
}
if (Choice==UIASKREP_R_CANCEL)
ErrHandler.Exit(RARX_USERBREAK);
}
// Try to truncate the existing file first instead of delete,
// so we preserve existing file permissions such as NTFS permissions.
uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
if (NewFile!=NULL && NewFile->Create(Name,FileMode))
return true;
CreatePath(Name,true);
return NewFile!=NULL ? NewFile->Create(Name,FileMode):DelFile(Name);
if (NewFile!=NULL && NewFile->Create(Name,NameW))
return(true);
PrepareToDelete(Name,NameW);
CreatePath(Name,NameW,true);
return(NewFile!=NULL ? NewFile->Create(Name,NameW):DelFile(Name,NameW));
}
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize)
bool GetAutoRenamedName(char *Name)
{
wchar NewName[NM];
size_t NameLength=wcslen(Name);
wchar *Ext=GetExt(Name);
char NewName[NM];
if (strlen(Name)>sizeof(NewName)-10)
return(false);
char *Ext=GetExt(Name);
if (Ext==NULL)
Ext=Name+NameLength;
for (uint FileVer=1;;FileVer++)
Ext=Name+strlen(Name);
for (int FileVer=1;;FileVer++)
{
swprintf(NewName,ASIZE(NewName),L"%.*ls(%u)%ls",uint(Ext-Name),Name,FileVer,Ext);
sprintf(NewName,"%.*s(%d)%s",Ext-Name,Name,FileVer,Ext);
if (!FileExist(NewName))
{
wcsncpyz(Name,NewName,MaxNameSize);
strcpy(Name,NewName);
break;
}
if (FileVer>=1000000)
return false;
return(false);
}
return true;
return(true);
}
#if defined(_WIN_ALL)
// If we find a file, which short name is equal to 'Name', we try to change
// its short name, while preserving the long name. It helps when unpacking
// an archived file, which long name is equal to short name of already
// existing file. Otherwise we would overwrite the already existing file,
// even though its long name does not match the name of unpacking file.
bool UpdateExistingShortName(const wchar *Name)
#if defined(_WIN_32) && !defined(_WIN_CE)
bool UpdateExistingShortName(char *Name,wchar *NameW)
{
wchar LongPathName[NM];
DWORD Res=GetLongPathName(Name,LongPathName,ASIZE(LongPathName));
if (Res==0 || Res>=ASIZE(LongPathName))
return false;
wchar ShortPathName[NM];
Res=GetShortPathName(Name,ShortPathName,ASIZE(ShortPathName));
if (Res==0 || Res>=ASIZE(ShortPathName))
return false;
wchar *LongName=PointToName(LongPathName);
wchar *ShortName=PointToName(ShortPathName);
FindData fd;
if (!FindFile::FastFind(Name,NameW,&fd))
return(false);
if (*fd.Name==0 || *fd.ShortName==0)
return(false);
if (stricomp(PointToName(fd.Name),fd.ShortName)==0 ||
stricomp(PointToName(Name),fd.ShortName)!=0)
return(false);
// We continue only if file has a short name, which does not match its
// long name, and this short name is equal to name of file which we need
// to create.
if (*ShortName==0 || wcsicomp(LongName,ShortName)==0 ||
wcsicomp(PointToName(Name),ShortName)!=0)
return false;
// Generate the temporary new name for existing file.
wchar NewName[NM];
*NewName=0;
for (int I=0;I<10000 && *NewName==0;I+=123)
char NewName[NM];
for (int I=0;I<10000;I+=123)
{
// Here we copy the path part of file to create. We'll make the temporary
// file in the same folder.
wcsncpyz(NewName,Name,ASIZE(NewName));
// Here we set the random name part.
swprintf(PointToName(NewName),ASIZE(NewName),L"rtmp%d",I);
// If such file is already exist, try next random name.
if (FileExist(NewName))
*NewName=0;
strncpy(NewName,Name,sizeof(NewName));
sprintf(PointToName(NewName),"rtmp%d",I);
if (!FileExist(NewName))
break;
}
// If we could not generate the name not used by any other file, we return.
if (*NewName==0)
return false;
// FastFind returns the name without path, but we need the fully qualified
// name for renaming, so we use the path from file to create and long name
// from existing file.
wchar FullName[NM];
wcsncpyz(FullName,Name,ASIZE(FullName));
SetName(FullName,LongName,ASIZE(FullName));
// Rename the existing file to randomly generated name. Normally it changes
// the short name too.
if (FileExist(NewName))
return(false);
char FullName[NM];
strncpy(FullName,Name,sizeof(FullName));
strcpy(PointToName(FullName),PointToName(fd.Name));
if (!MoveFile(FullName,NewName))
return false;
// Now we need to create the temporary empty file with same name as
// short name of our already existing file. We do it to occupy its previous
// short name and not allow to use it again when renaming the file back to
// its original long name.
return(false);
File KeepShortFile;
bool Created=false;
if (!FileExist(Name))
Created=KeepShortFile.Create(Name,FMF_WRITE|FMF_SHAREREAD);
// Now we rename the existing file from temporary name to original long name.
// Since its previous short name is occupied by another file, it should
// get another short name.
Created=KeepShortFile.Create(Name);
MoveFile(NewName,FullName);
if (Created)
{
// Delete the temporary zero length file occupying the short name,
KeepShortFile.Close();
KeepShortFile.Delete();
}
// We successfully changed the short name. Maybe sometimes we'll simplify
// this function by use of SetFileShortName Windows API call.
// But SetFileShortName is not available in older Windows.
return true;
return(true);
}
/*
bool UpdateExistingShortName(char *Name,wchar *NameW)
{
if (WinNT()<5)
return(false);
FindData fd;
if (!FindFile::FastFind(Name,NameW,&fd))
return(false);
if (*fd.Name==0 || *fd.ShortName==0)
return(false);
if (stricomp(PointToName(fd.Name),fd.ShortName)==0 ||
stricomp(PointToName(Name),fd.ShortName)!=0)
return(false);
typedef BOOL (WINAPI *SETFILESHORTNAME)(HANDLE,LPCSTR);
static SETFILESHORTNAME pSetFileShortName=NULL;
if (pSetFileShortName==NULL)
{
HMODULE hKernel=GetModuleHandle("kernel32.dll");
if (hKernel!=NULL)
pSetFileShortName=(SETFILESHORTNAME)GetProcAddress(hKernel,"SetFileShortNameA");
if (pSetFileShortName==NULL)
return(false);
}
static bool RestoreEnabled=false;
if (!RestoreEnabled)
{
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
return(false);
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(NULL,SE_RESTORE_NAME,&tp.Privileges[0].Luid))
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
CloseHandle(hToken);
RestoreEnabled=true;
}
wchar FileNameW[NM];
GetWideName(Name,NameW,FileNameW);
HANDLE hFile=CreateFileW(FileNameW,GENERIC_WRITE|DELETE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
if (hFile==INVALID_HANDLE_VALUE)
return(false);
bool RetCode=false;
char FullName[NM];
wchar FullNameW[NM];
strcpy(FullName,Name);
strcpyw(FullNameW,NullToEmpty(NameW));
for (int I=1;I<1000000;I++)
{
char NewName[NM];
sprintf(NewName,"NAME~%d.%d",I%1000,I/1000+1);
strcpy(PointToName(FullName),NewName);
if (*FullNameW)
CharToWide(NewName,PointToName(FullNameW));
if (!FileExist(FullName,FullNameW))
{
RetCode=pSetFileShortName(hFile,NewName);
break;
}
}
CloseHandle(hFile);
return(RetCode);
}
*/
#endif
+6 -7
View File
@@ -1,14 +1,13 @@
#ifndef _RAR_FILECREATE_
#define _RAR_FILECREATE_
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
bool *UserReject,int64 FileSize=INT64NDF,
RarTime *FileTime=NULL,bool WriteOnly=false);
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize=INT64ERR,
uint FileTime=0);
bool GetAutoRenamedName(char *Name);
bool GetAutoRenamedName(wchar *Name,size_t MaxNameSize);
#if defined(_WIN_ALL)
bool UpdateExistingShortName(const wchar *Name);
#if defined(_WIN_32) && !defined(_WIN_CE)
bool UpdateExistingShortName(char *Name,wchar *NameW);
#endif
#endif
+320 -378
View File
File diff suppressed because it is too large Load Diff
+49 -91
View File
@@ -1,55 +1,34 @@
#ifndef _RAR_FILE_
#define _RAR_FILE_
#define FILE_USE_OPEN
#ifdef _WIN_ALL
typedef HANDLE FileHandle;
#define FILE_BAD_HANDLE INVALID_HANDLE_VALUE
#elif defined(FILE_USE_OPEN)
typedef off_t FileHandle;
#define FILE_BAD_HANDLE -1
#ifdef _WIN_32
typedef HANDLE FileHandle;
#define BAD_HANDLE INVALID_HANDLE_VALUE
#else
typedef FILE* FileHandle;
#define FILE_BAD_HANDLE NULL
typedef FILE* FileHandle;
#define BAD_HANDLE NULL
#endif
class RAROptions;
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD};
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD,FILE_HANDLEERR};
enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR};
enum FILE_MODE_FLAGS {
// Request read only access to file. Default for Open.
FMF_READ=0,
// Request both read and write access to file. Default for Create.
FMF_UPDATE=1,
// Request write only access to file.
FMF_WRITE=2,
// Open files which are already opened for write by other programs.
FMF_OPENSHARED=4,
// Open files only if no other program is opened it even in shared mode.
FMF_OPENEXCLUSIVE=8,
// Provide read access to created file for other programs.
FMF_SHAREREAD=16,
// Use standard NTFS names without trailing dots and spaces.
FMF_STANDARDNAMES=32,
// Mode flags are not defined yet.
FMF_UNDEFINED=256
struct FileStat
{
uint FileAttr;
uint FileTime;
Int64 FileSize;
bool IsDir;
};
class File
{
private:
void AddFileToList(FileHandle hFile);
FileHandle hFile;
bool LastWrite;
FILE_HANDLETYPE HandleType;
@@ -58,85 +37,64 @@ class File
bool NewFile;
bool AllowDelete;
bool AllowExceptions;
#ifdef _WIN_ALL
#ifdef _WIN_32
bool NoSequentialRead;
uint CreateMode;
#endif
bool PreserveAtime;
protected:
bool OpenShared; // Set by 'Archive' class.
bool OpenShared;
public:
wchar FileName[NM];
char FileName[NM];
wchar FileNameW[NM];
FILE_ERRORTYPE ErrorType;
uint CloseCount;
public:
File();
virtual ~File();
void operator = (File &SrcFile);
// Several functions below are 'virtual', because they are redefined
// by Archive for QOpen and by MultiFile for split files in WinRAR.
virtual bool Open(const wchar *Name,uint Mode=FMF_READ);
void TOpen(const wchar *Name);
bool WOpen(const wchar *Name);
bool Create(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
void TCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
bool WCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
virtual bool Close(); // 'virtual' for MultiFile class.
bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false);
void TOpen(const char *Name,const wchar *NameW=NULL);
bool WOpen(const char *Name,const wchar *NameW=NULL);
bool Create(const char *Name,const wchar *NameW=NULL);
void TCreate(const char *Name,const wchar *NameW=NULL);
bool WCreate(const char *Name,const wchar *NameW=NULL);
bool Close();
void Flush();
bool Delete();
bool Rename(const wchar *NewName);
bool Write(const void *Data,size_t Size);
virtual int Read(void *Data,size_t Size);
int DirectRead(void *Data,size_t Size);
virtual void Seek(int64 Offset,int Method);
bool RawSeek(int64 Offset,int Method);
virtual int64 Tell();
void Prealloc(int64 Size);
bool Rename(const char *NewName);
void Write(const void *Data,int Size);
int Read(void *Data,int Size);
int DirectRead(void *Data,int Size);
void Seek(Int64 Offset,int Method);
bool RawSeek(Int64 Offset,int Method);
Int64 Tell();
void Prealloc(Int64 Size);
byte GetByte();
void PutByte(byte Byte);
bool Truncate();
void Flush();
void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
static void SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta);
void SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta);
void SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr);
void GetOpenFileTime(RarTime *ft);
virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class.
int64 FileLength();
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
FILE_HANDLETYPE GetHandleType() {return HandleType;}
bool IsOpened() {return(hFile!=BAD_HANDLE);};
Int64 FileLength();
void SetHandleType(FILE_HANDLETYPE Type);
FILE_HANDLETYPE GetHandleType() {return(HandleType);};
bool IsDevice();
void fprintf(const char *fmt,...);
static bool RemoveCreated();
FileHandle GetHandle() {return hFile;}
void SetHandle(FileHandle Handle) {Close();hFile=Handle;}
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;}
int64 Copy(File &Dest,int64 Length=INT64NDF);
FileHandle GetHandle() {return(hFile);};
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;};
char *GetName() {return(FileName);}
long Copy(File &Dest,Int64 Length=INT64ERR);
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
#ifdef _WIN_ALL
#ifdef _WIN_32
void RemoveSequentialFlag() {NoSequentialRead=true;}
#endif
void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
#ifdef _UNIX
int GetFD()
{
#ifdef FILE_USE_OPEN
return hFile;
#else
return fileno(hFile);
#endif
}
#endif
static size_t CopyBufferSize()
{
#ifdef _WIN_ALL
// USB flash performance is poor with 64 KB buffer, 256+ KB resolved it.
// For copying from HDD to same HDD the best performance was with 256 KB
// buffer in XP and with 1 MB buffer in Win10.
return WinNT()==WNT_WXP ? 0x40000:0x100000;
#else
return 0x100000;
#endif
}
};
#endif
+366 -336
View File
@@ -1,126 +1,138 @@
#include "rar.hpp"
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr)
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
{
#ifdef _WIN_ALL
// Windows automatically removes dots and spaces in the end of directory
// name. So we detect such names and process them with \\?\ prefix.
wchar *LastChar=PointToLastChar(Name);
bool Special=*LastChar=='.' || *LastChar==' ';
BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL);
if (RetCode==0 && !FileExist(Name))
#ifdef _WIN_32
int Success;
if (WinNT() && NameW!=NULL && *NameW!=0)
Success=CreateDirectoryW(NameW,NULL);
else
Success=CreateDirectory(Name,NULL);
if (Success)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
RetCode=CreateDirectory(LongName,NULL);
}
if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
{
if (SetAttr)
SetFileAttr(Name,Attr);
return MKDIR_SUCCESS;
SetFileAttr(Name,NameW,Attr);
return(MKDIR_SUCCESS);
}
int ErrCode=GetLastError();
if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
return MKDIR_BADPATH;
return MKDIR_ERROR;
#elif defined(_UNIX)
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
mode_t uattr=SetAttr ? (mode_t)Attr:0777;
int ErrCode=mkdir(NameA,uattr);
if (ErrCode==-1)
return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR;
return MKDIR_SUCCESS;
return(MKDIR_BADPATH);
return(MKDIR_ERROR);
#endif
#ifdef _EMX
#ifdef _DJGPP
if (mkdir(Name,(Attr & FA_RDONLY) ? 0:S_IWUSR)==0)
#else
return MKDIR_ERROR;
if (__mkdir(Name)==0)
#endif
{
SetFileAttr(Name,NameW,Attr);
return(MKDIR_SUCCESS);
}
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
#endif
#ifdef _UNIX
int prevmask=umask(0);
int ErrCode=Name==NULL ? -1:mkdir(Name,(mode_t)Attr);
umask(prevmask);
if (ErrCode==-1)
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
return(MKDIR_SUCCESS);
#endif
}
bool CreatePath(const wchar *Path,bool SkipLastName)
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
{
if (Path==NULL || *Path==0)
return false;
#if defined(_WIN_ALL) || defined(_EMX)
#ifdef _WIN_32
uint DirAttr=0;
#else
uint DirAttr=0777;
#endif
bool Success=true;
for (const wchar *s=Path;*s!=0;s++)
{
wchar DirName[NM];
if (s-Path>=ASIZE(DirName))
break;
// Process all kinds of path separators, so user can enter Unix style
// path in Windows or Windows in Unix. s>Path check avoids attempting
// creating an empty directory for paths starting from path separator.
if (IsPathDiv(*s) && s>Path)
{
#ifdef _WIN_ALL
// We must not attempt to create "D:" directory, because first
// CreateDirectory will fail, so we'll use \\?\D:, which forces Wine
// to create "D:" directory.
if (s==Path+2 && Path[1]==':')
continue;
#ifdef UNICODE_SUPPORTED
bool Wide=PathW!=NULL && *PathW!=0 && UnicodeEnabled();
#else
bool Wide=false;
#endif
wcsncpy(DirName,Path,s-Path);
DirName[s-Path]=0;
bool IgnoreAscii=false;
Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS;
if (Success)
const char *s=Path;
for (int PosW=0;;PosW++)
{
if (s==NULL || s-Path>=NM || *s==0)
IgnoreAscii=true;
if (Wide && (PosW>=NM || PathW[PosW]==0) || !Wide && IgnoreAscii)
break;
if (Wide && PathW[PosW]==CPATHDIVIDER || !Wide && *s==CPATHDIVIDER)
{
wchar *DirPtrW=NULL,DirNameW[NM];
if (Wide)
{
strncpyw(DirNameW,PathW,PosW);
DirNameW[PosW]=0;
DirPtrW=DirNameW;
}
char DirName[NM];
if (IgnoreAscii)
WideToChar(DirPtrW,DirName);
else
{
#ifndef DBCS_SUPPORTED
if (*s!=CPATHDIVIDER)
for (const char *n=s;*n!=0 && n-Path<NM;n++)
if (*n==CPATHDIVIDER)
{
s=n;
break;
}
#endif
strncpy(DirName,Path,s-Path);
DirName[s-Path]=0;
}
if (MakeDir(DirName,DirPtrW,DirAttr)==MKDIR_SUCCESS)
{
#ifndef GUI
mprintf(St(MCreatDir),DirName);
mprintf(L" %s",St(MOk));
mprintf(" %s",St(MOk));
#endif
}
}
if (!IgnoreAscii)
s=charnext(s);
}
if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS;
return Success;
MakeDir(Path,PathW,DirAttr);
}
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
{
#if defined(_WIN_ALL)
#ifdef _WIN_32
if (!WinNT())
return;
bool sm=ftm!=NULL && ftm->IsSet();
bool sc=ftc!=NULL && ftc->IsSet();
bool sa=fta!=NULL && fta->IsSet();
uint DirAttr=GetFileAttr(Name);
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FILE_ATTRIBUTE_READONLY)!=0);
unsigned int DirAttr=GetFileAttr(Name);
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0);
if (ResetAttr)
SetFileAttr(Name,0);
SetFileAttr(Name,NULL,0);
HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
hFile=CreateFile(LongName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
}
if (hFile==INVALID_HANDLE_VALUE)
return;
FILETIME fm,fc,fa;
if (sm)
ftm->GetWinFT(&fm);
ftm->GetWin32(&fm);
if (sc)
ftc->GetWinFT(&fc);
ftc->GetWin32(&fc);
if (sa)
fta->GetWinFT(&fa);
fta->GetWin32(&fa);
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
CloseHandle(hFile);
if (ResetAttr)
SetFileAttr(Name,DirAttr);
SetFileAttr(Name,NULL,DirAttr);
#endif
#if defined(_UNIX) || defined(_EMX)
File::SetCloseFileTimeByName(Name,ftm,fta);
@@ -128,100 +140,139 @@ void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
}
bool IsRemovable(const wchar *Name)
bool IsRemovable(const char *Name)
{
#if defined(_WIN_ALL)
wchar Root[NM];
GetPathRoot(Name,Root,ASIZE(Root));
int Type=GetDriveType(*Root!=0 ? Root:NULL);
return Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM;
#ifdef _WIN_32
char Root[NM];
GetPathRoot(Name,Root);
int Type=GetDriveType(*Root ? Root:NULL);
return(Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM);
#elif defined(_EMX)
char Drive=toupper(Name[0]);
return((Drive=='A' || Drive=='B') && Name[1]==':');
#else
return false;
return(false);
#endif
}
#ifndef SFX_MODULE
int64 GetFreeDisk(const wchar *Name)
Int64 GetFreeDisk(const char *Name)
{
#ifdef _WIN_ALL
wchar Root[NM];
GetFilePath(Name,Root,ASIZE(Root));
#ifdef _WIN_32
char Root[NM];
GetPathRoot(Name,Root);
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
if (GetDiskFreeSpaceEx(*Root!=0 ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
return INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart);
return 0;
typedef BOOL (WINAPI *GETDISKFREESPACEEX)(
LPCTSTR,PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER
);
static GETDISKFREESPACEEX pGetDiskFreeSpaceEx=NULL;
if (pGetDiskFreeSpaceEx==NULL)
{
HMODULE hKernel=GetModuleHandle("kernel32.dll");
if (hKernel!=NULL)
pGetDiskFreeSpaceEx=(GETDISKFREESPACEEX)GetProcAddress(hKernel,"GetDiskFreeSpaceExA");
}
if (pGetDiskFreeSpaceEx!=NULL)
{
GetFilePath(Name,Root);
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
if (pGetDiskFreeSpaceEx(*Root ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
return(int32to64(uiUserFree.u.HighPart,uiUserFree.u.LowPart));
}
DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters;
if (!GetDiskFreeSpace(*Root ? Root:NULL,&SectorsPerCluster,&BytesPerSector,&FreeClusters,&TotalClusters))
return(1457664);
Int64 FreeSize=SectorsPerCluster*BytesPerSector;
FreeSize=FreeSize*FreeClusters;
return(FreeSize);
#elif defined(_BEOS)
char Root[NM];
GetFilePath(Name,Root);
dev_t Dev=dev_for_path(*Root ? Root:".");
if (Dev<0)
return(1457664);
fs_info Info;
if (fs_stat_dev(Dev,&Info)!=0)
return(1457664);
Int64 FreeSize=Info.block_size;
FreeSize=FreeSize*Info.free_blocks;
return(FreeSize);
#elif defined(_UNIX)
wchar Root[NM];
GetFilePath(Name,Root,ASIZE(Root));
char RootA[NM];
WideToChar(Root,RootA,ASIZE(RootA));
struct statvfs sfs;
if (statvfs(*RootA!=0 ? RootA:".",&sfs)!=0)
return 0;
int64 FreeSize=sfs.f_bsize;
FreeSize=FreeSize*sfs.f_bavail;
return FreeSize;
return(1457664);
#elif defined(_EMX)
int Drive=(!isalpha(Name[0]) || Name[1]!=':') ? 0:toupper(Name[0])-'A'+1;
if (_osmode == OS2_MODE)
{
FSALLOCATE fsa;
if (DosQueryFSInfo(Drive,1,&fsa,sizeof(fsa))!=0)
return(1457664);
Int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
FreeSize=FreeSize*fsa.cUnitAvail;
return(FreeSize);
}
else
{
union REGS regs,outregs;
memset(&regs,0,sizeof(regs));
regs.h.ah=0x36;
regs.h.dl=Drive;
_int86 (0x21,&regs,&outregs);
if (outregs.x.ax==0xffff)
return(1457664);
Int64 FreeSize=outregs.x.ax*outregs.x.cx;
FreeSize=FreeSize*outregs.x.bx;
return(FreeSize);
}
#else
return 0;
#define DISABLEAUTODETECT
return(1457664);
#endif
}
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
// Return 'true' for FAT and FAT32, so we can adjust the maximum supported
// file size to 4 GB for these file systems.
bool IsFAT(const wchar *Name)
bool FileExist(const char *Name,const wchar *NameW)
{
wchar Root[NM];
GetPathRoot(Name,Root,ASIZE(Root));
wchar FileSystem[MAX_PATH+1];
if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem)))
return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0;
return false;
}
#endif
bool FileExist(const wchar *Name)
{
#ifdef _WIN_ALL
return GetFileAttr(Name)!=0xffffffff;
#ifdef _WIN_32
if (WinNT() && NameW!=NULL && *NameW!=0)
return(GetFileAttributesW(NameW)!=0xffffffff);
else
return(GetFileAttributes(Name)!=0xffffffff);
#elif defined(ENABLE_ACCESS)
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
return access(NameA,0)==0;
return(access(Name,0)==0);
#else
FindData FD;
return FindFile::FastFind(Name,&FD);
struct FindData FD;
return(FindFile::FastFind(Name,NameW,&FD));
#endif
}
bool WildFileExist(const wchar *Name)
bool WildFileExist(const char *Name,const wchar *NameW)
{
if (IsWildcard(Name))
if (IsWildcard(Name,NameW))
{
FindFile Find;
Find.SetMask(Name);
FindData fd;
return Find.Next(&fd);
Find.SetMaskW(NameW);
struct FindData fd;
return(Find.Next(&fd));
}
return FileExist(Name);
return(FileExist(Name,NameW));
}
bool IsDir(uint Attr)
{
#ifdef _WIN_ALL
return Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_DIRECTORY)!=0;
#if defined (_WIN_32) || defined(_EMX)
return(Attr!=0xffffffff && (Attr & 0x10)!=0);
#endif
#if defined(_UNIX)
return (Attr & 0xF000)==0x4000;
return((Attr & 0xF000)==0x4000);
#endif
}
@@ -229,20 +280,28 @@ bool IsDir(uint Attr)
bool IsUnreadable(uint Attr)
{
#if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
return S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr);
return(S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr));
#endif
return(false);
}
bool IsLabel(uint Attr)
{
#if defined (_WIN_32) || defined(_EMX)
return((Attr & 8)!=0);
#else
return(false);
#endif
return false;
}
bool IsLink(uint Attr)
{
#ifdef _UNIX
return (Attr & 0xF000)==0xA000;
#elif defined(_WIN_ALL)
return (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0;
return((Attr & 0xF000)==0xA000);
#else
return false;
return(false);
#endif
}
@@ -253,260 +312,231 @@ bool IsLink(uint Attr)
bool IsDeleteAllowed(uint FileAttr)
{
#ifdef _WIN_ALL
return (FileAttr & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN))==0;
#if defined(_WIN_32) || defined(_EMX)
return((FileAttr & (FA_RDONLY|FA_SYSTEM|FA_HIDDEN))==0);
#else
return (FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR);
return((FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR));
#endif
}
void PrepareToDelete(const wchar *Name)
void PrepareToDelete(const char *Name,const wchar *NameW)
{
#if defined(_WIN_ALL) || defined(_EMX)
SetFileAttr(Name,0);
#if defined(_WIN_32) || defined(_EMX)
SetFileAttr(Name,NameW,0);
#endif
#ifdef _UNIX
if (Name!=NULL)
{
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
chmod(NameA,S_IRUSR|S_IWUSR|S_IXUSR);
}
chmod(Name,S_IRUSR|S_IWUSR|S_IXUSR);
#endif
}
uint GetFileAttr(const wchar *Name)
uint GetFileAttr(const char *Name,const wchar *NameW)
{
#ifdef _WIN_ALL
DWORD Attr=GetFileAttributes(Name);
if (Attr==0xffffffff)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
Attr=GetFileAttributes(LongName);
}
return Attr;
#ifdef _WIN_32
if (WinNT() && NameW!=NULL && *NameW!=0)
return(GetFileAttributesW(NameW));
else
return(GetFileAttributes(Name));
#elif defined(_DJGPP)
return(_chmod(Name,0));
#else
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
struct stat st;
if (stat(NameA,&st)!=0)
return 0;
return st.st_mode;
#endif
}
bool SetFileAttr(const wchar *Name,uint Attr)
{
#ifdef _WIN_ALL
bool Success=SetFileAttributes(Name,Attr)!=0;
if (!Success)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
Success=SetFileAttributes(LongName,Attr)!=0;
}
return Success;
#elif defined(_UNIX)
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
return chmod(NameA,(mode_t)Attr)==0;
if (stat(Name,&st)!=0)
return(0);
#ifdef _EMX
return(st.st_attr);
#else
return false;
return(st.st_mode);
#endif
#endif
}
#if 0
wchar *MkTemp(wchar *Name,size_t MaxSize)
bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr)
{
size_t Length=wcslen(Name);
RarTime CurTime;
CurTime.SetCurrentTime();
// We cannot use CurTime.GetWin() as is, because its lowest bits can
// have low informational value, like being a zero or few fixed numbers.
uint Random=(uint)(CurTime.GetWin()/100000);
// Using PID we guarantee that different RAR copies use different temp names
// even if started in exactly the same time.
uint PID=0;
#ifdef _WIN_ALL
PID=(uint)GetCurrentProcessId();
bool Success;
#ifdef _WIN_32
if (WinNT() && NameW!=NULL && *NameW!=0)
Success=SetFileAttributesW(NameW,Attr)!=0;
else
Success=SetFileAttributes(Name,Attr)!=0;
#elif defined(_DJGPP)
Success=_chmod(Name,1,Attr)!=-1;
#elif defined(_EMX)
Success=__chmod(Name,1,Attr)!=-1;
#elif defined(_UNIX)
PID=(uint)getpid();
Success=chmod(Name,(mode_t)Attr)==0;
#else
Success=false;
#endif
return(Success);
}
void ConvertNameToFull(const char *Src,char *Dest)
{
#ifdef _WIN_32
#ifndef _WIN_CE
char FullName[NM],*NamePtr;
if (GetFullPathName(Src,sizeof(FullName),FullName,&NamePtr))
strcpy(Dest,FullName);
else
#endif
if (Src!=Dest)
strcpy(Dest,Src);
#else
char FullName[NM];
if (IsPathDiv(*Src) || IsDiskLetter(Src))
strcpy(FullName,Src);
else
{
getcwd(FullName,sizeof(FullName));
AddEndSlash(FullName);
strcat(FullName,Src);
}
strcpy(Dest,FullName);
#endif
}
#ifndef SFX_MODULE
void ConvertNameToFull(const wchar *Src,wchar *Dest)
{
if (Src==NULL || *Src==0)
{
*Dest=0;
return;
}
#ifdef _WIN_32
#ifndef _WIN_CE
if (WinNT())
#endif
{
#ifndef _WIN_CE
wchar FullName[NM],*NamePtr;
if (GetFullPathNameW(Src,sizeof(FullName)/sizeof(FullName[0]),FullName,&NamePtr))
strcpyw(Dest,FullName);
else
#endif
if (Src!=Dest)
strcpyw(Dest,Src);
}
#ifndef _WIN_CE
else
{
char AnsiName[NM];
WideToChar(Src,AnsiName);
ConvertNameToFull(AnsiName,AnsiName);
CharToWide(AnsiName,Dest);
}
#endif
#else
char AnsiName[NM];
WideToChar(Src,AnsiName);
ConvertNameToFull(AnsiName,AnsiName);
CharToWide(AnsiName,Dest);
#endif
}
#endif
for (uint Attempt=0;;Attempt++)
#ifndef SFX_MODULE
char *MkTemp(char *Name)
{
int Length=strlen(Name);
if (Length<=6)
return(NULL);
int Random=clock();
for (int Attempt=0;;Attempt++)
{
uint Ext=Random%50000+Attempt;
wchar RndText[50];
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
return NULL;
wcsncpyz(Name+Length,RndText,MaxSize-Length);
sprintf(Name+Length-6,"%06u",Random+Attempt);
Name[Length-4]='.';
if (!FileExist(Name))
break;
if (Attempt==1000)
return(NULL);
}
return Name;
return(Name);
}
#endif
#if !defined(SFX_MODULE)
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
#ifndef SFX_MODULE
uint CalcFileCRC(File *SrcFile,Int64 Size)
{
int64 SavePos=SrcFile->Tell();
#ifndef SILENT
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
#endif
if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWPERCENT))!=0)
uiMsg(UIEVENT_FILESUMSTART);
if ((Flags & CALCFSUM_CURPOS)==0)
SrcFile->Seek(0,SEEK_SET);
const size_t BufSize=0x100000;
SaveFilePos SavePos(*SrcFile);
const int BufSize=0x10000;
Array<byte> Data(BufSize);
Int64 BlockCount=0;
uint DataCRC=0xffffffff;
int ReadSize;
DataHash HashCRC,HashBlake2;
HashCRC.Init(HASH_CRC32,Threads);
HashBlake2.Init(HASH_BLAKE2,Threads);
int64 BlockCount=0;
int64 TotalRead=0;
while (true)
SrcFile->Seek(0,SEEK_SET);
while ((ReadSize=SrcFile->Read(&Data[0],int64to32(Size==INT64ERR ? Int64(BufSize):Min(Int64(BufSize),Size))))!=0)
{
size_t SizeToRead;
if (Size==INT64NDF) // If we process the entire file.
SizeToRead=BufSize; // Then always attempt to read the entire buffer.
else
SizeToRead=(size_t)Min((int64)BufSize,Size);
int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
if (ReadSize==0)
break;
TotalRead+=ReadSize;
if ((++BlockCount & 0xf)==0)
++BlockCount;
if ((BlockCount & 15)==0)
{
#ifndef SILENT
if ((Flags & CALCFSUM_SHOWPROGRESS)!=0)
uiExtractProgress(TotalRead,FileLength,TotalRead,FileLength);
else
{
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
uiMsg(UIEVENT_FILESUMPROGRESS,ToPercent(TotalRead,FileLength));
}
#endif
Wait();
}
if (CRC32!=NULL)
HashCRC.Update(&Data[0],ReadSize);
if (Blake2!=NULL)
HashBlake2.Update(&Data[0],ReadSize);
if (Size!=INT64NDF)
DataCRC=CRC(DataCRC,&Data[0],ReadSize);
if (Size!=INT64ERR)
Size-=ReadSize;
}
SrcFile->Seek(SavePos,SEEK_SET);
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
uiMsg(UIEVENT_FILESUMEND);
if (CRC32!=NULL)
*CRC32=HashCRC.GetCRC32();
if (Blake2!=NULL)
{
HashValue Result;
HashBlake2.Result(&Result);
memcpy(Blake2,Result.Digest,sizeof(Result.Digest));
}
return(DataCRC^0xffffffff);
}
#endif
bool RenameFile(const wchar *SrcName,const wchar *DestName)
bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW)
{
#ifdef _WIN_ALL
bool Success=MoveFile(SrcName,DestName)!=0;
if (!Success)
{
wchar LongName1[NM],LongName2[NM];
if (GetWinLongPath(SrcName,LongName1,ASIZE(LongName1)) &&
GetWinLongPath(DestName,LongName2,ASIZE(LongName2)))
Success=MoveFile(LongName1,LongName2)!=0;
}
return Success;
#else
char SrcNameA[NM],DestNameA[NM];
WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA));
WideToChar(DestName,DestNameA,ASIZE(DestNameA));
bool Success=rename(SrcNameA,DestNameA)==0;
return Success;
#endif
return(rename(SrcName,DestName)==0);
}
bool DelFile(const wchar *Name)
bool DelFile(const char *Name)
{
#ifdef _WIN_ALL
bool Success=DeleteFile(Name)!=0;
if (!Success)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
Success=DeleteFile(LongName)!=0;
}
return Success;
#else
char NameA[NM];
WideToChar(Name,NameA,ASIZE(NameA));
bool Success=remove(NameA)==0;
return Success;
#endif
return(DelFile(Name,NULL));
}
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
bool SetFileCompression(const wchar *Name,bool State)
bool DelFile(const char *Name,const wchar *NameW)
{
HANDLE hFile=CreateFile(Name,FILE_READ_DATA|FILE_WRITE_DATA,
return(remove(Name)==0);
}
bool DelDir(const char *Name)
{
return(DelDir(Name,NULL));
}
bool DelDir(const char *Name,const wchar *NameW)
{
return(rmdir(Name)==0);
}
#if defined(_WIN_32) && !defined(_WIN_CE)
bool SetFileCompression(char *Name,wchar *NameW,bool State)
{
wchar FileNameW[NM];
GetWideName(Name,NameW,FileNameW);
HANDLE hFile=CreateFileW(FileNameW,FILE_READ_DATA|FILE_WRITE_DATA,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
wchar LongName[NM];
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
hFile=CreateFile(LongName,FILE_READ_DATA|FILE_WRITE_DATA,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
}
if (hFile==INVALID_HANDLE_VALUE)
return false;
return(false);
SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
DWORD Result;
int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
sizeof(NewState),NULL,0,&Result,NULL);
CloseHandle(hFile);
return RetCode!=0;
return(RetCode!=0);
}
#endif
+27 -38
View File
@@ -3,48 +3,37 @@
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr);
bool CreatePath(const wchar *Path,bool SkipLastName);
void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
bool IsRemovable(const wchar *Name);
#ifndef SFX_MODULE
int64 GetFreeDisk(const wchar *Name);
#endif
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
bool IsFAT(const wchar *Root);
#endif
bool FileExist(const wchar *Name);
bool WildFileExist(const wchar *Name);
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr);
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
bool IsRemovable(const char *Name);
Int64 GetFreeDisk(const char *Name);
bool FileExist(const char *Name,const wchar *NameW=NULL);
bool WildFileExist(const char *Name,const wchar *NameW=NULL);
bool IsDir(uint Attr);
bool IsUnreadable(uint Attr);
bool IsLabel(uint Attr);
bool IsLink(uint Attr);
void SetSFXMode(const wchar *FileName);
void EraseDiskContents(const wchar *FileName);
void SetSFXMode(const char *FileName);
void EraseDiskContents(const char *FileName);
bool IsDeleteAllowed(uint FileAttr);
void PrepareToDelete(const wchar *Name);
uint GetFileAttr(const wchar *Name);
bool SetFileAttr(const wchar *Name,uint Attr);
#if 0
wchar* MkTemp(wchar *Name,size_t MaxSize);
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);
void ConvertNameToFull(const char *Src,char *Dest);
void ConvertNameToFull(const wchar *Src,wchar *Dest);
char* MkTemp(char *Name);
uint CalcFileCRC(File *SrcFile,Int64 Size=INT64ERR);
bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW);
bool DelFile(const char *Name);
bool DelFile(const char *Name,const wchar *NameW);
bool DelDir(const char *Name);
bool DelDir(const char *Name,const wchar *NameW);
#if defined(_WIN_32) && !defined(_WIN_CE)
bool SetFileCompression(char *Name,wchar *NameW,bool State);
#endif
enum CALCFSUM_FLAGS {CALCFSUM_SHOWTEXT=1,CALCFSUM_SHOWPERCENT=2,CALCFSUM_SHOWPROGRESS=4,CALCFSUM_CURPOS=8};
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size=INT64NDF,uint Flags=0);
bool RenameFile(const wchar *SrcName,const wchar *DestName);
bool DelFile(const wchar *Name);
bool DelDir(const wchar *Name);
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
bool SetFileCompression(const wchar *Name,bool State);
#endif
#endif
+106 -133
View File
@@ -1,166 +1,139 @@
#include "rar.hpp"
bool ReadTextFile(
const wchar *Name,
StringList *List,
bool Config,
bool AbortOnError,
RAR_CHARSET SrcCharset,
bool Unquote,
bool SkipComments,
bool ExpandEnvStr)
{
wchar FileName[NM];
*FileName=0;
static bool IsUnicode(byte *Data,int Size);
if (Name!=NULL)
if (Config)
GetConfigName(Name,FileName,ASIZE(FileName),true,false);
else
wcsncpyz(FileName,Name,ASIZE(FileName));
bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
bool ConvertToAnsi,bool Unquote,bool SkipComments)
{
char FileName[NM];
if (Config)
GetConfigName(Name,FileName,true);
else
strcpy(FileName,Name);
File SrcFile;
if (*FileName!=0)
if (*FileName)
{
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName):SrcFile.Open(FileName,0);
bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName):SrcFile.Open(FileName);
if (!OpenCode)
{
if (AbortOnError)
ErrHandler.Exit(RARX_OPEN);
return false;
ErrHandler.Exit(RAR_OPEN_ERROR);
return(false);
}
}
else
SrcFile.SetHandleType(FILE_HANDLESTD);
uint DataSize=0,ReadSize;
const int ReadBlock=4096;
Array<byte> Data(ReadBlock);
unsigned int DataSize=0,ReadSize;
const int ReadBlock=1024;
Array<char> Data(ReadBlock+5);
while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0)
{
DataSize+=ReadSize;
Data.Add(ReadSize); // Always have ReadBlock available for next data.
}
// Set to really read size, so we can zero terminate it correctly.
Data.Alloc(DataSize);
int LittleEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0;
int BigEndian=DataSize>=2 && Data[0]==254 && Data[1]==255 ? 1:0;
bool Utf8=DataSize>=3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf;
if (SrcCharset==RCH_DEFAULT)
SrcCharset=DetectTextEncoding(&Data[0],DataSize);
Array<wchar> DataW;
if (SrcCharset==RCH_DEFAULT || SrcCharset==RCH_OEM || SrcCharset==RCH_ANSI)
{
Data.Push(0); // Zero terminate.
#if defined(_WIN_ALL)
if (SrcCharset==RCH_OEM)
OemToCharA((char *)&Data[0],(char *)&Data[0]);
#endif
DataW.Alloc(Data.Size());
CharToWide((char *)&Data[0],&DataW[0],DataW.Size());
Data.Add(ReadSize);
}
if (SrcCharset==RCH_UNICODE)
memset(&Data[DataSize],0,5);
if (IsUnicode((byte *)&Data[0],DataSize))
{
size_t Start=2; // Skip byte order mark.
if (!LittleEndian && !BigEndian) // No byte order mask.
wchar *CurStr=(wchar *)&Data[2];
Array<char> AnsiName;
while (*CurStr!=0)
{
Start=0;
LittleEndian=1;
}
DataW.Alloc(Data.Size()/2+1);
size_t End=Data.Size() & ~1; // We need even bytes number for UTF-16.
for (size_t I=Start;I<End;I+=2)
DataW[(I-Start)/2]=Data[I+BigEndian]+Data[I+LittleEndian]*256;
DataW[(End-Start)/2]=0;
}
if (SrcCharset==RCH_UTF8)
{
Data.Push(0); // Zero terminate data.
DataW.Alloc(Data.Size());
UtfToWide((const char *)(Data+(Utf8 ? 3:0)),&DataW[0],DataW.Size());
}
wchar *CurStr=&DataW[0];
while (*CurStr!=0)
{
wchar *NextStr=CurStr,*CmtPtr=NULL;
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
{
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
wchar *NextStr=CurStr,*CmtPtr=NULL;
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
{
*NextStr=0;
CmtPtr=NextStr;
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
{
*NextStr=0;
CmtPtr=NextStr;
}
NextStr++;
}
NextStr++;
}
bool Done=*NextStr==0;
*NextStr=0;
for (wchar *SpacePtr=(CmtPtr!=NULL ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
{
if (*SpacePtr!=' ' && *SpacePtr!='\t')
break;
*SpacePtr=0;
}
if (Unquote && *CurStr=='\"')
{
size_t Length=wcslen(CurStr);
if (CurStr[Length-1]=='\"')
*NextStr=0;
for (wchar *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
{
CurStr[Length-1]=0;
if (*SpacePtr!=' ' && *SpacePtr!='\t')
break;
*SpacePtr=0;
}
if (*CurStr)
{
int Length=strlenw(CurStr);
int AddSize=4*(Length-AnsiName.Size()+1);
if (AddSize>0)
AnsiName.Add(AddSize);
if (Unquote && *CurStr=='\"' && CurStr[Length-1]=='\"')
{
CurStr[Length-1]=0;
CurStr++;
}
WideToChar(CurStr,&AnsiName[0],AnsiName.Size());
List->AddString(&AnsiName[0],CurStr);
}
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
CurStr++;
}
}
bool Expanded=false;
#if defined(_WIN_ALL)
if (ExpandEnvStr && *CurStr=='%') // Expand environment variables in Windows.
{
wchar ExpName[NM];
*ExpName=0;
DWORD Result=ExpandEnvironmentStrings(CurStr,ExpName,ASIZE(ExpName));
Expanded=Result!=0 && Result<ASIZE(ExpName);
if (Expanded && *ExpName!=0)
List->AddString(ExpName);
}
#endif
if (!Expanded && *CurStr!=0)
List->AddString(CurStr);
if (Done)
break;
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
CurStr++;
}
return true;
else
{
char *CurStr=&Data[0];
while (*CurStr!=0)
{
char *NextStr=CurStr,*CmtPtr=NULL;
while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
{
if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
{
*NextStr=0;
CmtPtr=NextStr;
}
NextStr++;
}
*NextStr=0;
for (char *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
{
if (*SpacePtr!=' ' && *SpacePtr!='\t')
break;
*SpacePtr=0;
}
if (*CurStr)
{
if (Unquote && *CurStr=='\"')
{
int Length=strlen(CurStr);
if (CurStr[Length-1]=='\"')
{
CurStr[Length-1]=0;
CurStr++;
}
}
#if defined(_WIN_32)
if (ConvertToAnsi)
OemToChar(CurStr,CurStr);
#endif
List->AddString(CurStr);
}
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
CurStr++;
}
}
return(true);
}
RAR_CHARSET DetectTextEncoding(const byte *Data,size_t DataSize)
bool IsUnicode(byte *Data,int Size)
{
if (DataSize>3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf &&
IsTextUtf8(Data+3,DataSize-3))
return RCH_UTF8;
bool LittleEndian=DataSize>2 && Data[0]==255 && Data[1]==254;
bool BigEndian=DataSize>2 && Data[0]==254 && Data[1]==255;
if (LittleEndian || BigEndian)
for (size_t I=LittleEndian ? 3 : 2;I<DataSize;I+=2)
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
return RCH_UNICODE; // High byte in UTF-16 char is found.
return RCH_DEFAULT;
if (Size<4 || Data[0]!=0xff || Data[1]!=0xfe)
return(false);
for (int I=2;I<Size;I++)
if (Data[I]<32)
return(true);
return(false);
}
+3 -12
View File
@@ -1,17 +1,8 @@
#ifndef _RAR_FILESTR_
#define _RAR_FILESTR_
bool ReadTextFile(
const wchar *Name,
StringList *List,
bool Config,
bool AbortOnError=false,
RAR_CHARSET SrcCharset=RCH_DEFAULT,
bool Unquote=false,
bool SkipComments=false,
bool ExpandEnvStr=false
);
RAR_CHARSET DetectTextEncoding(const byte *Data,size_t DataSize);
bool ReadTextFile(char *Name,StringList *List,bool Config,
bool AbortOnError=false,bool ConvertToAnsi=false,
bool Unquote=false,bool SkipComments=false);
#endif
+179 -110
View File
@@ -3,8 +3,9 @@
FindFile::FindFile()
{
*FindMask=0;
FirstCall=true;
#ifdef _WIN_ALL
*FindMaskW=0;
FirstCall=TRUE;
#ifdef _WIN_32
hFind=INVALID_HANDLE_VALUE;
#else
dirp=NULL;
@@ -14,7 +15,7 @@ FindFile::FindFile()
FindFile::~FindFile()
{
#ifdef _WIN_ALL
#ifdef _WIN_32
if (hFind!=INVALID_HANDLE_VALUE)
FindClose(hFind);
#else
@@ -24,195 +25,263 @@ FindFile::~FindFile()
}
void FindFile::SetMask(const wchar *Mask)
void FindFile::SetMask(const char *FindMask)
{
wcsncpyz(FindMask,Mask,ASIZE(FindMask));
FirstCall=true;
strcpy(FindFile::FindMask,FindMask);
if (*FindMaskW==0)
CharToWide(FindMask,FindMaskW);
FirstCall=TRUE;
}
bool FindFile::Next(FindData *fd,bool GetSymLink)
void FindFile::SetMaskW(const wchar *FindMaskW)
{
if (FindMaskW==NULL)
return;
strcpyw(FindFile::FindMaskW,FindMaskW);
if (*FindMask==0)
WideToChar(FindMaskW,FindMask);
FirstCall=TRUE;
}
bool FindFile::Next(struct FindData *fd,bool GetSymLink)
{
fd->Error=false;
if (*FindMask==0)
return false;
#ifdef _WIN_ALL
return(false);
#ifdef _WIN_32
if (FirstCall)
{
if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
return false;
if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE)
return(false);
}
else
if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
return false;
if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE)
return(false);
#else
if (FirstCall)
{
wchar DirName[NM];
wcsncpyz(DirName,FindMask,ASIZE(DirName));
char DirName[NM];
strcpy(DirName,FindMask);
RemoveNameFromPath(DirName);
if (*DirName==0)
wcsncpyz(DirName,L".",ASIZE(DirName));
char DirNameA[NM];
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
if ((dirp=opendir(DirNameA))==NULL)
strcpy(DirName,".");
/*
else
{
int Length=strlen(DirName);
if (Length>1 && DirName[Length-1]==CPATHDIVIDER && (Length!=3 || !IsDriveDiv(DirName[1])))
DirName[Length-1]=0;
}
*/
if ((dirp=opendir(DirName))==NULL)
{
fd->Error=(errno!=ENOENT);
return false;
return(false);
}
}
while (1)
{
wchar Name[NM];
struct dirent *ent=readdir(dirp);
if (ent==NULL)
return false;
return(false);
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
continue;
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
if (CmpName(FindMask,Name,MATCH_NAMES))
if (CmpName(FindMask,ent->d_name,MATCH_NAMES))
{
wchar FullName[NM];
wcsncpyz(FullName,FindMask,ASIZE(FullName));
*PointToName(FullName)=0;
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
{
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
return false;
}
wcsncatz(FullName,Name,ASIZE(FullName));
if (!FastFind(FullName,fd,GetSymLink))
char FullName[NM];
strcpy(FullName,FindMask);
strcpy(PointToName(FullName),ent->d_name);
if (!FastFind(FullName,NULL,fd,GetSymLink))
{
ErrHandler.OpenErrorMsg(FullName);
continue;
}
wcsncpyz(fd->Name,FullName,ASIZE(fd->Name));
strcpy(fd->Name,FullName);
break;
}
}
*fd->NameW=0;
#ifdef _APPLE
if (!LowAscii(fd->Name))
UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
if (!LowAscii(fd->Name) && UnicodeEnabled())
CharToWide(fd->Name,fd->NameW);
#endif
#endif
fd->Flags=0;
fd->IsDir=IsDir(fd->FileAttr);
fd->IsLink=IsLink(fd->FileAttr);
FirstCall=false;
wchar *NameOnly=PointToName(fd->Name);
if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
return Next(fd);
return true;
FirstCall=FALSE;
char *Name=PointToName(fd->Name);
if (strcmp(Name,".")==0 || strcmp(Name,"..")==0)
return(Next(fd));
return(true);
}
bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
bool FindFile::FastFind(const char *FindMask,const wchar *FindMaskW,struct FindData *fd,bool GetSymLink)
{
fd->Error=false;
#ifndef _UNIX
if (IsWildcard(FindMask))
return false;
if (IsWildcard(FindMask,FindMaskW))
return(false);
#endif
#ifdef _WIN_ALL
HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd);
#ifdef _WIN_32
HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd);
if (hFind==INVALID_HANDLE_VALUE)
return false;
return(false);
FindClose(hFind);
#else
char FindMaskA[NM];
WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA));
struct stat st;
if (GetSymLink)
{
#ifdef SAVE_LINKS
if (lstat(FindMaskA,&st)!=0)
if (lstat(FindMask,&st)!=0)
#else
if (stat(FindMaskA,&st)!=0)
if (stat(FindMask,&st)!=0)
#endif
{
fd->Error=(errno!=ENOENT);
return false;
return(false);
}
}
else
if (stat(FindMaskA,&st)!=0)
if (stat(FindMask,&st)!=0)
{
fd->Error=(errno!=ENOENT);
return false;
return(false);
}
#ifdef _DJGPP
fd->FileAttr=chmod(FindMask,0);
#elif defined(_EMX)
fd->FileAttr=st.st_attr;
#else
fd->FileAttr=st.st_mode;
#endif
fd->IsDir=IsDir(st.st_mode);
fd->Size=st.st_size;
fd->mtime=st.st_mtime;
fd->atime=st.st_atime;
fd->ctime=st.st_ctime;
fd->FileTime=fd->mtime.GetDos();
strcpy(fd->Name,FindMask);
#ifdef UNIX_TIME_NS
fd->mtime.SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec);
fd->atime.SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec);
fd->ctime.SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec);
#else
fd->mtime.SetUnix(st.st_mtime);
fd->atime.SetUnix(st.st_atime);
fd->ctime.SetUnix(st.st_ctime);
*fd->NameW=0;
#ifdef _APPLE
if (!LowAscii(fd->Name))
UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
if (!LowAscii(fd->Name) && UnicodeEnabled())
CharToWide(fd->Name,fd->NameW);
#endif
wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name));
#endif
fd->Flags=0;
fd->IsDir=IsDir(fd->FileAttr);
fd->IsLink=IsLink(fd->FileAttr);
return true;
return(true);
}
#ifdef _WIN_ALL
HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd)
#ifdef _WIN_32
HANDLE FindFile::Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd)
{
WIN32_FIND_DATA FindData;
if (hFind==INVALID_HANDLE_VALUE)
#ifndef _WIN_CE
if (WinNT())
#endif
{
hFind=FindFirstFile(Mask,&FindData);
wchar WideMask[NM];
if (MaskW!=NULL && *MaskW!=0)
strcpyw(WideMask,MaskW);
else
CharToWide(Mask,WideMask);
WIN32_FIND_DATAW FindData;
if (hFind==INVALID_HANDLE_VALUE)
{
wchar LongMask[NM];
if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask)))
hFind=FindFirstFile(LongMask,&FindData);
hFind=FindFirstFileW(WideMask,&FindData);
if (hFind==INVALID_HANDLE_VALUE)
{
int SysErr=GetLastError();
fd->Error=(SysErr!=ERROR_FILE_NOT_FOUND &&
SysErr!=ERROR_PATH_NOT_FOUND &&
SysErr!=ERROR_NO_MORE_FILES);
}
}
if (hFind==INVALID_HANDLE_VALUE)
else
if (!FindNextFileW(hFind,&FindData))
{
hFind=INVALID_HANDLE_VALUE;
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
}
if (hFind!=INVALID_HANDLE_VALUE)
{
int SysErr=GetLastError();
// We must not issue an error for "file not found" and "path not found",
// because it is normal to not find anything for wildcard mask when
// archiving. Also searching for non-existent file is normal in some
// other modules, like WinRAR scanning for winrar_theme_description.txt
// to check if any themes are available.
fd->Error=SysErr!=ERROR_FILE_NOT_FOUND &&
SysErr!=ERROR_PATH_NOT_FOUND &&
SysErr!=ERROR_NO_MORE_FILES;
strcpyw(fd->NameW,WideMask);
strcpyw(PointToName(fd->NameW),FindData.cFileName);
WideToChar(fd->NameW,fd->Name);
fd->Size=int32to64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
fd->FileAttr=FindData.dwFileAttributes;
WideToChar(FindData.cAlternateFileName,fd->ShortName);
fd->ftCreationTime=FindData.ftCreationTime;
fd->ftLastAccessTime=FindData.ftLastAccessTime;
fd->ftLastWriteTime=FindData.ftLastWriteTime;
fd->mtime=FindData.ftLastWriteTime;
fd->ctime=FindData.ftCreationTime;
fd->atime=FindData.ftLastAccessTime;
fd->FileTime=fd->mtime.GetDos();
#ifndef _WIN_CE
if (LowAscii(fd->NameW))
*fd->NameW=0;
#endif
}
}
#ifndef _WIN_CE
else
if (!FindNextFile(hFind,&FindData))
{
hFind=INVALID_HANDLE_VALUE;
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
}
if (hFind!=INVALID_HANDLE_VALUE)
{
wcsncpyz(fd->Name,Mask,ASIZE(fd->Name));
SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name));
fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
fd->FileAttr=FindData.dwFileAttributes;
fd->ftCreationTime=FindData.ftCreationTime;
fd->ftLastAccessTime=FindData.ftLastAccessTime;
fd->ftLastWriteTime=FindData.ftLastWriteTime;
fd->mtime.SetWinFT(&FindData.ftLastWriteTime);
fd->ctime.SetWinFT(&FindData.ftCreationTime);
fd->atime.SetWinFT(&FindData.ftLastAccessTime);
char CharMask[NM];
if (Mask!=NULL && *Mask!=0)
strcpy(CharMask,Mask);
else
WideToChar(MaskW,CharMask);
WIN32_FIND_DATA FindData;
if (hFind==INVALID_HANDLE_VALUE)
{
hFind=FindFirstFile(CharMask,&FindData);
if (hFind==INVALID_HANDLE_VALUE)
{
int SysErr=GetLastError();
fd->Error=SysErr!=ERROR_FILE_NOT_FOUND && SysErr!=ERROR_PATH_NOT_FOUND;
}
}
else
if (!FindNextFile(hFind,&FindData))
{
hFind=INVALID_HANDLE_VALUE;
fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
}
if (hFind!=INVALID_HANDLE_VALUE)
{
strcpy(fd->Name,CharMask);
strcpy(PointToName(fd->Name),FindData.cFileName);
CharToWide(fd->Name,fd->NameW);
fd->Size=int32to64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
fd->FileAttr=FindData.dwFileAttributes;
strcpy(fd->ShortName,FindData.cAlternateFileName);
fd->ftCreationTime=FindData.ftCreationTime;
fd->ftLastAccessTime=FindData.ftLastAccessTime;
fd->ftLastWriteTime=FindData.ftLastWriteTime;
fd->mtime=FindData.ftLastWriteTime;
fd->ctime=FindData.ftCreationTime;
fd->atime=FindData.ftLastAccessTime;
fd->FileTime=fd->mtime.GetDos();
if (LowAscii(fd->Name))
*fd->NameW=0;
}
}
fd->Flags=0;
return hFind;
#endif
return(hFind);
}
#endif
+16 -17
View File
@@ -1,39 +1,37 @@
#ifndef _RAR_FINDDATA_
#define _RAR_FINDDATA_
enum FINDDATA_FLAGS {
FDDF_SECONDDIR=1 // Second encounter of same directory in SCAN_GETDIRSTWICE ScanTree mode.
};
struct FindData
{
wchar Name[NM];
uint64 Size;
char Name[NM];
wchar NameW[NM];
Int64 Size;
uint FileAttr;
uint FileTime;
bool IsDir;
bool IsLink;
RarTime mtime;
RarTime ctime;
RarTime atime;
#ifdef _WIN_ALL
#ifdef _WIN_32
char ShortName[NM];
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
#endif
uint Flags;
bool Error;
};
class FindFile
{
private:
#ifdef _WIN_ALL
static HANDLE Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd);
#ifdef _WIN_32
static HANDLE Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd);
#endif
wchar FindMask[NM];
bool FirstCall;
#ifdef _WIN_ALL
char FindMask[NM];
wchar FindMaskW[NM];
int FirstCall;
#ifdef _WIN_32
HANDLE hFind;
#else
DIR *dirp;
@@ -41,9 +39,10 @@ class FindFile
public:
FindFile();
~FindFile();
void SetMask(const wchar *Mask);
bool Next(FindData *fd,bool GetSymLink=false);
static bool FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink=false);
void SetMask(const char *FindMask);
void SetMaskW(const wchar *FindMaskW);
bool Next(struct FindData *fd,bool GetSymLink=false);
static bool FastFind(const char *FindMask,const wchar *FindMaskW,struct FindData *fd,bool GetSymLink=false);
};
#endif
+6 -34
View File
@@ -1,52 +1,24 @@
#include "rar.hpp"
BitInput::BitInput(bool AllocBuffer)
BitInput::BitInput()
{
ExternalBuffer=false;
if (AllocBuffer)
{
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
// So let's allocate 3 additional bytes for situation, when we need to
// read only 1 byte from the last position of buffer and avoid a crash
// from access to next 3 bytes, which contents we do not need.
size_t BufSize=MAX_SIZE+3;
InBuf=new byte[BufSize];
// Ensure that we get predictable results when accessing bytes in area
// not filled with read data.
memset(InBuf,0,BufSize);
}
else
InBuf=NULL;
InBuf=new byte[MAX_SIZE];
}
BitInput::~BitInput()
{
if (!ExternalBuffer)
delete[] InBuf;
delete[] InBuf;
}
void BitInput::faddbits(uint Bits)
void BitInput::faddbits(int Bits)
{
// Function wrapped version of inline addbits to save code size.
addbits(Bits);
}
uint BitInput::fgetbits()
unsigned int BitInput::fgetbits()
{
// Function wrapped version of inline getbits to save code size.
return getbits();
return(getbits());
}
void BitInput::SetExternalBuffer(byte *Buf)
{
if (InBuf!=NULL && !ExternalBuffer)
delete[] InBuf;
InBuf=Buf;
ExternalBuffer=true;
}
+11 -42
View File
@@ -4,65 +4,34 @@
class BitInput
{
public:
enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer.
int InAddr; // Curent byte position in the buffer.
int InBit; // Current bit position in the current byte.
bool ExternalBuffer;
enum BufferSize {MAX_SIZE=0x8000};
protected:
int InAddr,InBit;
public:
BitInput(bool AllocBuffer);
BitInput();
~BitInput();
byte *InBuf; // Dynamically allocated input buffer.
byte *InBuf;
void InitBitInput()
{
InAddr=InBit=0;
}
// Move forward by 'Bits' bits.
void addbits(uint Bits)
void addbits(int Bits)
{
Bits+=InBit;
InAddr+=Bits>>3;
InBit=Bits&7;
}
// Return 16 bits from current position in the buffer.
// Bit at (InAddr,InBit) has the highest position in returning data.
uint getbits()
unsigned int getbits()
{
uint BitField=(uint)InBuf[InAddr] << 16;
unsigned int BitField=(uint)InBuf[InAddr] << 16;
BitField|=(uint)InBuf[InAddr+1] << 8;
BitField|=(uint)InBuf[InAddr+2];
BitField >>= (8-InBit);
return BitField & 0xffff;
return(BitField & 0xffff);
}
// Return 32 bits from current position in the buffer.
// Bit at (InAddr,InBit) has the highest position in returning data.
uint getbits32()
{
uint BitField=(uint)InBuf[InAddr] << 24;
BitField|=(uint)InBuf[InAddr+1] << 16;
BitField|=(uint)InBuf[InAddr+2] << 8;
BitField|=(uint)InBuf[InAddr+3];
BitField <<= InBit;
BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
return BitField & 0xffffffff;
}
void faddbits(uint Bits);
uint fgetbits();
// Check if buffer has enough space for IncPtr bytes. Returns 'true'
// if buffer will be overflown.
bool Overflow(uint IncPtr)
{
return InAddr+IncPtr>=MAX_SIZE;
}
void SetExternalBuffer(byte *Buf);
void faddbits(int Bits);
unsigned int fgetbits();
};
#endif
-3
View File
@@ -1,7 +1,4 @@
#define INCLUDEGLOBAL
#if defined(__BORLANDC__) || defined(_MSC_VER)
#pragma hdrstop
#endif
#include "rar.hpp"
-39
View File
@@ -1,39 +0,0 @@
bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
{
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
if (!FileExist(NameExisting))
{
uiMsg(UIERROR_HLINKCREATE,NameNew);
uiMsg(UIERROR_NOLINKTARGET);
ErrHandler.SetErrorCode(RARX_CREATE);
return false;
}
CreatePath(NameNew,true);
#ifdef _WIN_ALL
bool Success=CreateHardLink(NameNew,NameExisting,NULL)!=0;
if (!Success)
{
uiMsg(UIERROR_HLINKCREATE,NameNew);
ErrHandler.SysErrMsg();
ErrHandler.SetErrorCode(RARX_CREATE);
}
return Success;
#elif defined(_UNIX)
char NameExistingA[NM],NameNewA[NM];
WideToChar(NameExisting,NameExistingA,ASIZE(NameExistingA));
WideToChar(NameNew,NameNewA,ASIZE(NameNewA));
bool Success=link(NameExistingA,NameNewA)==0;
if (!Success)
{
uiMsg(UIERROR_HLINKCREATE,NameNew);
ErrHandler.SysErrMsg();
ErrHandler.SetErrorCode(RARX_CREATE);
}
return Success;
#else
return false;
#endif
}
-135
View File
@@ -1,135 +0,0 @@
#include "rar.hpp"
void HashValue::Init(HASH_TYPE Type)
{
HashValue::Type=Type;
// Zero length data CRC32 is 0. It is important to set it when creating
// headers with no following data like directories or symlinks.
if (Type==HASH_RAR14 || Type==HASH_CRC32)
CRC32=0;
if (Type==HASH_BLAKE2)
{
// dd0e891776933f43c7d032b08a917e25741f8aa9a12c12e1cac8801500f2ca4f
// is BLAKE2sp hash of empty data. We init the structure to this value,
// so if we create a file or service header with no following data like
// "file copy" or "symlink", we set the checksum to proper value avoiding
// additional header type or size checks when extracting.
static byte EmptyHash[32]={
0xdd, 0x0e, 0x89, 0x17, 0x76, 0x93, 0x3f, 0x43,
0xc7, 0xd0, 0x32, 0xb0, 0x8a, 0x91, 0x7e, 0x25,
0x74, 0x1f, 0x8a, 0xa9, 0xa1, 0x2c, 0x12, 0xe1,
0xca, 0xc8, 0x80, 0x15, 0x00, 0xf2, 0xca, 0x4f
};
memcpy(Digest,EmptyHash,sizeof(Digest));
}
}
bool HashValue::operator == (const HashValue &cmp)
{
if (Type==HASH_NONE || cmp.Type==HASH_NONE)
return true;
if (Type==HASH_RAR14 && cmp.Type==HASH_RAR14 ||
Type==HASH_CRC32 && cmp.Type==HASH_CRC32)
return CRC32==cmp.CRC32;
if (Type==HASH_BLAKE2 && cmp.Type==HASH_BLAKE2)
return memcmp(Digest,cmp.Digest,sizeof(Digest))==0;
return false;
}
DataHash::DataHash()
{
blake2ctx=NULL;
HashType=HASH_NONE;
#ifdef RAR_SMP
ThPool=NULL;
MaxThreads=0;
#endif
}
DataHash::~DataHash()
{
#ifdef RAR_SMP
delete ThPool;
#endif
cleandata(&CurCRC32, sizeof(CurCRC32));
if (blake2ctx!=NULL)
{
cleandata(blake2ctx, sizeof(blake2sp_state));
delete blake2ctx;
}
}
void DataHash::Init(HASH_TYPE Type,uint MaxThreads)
{
if (blake2ctx==NULL)
blake2ctx=new blake2sp_state;
HashType=Type;
if (Type==HASH_RAR14)
CurCRC32=0;
if (Type==HASH_CRC32)
CurCRC32=0xffffffff; // Initial CRC32 value.
if (Type==HASH_BLAKE2)
blake2sp_init(blake2ctx);
#ifdef RAR_SMP
DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads);
#endif
}
void DataHash::Update(const void *Data,size_t DataSize)
{
#ifndef SFX_MODULE
if (HashType==HASH_RAR14)
CurCRC32=Checksum14((ushort)CurCRC32,Data,DataSize);
#endif
if (HashType==HASH_CRC32)
CurCRC32=CRC32(CurCRC32,Data,DataSize);
if (HashType==HASH_BLAKE2)
{
#ifdef RAR_SMP
if (MaxThreads>1 && ThPool==NULL)
ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER);
blake2ctx->ThPool=ThPool;
blake2ctx->MaxThreads=MaxThreads;
#endif
blake2sp_update( blake2ctx, (byte *)Data, DataSize);
}
}
void DataHash::Result(HashValue *Result)
{
Result->Type=HashType;
if (HashType==HASH_RAR14)
Result->CRC32=CurCRC32;
if (HashType==HASH_CRC32)
Result->CRC32=CurCRC32^0xffffffff;
if (HashType==HASH_BLAKE2)
{
// Preserve the original context, so we can continue hashing if necessary.
blake2sp_state res=*blake2ctx;
blake2sp_final(&res,Result->Digest);
}
}
uint DataHash::GetCRC32()
{
return HashType==HASH_CRC32 ? CurCRC32^0xffffffff : 0;
}
bool DataHash::Cmp(HashValue *CmpValue,byte *Key)
{
HashValue Final;
Result(&Final);
if (Key!=NULL)
ConvertHashToMAC(&Final,Key);
return Final==*CmpValue;
}
-52
View File
@@ -1,52 +0,0 @@
#ifndef _RAR_DATAHASH_
#define _RAR_DATAHASH_
enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
struct HashValue
{
void Init(HASH_TYPE Type);
bool operator == (const HashValue &cmp);
bool operator != (const HashValue &cmp) {return !(*this==cmp);}
HASH_TYPE Type;
union
{
uint CRC32;
byte Digest[SHA256_DIGEST_SIZE];
};
};
#ifdef RAR_SMP
class ThreadPool;
class DataHash;
#endif
class DataHash
{
private:
HASH_TYPE HashType;
uint CurCRC32;
blake2sp_state *blake2ctx;
#ifdef RAR_SMP
ThreadPool *ThPool;
uint MaxThreads;
// Upper limit for maximum threads to prevent wasting threads in pool.
static const uint MaxHashThreads=8;
#endif
public:
DataHash();
~DataHash();
void Init(HASH_TYPE Type,uint MaxThreads);
void Update(const void *Data,size_t DataSize);
void Result(HashValue *Result);
uint GetCRC32();
bool Cmp(HashValue *CmpValue,byte *Key);
HASH_TYPE Type() {return HashType;}
};
#endif
-61
View File
@@ -1,61 +0,0 @@
#include "rar.hpp"
void FileHeader::Reset(size_t SubDataSize)
{
SubData.Alloc(SubDataSize);
BaseBlock::Reset();
FileHash.Init(HASH_NONE);
mtime.Reset();
atime.Reset();
ctime.Reset();
SplitBefore=false;
SplitAfter=false;
UnknownUnpSize=0;
SubFlags=0; // Important for RAR 3.0 subhead.
CryptMethod=CRYPT_NONE;
Encrypted=false;
SaltSet=false;
UsePswCheck=false;
UseHashKey=false;
Lg2Count=0;
Solid=false;
Dir=false;
WinSize=0;
Inherited=false;
SubBlock=false;
CommentInHeader=false;
Version=false;
LargeFile=false;
RedirType=FSREDIR_NONE;
DirTarget=false;
UnixOwnerSet=false;
}
FileHeader& FileHeader::operator = (FileHeader &hd)
{
SubData.Reset();
memcpy(this,&hd,sizeof(*this));
SubData.CleanData();
SubData=hd.SubData;
return *this;
}
void MainHeader::Reset()
{
HighPosAV=0;
PosAV=0;
CommentInHeader=false;
PackComment=false;
Locator=false;
QOpenOffset=0;
QOpenMaxSize=0;
RROffset=0;
RRMaxSize=0;
}
+168 -216
View File
@@ -1,159 +1,154 @@
#ifndef _RAR_HEADERS_
#define _RAR_HEADERS_
#define SIZEOF_MARKHEAD3 7 // Size of RAR 4.x archive mark header.
#define SIZEOF_MAINHEAD14 7 // Size of RAR 1.4 main archive header.
#define SIZEOF_MAINHEAD3 13 // Size of RAR 4.x main archive header.
#define SIZEOF_FILEHEAD14 21 // Size of RAR 1.4 file header.
#define SIZEOF_FILEHEAD3 32 // Size of RAR 3.0 file header.
#define SIZEOF_MARKHEAD 7
#define SIZEOF_OLDMHD 7
#define SIZEOF_NEWMHD 13
#define SIZEOF_OLDLHD 21
#define SIZEOF_NEWLHD 32
#define SIZEOF_SHORTBLOCKHEAD 7
#define SIZEOF_LONGBLOCKHEAD 11
#define SIZEOF_SUBBLOCKHEAD 14
#define SIZEOF_COMMHEAD 13
#define SIZEOF_PROTECTHEAD 26
#define SIZEOF_AVHEAD 14
#define SIZEOF_SIGNHEAD 15
#define SIZEOF_UOHEAD 18
#define SIZEOF_MACHEAD 22
#define SIZEOF_EAHEAD 24
#define SIZEOF_BEEAHEAD 24
#define SIZEOF_STREAMHEAD 26
#define VER_PACK 29U
#define VER_PACK5 50U // It is stored as 0, but we subtract 50 when saving an archive.
#define VER_UNPACK 29U
#define VER_UNPACK5 50U // It is stored as 0, but we add 50 when reading an archive.
#define VER_UNKNOWN 9999U // Just some large value.
#define PACK_VER 29
#define PACK_CRYPT_VER 29
#define UNP_VER 36
#define CRYPT_VER 29
#define AV_VER 20
#define PROTECT_VER 20
#define MHD_VOLUME 0x0001U
#define MHD_VOLUME 0x0001
#define MHD_COMMENT 0x0002
#define MHD_LOCK 0x0004
#define MHD_SOLID 0x0008
#define MHD_PACK_COMMENT 0x0010
#define MHD_NEWNUMBERING 0x0010
#define MHD_AV 0x0020
#define MHD_PROTECT 0x0040
#define MHD_PASSWORD 0x0080
#define MHD_FIRSTVOLUME 0x0100
#define MHD_ENCRYPTVER 0x0200
// Old style main archive comment embed into main archive header. Must not
// be used in new archives anymore.
#define MHD_COMMENT 0x0002U
#define LHD_SPLIT_BEFORE 0x0001
#define LHD_SPLIT_AFTER 0x0002
#define LHD_PASSWORD 0x0004
#define LHD_COMMENT 0x0008
#define LHD_SOLID 0x0010
#define MHD_LOCK 0x0004U
#define MHD_SOLID 0x0008U
#define MHD_PACK_COMMENT 0x0010U
#define MHD_NEWNUMBERING 0x0010U
#define MHD_AV 0x0020U
#define MHD_PROTECT 0x0040U
#define MHD_PASSWORD 0x0080U
#define MHD_FIRSTVOLUME 0x0100U
#define LHD_WINDOWMASK 0x00e0
#define LHD_WINDOW64 0x0000
#define LHD_WINDOW128 0x0020
#define LHD_WINDOW256 0x0040
#define LHD_WINDOW512 0x0060
#define LHD_WINDOW1024 0x0080
#define LHD_WINDOW2048 0x00a0
#define LHD_WINDOW4096 0x00c0
#define LHD_DIRECTORY 0x00e0
#define LHD_SPLIT_BEFORE 0x0001U
#define LHD_SPLIT_AFTER 0x0002U
#define LHD_PASSWORD 0x0004U
#define LHD_LARGE 0x0100
#define LHD_UNICODE 0x0200
#define LHD_SALT 0x0400
#define LHD_VERSION 0x0800
#define LHD_EXTTIME 0x1000
#define LHD_EXTFLAGS 0x2000
// Old style file comment embed into file header. Must not be used
// in new archives anymore.
#define LHD_COMMENT 0x0008U
#define SKIP_IF_UNKNOWN 0x4000
#define LONG_BLOCK 0x8000
// For non-file subheaders it denotes 'subblock having a parent file' flag.
#define LHD_SOLID 0x0010U
#define LHD_WINDOWMASK 0x00e0U
#define LHD_WINDOW64 0x0000U
#define LHD_WINDOW128 0x0020U
#define LHD_WINDOW256 0x0040U
#define LHD_WINDOW512 0x0060U
#define LHD_WINDOW1024 0x0080U
#define LHD_WINDOW2048 0x00a0U
#define LHD_WINDOW4096 0x00c0U
#define LHD_DIRECTORY 0x00e0U
#define LHD_LARGE 0x0100U
#define LHD_UNICODE 0x0200U
#define LHD_SALT 0x0400U
#define LHD_VERSION 0x0800U
#define LHD_EXTTIME 0x1000U
#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 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.
#define EARC_NEXT_VOLUME 0x0001
#define EARC_DATACRC 0x0002
#define EARC_REVSPACE 0x0004
#define EARC_VOLNUMBER 0x0008
enum HEADER_TYPE {
// RAR 5.0 header types.
HEAD_MARK=0x00, HEAD_MAIN=0x01, HEAD_FILE=0x02, HEAD_SERVICE=0x03,
HEAD_CRYPT=0x04, HEAD_ENDARC=0x05, HEAD_UNKNOWN=0xff,
// RAR 1.5 - 4.x header types.
HEAD3_MARK=0x72,HEAD3_MAIN=0x73,HEAD3_FILE=0x74,HEAD3_CMT=0x75,
HEAD3_AV=0x76,HEAD3_OLDSERVICE=0x77,HEAD3_PROTECT=0x78,HEAD3_SIGN=0x79,
HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b
MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76,
SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a,
ENDARC_HEAD=0x7b
};
// RAR 2.9 and earlier.
enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
// Internal implementation, depends on archive format version.
enum HOST_SYSTEM {
// RAR 5.0 host OS
HOST5_WINDOWS=0,HOST5_UNIX=1,
// RAR 3.0 host OS.
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
HOST_BEOS=5,HOST_MAX
};
// Unified archive format independent implementation.
enum HOST_SYSTEM_TYPE {
HSYS_WINDOWS, HSYS_UNIX, HSYS_UNKNOWN
};
// We also use these values in extra field, so do not modify them.
enum FILE_SYSTEM_REDIRECT {
FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
FSREDIR_HARDLINK, FSREDIR_FILECOPY
};
#define SUBHEAD_TYPE_CMT L"CMT"
#define SUBHEAD_TYPE_QOPEN L"QO"
#define SUBHEAD_TYPE_ACL L"ACL"
#define SUBHEAD_TYPE_STREAM L"STM"
#define SUBHEAD_TYPE_UOWNER L"UOW"
#define SUBHEAD_TYPE_AV L"AV"
#define SUBHEAD_TYPE_RR L"RR"
#define SUBHEAD_TYPE_OS2EA L"EA2"
#define SUBHEAD_TYPE_CMT "CMT"
#define SUBHEAD_TYPE_ACL "ACL"
#define SUBHEAD_TYPE_STREAM "STM"
#define SUBHEAD_TYPE_UOWNER "UOW"
#define SUBHEAD_TYPE_AV "AV"
#define SUBHEAD_TYPE_RR "RR"
#define SUBHEAD_TYPE_OS2EA "EA2"
#define SUBHEAD_TYPE_BEOSEA "EABE"
/* new file inherits a subblock when updating a host file */
#define SUBHEAD_FLAGS_INHERITED 0x80000000
#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001
struct OldMainHeader
{
byte Mark[4];
ushort HeadSize;
byte Flags;
};
struct OldFileHeader
{
uint PackSize;
uint UnpSize;
ushort FileCRC;
ushort HeadSize;
uint FileTime;
byte FileAttr;
byte Flags;
byte UnpVer;
byte NameSize;
byte Method;
};
struct MarkHeader
{
byte Mark[8];
// Following fields are virtual and not present in real blocks.
uint HeadSize;
byte Mark[7];
};
struct BaseBlock
{
uint HeadCRC; // 'ushort' for RAR 1.5.
HEADER_TYPE HeaderType; // 1 byte for RAR 1.5.
uint Flags; // 'ushort' for RAR 1.5.
uint HeadSize; // 'ushort' for RAR 1.5, up to 2 MB for RAR 5.0.
ushort HeadCRC;
HEADER_TYPE HeadType;//byte
ushort Flags;
ushort HeadSize;
bool SkipIfUnknown;
void Reset()
bool IsSubBlock()
{
SkipIfUnknown=false;
if (HeadType==SUB_HEAD)
return(true);
if (HeadType==NEWSUB_HEAD && (Flags & LHD_SOLID)!=0)
return(true);
return(false);
}
};
struct BlockHeader:BaseBlock
{
uint DataSize;
union {
uint DataSize;
uint PackSize;
};
};
@@ -161,141 +156,73 @@ struct MainHeader:BaseBlock
{
ushort HighPosAV;
uint PosAV;
bool CommentInHeader;
bool PackComment; // For RAR 1.4 archive format only.
bool Locator;
uint64 QOpenOffset; // Offset of quick list record.
uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
uint64 RROffset; // Offset of recovery record.
uint64 RRMaxSize; // Maximum size of RR offset in locator extra field.
void Reset();
byte EncryptVer;
};
#define SALT_SIZE 8
struct FileHeader:BlockHeader
{
uint UnpSize;
byte HostOS;
uint UnpVer; // It is 1 byte in RAR29 and bit field in RAR5.
uint FileCRC;
uint FileTime;
byte UnpVer;
byte Method;
ushort NameSize;
union {
uint FileAttr;
uint SubFlags;
};
wchar FileName[NM];
/* optional */
uint HighPackSize;
uint HighUnpSize;
/* names */
char FileName[NM];
wchar FileNameW[NM];
/* optional */
Array<byte> SubData;
byte Salt[SALT_SIZE];
RarTime mtime;
RarTime ctime;
RarTime atime;
RarTime arctime;
/* dummy */
Int64 FullPackSize;
Int64 FullUnpSize;
int64 PackSize;
int64 UnpSize;
int64 MaxSize; // Reserve packed and unpacked size bytes for vint of this size.
HashValue FileHash;
uint FileFlags;
bool SplitBefore;
bool SplitAfter;
bool UnknownUnpSize;
bool Encrypted;
CRYPT_METHOD CryptMethod;
bool SaltSet;
byte Salt[SIZE_SALT50];
byte InitV[SIZE_INITV];
bool UsePswCheck;
byte PswCheck[SIZE_PSWCHECK];
// Use HMAC calculated from HashKey and checksum instead of plain checksum.
bool UseHashKey;
// Key to convert checksum to HMAC. Derived from password with PBKDF2
// using additional iterations.
byte HashKey[SHA256_DIGEST_SIZE];
uint Lg2Count; // Log2 of PBKDF2 repetition count.
bool Solid;
bool Dir;
bool CommentInHeader; // RAR 2.0 file comment.
bool Version; // name.ext;ver file name containing the version number.
size_t WinSize;
bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only).
// 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0.
bool LargeFile;
// 'true' for HEAD_SERVICE block, which is a child of preceding file block.
// RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
bool SubBlock;
HOST_SYSTEM_TYPE HSType;
FILE_SYSTEM_REDIRECT RedirType;
wchar RedirName[NM];
bool DirTarget;
bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric;
char UnixOwnerName[256],UnixGroupName[256];
#ifdef _UNIX
uid_t UnixOwnerID;
gid_t UnixGroupID;
#else // Need these Unix fields in Windows too for 'list' command.
uint UnixOwnerID;
uint UnixGroupID;
#endif
void Reset(size_t SubDataSize=0);
bool CmpName(const wchar *Name)
void Clear(int SubDataSize)
{
return(wcscmp(FileName,Name)==0);
SubData.Alloc(SubDataSize);
Flags=LONG_BLOCK;
SubFlags=0;
}
FileHeader& operator = (FileHeader &hd);
bool CmpName(const char *Name)
{
return(strcmp(FileName,Name)==0);
}
FileHeader& operator = (FileHeader &hd)
{
SubData.Reset();
memcpy(this,&hd,sizeof(*this));
SubData.CleanData();
SubData=hd.SubData;
return(*this);
}
};
struct EndArcHeader:BaseBlock
{
// Optional CRC32 of entire archive up to start of EndArcHeader block.
// Present in RAR 4.x archives if EARC_DATACRC flag is set.
uint ArcDataCRC;
uint VolNumber; // Optional number of current volume.
// 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
bool NextVolume; // Not last volume.
bool DataCRC;
bool RevSpace;
bool StoreVolNumber;
void Reset()
{
BaseBlock::Reset();
NextVolume=false;
DataCRC=false;
RevSpace=false;
StoreVolNumber=false;
}
uint ArcDataCRC;
ushort VolNumber;
};
struct CryptHeader:BaseBlock
{
bool UsePswCheck;
uint Lg2Count; // Log2 of PBKDF2 repetition count.
byte Salt[SIZE_SALT50];
byte PswCheck[SIZE_PSWCHECK];
};
// SubBlockHeader and its successors were used in RAR 2.x format.
// RAR 4.x uses FileHeader with HEAD_SERVICE HeaderType for subblocks.
struct SubBlockHeader:BlockHeader
{
ushort SubType;
@@ -321,13 +248,30 @@ struct ProtectHeader:BlockHeader
};
struct AVHeader:BaseBlock
{
byte UnpVer;
byte Method;
byte AVVer;
uint AVInfoCRC;
};
struct SignHeader:BaseBlock
{
uint CreationTime;
ushort ArcNameSize;
ushort UserNameSize;
};
struct UnixOwnersHeader:SubBlockHeader
{
ushort OwnerNameSize;
ushort GroupNameSize;
/* dummy */
char OwnerName[256];
char GroupName[256];
char OwnerName[NM];
char GroupName[NM];
};
@@ -347,7 +291,15 @@ struct StreamHeader:SubBlockHeader
byte Method;
uint StreamCRC;
ushort StreamNameSize;
char StreamName[260];
/* dummy */
byte StreamName[NM];
};
struct MacFInfoHeader:SubBlockHeader
{
uint fileType;
uint fileCreator;
};
-100
View File
@@ -1,100 +0,0 @@
#ifndef _RAR_HEADERS5_
#define _RAR_HEADERS5_
#define SIZEOF_MARKHEAD5 8 // RAR 5.0 signature length.
#define SIZEOF_SHORTBLOCKHEAD5 7 // Smallest RAR 5.0 block size.
// RAR 5.0 block flags common for all blocks.
// Additional extra area is present in the end of block header.
#define HFL_EXTRA 0x0001
// Additional data area is present in the end of block header.
#define HFL_DATA 0x0002
// Unknown blocks with this flag must be skipped when updating an archive.
#define HFL_SKIPIFUNKNOWN 0x0004
// Data area of this block is continuing from previous volume.
#define HFL_SPLITBEFORE 0x0008
// Data area of this block is continuing in next volume.
#define HFL_SPLITAFTER 0x0010
// Block depends on preceding file block.
#define HFL_CHILD 0x0020
// Preserve a child block if host is modified.
#define HFL_INHERITED 0x0040
// RAR 5.0 main archive header specific flags.
#define MHFL_VOLUME 0x0001 // Volume.
#define MHFL_VOLNUMBER 0x0002 // Volume number field is present. True for all volumes except first.
#define MHFL_SOLID 0x0004 // Solid archive.
#define MHFL_PROTECT 0x0008 // Recovery record is present.
#define MHFL_LOCK 0x0010 // Locked archive.
// RAR 5.0 file header specific flags.
#define FHFL_DIRECTORY 0x0001 // Directory.
#define FHFL_UTIME 0x0002 // Time field in Unix format is present.
#define FHFL_CRC32 0x0004 // CRC32 field is present.
#define FHFL_UNPUNKNOWN 0x0008 // Unknown unpacked size.
// RAR 5.0 end of archive header specific flags.
#define EHFL_NEXTVOLUME 0x0001 // Not last volume.
// RAR 5.0 archive encryption header specific flags.
#define CHFL_CRYPT_PSWCHECK 0x0001 // Password check data is present.
// RAR 5.0 file compression flags.
#define FCI_ALGO_BIT0 0x0001 // Version of compression algorithm.
#define FCI_ALGO_BIT1 0x0002 // 0 .. 63.
#define FCI_ALGO_BIT2 0x0004
#define FCI_ALGO_BIT3 0x0008
#define FCI_ALGO_BIT4 0x0010
#define FCI_ALGO_BIT5 0x0020
#define FCI_SOLID 0x0040 // Solid flag.
#define FCI_METHOD_BIT0 0x0080 // Compression method.
#define FCI_METHOD_BIT1 0x0100 // 0 .. 5 (6 and 7 are not used).
#define FCI_METHOD_BIT2 0x0200
#define FCI_DICT_BIT0 0x0400 // Dictionary size.
#define FCI_DICT_BIT1 0x0800 // 128 KB .. 4 GB.
#define FCI_DICT_BIT2 0x1000
#define FCI_DICT_BIT3 0x2000
// Main header extra field values.
#define MHEXTRA_LOCATOR 0x01 // Position of quick list and other blocks.
// Flags for MHEXTRA_LOCATOR.
#define MHEXTRA_LOCATOR_QLIST 0x01 // Quick open offset is present.
#define MHEXTRA_LOCATOR_RR 0x02 // Recovery record offset is present.
// File and service header extra field values.
#define FHEXTRA_CRYPT 0x01 // Encryption parameters.
#define FHEXTRA_HASH 0x02 // File hash.
#define FHEXTRA_HTIME 0x03 // High precision file time.
#define FHEXTRA_VERSION 0x04 // File version information.
#define FHEXTRA_REDIR 0x05 // File system redirection (links, etc.).
#define FHEXTRA_UOWNER 0x06 // Unix owner and group information.
#define FHEXTRA_SUBDATA 0x07 // Service header subdata array.
// Hash type values for FHEXTRA_HASH.
#define FHEXTRA_HASH_BLAKE2 0x00
// Flags for FHEXTRA_HTIME.
#define FHEXTRA_HTIME_UNIXTIME 0x01 // Use Unix time_t format.
#define FHEXTRA_HTIME_MTIME 0x02 // mtime is present.
#define FHEXTRA_HTIME_CTIME 0x04 // ctime is present.
#define FHEXTRA_HTIME_ATIME 0x08 // atime is present.
#define FHEXTRA_HTIME_UNIX_NS 0x10 // Unix format with nanosecond precision.
// Flags for FHEXTRA_CRYPT.
#define FHEXTRA_CRYPT_PSWCHECK 0x01 // Store password check data.
#define FHEXTRA_CRYPT_HASHMAC 0x02 // Use MAC for unpacked data checksums.
// Flags for FHEXTRA_REDIR.
#define FHEXTRA_REDIR_DIR 0x01 // Link target is directory.
// Flags for FHEXTRA_UOWNER.
#define FHEXTRA_UOWNER_UNAME 0x01 // User name string is present.
#define FHEXTRA_UOWNER_GNAME 0x02 // Group name string is present.
#define FHEXTRA_UOWNER_NUMUID 0x04 // Numeric user ID is present.
#define FHEXTRA_UOWNER_NUMGID 0x08 // Numeric group ID is present.
#endif
+274
View File
@@ -0,0 +1,274 @@
#include "rar.hpp"
#ifndef NATIVE_INT64
Int64::Int64()
{
}
Int64::Int64(uint n)
{
HighPart=0;
LowPart=n;
}
Int64::Int64(uint HighPart,uint LowPart)
{
Int64::HighPart=HighPart;
Int64::LowPart=LowPart;
}
/*
Int64 Int64::operator = (Int64 n)
{
HighPart=n.HighPart;
LowPart=n.LowPart;
return(*this);
}
*/
Int64 Int64::operator << (int n)
{
Int64 res=*this;
while (n--)
{
res.HighPart<<=1;
if (res.LowPart & 0x80000000)
res.HighPart|=1;
res.LowPart<<=1;
}
return(res);
}
Int64 Int64::operator >> (int n)
{
Int64 res=*this;
while (n--)
{
res.LowPart>>=1;
if (res.HighPart & 1)
res.LowPart|=0x80000000;
res.HighPart>>=1;
}
return(res);
}
Int64 operator / (Int64 n1,Int64 n2)
{
if (n1.HighPart==0 && n2.HighPart==0)
return(Int64(0,n1.LowPart/n2.LowPart));
int ShiftCount=0;
while (n1>n2)
{
n2=n2<<1;
if (++ShiftCount>64)
return(0);
}
Int64 res=0;
while (ShiftCount-- >= 0)
{
res=res<<1;
if (n1>=n2)
{
n1-=n2;
++res;
}
n2=n2>>1;
}
return(res);
}
Int64 operator * (Int64 n1,Int64 n2)
{
if (n1<0x10000 && n2<0x10000)
return(Int64(0,n1.LowPart*n2.LowPart));
Int64 res=0;
for (int I=0;I<64;I++)
{
if (n2.LowPart & 1)
res+=n1;
n1=n1<<1;
n2=n2>>1;
}
return(res);
}
Int64 operator % (Int64 n1,Int64 n2)
{
if (n1.HighPart==0 && n2.HighPart==0)
return(Int64(0,n1.LowPart%n2.LowPart));
return(n1-n1/n2*n2);
}
Int64 operator + (Int64 n1,Int64 n2)
{
n1.LowPart+=n2.LowPart;
if (n1.LowPart<n2.LowPart)
n1.HighPart++;
n1.HighPart+=n2.HighPart;
return(n1);
}
Int64 operator - (Int64 n1,Int64 n2)
{
if (n1.LowPart<n2.LowPart)
n1.HighPart--;
n1.LowPart-=n2.LowPart;
n1.HighPart-=n2.HighPart;
return(n1);
}
Int64 operator += (Int64 &n1,Int64 n2)
{
n1=n1+n2;
return(n1);
}
Int64 operator -= (Int64 &n1,Int64 n2)
{
n1=n1-n2;
return(n1);
}
Int64 operator *= (Int64 &n1,Int64 n2)
{
n1=n1*n2;
return(n1);
}
Int64 operator /= (Int64 &n1,Int64 n2)
{
n1=n1/n2;
return(n1);
}
Int64 operator | (Int64 n1,Int64 n2)
{
n1.LowPart|=n2.LowPart;
n1.HighPart|=n2.HighPart;
return(n1);
}
Int64 operator & (Int64 n1,Int64 n2)
{
n1.LowPart&=n2.LowPart;
n1.HighPart&=n2.HighPart;
return(n1);
}
/*
inline void operator -= (Int64 &n1,unsigned int n2)
{
if (n1.LowPart<n2)
n1.HighPart--;
n1.LowPart-=n2;
}
inline void operator ++ (Int64 &n)
{
if (++n.LowPart == 0)
++n.HighPart;
}
inline void operator -- (Int64 &n)
{
if (n.LowPart-- == 0)
n.HighPart--;
}
*/
bool operator == (Int64 n1,Int64 n2)
{
return(n1.LowPart==n2.LowPart && n1.HighPart==n2.HighPart);
}
bool operator > (Int64 n1,Int64 n2)
{
return((int)n1.HighPart>(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart>n2.LowPart);
}
bool operator < (Int64 n1,Int64 n2)
{
return((int)n1.HighPart<(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart<n2.LowPart);
}
bool operator != (Int64 n1,Int64 n2)
{
return(n1.LowPart!=n2.LowPart || n1.HighPart!=n2.HighPart);
}
bool operator >= (Int64 n1,Int64 n2)
{
return(n1>n2 || n1==n2);
}
bool operator <= (Int64 n1,Int64 n2)
{
return(n1<n2 || n1==n2);
}
void Int64::Set(uint HighPart,uint LowPart)
{
Int64::HighPart=HighPart;
Int64::LowPart=LowPart;
}
#endif
void itoa(Int64 n,char *Str)
{
if (n<=0xffffffff)
{
sprintf(Str,"%u",int64to32(n));
return;
}
char NumStr[50];
int Pos=0;
do
{
NumStr[Pos++]=int64to32(n%10)+'0';
n=n/10;
} while (n!=0);
for (int I=0;I<Pos;I++)
Str[I]=NumStr[Pos-I-1];
Str[Pos]=0;
}
Int64 atoil(char *Str)
{
Int64 n=0;
while (*Str>='0' && *Str<='9')
{
n=n*10+*Str-'0';
Str++;
}
return(n);
}
+86
View File
@@ -0,0 +1,86 @@
#ifndef _RAR_INT64_
#define _RAR_INT64_
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define NATIVE_INT64
typedef __int64 Int64;
#endif
#if defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC)
#define NATIVE_INT64
typedef long long Int64;
#endif
#ifdef NATIVE_INT64
#define int64to32(x) ((uint)(x))
#define int32to64(high,low) ((((Int64)(high))<<32)+(low))
#define is64plus(x) (x>=0)
#else
class Int64
{
public:
Int64();
Int64(uint n);
Int64(uint HighPart,uint LowPart);
// Int64 operator = (Int64 n);
Int64 operator << (int n);
Int64 operator >> (int n);
friend Int64 operator / (Int64 n1,Int64 n2);
friend Int64 operator * (Int64 n1,Int64 n2);
friend Int64 operator % (Int64 n1,Int64 n2);
friend Int64 operator + (Int64 n1,Int64 n2);
friend Int64 operator - (Int64 n1,Int64 n2);
friend Int64 operator += (Int64 &n1,Int64 n2);
friend Int64 operator -= (Int64 &n1,Int64 n2);
friend Int64 operator *= (Int64 &n1,Int64 n2);
friend Int64 operator /= (Int64 &n1,Int64 n2);
friend Int64 operator | (Int64 n1,Int64 n2);
friend Int64 operator & (Int64 n1,Int64 n2);
inline friend void operator -= (Int64 &n1,unsigned int n2)
{
if (n1.LowPart<n2)
n1.HighPart--;
n1.LowPart-=n2;
}
inline friend void operator ++ (Int64 &n)
{
if (++n.LowPart == 0)
++n.HighPart;
}
inline friend void operator -- (Int64 &n)
{
if (n.LowPart-- == 0)
n.HighPart--;
}
friend bool operator == (Int64 n1,Int64 n2);
friend bool operator > (Int64 n1,Int64 n2);
friend bool operator < (Int64 n1,Int64 n2);
friend bool operator != (Int64 n1,Int64 n2);
friend bool operator >= (Int64 n1,Int64 n2);
friend bool operator <= (Int64 n1,Int64 n2);
void Set(uint HighPart,uint LowPart);
uint GetLowPart() {return(LowPart);}
uint LowPart;
uint HighPart;
};
inline uint int64to32(Int64 n) {return(n.GetLowPart());}
#define int32to64(high,low) (Int64((high),(low)))
#define is64plus(x) ((int)(x).HighPart>=0)
#endif
#define INT64ERR int32to64(0x80000000,0)
#define INT64MAX int32to64(0x7fffffff,0)
void itoa(Int64 n,char *Str);
Int64 atoil(char *Str);
#endif
+4 -11
View File
@@ -1,10 +1,9 @@
#include "rar.hpp"
#ifdef _WIN_ALL
DWORD WinNT()
#ifdef _WIN_32
int WinNT()
{
static int dwPlatformId=-1;
static DWORD dwMajorVersion,dwMinorVersion;
static int dwPlatformId=-1,dwMajorVersion;
if (dwPlatformId==-1)
{
OSVERSIONINFO WinVer;
@@ -12,13 +11,7 @@ DWORD WinNT()
GetVersionEx(&WinVer);
dwPlatformId=WinVer.dwPlatformId;
dwMajorVersion=WinVer.dwMajorVersion;
dwMinorVersion=WinVer.dwMinorVersion;
}
DWORD Result=0;
if (dwPlatformId==VER_PLATFORM_WIN32_NT)
Result=dwMajorVersion*0x100+dwMinorVersion;
return Result;
return(dwPlatformId==VER_PLATFORM_WIN32_NT ? dwMajorVersion:0);
}
#endif
+1 -8
View File
@@ -1,13 +1,6 @@
#ifndef _RAR_ISNT_
#define _RAR_ISNT_
enum WINNT_VERSION {
WNT_NONE=0,WNT_NT351=0x0333,WNT_NT4=0x0400,WNT_W2000=0x0500,
WNT_WXP=0x0501,WNT_W2003=0x0502,WNT_VISTA=0x0600,WNT_W7=0x0601,
WNT_W8=0x0602,WNT_W81=0x0603,WNT_W10=0x0a00
};
DWORD WinNT();
int WinNT();
#endif
-42
View File
@@ -1,42 +0,0 @@
****** ***** ****** UnRAR - free utility for RAR archives
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
****** ******* ****** License for use and distribution of
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** ** ** ** ** ** FREE portable version
~~~~~~~~~~~~~~~~~~~~~
The source code of UnRAR utility is freeware. This means:
1. All copyrights to RAR and the utility UnRAR are exclusively
owned by the author - Alexander Roshal.
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.
4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
OR MISUSING THIS SOFTWARE.
5. Installing and using the UnRAR utility signifies acceptance of
these terms and conditions of the license.
6. If you don't agree with terms of the license you must remove
UnRAR files from your storage devices and cease to use the
utility.
Thank you for your interest in RAR and UnRAR.
Alexander L. Roshal
+267 -358
View File
@@ -1,145 +1,135 @@
#include "rar.hpp"
static void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare);
static void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare);
static void ListSymLink(Archive &Arc);
static void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize);
static void ListFileAttr(uint A,int HostOS);
static void ListOldSubHeader(Archive &Arc);
static void ListNewSubHeader(CommandData *Cmd,Archive &Arc);
static void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical);
void ListArchive(CommandData *Cmd)
{
int64 SumPackSize=0,SumUnpSize=0;
Int64 SumPackSize=0,SumUnpSize=0;
uint ArcCount=0,SumFileCount=0;
bool Technical=(Cmd->Command[1]=='T');
bool ShowService=Technical && Cmd->Command[2]=='A';
bool Bare=(Cmd->Command[1]=='B');
bool Verbose=(Cmd->Command[0]=='V');
bool Verbose=(*Cmd->Command=='V');
wchar ArcName[NM];
while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
char ArcName[NM];
wchar ArcNameW[NM];
while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
{
if (Cmd->ManualPassword)
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
Archive Arc(Cmd);
#ifdef _WIN_ALL
#ifdef _WIN_32
Arc.RemoveSequentialFlag();
#endif
if (!Arc.WOpen(ArcName))
if (!Arc.WOpen(ArcName,ArcNameW))
continue;
bool FileMatched=true;
while (1)
{
int64 TotalPackSize=0,TotalUnpSize=0;
Int64 TotalPackSize=0,TotalUnpSize=0;
uint FileCount=0;
if (Arc.IsArchive(true))
{
if (!Arc.IsOpened())
break;
bool TitleShown=false;
if (!Bare)
{
Arc.ViewComment();
mprintf(L"\n%s: %s",St(MListArchive),Arc.FileName);
mprintf(L"\n%s: ",St(MListDetails));
uint SetCount=0;
const wchar *Fmt=Arc.Format==RARFMT14 ? L"RAR 1.4":(Arc.Format==RARFMT15 ? L"RAR 4":L"RAR 5");
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", Fmt);
mprintf("\n");
if (Arc.Solid)
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSolid));
mprintf(St(MListSolid));
if (Arc.SFXSize>0)
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListSFX));
mprintf(St(MListSFX));
if (Arc.Volume)
if (Arc.Format==RARFMT50)
{
// RAR 5.0 archives store the volume number in main header,
// so it is already available now.
if (SetCount++ > 0)
mprintf(L", ");
mprintf(St(MVolumeNumber),Arc.VolNumber+1);
}
if (Arc.Solid)
mprintf(St(MListVol1));
else
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListVolume));
if (Arc.Protected)
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListRR));
if (Arc.Locked)
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListLock));
if (Arc.Encrypted)
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListEncHead));
mprintf(L"\n");
mprintf(St(MListVol2));
else
if (Arc.Solid)
mprintf(St(MListArc1));
else
mprintf(St(MListArc2));
mprintf(" %s\n",Arc.FileName);
if (Technical)
{
if (Arc.Protected)
mprintf(St(MListRecRec));
if (Arc.Locked)
mprintf(St(MListLock));
}
}
wchar VolNumText[50];
*VolNumText=0;
while(Arc.ReadHeader()>0)
{
Wait(); // Allow quit listing with Ctrl+C.
HEADER_TYPE HeaderType=Arc.GetHeaderType();
if (HeaderType==HEAD_ENDARC)
{
#ifndef SFX_MODULE
// Only RAR 1.5 archives store the volume number in end record.
if (Arc.EndArcHead.StoreVolNumber && Arc.Format==RARFMT15)
swprintf(VolNumText,ASIZE(VolNumText),L"%.10ls %u",St(MListVolume),Arc.VolNumber+1);
#endif
if (Technical && ShowService)
{
mprintf(L"\n%12ls: %ls",St(MListService),L"EOF");
if (*VolNumText!=0)
mprintf(L"\n%12ls: %ls",St(MListFlags),VolNumText);
mprintf(L"\n");
}
int HeaderType=Arc.GetHeaderType();
if (HeaderType==ENDARC_HEAD)
break;
}
switch(HeaderType)
{
case HEAD_FILE:
FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0;
if (FileMatched)
case FILE_HEAD:
IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName);
if ((FileMatched=Cmd->IsProcessFile(Arc.NewLhd))==true)
{
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
if (!Arc.FileHead.SplitBefore)
ListFileHeader(Arc.NewLhd,Verbose,Technical,TitleShown,Bare);
if (!(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
{
TotalUnpSize+=Arc.FileHead.UnpSize;
TotalUnpSize+=Arc.NewLhd.FullUnpSize;
FileCount++;
}
TotalPackSize+=Arc.FileHead.PackSize;
TotalPackSize+=Arc.NewLhd.FullPackSize;
if (Technical)
ListSymLink(Arc);
#ifndef SFX_MODULE
if (Verbose)
Arc.ViewFileComment();
#endif
}
break;
case HEAD_SERVICE:
#ifndef SFX_MODULE
case SUB_HEAD:
if (Technical && FileMatched && !Bare)
ListOldSubHeader(Arc);
break;
#endif
case NEWSUB_HEAD:
if (FileMatched && !Bare)
{
if (Technical && ShowService)
ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false);
if (Technical)
ListFileHeader(Arc.SubHead,Verbose,true,TitleShown,false);
ListNewSubHeader(Cmd,Arc,Technical);
}
break;
}
Arc.SeekToNext();
}
if (!Bare && !Technical)
if (!Bare)
if (TitleShown)
{
wchar UnpSizeText[20];
itoa(TotalUnpSize,UnpSizeText,ASIZE(UnpSizeText));
mprintf("\n");
for (int I=0;I<79;I++)
mprintf("-");
char UnpSizeText[20];
itoa(TotalUnpSize,UnpSizeText);
wchar PackSizeText[20];
itoa(TotalPackSize,PackSizeText,ASIZE(PackSizeText));
char PackSizeText[20];
itoa(TotalPackSize,PackSizeText);
if (Verbose)
{
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
mprintf(L"\n%21ls %9ls %3d%% %-27ls %u",UnpSizeText,
PackSizeText,ToPercentUnlim(TotalPackSize,TotalUnpSize),
VolNumText,FileCount);
}
else
{
mprintf(L"\n----------- --------- ---------- ----- ----");
mprintf(L"\n%21ls %-16ls %u",UnpSizeText,VolNumText,FileCount);
}
mprintf("\n%5lu %16s %8s %3d%%",FileCount,UnpSizeText,
PackSizeText,ToPercent(TotalPackSize,TotalUnpSize));
SumFileCount+=FileCount;
SumUnpSize+=TotalUnpSize;
SumPackSize+=TotalPackSize;
mprintf(L"\n");
#ifndef SFX_MODULE
if (Arc.EndArcHead.Flags & EARC_VOLNUMBER)
{
mprintf(" ");
mprintf(St(MVolumeNumber),Arc.EndArcHead.VolNumber+1);
}
#endif
mprintf("\n");
}
else
mprintf(St(MListNoFiles));
@@ -147,328 +137,247 @@ void ListArchive(CommandData *Cmd)
ArcCount++;
#ifndef NOVOLUME
if (Cmd->VolSize!=0 && (Arc.FileHead.SplitAfter ||
Arc.GetHeaderType()==HEAD_ENDARC && Arc.EndArcHead.NextVolume) &&
MergeArchive(Arc,NULL,false,Cmd->Command[0]))
if (Cmd->VolSize!=0 && ((Arc.NewLhd.Flags & LHD_SPLIT_AFTER) ||
Arc.GetHeaderType()==ENDARC_HEAD &&
(Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)!=0) &&
MergeArchive(Arc,NULL,false,*Cmd->Command))
{
Arc.Seek(0,SEEK_SET);
}
else
#endif
break;
}
else
{
if (Cmd->ArcNames.ItemsCount()<2 && !Bare)
if (Cmd->ArcNames->ItemsCount()<2 && !Bare)
mprintf(St(MNotRAR),Arc.FileName);
break;
}
}
}
// Clean user entered password. Not really required, just for extra safety.
if (Cmd->ManualPassword)
Cmd->Password.Clean();
if (ArcCount>1 && !Bare && !Technical)
if (ArcCount>1 && !Bare)
{
wchar UnpSizeText[20],PackSizeText[20];
itoa(SumUnpSize,UnpSizeText,ASIZE(UnpSizeText));
itoa(SumPackSize,PackSizeText,ASIZE(PackSizeText));
if (Verbose)
mprintf(L"%21ls %9ls %3d%% %28ls %u",UnpSizeText,PackSizeText,
ToPercentUnlim(SumPackSize,SumUnpSize),L"",SumFileCount);
else
mprintf(L"%21ls %18s %lu",UnpSizeText,L"",SumFileCount);
char UnpSizeText[20],PackSizeText[20];
itoa(SumUnpSize,UnpSizeText);
itoa(SumPackSize,PackSizeText);
mprintf("\n%5lu %16s %8s %3d%%\n",SumFileCount,UnpSizeText,
PackSizeText,ToPercent(SumPackSize,SumUnpSize));
}
}
enum LISTCOL_TYPE {
LCOL_NAME,LCOL_ATTR,LCOL_SIZE,LCOL_PACKED,LCOL_RATIO,LCOL_CSUM,LCOL_ENCR
};
void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare)
void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare)
{
wchar *Name=hd.FileName;
RARFORMAT Format=Arc.Format;
if (!Bare)
{
if (!TitleShown)
{
if (Verbose)
mprintf(St(MListPathComm));
else
mprintf(St(MListName));
mprintf(St(MListTitle));
if (Technical)
mprintf(St(MListTechTitle));
for (int I=0;I<79;I++)
mprintf("-");
TitleShown=true;
}
if (hd.HeadType==NEWSUB_HEAD)
mprintf(St(MSubHeadType),hd.FileName);
mprintf("\n%c",(hd.Flags & LHD_PASSWORD) ? '*' : ' ');
}
char *Name=hd.FileName;
#ifdef UNICODE_SUPPORTED
char ConvertedName[NM];
if ((hd.Flags & LHD_UNICODE)!=0 && *hd.FileNameW!=0 && UnicodeEnabled())
{
if (WideToChar(hd.FileNameW,ConvertedName) && *ConvertedName!=0)
Name=ConvertedName;
}
#endif
if (Bare)
{
mprintf(L"%s\n",Name);
mprintf("%s\n",Verbose ? Name:PointToName(Name));
return;
}
if (!TitleShown && !Technical)
{
if (Verbose)
{
mprintf(L"\n%ls",St(MListTitleV));
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
}
if (Verbose)
mprintf("%s\n%12s ",Name,"");
else
mprintf("%-12s",PointToName(Name));
char UnpSizeText[20],PackSizeText[20];
if (hd.FullUnpSize==INT64MAX)
strcpy(UnpSizeText,"?");
else
itoa(hd.FullUnpSize,UnpSizeText);
itoa(hd.FullPackSize,PackSizeText);
mprintf(" %8s %8s ",UnpSizeText,PackSizeText);
if ((hd.Flags & LHD_SPLIT_BEFORE) && (hd.Flags & LHD_SPLIT_AFTER))
mprintf(" <->");
else
if (hd.Flags & LHD_SPLIT_BEFORE)
mprintf(" <--");
else
{
mprintf(L"\n%ls",St(MListTitleL));
mprintf(L"\n----------- --------- ---------- ----- ----");
}
TitleShown=true;
}
wchar UnpSizeText[30],PackSizeText[30];
if (hd.UnpSize==INT64NDF)
wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText));
else
itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));
wchar AttrStr[30];
if (hd.HeaderType==HEAD_SERVICE)
swprintf(AttrStr,ASIZE(AttrStr),L"%cB",hd.Inherited ? 'I' : '.');
else
ListFileAttr(hd.FileAttr,hd.HSType,AttrStr,ASIZE(AttrStr));
wchar RatioStr[10];
if (hd.SplitBefore && hd.SplitAfter)
wcsncpyz(RatioStr,L"<->",ASIZE(RatioStr));
else
if (hd.SplitBefore)
wcsncpyz(RatioStr,L"<--",ASIZE(RatioStr));
else
if (hd.SplitAfter)
wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr));
if (hd.Flags & LHD_SPLIT_AFTER)
mprintf(" -->");
else
swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));
mprintf("%3d%%",ToPercent(hd.FullPackSize,hd.FullUnpSize));
wchar DateStr[50];
hd.mtime.GetText(DateStr,ASIZE(DateStr),Technical);
char DateStr[50];
hd.mtime.GetText(DateStr,false);
mprintf(" %s ",DateStr);
if (hd.HeadType==NEWSUB_HEAD)
mprintf(" %c....B ",(hd.SubFlags & SUBHEAD_FLAGS_INHERITED) ? 'I' : '.');
else
ListFileAttr(hd.FileAttr,hd.HostOS);
mprintf(" %8.8X",hd.FileCRC);
mprintf(" m%d",hd.Method-0x30);
if ((hd.Flags & LHD_WINDOWMASK)<=6*32)
mprintf("%c",((hd.Flags&LHD_WINDOWMASK)>>5)+'a');
else
mprintf(" ");
mprintf(" %d.%d",hd.UnpVer/10,hd.UnpVer%10);
static const char *RarOS[]={
"DOS","OS/2","Win95/NT","Unix","MacOS","BeOS","WinCE","","",""
};
if (Technical)
{
mprintf(L"\n%12s: %s",St(MListName),Name);
bool FileBlock=hd.HeaderType==HEAD_FILE;
if (!FileBlock && Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
{
mprintf(L"\n%12ls: %ls",St(MListType),St(MListStream));
wchar StreamName[NM];
GetStreamNameNTFS(Arc,StreamName,ASIZE(StreamName));
mprintf(L"\n%12ls: %ls",St(MListTarget),StreamName);
}
else
{
const wchar *Type=St(FileBlock ? (hd.Dir ? MListDir:MListFile):MListService);
if (hd.RedirType!=FSREDIR_NONE)
switch(hd.RedirType)
{
case FSREDIR_UNIXSYMLINK:
Type=St(MListUSymlink); break;
case FSREDIR_WINSYMLINK:
Type=St(MListWSymlink); break;
case FSREDIR_JUNCTION:
Type=St(MListJunction); break;
case FSREDIR_HARDLINK:
Type=St(MListHardlink); break;
case FSREDIR_FILECOPY:
Type=St(MListCopy); break;
}
mprintf(L"\n%12ls: %ls",St(MListType),Type);
if (hd.RedirType!=FSREDIR_NONE)
if (Format==RARFMT15)
{
char LinkTargetA[NM];
if (Arc.FileHead.Encrypted)
{
// Link data are encrypted. We would need to ask for password
// and initialize decryption routine to display the link target.
strncpyz(LinkTargetA,"*<-?->",ASIZE(LinkTargetA));
}
else
{
int DataSize=(int)Min(hd.PackSize,ASIZE(LinkTargetA)-1);
Arc.Read(LinkTargetA,DataSize);
LinkTargetA[DataSize > 0 ? DataSize : 0] = 0;
}
wchar LinkTarget[NM];
CharToWide(LinkTargetA,LinkTarget,ASIZE(LinkTarget));
mprintf(L"\n%12ls: %ls",St(MListTarget),LinkTarget);
}
else
mprintf(L"\n%12ls: %ls",St(MListTarget),hd.RedirName);
}
if (!hd.Dir)
{
mprintf(L"\n%12ls: %ls",St(MListSize),UnpSizeText);
mprintf(L"\n%12ls: %ls",St(MListPacked),PackSizeText);
mprintf(L"\n%12ls: %ls",St(MListRatio),RatioStr);
}
if (hd.mtime.IsSet())
mprintf(L"\n%12ls: %ls",St(MListMtime),DateStr);
if (hd.ctime.IsSet())
{
hd.ctime.GetText(DateStr,ASIZE(DateStr),true);
mprintf(L"\n%12ls: %ls",St(MListCtime),DateStr);
}
if (hd.atime.IsSet())
{
hd.atime.GetText(DateStr,ASIZE(DateStr),true);
mprintf(L"\n%12ls: %ls",St(MListAtime),DateStr);
}
mprintf(L"\n%12ls: %ls",St(MListAttr),AttrStr);
if (hd.FileHash.Type==HASH_CRC32)
mprintf(L"\n%12ls: %8.8X",
hd.UseHashKey ? L"CRC32 MAC":hd.SplitAfter ? L"Pack-CRC32":L"CRC32",
hd.FileHash.CRC32);
if (hd.FileHash.Type==HASH_BLAKE2)
{
wchar BlakeStr[BLAKE2_DIGEST_SIZE*2+1];
BinToHex(hd.FileHash.Digest,BLAKE2_DIGEST_SIZE,NULL,BlakeStr,ASIZE(BlakeStr));
mprintf(L"\n%12ls: %ls",
hd.UseHashKey ? L"BLAKE2 MAC":hd.SplitAfter ? L"Pack-BLAKE2":L"BLAKE2",
BlakeStr);
}
const wchar *HostOS=L"";
if (Format==RARFMT50 && hd.HSType!=HSYS_UNKNOWN)
HostOS=hd.HSType==HSYS_WINDOWS ? L"Windows":L"Unix";
if (Format==RARFMT15)
{
static const wchar *RarOS[]={
L"DOS",L"OS/2",L"Windows",L"Unix",L"Mac OS",L"BeOS",L"WinCE",L"",L"",L""
};
if (hd.HostOS<ASIZE(RarOS))
HostOS=RarOS[hd.HostOS];
}
if (*HostOS!=0)
mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS);
mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo),
Format==RARFMT15 ? L"1.5":L"5.0",
hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method,
hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400,
hd.WinSize>=0x100000 ? L"M":L"K");
if (hd.Solid || hd.Encrypted)
{
mprintf(L"\n%12ls: ",St(MListFlags));
if (hd.Solid)
mprintf(L"%ls ",St(MListSolid));
if (hd.Encrypted)
mprintf(L"%ls ",St(MListEnc));
}
if (hd.Version)
{
uint Version=ParseVersionFileName(Name,false);
if (Version!=0)
mprintf(L"\n%12ls: %u",St(MListFileVer),Version);
}
if (hd.UnixOwnerSet)
{
mprintf(L"\n%12ls: ",L"Unix owner");
if (*hd.UnixOwnerName!=0)
mprintf(L"%ls:",GetWide(hd.UnixOwnerName));
if (*hd.UnixGroupName!=0)
mprintf(L"%ls",GetWide(hd.UnixGroupName));
if ((*hd.UnixOwnerName!=0 || *hd.UnixGroupName!=0) && (hd.UnixOwnerNumeric || hd.UnixGroupNumeric))
mprintf(L" ");
if (hd.UnixOwnerNumeric)
mprintf(L"#%d:",hd.UnixOwnerID);
if (hd.UnixGroupNumeric)
mprintf(L"#%d:",hd.UnixGroupID);
}
mprintf(L"\n");
return;
}
mprintf(L"\n%c%10ls %9ls ",hd.Encrypted ? '*' : ' ',AttrStr,UnpSizeText);
if (Verbose)
mprintf(L"%9ls %4ls ",PackSizeText,RatioStr);
mprintf(L" %ls ",DateStr);
if (Verbose)
{
if (hd.FileHash.Type==HASH_CRC32)
mprintf(L"%8.8X ",hd.FileHash.CRC32);
else
if (hd.FileHash.Type==HASH_BLAKE2)
{
byte *S=hd.FileHash.Digest;
mprintf(L"%02x%02x..%02x ",S[0],S[1],S[31]);
}
else
mprintf(L"???????? ");
}
mprintf(L"%ls",Name);
mprintf("\n%22s %8s %4s",
(hd.HostOS<sizeof(RarOS)/sizeof(RarOS[0]) ? RarOS[hd.HostOS]:""),
(hd.Flags & LHD_SOLID) ? St(MYes):St(MNo),
(hd.Flags & LHD_VERSION) ? St(MYes):St(MNo));
}
/*
void ListSymLink(Archive &Arc)
{
if (Arc.FileHead.HSType==HSYS_UNIX && (Arc.FileHead.FileAttr & 0xF000)==0xA000)
if (Arc.FileHead.Encrypted)
{
// Link data are encrypted. We would need to ask for password
// and initialize decryption routine to display the link target.
mprintf(L"\n%22ls %ls",L"-->",L"*<-?->");
}
else
{
char FileName[NM];
uint DataSize=(uint)Min(Arc.FileHead.PackSize,sizeof(FileName)-1);
Arc.Read(FileName,DataSize);
FileName[DataSize]=0;
mprintf(L"\n%22ls %ls",L"-->",GetWide(FileName));
}
}
*/
void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize)
{
switch(HostType)
if (Arc.NewLhd.HostOS==HOST_UNIX && (Arc.NewLhd.FileAttr & 0xF000)==0xA000)
{
case HSYS_WINDOWS:
swprintf(AttrStr,AttrSize,L"%c%c%c%c%c%c%c",
(A & 0x2000)!=0 ? 'I' : '.', // Not content indexed.
(A & 0x0800)!=0 ? 'C' : '.', // Compressed.
(A & 0x0020)!=0 ? 'A' : '.', // Archive.
(A & 0x0010)!=0 ? 'D' : '.', // Directory.
(A & 0x0004)!=0 ? 'S' : '.', // System.
(A & 0x0002)!=0 ? 'H' : '.', // Hidden.
(A & 0x0001)!=0 ? 'R' : '.'); // Read-only.
char FileName[NM];
int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1);
Arc.Read(FileName,DataSize);
FileName[DataSize]=0;
mprintf("\n%22s %s","-->",FileName);
}
}
void ListFileAttr(uint A,int HostOS)
{
switch(HostOS)
{
case HOST_MSDOS:
case HOST_OS2:
case HOST_WIN32:
case HOST_MACOS:
mprintf(" %c%c%c%c%c%c%c ",
(A & 0x08) ? 'V' : '.',
(A & 0x10) ? 'D' : '.',
(A & 0x01) ? 'R' : '.',
(A & 0x02) ? 'H' : '.',
(A & 0x04) ? 'S' : '.',
(A & 0x20) ? 'A' : '.',
(A & 0x800) ? 'C' : '.');
break;
case HSYS_UNIX:
case HOST_UNIX:
case HOST_BEOS:
switch (A & 0xF000)
{
case 0x4000:
AttrStr[0]='d';
mprintf("d");
break;
case 0xA000:
AttrStr[0]='l';
mprintf("l");
break;
default:
AttrStr[0]='-';
mprintf("-");
break;
}
swprintf(AttrStr+1,AttrSize-1,L"%c%c%c%c%c%c%c%c%c",
mprintf("%c%c%c%c%c%c%c%c%c",
(A & 0x0100) ? 'r' : '-',
(A & 0x0080) ? 'w' : '-',
(A & 0x0040) ? ((A & 0x0800)!=0 ? 's':'x'):((A & 0x0800)!=0 ? 'S':'-'),
(A & 0x0040) ? ((A & 0x0800) ? 's':'x'):((A & 0x0800) ? 'S':'-'),
(A & 0x0020) ? 'r' : '-',
(A & 0x0010) ? 'w' : '-',
(A & 0x0008) ? ((A & 0x0400)!=0 ? 's':'x'):((A & 0x0400)!=0 ? 'S':'-'),
(A & 0x0008) ? ((A & 0x0400) ? 's':'x'):((A & 0x0400) ? 'S':'-'),
(A & 0x0004) ? 'r' : '-',
(A & 0x0002) ? 'w' : '-',
(A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-');
break;
case HSYS_UNKNOWN:
wcsncpyz(AttrStr,L"?",AttrSize);
(A & 0x0001) ? 'x' : '-');
break;
}
}
#ifndef SFX_MODULE
void ListOldSubHeader(Archive &Arc)
{
switch(Arc.SubBlockHead.SubType)
{
case EA_HEAD:
mprintf(St(MListEAHead));
break;
case UO_HEAD:
mprintf(St(MListUOHead),Arc.UOHead.OwnerName,Arc.UOHead.GroupName);
break;
case MAC_HEAD:
mprintf(St(MListMACHead1),Arc.MACHead.fileType>>24,Arc.MACHead.fileType>>16,Arc.MACHead.fileType>>8,Arc.MACHead.fileType);
mprintf(St(MListMACHead2),Arc.MACHead.fileCreator>>24,Arc.MACHead.fileCreator>>16,Arc.MACHead.fileCreator>>8,Arc.MACHead.fileCreator);
break;
case BEEA_HEAD:
mprintf(St(MListBeEAHead));
break;
case NTACL_HEAD:
mprintf(St(MListNTACLHead));
break;
case STREAM_HEAD:
mprintf(St(MListStrmHead),Arc.StreamHead.StreamName);
break;
default:
mprintf(St(MListUnkHead),Arc.SubBlockHead.SubType);
break;
}
}
#endif
void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical)
{
if (Technical && Arc.SubHead.CmpName(SUBHEAD_TYPE_CMT) &&
(Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0 && !Cmd->DisableComment)
{
Array<byte> CmtData;
int ReadSize=Arc.ReadCommentData(&CmtData,NULL);
if (ReadSize!=0)
{
mprintf(St(MFileComment));
OutComment((char *)&CmtData[0],ReadSize);
}
}
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM) &&
(Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0)
{
int DestSize=Arc.SubHead.SubData.Size()/2;
wchar DestNameW[NM];
char DestName[NM];
if (DestSize<sizeof(DestName))
{
RawToWide(&Arc.SubHead.SubData[0],DestNameW,DestSize);
DestNameW[DestSize]=0;
WideToChar(DestNameW,DestName);
mprintf("\n %s",DestName);
}
}
}
+347 -382
View File
@@ -1,382 +1,347 @@
#define MYesNo L"_Yes_No"
#define MYesNoAll L"_Yes_No_All"
#define MYesNoAllQ L"_Yes_No_All_nEver_Quit"
#define MYesNoAllRenQ L"_Yes_No_All_nEver_Rename_Quit"
#define MContinueQuit L"_Continue_Quit"
#define MRetryAbort L"_Retry_Abort"
#define MCopyright L"\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d"
#define MRegTo L"\nRegistered to %s\n"
#define MShare L"\nTrial version Type 'rar -?' for help\n"
#define MRegKeyWarning L"\nAvailable license key is valid only for %s\n"
#define MUCopyright L"\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
#define MBeta L"beta"
#define Mx86 L"x86"
#define Mx64 L"x64"
#define MMonthJan L"Jan"
#define MMonthFeb L"Feb"
#define MMonthMar L"Mar"
#define MMonthApr L"Apr"
#define MMonthMay L"May"
#define MMonthJun L"Jun"
#define MMonthJul L"Jul"
#define MMonthAug L"Aug"
#define MMonthSep L"Sep"
#define MMonthOct L"Oct"
#define MMonthNov L"Nov"
#define MMonthDec L"Dec"
#define MRARTitle1 L"\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
#define MUNRARTitle1 L"\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
#define MRARTitle2 L"\n <@listfiles...> <path_to_extract\\>"
#define MCHelpCmd L"\n\n<Commands>"
#define MCHelpCmdA L"\n a Add files to archive"
#define MCHelpCmdC L"\n c Add archive comment"
#define MCHelpCmdCH L"\n ch Change archive parameters"
#define MCHelpCmdCW L"\n cw Write archive comment to file"
#define MCHelpCmdD L"\n d Delete files from archive"
#define MCHelpCmdE L"\n e Extract files without archived paths"
#define MCHelpCmdF L"\n f Freshen files in archive"
#define MCHelpCmdI L"\n i[par]=<str> Find string in archives"
#define MCHelpCmdK L"\n k Lock archive"
#define MCHelpCmdL L"\n l[t[a],b] List archive contents [technical[all], bare]"
#define MCHelpCmdM L"\n m[f] Move to archive [files only]"
#define MCHelpCmdP L"\n p Print file to stdout"
#define MCHelpCmdR L"\n r Repair archive"
#define MCHelpCmdRC L"\n rc Reconstruct missing volumes"
#define MCHelpCmdRN L"\n rn Rename archived files"
#define MCHelpCmdRR L"\n rr[N] Add data recovery record"
#define MCHelpCmdRV L"\n rv[N] Create recovery volumes"
#define MCHelpCmdS L"\n s[name|-] Convert archive to or from SFX"
#define MCHelpCmdT L"\n t Test archive files"
#define MCHelpCmdU L"\n u Update files in archive"
#define MCHelpCmdV L"\n v[t[a],b] Verbosely list archive contents [technical[all],bare]"
#define MCHelpCmdX L"\n x Extract files with full path"
#define MCHelpSw L"\n\n<Switches>"
#define MCHelpSwm L"\n - Stop switches scanning"
#define MCHelpSwAT L"\n @[+] Disable [enable] file lists"
#define MCHelpSwAC L"\n ac Clear Archive attribute after compression or extraction"
#define MCHelpSwAD L"\n ad Append archive name to destination path"
#define MCHelpSwAG L"\n ag[format] Generate archive name using the current date"
#define MCHelpSwAI L"\n ai Ignore file attributes"
#define MCHelpSwAO L"\n ao Add files with Archive attribute set"
#define MCHelpSwAP L"\n ap<path> Set path inside archive"
#define MCHelpSwAS L"\n as Synchronize archive contents"
#define MCHelpSwCm L"\n c- Disable comments show"
#define MCHelpSwCFGm L"\n cfg- Disable read configuration"
#define MCHelpSwCL L"\n cl Convert names to lower case"
#define MCHelpSwCU L"\n cu Convert names to upper case"
#define MCHelpSwDF L"\n df Delete files after archiving"
#define MCHelpSwDH L"\n dh Open shared files"
#define MCHelpSwDR L"\n dr Delete files to Recycle Bin"
#define MCHelpSwDS L"\n ds Disable name sort for solid archive"
#define MCHelpSwDW L"\n dw Wipe files after archiving"
#define MCHelpSwEa L"\n e[+]<attr> Set file exclude and include attributes"
#define MCHelpSwED L"\n ed Do not add empty directories"
#define MCHelpSwEN L"\n en Do not put 'end of archive' block"
#define MCHelpSwEP L"\n ep Exclude paths from names"
#define MCHelpSwEP1 L"\n ep1 Exclude base directory from names"
#define MCHelpSwEP2 L"\n ep2 Expand paths to full"
#define MCHelpSwEP3 L"\n ep3 Expand paths to full including the drive letter"
#define MCHelpSwF L"\n f Freshen files"
#define MCHelpSwHP L"\n hp[password] Encrypt both file data and headers"
#define MCHelpSwHT L"\n ht[b|c] Select hash type [BLAKE2,CRC32] for file checksum"
#define MCHelpSwIDP L"\n id[c,d,p,q] Disable messages"
#define MCHelpSwIEML L"\n ieml[addr] Send archive by email"
#define MCHelpSwIERR L"\n ierr Send all messages to stderr"
#define MCHelpSwILOG L"\n ilog[name] Log errors to file"
#define MCHelpSwINUL L"\n inul Disable all messages"
#define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation"
#define MCHelpSwISND L"\n isnd[-] Control notification sounds"
#define MCHelpSwIVER L"\n iver Display the version number"
#define MCHelpSwK L"\n k Lock archive"
#define MCHelpSwKB L"\n kb Keep broken extracted files"
#define MCHelpSwLog L"\n log[f][=name] Write names to log file"
#define MCHelpSwMn L"\n m<0..5> Set compression level (0-store...3-default...5-maximal)"
#define MCHelpSwMA L"\n ma[4|5] Specify a version of archiving format"
#define MCHelpSwMC L"\n mc<par> Set advanced compression parameters"
#define MCHelpSwMD L"\n md<n>[k,m,g] Dictionary size in KB, MB or GB"
#define MCHelpSwMS L"\n ms[ext;ext] Specify file types to store"
#define MCHelpSwMT L"\n mt<threads> Set the number of threads"
#define MCHelpSwN L"\n n<file> Additionally filter included files"
#define MCHelpSwNa L"\n n@ Read additional filter masks from stdin"
#define MCHelpSwNal L"\n n@<list> Read additional filter masks from list file"
#define MCHelpSwO L"\n o[+|-] Set the overwrite mode"
#define MCHelpSwOC L"\n oc Set NTFS Compressed attribute"
#define MCHelpSwOH L"\n oh Save hard links as the link instead of the file"
#define MCHelpSwOI L"\n oi[0-4][:min] Save identical files as references"
#define MCHelpSwOL L"\n ol[a] Process symbolic links as the link [absolute paths]"
#define MCHelpSwONI L"\n oni Allow potentially incompatible names"
#define MCHelpSwOR L"\n or Rename files automatically"
#define MCHelpSwOS L"\n os Save NTFS streams"
#define MCHelpSwOW L"\n ow Save or restore file owner and group"
#define MCHelpSwP L"\n p[password] Set password"
#define MCHelpSwPm L"\n p- Do not query password"
#define MCHelpSwQO L"\n qo[-|+] Add quick open information [none|force]"
#define MCHelpSwR L"\n r Recurse subdirectories"
#define MCHelpSwRm L"\n r- Disable recursion"
#define MCHelpSwR0 L"\n r0 Recurse subdirectories for wildcard names only"
#define MCHelpSwRI L"\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms"
#define MCHelpSwRR L"\n rr[N] Add data recovery record"
#define MCHelpSwRV L"\n rv[N] Create recovery volumes"
#define MCHelpSwS L"\n s[<N>,v[-],e] Create solid archive"
#define MCHelpSwSm L"\n s- Disable solid archiving"
#define MCHelpSwSC L"\n sc<chr>[obj] Specify the character set"
#define MCHelpSwSFX L"\n sfx[name] Create SFX archive"
#define MCHelpSwSI L"\n si[name] Read data from standard input (stdin)"
#define MCHelpSwSL L"\n sl<size> Process files with size less than specified"
#define MCHelpSwSM L"\n sm<size> Process files with size more than specified"
#define MCHelpSwT L"\n t Test files after archiving"
#define MCHelpSwTK L"\n tk Keep original archive time"
#define MCHelpSwTL L"\n tl Set archive time to latest file"
#define MCHelpSwTN L"\n tn[mcao]<t> Process files newer than <t> time"
#define MCHelpSwTO L"\n to[mcao]<t> Process files older than <t> time"
#define MCHelpSwTA L"\n ta[mcao]<d> Process files modified after <d> YYYYMMDDHHMMSS date"
#define MCHelpSwTB L"\n tb[mcao]<d> Process files modified before <d> YYYYMMDDHHMMSS date"
#define MCHelpSwTS L"\n ts[m,c,a,p] Save or restore time (modification, creation, access, preserve)"
#define MCHelpSwU L"\n u Update files"
#define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes"
#define MCHelpSwVUnr L"\n v List all volumes"
#define MCHelpSwVn L"\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]"
#define MCHelpSwVD L"\n vd Erase disk contents before creating volume"
#define MCHelpSwVER L"\n ver[n] File version control"
#define MCHelpSwVN L"\n vn Use the old style volume naming scheme"
#define MCHelpSwVP L"\n vp Pause before each volume"
#define MCHelpSwW L"\n w<path> Assign work directory"
#define MCHelpSwX L"\n x<file> Exclude specified file"
#define MCHelpSwXa L"\n x@ Read file names to exclude from stdin"
#define MCHelpSwXal L"\n x@<list> Exclude files listed in specified list file"
#define MCHelpSwY L"\n y Assume Yes on all queries"
#define MCHelpSwZ L"\n z[file] Read archive comment from file"
#define MBadArc L"\nERROR: Bad archive %s\n"
#define MAskPsw L"Enter password (will not be echoed)"
#define MAskPswFor L"\nEnter password (will not be echoed) for %s: "
#define MReAskPsw L"\nReenter password: "
#define MNotMatchPsw L"\nERROR: Passwords do not match\n"
#define MErrWrite L"Write error in the file %s"
#define MErrRead L"Read error in the file %s"
#define MErrSeek L"Seek error in the file %s"
#define MErrFClose L"Cannot close the file %s"
#define MErrOutMem L"Not enough memory"
#define MErrBrokenArc L"Corrupt archive - use 'Repair' command"
#define MProgAborted L"Program aborted"
#define MErrRename L"\nCannot rename %s to %s"
#define MAbsNextVol L"\nCannot find volume %s"
#define MBreak L"\nUser break\n"
#define MAskCreatVol L"\nCreate next volume ?"
#define MAskNextDisk L"\nDisk full. Insert next"
#define MCreatVol L"\n\nCreating %sarchive %s\n"
#define MAskNextVol L"\nInsert disk with %s"
#define MTestVol L"\n\nTesting archive %s\n"
#define MExtrVol L"\n\nExtracting from %s\n"
#define MConverting L"\nConverting %s"
#define MCvtToSFX L"\nConvert archives to SFX"
#define MCvtFromSFX L"\nRemoving SFX module"
#define MNotSFX L"\n%s is not SFX archive"
#define MNotRAR L"\n%s is not RAR archive"
#define MNotFirstVol L"\n%s is not the first volume"
#define MCvtOldFormat L"\n%s - cannot convert to SFX archive with old format"
#define MCannotCreate L"\nCannot create %s"
#define MCannotOpen L"\nCannot open %s"
#define MUnknownMeth L"\nUnknown method in %s"
#define MNewRarFormat L"\nUnsupported archive format. Please update RAR to a newer version."
#define MOk L" OK"
#define MDone L"\nDone"
#define MLockingArc L"\nLocking archive"
#define MNotMdfOld L"\n\nERROR: Cannot modify old format archive"
#define MNotMdfLock L"\n\nERROR: Locked archive"
#define MNotMdfVol L"\n\nERROR: Cannot modify volume"
#define MPackAskReg L"\nEvaluation copy. Please register.\n"
#define MCreateArchive L"\nCreating %sarchive %s\n"
#define MUpdateArchive L"\nUpdating %sarchive %s\n"
#define MAddSolid L"solid "
#define MAddFile L"\nAdding %-58s "
#define MUpdFile L"\nUpdating %-58s "
#define MAddPoints L"\n... %-58s "
#define MMoveDelFiles L"\n\nDeleting files %s..."
#define MMoveDelDirs L"and directories"
#define MMoveDelFile L"\nDeleting %-30s"
#define MMoveDeleted L" deleted"
#define MMoveNotDeleted L" NOT DELETED"
#define MClearAttrib L"\n\nClearing attributes..."
#define MMoveDelDir L"\nDeleting directory %-30s"
#define MWarErrFOpen L"\nWARNING: Cannot open %d %s"
#define MErrOpenFiles L"files"
#define MErrOpenFile L"file"
#define MAddNoFiles L"\nWARNING: No files"
#define MMdfEncrSol L"\n%s: encrypted"
#define MAddAnalyze L"\nAnalyzing archived files: "
#define MRepacking L"\nRepacking archived files: "
#define MCRCFailed L"\n%-20s - checksum error"
#define MExtrTest L"\n\nTesting archive %s\n"
#define MExtracting L"\n\nExtracting from %s\n"
#define MUseCurPsw L"\n%s - use current password ?"
#define MCreatDir L"\nCreating %-56s"
#define MExtrSkipFile L"\nSkipping %-56s"
#define MExtrTestFile L"\nTesting %-56s"
#define MExtrFile L"\nExtracting %-56s"
#define MExtrPoints L"\n... %-56s"
#define MExtrErrMkDir L"\nCannot create directory %s"
#define MExtrPrinting L"\n------ Printing %s\n\n"
#define MEncrBadCRC L"\nChecksum error in the encrypted file %s. Corrupt file or wrong password."
#define MExtrNoFiles L"\nNo files to extract"
#define MExtrAllOk L"\nAll OK"
#define MExtrTotalErr L"\nTotal errors: %ld"
#define MAskReplace L"\n\nWould you like to replace the existing file %s\n%6s bytes, modified on %s\nwith a new one\n%6s bytes, modified on %s\n"
#define MAskOverwrite L"\nOverwrite %s ?"
#define MAskNewName L"\nEnter new name: "
#define MHeaderBroken L"\nCorrupt header is found"
#define MMainHeaderBroken L"\nMain archive header is corrupt"
#define MLogFileHead L"\n%s - the file header is corrupt"
#define MLogProtectHead L"The data recovery header is corrupt"
#define MReadStdinCmt L"\nReading comment from stdin\n"
#define MReadCommFrom L"\nReading comment from %s"
#define MDelComment L"\nDeleting comment from %s"
#define MAddComment L"\nAdding comment to %s"
#define MFCommAdd L"\nAdding file comments"
#define MAskFComm L"\n\nReading comment for %s : %s from stdin\n"
#define MLogCommBrk L"\nThe archive comment is corrupt"
#define MCommAskCont L"\nPress 'Enter' to continue or 'Q' to quit:"
#define MWriteCommTo L"\nWrite comment to %s"
#define MCommNotPres L"\nComment is not present"
#define MDelFrom L"\nDeleting from %s"
#define MDeleting L"\nDeleting %s"
#define MEraseArc L"\nErasing empty archive %s"
#define MNoDelFiles L"\nNo files to delete"
#define MLogTitle L"-------- %2d %s %d, archive %s"
#define MPathTooLong L"\nERROR: Path too long\n"
#define MListArchive L"Archive"
#define MListDetails L"Details"
#define MListSolid L"solid"
#define MListSFX L"SFX"
#define MListVolume L"volume"
#define MListRR L"recovery record"
#define MListLock L"lock"
#define MListEnc L"encrypted"
#define MListEncHead L"encrypted headers"
#define MListTitleL L" Attributes Size Date Time Name"
#define MListTitleV L" Attributes Size Packed Ratio Date Time Checksum Name"
#define MListName L"Name"
#define MListType L"Type"
#define MListFile L"File"
#define MListDir L"Directory"
#define MListUSymlink L"Unix symbolic link"
#define MListWSymlink L"Windows symbolic link"
#define MListJunction L"NTFS junction point"
#define MListHardlink L"Hard link"
#define MListCopy L"File reference"
#define MListStream L"NTFS alternate data stream"
#define MListTarget L"Target"
#define MListSize L"Size"
#define MListPacked L"Packed size"
#define MListRatio L"Ratio"
#define MListMtime L"mtime"
#define MListCtime L"ctime"
#define MListAtime L"atime"
#define MListAttr L"Attributes"
#define MListFlags L"Flags"
#define MListCompInfo L"Compression"
#define MListHostOS L"Host OS"
#define MListFileVer L"File version"
#define MListService L"Service"
#define MListUOHead L"\n Unix Owner/Group data: %-14s %-14s"
#define MListNTACLHead L"\n NTFS security data"
#define MListStrmHead L"\n NTFS stream: %s"
#define MListUnkHead L"\n Unknown subheader type: 0x%04x"
#define MFileComment L"\nComment: "
#define MYes L"Yes"
#define MNo L"No"
#define MListNoFiles L" 0 files\n"
#define MRprReconstr L"\nReconstructing %s"
#define MRprBuild L"\nBuilding %s"
#define MRprOldFormat L"\nCannot repair archive with old format"
#define MRprFind L"\nFound %s"
#define MRprAskIsSol L"\nThe archive header is corrupt. Mark archive as solid ?"
#define MRprNoFiles L"\nNo files found"
#define MLogUnexpEOF L"\nUnexpected end of archive"
#define MRepAskReconst L"\nReconstruct archive structure ?"
#define MRRSearch L"\nSearching for recovery record"
#define MAnalyzeFileData L"\nAnalyzing file data"
#define MRecRNotFound L"\nData recovery record not found"
#define MRecRFound L"\nData recovery record found"
#define MRecSecDamage L"\nSector %ld (offsets %lX...%lX) damaged"
#define MRecCorrected L" - data recovered"
#define MRecFailed L" - cannot recover data"
#define MAddRecRec L"\nAdding data recovery record"
#define MEraseForVolume L"\n\nErasing contents of drive %c:\n"
#define MGetOwnersError L"\nWARNING: Cannot get %s owner and group\n"
#define MErrGetOwnerID L"\nWARNING: Cannot get owner %s ID\n"
#define MErrGetGroupID L"\nWARNING: Cannot get group %s ID\n"
#define MOwnersBroken L"\nERROR: %s group and owner data are corrupt\n"
#define MSetOwnersError L"\nWARNING: Cannot set %s owner and group\n"
#define MErrLnkRead L"\nWARNING: Cannot read symbolic link %s"
#define MSymLinkExists L"\nWARNING: Symbolic link %s already exists"
#define MAskRetryCreate L"\nCannot create %s. Retry ?"
#define MDataBadCRC L"\n%-20s : packed data checksum error in volume %s"
#define MFileRO L"\n%s is read-only"
#define MACLGetError L"\nWARNING: Cannot get %s security data\n"
#define MACLSetError L"\nWARNING: Cannot set %s security data\n"
#define MACLBroken L"\nERROR: %s security data are corrupt\n"
#define MACLUnknown L"\nWARNING: Unknown format of %s security data\n"
#define MStreamBroken L"\nERROR: %s stream data are corrupt\n"
#define MStreamUnknown L"\nWARNING: Unknown format of %s stream data\n"
#define MInvalidName L"\nERROR: Invalid file name %s"
#define MProcessArc L"\n\nProcessing archive %s"
#define MCorrectingName L"\nWARNING: Attempting to correct the invalid file name"
#define MUnpCannotMerge L"\nWARNING: You need to start extraction from a previous volume to unpack %s"
#define MUnknownOption L"\nERROR: Unknown option: %s"
#define MSubHeadCorrupt L"\nERROR: Corrupt data header found, ignored"
#define MSubHeadUnknown L"\nWARNING: Unknown data header format, ignored"
#define MSubHeadDataCRC L"\nERROR: Corrupt %s data block"
#define MSubHeadType L"\nData header type: %s"
#define MScanError L"\nCannot read contents of %s"
#define MNotVolume L"\n%s is not volume"
#define MRecVolDiffSets L"\nERROR: %s and %s belong to different sets"
#define MRecVolMissing L"\n%d volumes missing"
#define MRecVolFound L"\n%d recovery volumes found"
#define MRecVolAllExist L"\nNothing to reconstruct"
#define MRecVolCannotFix L"\nReconstruction impossible"
#define MReconstructing L"\nReconstructing..."
#define MCreating L"\nCreating %s"
#define MRenaming L"\nRenaming %s to %s"
#define MNTFSRequired L"\nWrite error: only NTFS file system supports files larger than 4 GB"
#define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files"
#define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s"
#define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives"
#define MHeadEncMismatch L"\nCannot change the header encryption mode in already encrypted archive"
#define MCannotEmail L"\nCannot email the file %s"
#define MCopyrightS L"\nRAR SFX archive"
#define MSHelpCmd L"\n\n<Commands>"
#define MSHelpCmdE L"\n -x Extract from archive (default)"
#define MSHelpCmdT L"\n -t Test archive files"
#define MSHelpCmdV L"\n -v Verbosely list contents of archive"
#define MRecVolLimit L"\nTotal number of usual and recovery volumes must not exceed %d"
#define MVolumeNumber L"volume %d"
#define MCannotDelete L"\nCannot delete %s"
#define MRecycleFailed L"\nCannot move some files and folders to Recycle Bin"
#define MCalcCRC L"\nCalculating the checksum"
#define MTooLargeSFXArc L"\nToo large SFX archive. Windows cannot run the executable file exceeding 4 GB."
#define MCalcCRCAllVol L"\nCalculating checksums of all volumes."
#define MNotEnoughDisk L"\nERROR: Not enough disk space for %s."
#define MNewerRAR L"\nYou may need a newer version of RAR."
#define MUnkEncMethod L"\nUnknown encryption method in %s"
#define MWrongPassword L"\nThe specified password is incorrect."
#define MWrongFilePassword L"\nIncorrect password for %s"
#define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x"
#define MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated"
#define MRRDamaged L"\nRecovery record is corrupt."
#define MTestingRR L"\nTesting the recovery record"
#define MFailed L"Failed"
#define MIncompatSwitch L"\n%s switch is not supported for RAR %d.x archive format."
#define MSearchDupFiles L"\nSearching for identical files"
#define MNumFound L"%d found."
#define MUnknownExtra L"\nUnknown extra field in %s."
#define MCorruptExtra L"\nCorrupt %s extra field in %s."
#define MCopyError L"\nCannot copy %s to %s."
#define MCopyErrorHint L"\nYou need to unpack the entire archive to create file reference entries."
#define MCopyingData L"\nCopying data"
#define MErrCreateLnkS L"\nCannot create symbolic link %s"
#define MErrCreateLnkH L"\nCannot create hard link %s"
#define MErrLnkTarget L"\nYou need to unpack the link target first"
#define MNeedAdmin L"\nYou may need to run RAR as administrator"
#define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB."
#define MUseSmalllerDict L"\nPlease use a smaller compression dictionary."
#define MOpenErrAtime L"\nYou may need to remove -tsp switch to open this file."
#define MYesNo "_Yes_No"
#define MYesNoAll "_Yes_No_All"
#define MYesNoAllRenQ "_Yes_No_All_nEver_Rename_Quit"
#define MContinueQuit "_Continue_Quit"
#define MRetryAbort "_Retry_Abort"
#define MCopyright "\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d"
#define MRegTo "\nRegistered to %s\n"
#define MShare "\nShareware version Type RAR -? for help\n"
#define MUCopyright "\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
#define MBeta "beta"
#define MMonthJan "Jan"
#define MMonthFeb "Feb"
#define MMonthMar "Mar"
#define MMonthApr "Apr"
#define MMonthMay "May"
#define MMonthJun "Jun"
#define MMonthJul "Jul"
#define MMonthAug "Aug"
#define MMonthSep "Sep"
#define MMonthOct "Oct"
#define MMonthNov "Nov"
#define MMonthDec "Dec"
#define MRARTitle1 "\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
#define MUNRARTitle1 "\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
#define MRARTitle2 "\n <@listfiles...> <path_to_extract\\>"
#define MCHelpCmd "\n\n<Commands>"
#define MCHelpCmdA "\n a Add files to archive"
#define MCHelpCmdC "\n c Add archive comment"
#define MCHelpCmdCF "\n cf Add files comment"
#define MCHelpCmdCH "\n ch Change archive parameters"
#define MCHelpCmdCW "\n cw Write archive comment to file"
#define MCHelpCmdD "\n d Delete files from archive"
#define MCHelpCmdE "\n e Extract files to current directory"
#define MCHelpCmdF "\n f Freshen files in archive"
#define MCHelpCmdI "\n i[par]=<str> Find string in archives"
#define MCHelpCmdK "\n k Lock archive"
#define MCHelpCmdL "\n l[t,b] List archive [technical, bare]"
#define MCHelpCmdM "\n m[f] Move to archive [files only]"
#define MCHelpCmdP "\n p Print file to stdout"
#define MCHelpCmdR "\n r Repair archive"
#define MCHelpCmdRC "\n rc Reconstruct missing volumes"
#define MCHelpCmdRN "\n rn Rename archived files"
#define MCHelpCmdRR "\n rr[N] Add data recovery record"
#define MCHelpCmdRV "\n rv[N] Create recovery volumes"
#define MCHelpCmdS "\n s[name|-] Convert archive to or from SFX"
#define MCHelpCmdT "\n t Test archive files"
#define MCHelpCmdU "\n u Update files in archive"
#define MCHelpCmdV "\n v[t,b] Verbosely list archive [technical,bare]"
#define MCHelpCmdX "\n x Extract files with full path"
#define MCHelpSw "\n\n<Switches>"
#define MCHelpSwm "\n - Stop switches scanning"
#define MCHelpSwAC "\n ac Clear Archive attribute after compression or extraction"
#define MCHelpSwAD "\n ad Append archive name to destination path"
#define MCHelpSwAG "\n ag[format] Generate archive name using the current date"
#define MCHelpSwAO "\n ao Add files with Archive attribute set"
#define MCHelpSwAP "\n ap<path> Set path inside archive"
#define MCHelpSwAS "\n as Synchronize archive contents"
#define MCHelpSwAV "\n av Put authenticity verification (registered versions only)"
#define MCHelpSwAVm "\n av- Disable authenticity verification check"
#define MCHelpSwCm "\n c- Disable comments show"
#define MCHelpSwCFGm "\n cfg- Disable read configuration"
#define MCHelpSwCL "\n cl Convert names to lower case"
#define MCHelpSwCU "\n cu Convert names to upper case"
#define MCHelpSwDF "\n df Delete files after archiving"
#define MCHelpSwDH "\n dh Open shared files"
#define MCHelpSwDS "\n ds Disable name sort for solid archive"
#define MCHelpSwEa "\n e[+]<attr> Set file exclude and include attributes"
#define MCHelpSwED "\n ed Do not add empty directories"
#define MCHelpSwEE "\n ee Do not save and extract extended attributes"
#define MCHelpSwEN "\n en Do not put 'end of archive' block"
#define MCHelpSwEP "\n ep Exclude paths from names"
#define MCHelpSwEP1 "\n ep1 Exclude base directory from names"
#define MCHelpSwEP2 "\n ep2 Expand paths to full"
#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter"
#define MCHelpSwF "\n f Freshen files"
#define MCHelpSwFCU "\n fcu[file] Read archive comment from Unicode file"
#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers"
#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages"
#define MCHelpSwIEML "\n ieml[addr] Send archive by email"
#define MCHelpSwIERR "\n ierr Send all messages to stderr"
#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)"
#define MCHelpSwINUL "\n inul Disable all messages"
#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation"
#define MCHelpSwISND "\n isnd Enable sound"
#define MCHelpSwK "\n k Lock archive"
#define MCHelpSwKB "\n kb Keep broken extracted files"
#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)"
#define MCHelpSwMC "\n mc<par> Set advanced compression parameters"
#define MCHelpSwMD "\n md<size> Dictionary size in KB (64,128,256,512,1024,2048,4096 or A-G)"
#define MCHelpSwMS "\n ms[ext;ext] Specify file types to store"
#define MCHelpSwMT "\n mt<threads> Set the number of threads"
#define MCHelpSwN "\n n<file> Include only specified file"
#define MCHelpSwNa "\n n@ Read file names to include from stdin"
#define MCHelpSwNal "\n n@<list> Include files in specified list file"
#define MCHelpSwOp "\n o+ Overwrite existing files"
#define MCHelpSwOm "\n o- Do not overwrite existing files"
#define MCHelpSwOC "\n oc Set NTFS Compressed attribute"
#define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file"
#define MCHelpSwOR "\n or Rename files automatically"
#define MCHelpSwOS "\n os Save NTFS streams"
#define MCHelpSwOW "\n ow Save or restore file owner and group"
#define MCHelpSwP "\n p[password] Set password"
#define MCHelpSwPm "\n p- Do not query password"
#define MCHelpSwR "\n r Recurse subdirectories"
#define MCHelpSwR0 "\n r0 Recurse subdirectories for wildcard names only"
#define MCHelpSwRI "\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms"
#define MCHelpSwRR "\n rr[N] Add data recovery record"
#define MCHelpSwRV "\n rv[N] Create recovery volumes"
#define MCHelpSwS "\n s[<N>,v[-],e] Create solid archive"
#define MCHelpSwSm "\n s- Disable solid archiving"
#define MCHelpSwSFX "\n sfx[name] Create SFX archive"
#define MCHelpSwSI "\n si[name] Read data from standard input (stdin)"
#define MCHelpSwSL "\n sl<size> Process files with size less than specified"
#define MCHelpSwSM "\n sm<size> Process files with size more than specified"
#define MCHelpSwT "\n t Test files after archiving"
#define MCHelpSwTK "\n tk Keep original archive time"
#define MCHelpSwTL "\n tl Set archive time to latest file"
#define MCHelpSwTN "\n tn<time> Process files newer than <time>"
#define MCHelpSwTO "\n to<time> Process files older than <time>"
#define MCHelpSwTA "\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
#define MCHelpSwTB "\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
#define MCHelpSwTS "\n ts<m,c,a>[N] Save or restore file time (modification, creation, access)"
#define MCHelpSwU "\n u Update files"
#define MCHelpSwV "\n v Create volumes with size autodetection or list all volumes"
#define MCHelpSwVUnr "\n v List all volumes"
#define MCHelpSwVn "\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]"
#define MCHelpSwVD "\n vd Erase disk contents before creating volume"
#define MCHelpSwVER "\n ver[n] File version control"
#define MCHelpSwVN "\n vn Use the old style volume naming scheme"
#define MCHelpSwVP "\n vp Pause before each volume"
#define MCHelpSwW "\n w<path> Assign work directory"
#define MCHelpSwX "\n x<file> Exclude specified file"
#define MCHelpSwXa "\n x@ Read file names to exclude from stdin"
#define MCHelpSwXal "\n x@<list> Exclude files in specified list file"
#define MCHelpSwY "\n y Assume Yes on all queries"
#define MCHelpSwZ "\n z[file] Read archive comment from file"
#define MBadArc "\nERROR: Bad archive %s\n"
#define MAskPsw "Enter password (will not be echoed)"
#define MAskPswEcho "Enter password"
#define MReAskPsw "\nReenter password: "
#define MFor " for "
#define MNotMatchPsw "\nERROR: Passwords do not match\n"
#define MErrWrite "Write error in the file %s"
#define MErrRead "Read error in the file %s"
#define MErrSeek "Seek error in the file %s"
#define MErrFClose "Cannot close the file %s"
#define MErrOutMem "Not enough memory"
#define MErrBrokenArc "Corrupt archive - use 'Repair' command"
#define MProgAborted "Program aborted"
#define MErrRename "\nCannot rename %s to %s"
#define MAbsNextVol "\nCannot find volume %s"
#define MBreak "\nUser break\n"
#define MAskCreatVol "\nCreate next volume ?"
#define MAskNextDisk "\nDisk full. Insert next"
#define MCreatVol "\n\nCreating %sarchive %s\n"
#define MAskNextVol "\nInsert disk with %s"
#define MTestVol "\n\nTesting archive %s\n"
#define MExtrVol "\n\nExtracting from %s\n"
#define MConverting "\nConverting %s"
#define MCvtToSFX "\nConvert archives to SFX"
#define MCvtFromSFX "\nRemoving SFX module"
#define MNotSFX "\n%s is not SFX archive"
#define MNotRAR "\n%s is not RAR archive"
#define MNotFirstVol "\n%s is not the first volume"
#define MCvtOldFormat "\n%s - cannot convert to SFX archive with old format"
#define MCannotCreate "\nCannot create %s"
#define MCannotOpen "\nCannot open %s"
#define MUnknownMeth "\nUnknown method in %s"
#define MVerRequired "\nYou need RAR %d.%d to unpack it"
#define MOk " OK"
#define MDone "\nDone"
#define MLockingArc "\nLocking archive"
#define MNotMdfOld "\n\nERROR: Cannot modify old format archive"
#define MNotMdfLock "\n\nERROR: Locked archive"
#define MNotMdfVol "\n\nERROR: Cannot modify volume"
#define MVerifyAV "\nVerifying authenticity information ... "
#define MFailedAV " Failed\n"
#define MStrAV1 "\n\nArchive %s"
#define MStrAV2 "\ncreated at %s"
#define MStrAV3 "\nby %s\n"
#define MLogFailedAV "Invalid authenticity information"
#define MAddingAV "\nAdding authenticity verification "
#define MAVOldStyle "\n\nOld style authenticity information"
#define MPackAskReg "\nEvaluation copy. Please register.\n"
#define MCreateArchive "\nCreating %sarchive %s\n"
#define MUpdateArchive "\nUpdating %sarchive %s\n"
#define MAddSolid "solid "
#define MAddFile "\nAdding %-58s "
#define MUpdFile "\nUpdating %-58s "
#define MAddPoints "\n... %-58s "
#define MCannotUpdPswSolid "\nERROR: Cannot update solid archives with password\n"
#define MMoveDelFiles "\n\nDeleting files %s..."
#define MMoveDelDirs "and directories"
#define MMoveDelFile "\nDeleting %-30s"
#define MMoveDeleted " deleted"
#define MMoveNotDeleted " NOT DELETED"
#define MClearAttrib "\n\nClearing attributes..."
#define MMoveDelDir "\nDeleting directory %-30s"
#define MWarErrFOpen "\nWARNING: Cannot open %d %s"
#define MErrOpenFiles "files"
#define MErrOpenFile "file"
#define MAddNoFiles "\nWARNING: No files"
#define MMdfEncrSol "\n%s: encrypted"
#define MCannotMdfEncrSol "\nCannot modify solid archive containing encrypted files"
#define MAddAnalyze "\nAnalyzing archived files: "
#define MRepacking "\nRepacking archived files: "
#define MCRCFailed "\n%-20s - CRC failed"
#define MExtrTest "\n\nTesting archive %s\n"
#define MExtracting "\n\nExtracting from %s\n"
#define MUseCurPsw "\n%s - use current password ?"
#define MCreatDir "\nCreating %-56s"
#define MExtrSkipFile "\nSkipping %-56s"
#define MExtrTestFile "\nTesting %-56s"
#define MExtrFile "\nExtracting %-56s"
#define MExtrPoints "\n... %-56s"
#define MExtrErrMkDir "\nCannot create directory %s"
#define MExtrPrinting "\n------ Printing %s\n\n"
#define MEncrBadCRC "\nEncrypted file: CRC failed in %s (password incorrect ?)"
#define MExtrNoFiles "\nNo files to extract"
#define MExtrAllOk "\nAll OK"
#define MExtrTotalErr "\nTotal errors: %ld"
#define MFileExists "\n\n%s already exists. Overwrite it ?"
#define MAskOverwrite "\nOverwrite %s ?"
#define MAskNewName "\nEnter new name: "
#define MLogMainHead "\nThe archive header is corrupt"
#define MLogFileHead "\n%s - the file header is corrupt"
#define MLogCommHead "\nThe comment header is corrupt\n"
#define MLogProtectHead "The data recovery header is corrupt"
#define MReadStdinCmt "\nReading comment from stdin\n"
#define MReadCommFrom "\nReading comment from %s"
#define MDelComment "\nDeleting comment from %s"
#define MAddComment "\nAdding comment to %s"
#define MFCommAdd "\nAdding file comments"
#define MAskFComm "\n\nReading comment for %s : %s from stdin\n"
#define MLogCommBrk "\nThe archive comment is corrupt"
#define MCommAskCont "\nPress 'Enter' to continue or 'Q' to quit:"
#define MLogBrokFCmt "\nThe file comment is corrupt"
#define MAbsDestName "\nDestination file name required"
#define MWriteCommTo "\nWrite comment to %s"
#define MCommNotPres "\nComment is not present"
#define MDelFrom "\nDeleting from %s"
#define MDeleting "\nDeleting %s"
#define MEraseArc "\nErasing empty archive %s"
#define MNoDelFiles "\nNo files to delete"
#define MLogTitle "\n\n-------- %2d %s %d, archive %s\n"
#define MPathTooLong "\nERROR: Path too long\n"
#define MListSolid "Solid "
#define MListSFX "SFX "
#define MListVol1 "volume"
#define MListVol2 "Volume"
#define MListArc1 "archive"
#define MListArc2 "Archive"
#define MListRecRec "\nRecovery record is present\n"
#define MListLock "\nLock is present\n"
#define MListPathComm "\nPathname/Comment\n "
#define MListName "\n Name "
#define MListTitle " Size Packed Ratio Date Time Attr CRC Meth Ver\n"
#define MListTechTitle " Host OS Solid Old\n"
#define MListEAHead "\n OS/2 extended attributes"
#define MListUOHead "\n Unix Owner/Group data: %-14s %-14s"
#define MListBeEAHead "\n BeOS extended attributes"
#define MListNTACLHead "\n NTFS security data"
#define MListStrmHead "\n NTFS stream: %s"
#define MListUnkHead "\n Unknown subheader type: 0x%04x"
#define MFileComment "\nComment: "
#define MYes "Yes"
#define MNo "No"
#define MListNoFiles " 0 files\n"
#define MRprReconstr "\nReconstructing %s"
#define MRprBuild "\nBuilding %s"
#define MRprOldFormat "\nCannot repair archive with old format"
#define MRprFind "\nFound %s"
#define MRprAskIsSol "\nThe archive header is corrupt. Mark archive as solid ?"
#define MRprNoFiles "\nNo files found"
#define MRprSuspEntry "\n\nSuspicious entry %s"
#define MRprDir "\nDirectory"
#define MRprSuspSize "\nSize %ld Packed %ld"
#define MRprSuspAdd "\nAdd it to archive ?"
#define MLogUnexpEOF "\nUnexpected end of archive"
#define MRepAskReconst "\nReconstruct archive structure ?"
#define MRecScanning "\nScanning..."
#define MRecRNotFound "\nData recovery record not found"
#define MRecRFound "\nData recovery record found"
#define MRecSecDamage "\nSector %ld (offsets %lX...%lX) damaged"
#define MRecCorrected " - data recovered"
#define MRecFailed " - cannot recover data"
#define MAddRecRec "\nAdding data recovery record"
#define MEraseForVolume "\n\nErasing contents of drive %c:\n"
#define MGetOwnersError "\nWARNING: Cannot get %s owner and group\n"
#define MErrGetOwnerID "\nWARNING: Cannot get owner %s ID\n"
#define MErrGetGroupID "\nWARNING: Cannot get group %s ID\n"
#define MOwnersBroken "\nERROR: %s group and owner data are corrupt\n"
#define MSetOwnersError "\nWARNING: Cannot set %s owner and group\n"
#define MErrLnkRead "\nWARNING: Cannot read symbolic link %s"
#define MErrCreateLnk "\nWARNING: Cannot create link %s"
#define MSymLinkExists "\nWARNING: Symbolic link %s already exists"
#define MAskRetryCreate "\nCannot create %s. Retry ?"
#define MListMACHead1 "\n MacOS file type: %c%c%c%c ; "
#define MListMACHead2 "file creator: %c%c%c%c\n"
#define MDataBadCRC "\n%-20s : packed data CRC failed in volume %s"
#define MFileRO "\n%s is read-only"
#define MACLGetError "\nWARNING: Cannot get %s security data\n"
#define MACLSetError "\nWARNING: Cannot set %s security data\n"
#define MACLBroken "\nERROR: %s security data are corrupt\n"
#define MACLUnknown "\nWARNING: Unknown format of %s security data\n"
#define MStreamBroken "\nERROR: %s stream data are corrupt\n"
#define MStreamUnknown "\nWARNING: Unknown format of %s stream data\n"
#define MInvalidName "\nERROR: Invalid file name %s"
#define MEABroken "\nERROR: %s extended attributes are corrupt\n"
#define MEAUnknHeader "\nWARNING: %s - unknown format of extended attributes\n"
#define MCannotSetEA "\nWARNING: cannot set extended attributes to %s\n"
#define MCannotGetEA "\nERROR: Cannot get extended attributes of %s\n"
#define MShowEA " (+EA)"
#define MSkipEA "\n...skipping extended attributes"
#define MProcessArc "\n\nProcessing archive %s"
#define MSyncScanError "\nFile search errors, cannot synchronize archive"
#define MCorrectingName "\nWARNING: Attempting to correct the invalid file name"
#define MUnpCannotMerge "\nWARNING: You need to start extraction from a previous volume to unpack %s"
#define MUnknownOption "\nERROR: Unknown option: %s"
#define MSubHeadCorrupt "\nERROR: Corrupt data header found, ignored"
#define MSubHeadUnknown "\nWARNING: Unknown data header format, ignored"
#define MSubHeadDataCRC "\nERROR: Corrupt %s data block"
#define MSubHeadType "\nData header type: %s"
#define MScanError "\nCannot read contents of %s"
#define MNotVolume "\n%s is not volume"
#define MRecVolDiffSets "\nERROR: %s and %s belong to different sets"
#define MRecVolMissing "\n%d volumes missing"
#define MRecVolFound "\n%d recovery volumes found"
#define MRecVolAllExist "\nNothing to reconstruct"
#define MRecVolCannotFix "\nReconstruction impossible"
#define MReconstructing "\nReconstructing..."
#define MCreating "\nCreating %s"
#define MRenaming "\nRenaming %s to %s"
#define MNTFSRequired "\nWrite error: only NTFS file system supports files larger than 4 GB"
#define MErrChangeAttr "\nWARNING: Cannot change attributes of %s"
#define MWrongSFXVer "\nERROR: default SFX module does not support RAR %d.%d archives"
#define MCannotEncName "\nCannot encrypt archive already contained encrypted files"
#define MCannotEmail "\nCannot email the file %s"
#define MCopyrightS "\nRAR SFX archive"
#define MSHelpCmd "\n\n<Commands>"
#define MSHelpCmdE "\n -x Extract from archive (default)"
#define MSHelpCmdT "\n -t Test archive files"
#define MSHelpCmdV "\n -v Verbosely list contents of archive"
#define MMaxPathLimit "\nTotal path and file name length must not exceed %d characters"
#define MRecVolLimit "\nTotal number of usual and recovery volumes must not exceed 255"
#define MVolumeNumber "volume %d"
#define MCannotDelete "\nCannot delete %s"
+10 -23
View File
@@ -1,36 +1,23 @@
#include "rar.hpp"
static wchar LogName[NM];
static RAR_CHARSET LogCharset=RCH_DEFAULT;
static char LogName[NM];
void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet)
void InitLogOptions(char *LogName)
{
wcsncpyz(LogName,LogFileName,ASIZE(LogName));
LogCharset=CSet;
strcpy(::LogName,LogName);
}
#ifndef SILENT
void Log(const wchar *ArcName,const wchar *fmt,...)
void Log(const char *ArcName,const char *Format,...)
{
// Preserve the error code for possible following system error message.
int Code=ErrHandler.GetSystemErrorCode();
uiAlarm(UIALARM_ERROR);
// This buffer is for format string only, not for entire output,
// so it can be short enough.
wchar fmtw[1024];
PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
safebuf wchar Msg[2*NM+1024];
va_list arglist;
va_start(arglist,fmt);
vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
va_end(arglist);
eprintf(L"%ls",Msg);
ErrHandler.SetSystemErrorCode(Code);
safebuf char Msg[2*NM+1024];
va_list ArgPtr;
va_start(ArgPtr,Format);
vsprintf(Msg,Format,ArgPtr);
va_end(ArgPtr);
eprintf("%s",Msg);
}
#endif
+9 -3
View File
@@ -1,12 +1,18 @@
#ifndef _RAR_LOG_
#define _RAR_LOG_
void InitLogOptions(const wchar *LogFileName,RAR_CHARSET CSet);
void InitLogOptions(char *LogName);
#ifndef SILENT
void Log(const char *ArcName,const char *Format,...);
#endif
#ifdef SILENT
inline void Log(const wchar *ArcName,const wchar *fmt,...) {}
#ifdef __GNUC__
#define Log(args...)
#else
void Log(const wchar *ArcName,const wchar *fmt,...);
inline void Log(const char *a,const char *b,const char *c=NULL,const char *d=NULL) {}
#endif
#endif
#endif
-174
View File
@@ -1,174 +0,0 @@
#
# Makefile for UNIX - unrar
# Linux using GCC
CXX=c++
CXXFLAGS=-O2 -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else
LIBFLAGS=-fPIC
DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
STRIP=strip
AR=ar
LDFLAGS=-pthread
DESTDIR=/usr
# Linux using LCC
#CXX=lcc
#CXXFLAGS=-O2
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=strip
#AR=ar
#DESTDIR=/usr
# CYGWIN using GCC
#CXX=c++
#CXXFLAGS=-O2
#LIBFLAGS=
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
#STRIP=strip
#AR=ar
#LDFLAGS=-pthread
#DESTDIR=/usr
# HP UX using aCC
#CXX=aCC
#CXXFLAGS=-AA +O2 +Onolimit
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=strip
#AR=ar
#DESTDIR=/usr
# IRIX using GCC
#CXX=g++
#CXXFLAGS=-O2
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1
#STRIP=strip
#AR=ar
#DESTDIR=/usr
# IRIX using MIPSPro (experimental)
#CXX=CC
#CXXFLAGS=-O2 -mips3 -woff 1234,1156,3284 -LANG:std
#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -Dint64=int64_t
#STRIP=strip
#AR=ar
#DESTDIR=/usr
# AIX using xlC (IBM VisualAge C++ 5.0)
#CXX=xlC
#CXXFLAGS=-O -qinline -qro -qroconst -qmaxmem=16384 -qcpluscmt
#DEFINES=-D_LARGE_FILES -D_LARGE_FILE_API
#LIBS=-lbsd
#STRIP=strip
#AR=ar
#DESTDIR=/usr
# Solaris using CC
#CXX=CC
#CXXFLAGS=-fast -erroff=wvarhidemem
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=strip
#AR=ar
#DESTDIR=/usr
# Solaris using GCC (optimized for UltraSPARC 1 CPU)
#CXX=g++
#CXXFLAGS=-O3 -mcpu=v9 -mtune=ultrasparc -m32
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=/usr/ccs/bin/strip
#AR=/usr/ccs/bin/ar
#DESTDIR=/usr
# Tru64 5.1B using GCC3
#CXX=g++
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_XOPEN_SOURCE=500
#STRIP=strip
#AR=ar
#LDFLAGS=-rpath /usr/local/gcc/lib
#DESTDIR=/usr
# Tru64 5.1B using DEC C++
#CXX=cxx
#CXXFLAGS=-O4 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Dint64=long
#STRIP=strip
#AR=ar
#LDFLAGS=
#DESTDIR=/usr
# QNX 6.x using GCC
#CXX=g++
#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fexceptions
#STRIP=strip
#AR=ar
#LDFLAGS=-fexceptions
#DESTDIR=/usr
# Cross-compile
# Linux using arm-linux-g++
#CXX=arm-linux-g++
#CXXFLAGS=-O2
#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
#STRIP=arm-linux-strip
#AR=arm-linux-ar
#LDFLAGS=-static
#DESTDIR=/usr
##########################
COMPILE=$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES)
LINK=$(CXX)
WHAT=UNRAR
UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o qopen.o
LIB_OBJ=filestr.o scantree.o dll.o qopen.o
OBJECTS=rar.o strlist.o strfn.o pathfn.o smallfn.o global.o file.o filefn.o filcreat.o \
archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
resource.o match.o timefn.o rdwrfn.o consio.o options.o errhnd.o rarvm.o secpassword.o \
rijndael.o getbits.o sha1.o sha256.o blake2s.o hash.o extinfo.o extract.o volume.o \
list.o find.o unpack.o headers.o threadpool.o rs16.o cmddata.o ui.o
.cpp.o:
$(COMPILE) -D$(WHAT) -c $<
all: unrar
install: install-unrar
uninstall: uninstall-unrar
clean:
@rm -f *.bak *~
@rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ)
@rm -f unrar libunrar.*
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
@rm -f unrar
$(LINK) -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
$(STRIP) unrar
sfx: WHAT=SFX_MODULE
sfx: clean $(OBJECTS)
@rm -f default.sfx
$(LINK) -o default.sfx $(LDFLAGS) $(OBJECTS)
$(STRIP) default.sfx
lib: WHAT=RARDLL
lib: CXXFLAGS+=$(LIBFLAGS)
lib: clean $(OBJECTS) $(LIB_OBJ)
@rm -f libunrar.*
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
install-unrar:
install -D unrar $(DESTDIR)/bin/unrar
uninstall-unrar:
rm -f $(DESTDIR)/bin/unrar
install-lib:
install libunrar.so $(DESTDIR)/lib
install libunrar.a $(DESTDIR)/lib
uninstall-lib:
rm -f $(DESTDIR)/lib/libunrar.so
+177 -62
View File
@@ -1,82 +1,175 @@
#include "rar.hpp"
static bool match(const wchar *pattern,const wchar *string,bool ForceCase);
static int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase);
static int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase);
static bool match(char *pattern,char *string,bool ForceCase);
static bool match(wchar *pattern,wchar *string,bool ForceCase);
inline uint touppercw(uint ch,bool ForceCase)
static int mstricompc(const char *Str1,const char *Str2,bool ForceCase);
static int mstricompcw(const wchar *Str1,const wchar *Str2,bool ForceCase);
static int mstrnicompc(const char *Str1,const char *Str2,int N,bool ForceCase);
static int mstrnicompcw(const wchar *Str1,const wchar *Str2,int N,bool ForceCase);
inline uint toupperc(byte ch,bool ForceCase)
{
if (ForceCase)
return ch;
#if defined(_UNIX)
return ch;
return(ch);
#ifdef _WIN_32
return((uint)CharUpper((LPTSTR)(ch)));
#elif defined(_UNIX)
return(ch);
#else
return toupperw(ch);
return(toupper(ch));
#endif
}
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
inline uint touppercw(uint ch,bool ForceCase)
{
bool ForceCase=(CmpMode&MATCH_FORCECASESENSITIVE)!=0;
if (ForceCase)
return(ch);
#if defined(_UNIX)
return(ch);
#else
return(toupperw(ch));
#endif
}
CmpMode&=MATCH_MODEMASK;
if (CmpMode!=MATCH_NAMES)
bool CmpName(char *Wildcard,char *Name,int CmpPath)
{
bool ForceCase=(CmpPath&MATCH_FORCECASESENSITIVE)!=0;
CmpPath&=MATCH_MODEMASK;
if (CmpPath!=MATCH_NAMES)
{
size_t WildLength=wcslen(Wildcard);
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH && CmpMode!=MATCH_ALLWILD &&
mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
int WildLength=strlen(Wildcard);
if (CmpPath!=MATCH_EXACTPATH && mstrnicompc(Wildcard,Name,WildLength,ForceCase)==0)
{
// For all modes except MATCH_NAMES, MATCH_EXACT, MATCH_EXACTPATH, MATCH_ALLWILD,
// "path1" mask must match "path1\path2\filename.ext" and "path1" names.
wchar NextCh=Name[WildLength];
if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
char NextCh=Name[WildLength];
if (NextCh=='\\' || NextCh=='/' || NextCh==0)
return(true);
}
// Nothing more to compare for MATCH_SUBPATHONLY.
if (CmpMode==MATCH_SUBPATHONLY)
char Path1[NM],Path2[NM];
GetFilePath(Wildcard,Path1);
GetFilePath(Name,Path2);
if (mstricompc(Wildcard,Path2,ForceCase)==0)
return(true);
if ((CmpPath==MATCH_PATH || CmpPath==MATCH_EXACTPATH) && mstricompc(Path1,Path2,ForceCase)!=0)
return(false);
wchar Path1[NM],Path2[NM];
GetFilePath(Wildcard,Path1,ASIZE(Path1));
GetFilePath(Name,Path2,ASIZE(Path2));
if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
mwcsicompc(Path1,Path2,ForceCase)!=0)
return(false);
if (CmpMode==MATCH_ALLWILD)
return match(Wildcard,Name,ForceCase);
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
if (CmpPath==MATCH_SUBPATH || CmpPath==MATCH_WILDSUBPATH)
if (IsWildcard(Path1))
return(match(Wildcard,Name,ForceCase));
else
if (CmpMode==MATCH_SUBPATH || IsWildcard(Wildcard))
if (CmpPath==MATCH_SUBPATH || IsWildcard(Wildcard))
{
if (*Path1 && mwcsnicompc(Path1,Path2,wcslen(Path1),ForceCase)!=0)
if (*Path1 && mstrnicompc(Path1,Path2,strlen(Path1),ForceCase)!=0)
return(false);
}
else
if (mwcsicompc(Path1,Path2,ForceCase)!=0)
if (mstricompc(Path1,Path2,ForceCase)!=0)
return(false);
}
wchar *Name1=PointToName(Wildcard);
wchar *Name2=PointToName(Name);
// Always return false for RAR temporary files to exclude them
// from archiving operations.
// if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
// return(false);
if (CmpMode==MATCH_EXACT)
return(mwcsicompc(Name1,Name2,ForceCase)==0);
char *Name1=PointToName(Wildcard);
char *Name2=PointToName(Name);
if (mstrnicompc("__rar_",Name2,6,false)==0)
return(false);
return(match(Name1,Name2,ForceCase));
}
bool match(const wchar *pattern,const wchar *string,bool ForceCase)
#ifndef SFX_MODULE
bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath)
{
bool ForceCase=(CmpPath&MATCH_FORCECASESENSITIVE)!=0;
CmpPath&=MATCH_MODEMASK;
if (CmpPath!=MATCH_NAMES)
{
int WildLength=strlenw(Wildcard);
if (CmpPath!=MATCH_EXACTPATH && mstrnicompcw(Wildcard,Name,WildLength,ForceCase)==0)
{
wchar NextCh=Name[WildLength];
if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
return(true);
}
wchar Path1[NM],Path2[NM];
GetFilePath(Wildcard,Path1);
GetFilePath(Name,Path2);
if ((CmpPath==MATCH_PATH || CmpPath==MATCH_EXACTPATH) && mstricompcw(Path1,Path2,ForceCase)!=0)
return(false);
if (CmpPath==MATCH_SUBPATH || CmpPath==MATCH_WILDSUBPATH)
if (IsWildcard(NULL,Path1))
return(match(Wildcard,Name,ForceCase));
else
if (CmpPath==MATCH_SUBPATH || IsWildcard(NULL,Wildcard))
{
if (*Path1 && mstrnicompcw(Path1,Path2,strlenw(Path1),ForceCase)!=0)
return(false);
}
else
if (mstricompcw(Path1,Path2,ForceCase)!=0)
return(false);
}
wchar *Name1=PointToName(Wildcard);
wchar *Name2=PointToName(Name);
if (mstrnicompcw(L"__rar_",Name2,6,false)==0)
return(false);
return(match(Name1,Name2,ForceCase));
}
#endif
bool match(char *pattern,char *string,bool ForceCase)
{
for (;; ++string)
{
char stringc=toupperc(*string,ForceCase);
char patternc=toupperc(*pattern++,ForceCase);
switch (patternc)
{
case 0:
return(stringc==0);
case '?':
if (stringc == 0)
return(false);
break;
case '*':
if (*pattern==0)
return(true);
if (*pattern=='.')
{
if (pattern[1]=='*' && pattern[2]==0)
return(true);
char *dot=strchr(string,'.');
if (pattern[1]==0)
return (dot==NULL || dot[1]==0);
if (dot!=NULL)
{
string=dot;
if (strpbrk(pattern,"*?")==NULL && strchr(string+1,'.')==NULL)
return(mstricompc(pattern+1,string+1,ForceCase)==0);
}
}
while (*string)
if (match(pattern,string++,ForceCase))
return(true);
return(false);
default:
if (patternc != stringc)
if (patternc=='.' && stringc==0)
return(match(pattern,string,ForceCase));
else
return(false);
break;
}
}
}
#ifndef SFX_MODULE
bool match(wchar *pattern,wchar *string,bool ForceCase)
{
for (;; ++string)
{
@@ -97,14 +190,14 @@ bool match(const wchar *pattern,const wchar *string,bool ForceCase)
{
if (pattern[1]=='*' && pattern[2]==0)
return(true);
const wchar *dot=wcschr(string,'.');
wchar *dot=strchrw(string,'.');
if (pattern[1]==0)
return (dot==NULL || dot[1]==0);
if (dot!=NULL)
{
string=dot;
if (wcspbrk(pattern,L"*?")==NULL && wcschr(string+1,'.')==NULL)
return(mwcsicompc(pattern+1,string+1,ForceCase)==0);
if (strpbrkw(pattern,L"*?")==NULL && strchrw(string+1,'.')==NULL)
return(mstricompcw(pattern+1,string+1,ForceCase)==0);
}
}
@@ -114,34 +207,56 @@ bool match(const wchar *pattern,const wchar *string,bool ForceCase)
return(false);
default:
if (patternc != stringc)
{
// Allow "name." mask match "name" and "name.\" match "name\".
if (patternc=='.' && (stringc==0 || stringc=='\\' || stringc=='.'))
if (patternc=='.' && stringc==0)
return(match(pattern,string,ForceCase));
else
return(false);
}
break;
}
}
}
#endif
int mwcsicompc(const wchar *Str1,const wchar *Str2,bool ForceCase)
int mstricompc(const char *Str1,const char *Str2,bool ForceCase)
{
if (ForceCase)
return wcscmp(Str1,Str2);
return wcsicompc(Str1,Str2);
return(strcmp(Str1,Str2));
return(stricompc(Str1,Str2));
}
int mwcsnicompc(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase)
#ifndef SFX_MODULE
int mstricompcw(const wchar *Str1,const wchar *Str2,bool ForceCase)
{
if (ForceCase)
return wcsncmp(Str1,Str2,N);
return(strcmpw(Str1,Str2));
return(stricompcw(Str1,Str2));
}
#endif
int mstrnicompc(const char *Str1,const char *Str2,int N,bool ForceCase)
{
if (ForceCase)
return(strncmp(Str1,Str2,N));
#if defined(_UNIX)
return wcsncmp(Str1,Str2,N);
return(strncmp(Str1,Str2,N));
#else
return wcsnicomp(Str1,Str2,N);
return(strnicomp(Str1,Str2,N));
#endif
}
#ifndef SFX_MODULE
int mstrnicompcw(const wchar *Str1,const wchar *Str2,int N,bool ForceCase)
{
if (ForceCase)
return(strncmpw(Str1,Str2,N));
#if defined(_UNIX)
return(strncmpw(Str1,Str2,N));
#else
return(strnicmpw(Str1,Str2,N));
#endif
}
#endif
+3 -29
View File
@@ -1,38 +1,12 @@
#ifndef _RAR_MATCH_
#define _RAR_MATCH_
enum {
MATCH_NAMES, // Paths are ignored.
// Compares names only using wildcards.
MATCH_SUBPATHONLY, // Paths must match either exactly or path in wildcard
// must be present in the beginning of file path.
// For example, "c:\path1\*" or "c:\path1" will match
// "c:\path1\path2\file".
// Names are not compared.
MATCH_EXACT, // Paths must match exactly.
// Names must match exactly.
MATCH_ALLWILD, // Paths and names are compared using wildcards.
// Unlike MATCH_SUBPATH, paths do not match subdirs
// unless a wildcard tells so.
MATCH_EXACTPATH, // Paths must match exactly.
// Names are compared using wildcards.
MATCH_SUBPATH, // Names must be the same, but path in mask is allowed
// to be only a part of name path. In other words,
// we match all files matching the file mask
// in current folder and subfolders.
MATCH_WILDSUBPATH // Works as MATCH_SUBPATH if file mask contains
// wildcards and as MATCH_EXACTPATH otherwise.
};
enum {MATCH_NAMES,MATCH_PATH,MATCH_EXACTPATH,MATCH_SUBPATH,MATCH_WILDSUBPATH};
#define MATCH_MODEMASK 0x0000ffff
#define MATCH_FORCECASESENSITIVE 0x80000000
bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode);
bool CmpName(char *Wildcard,char *Name,int CmpPath);
bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath);
#endif
+42 -81
View File
@@ -5,17 +5,10 @@
* Contents: model description and encoding/decoding routines *
****************************************************************************/
static const int MAX_O=64; /* maximum allowed model order */
const uint TOP=1 << 24, BOT=1 << 15;
template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
inline RARPPM_CONTEXT* RARPPM_CONTEXT::createChild(ModelPPM *Model,RARPPM_STATE* pStats,
RARPPM_STATE& FirstState)
inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats,
STATE& FirstState)
{
RARPPM_CONTEXT* pc = (RARPPM_CONTEXT*) Model->SubAlloc.AllocContext();
PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext();
if ( pc )
{
pc->NumStats=1;
@@ -41,15 +34,11 @@ void ModelPPM::RestartModelRare()
memset(CharMask,0,sizeof(CharMask));
SubAlloc.InitSubAllocator();
InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext();
if (MinContext == NULL)
throw std::bad_alloc();
MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext();
MinContext->Suffix=NULL;
OrderFall=MaxOrder;
MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2);
if (FoundState == NULL)
throw std::bad_alloc();
FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2);
for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
{
MinContext->U.Stats[i].Symbol=i;
@@ -116,10 +105,10 @@ void ModelPPM::StartModelRare(int MaxOrder)
}
void RARPPM_CONTEXT::rescale(ModelPPM *Model)
void PPM_CONTEXT::rescale(ModelPPM *Model)
{
int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
RARPPM_STATE* p1, * p;
STATE* p1, * p;
for (p=Model->FoundState;p != U.Stats;p--)
_PPMD_SWAP(p[0],p[-1]);
U.Stats->Freq += 4;
@@ -133,7 +122,7 @@ void RARPPM_CONTEXT::rescale(ModelPPM *Model)
U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
if (p[0].Freq > p[-1].Freq)
{
RARPPM_STATE tmp=*(p1=p);
STATE tmp=*(p1=p);
do
{
p1[0]=p1[-1];
@@ -150,7 +139,7 @@ void RARPPM_CONTEXT::rescale(ModelPPM *Model)
EscFreq += i;
if ((NumStats -= i) == 1)
{
RARPPM_STATE tmp=*U.Stats;
STATE tmp=*U.Stats;
do
{
tmp.Freq-=(tmp.Freq >> 1);
@@ -163,16 +152,19 @@ void RARPPM_CONTEXT::rescale(ModelPPM *Model)
U.SummFreq += (EscFreq -= (EscFreq >> 1));
int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
if (n0 != n1)
U.Stats = (RARPPM_STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
U.Stats = (STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
Model->FoundState=U.Stats;
}
inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1)
inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1)
{
RARPPM_STATE UpState;
RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
RARPPM_STATE * p, * ps[MAX_O], ** pps=ps;
#ifdef __ICL
static
#endif
STATE UpState;
PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
STATE * p, * ps[MAX_O], ** pps=ps;
if ( !Skip )
{
*pps++ = FoundState;
@@ -203,21 +195,14 @@ LOOP_ENTRY:
{
pc=p->Successor;
break;
}
// We ensure that PPM order input parameter does not exceed MAX_O (64),
// so we do not really need this check and added it for extra safety.
// See CVE-2017-17969 for details.
if (pps>=ps+ASIZE(ps))
return NULL;
*pps++ = p;
} while ( pc->Suffix );
NO_LOOP:
if (pps == ps)
return pc;
UpState.Symbol=*(byte*) UpBranch;
UpState.Successor=(RARPPM_CONTEXT*) (((byte*) UpBranch)+1);
UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
if (pc->NumStats != 1)
{
if ((byte*) pc <= SubAlloc.pText)
@@ -245,8 +230,8 @@ NO_LOOP:
inline void ModelPPM::UpdateModel()
{
RARPPM_STATE fs = *FoundState, *p = NULL;
RARPPM_CONTEXT *pc, *Successor;
STATE fs = *FoundState, *p = NULL;
PPM_CONTEXT *pc, *Successor;
uint ns1, ns, cf, sf, s0;
if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
{
@@ -284,7 +269,7 @@ inline void ModelPPM::UpdateModel()
return;
}
*SubAlloc.pText++ = fs.Symbol;
Successor = (RARPPM_CONTEXT*) SubAlloc.pText;
Successor = (PPM_CONTEXT*) SubAlloc.pText;
if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
goto RESTART_MODEL;
if ( fs.Successor )
@@ -310,7 +295,7 @@ inline void ModelPPM::UpdateModel()
{
if ((ns1 & 1) == 0)
{
pc->U.Stats=(RARPPM_STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
if ( !pc->U.Stats )
goto RESTART_MODEL;
}
@@ -318,7 +303,7 @@ inline void ModelPPM::UpdateModel()
}
else
{
p=(RARPPM_STATE*) SubAlloc.AllocUnits(1);
p=(STATE*) SubAlloc.AllocUnits(1);
if ( !p )
goto RESTART_MODEL;
*p=pc->OneState;
@@ -361,9 +346,9 @@ static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2,
inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
{
RARPPM_STATE& rs=OneState;
STATE& rs=OneState;
Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
Model->NS2BSIndx[Suffix->NumStats-1]+
@@ -375,14 +360,14 @@ inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
rs.Freq += (rs.Freq < 128);
Model->Coder.SubRange.LowCount=0;
Model->Coder.SubRange.HighCount=bs;
bs = GET_SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
bs = SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
Model->PrevSuccess=1;
Model->RunLength++;
}
else
{
Model->Coder.SubRange.LowCount=bs;
bs = GET_SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
bs = SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
Model->Coder.SubRange.HighCount=BIN_SCALE;
Model->InitEsc=ExpEscape[bs >> 10];
Model->NumMasked=1;
@@ -393,7 +378,7 @@ inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
}
inline void RARPPM_CONTEXT::update1(ModelPPM *Model,RARPPM_STATE* p)
inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
{
(Model->FoundState=p)->Freq += 4;
U.SummFreq += 4;
@@ -409,13 +394,13 @@ inline void RARPPM_CONTEXT::update1(ModelPPM *Model,RARPPM_STATE* p)
inline bool RARPPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
{
Model->Coder.SubRange.scale=U.SummFreq;
RARPPM_STATE* p=U.Stats;
STATE* p=U.Stats;
int i, HiCnt;
int count=Model->Coder.GetCurrentCount();
if (count>=(int)Model->Coder.SubRange.scale)
if (count>=Model->Coder.SubRange.scale)
return(false);
if (count < (HiCnt=p->Freq))
{
@@ -454,7 +439,7 @@ inline bool RARPPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
}
inline void RARPPM_CONTEXT::update2(ModelPPM *Model,RARPPM_STATE* p)
inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
{
(Model->FoundState=p)->Freq += 4;
U.SummFreq += 4;
@@ -465,9 +450,9 @@ inline void RARPPM_CONTEXT::update2(ModelPPM *Model,RARPPM_STATE* p)
}
inline RARPPM_SEE2_CONTEXT* RARPPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
{
RARPPM_SEE2_CONTEXT* psee2c;
SEE2_CONTEXT* psee2c;
if (NumStats != 256)
{
psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
@@ -487,11 +472,11 @@ inline RARPPM_SEE2_CONTEXT* RARPPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Dif
inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
{
int count, HiCnt, i=NumStats-Model->NumMasked;
RARPPM_SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
RARPPM_STATE* ps[256], ** pps=ps, * p=U.Stats-1;
SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
STATE* ps[256], ** pps=ps, * p=U.Stats-1;
HiCnt=0;
do
{
@@ -500,29 +485,18 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
p++;
} while (Model->CharMask[p->Symbol] == Model->EscCount);
HiCnt += p->Freq;
// We do not reuse PPMd coder in unstable state, so we do not really need
// this check and added it for extra safety. See CVE-2017-17969 for details.
if (pps>=ps+ASIZE(ps))
return false;
*pps++ = p;
} while ( --i );
Model->Coder.SubRange.scale += HiCnt;
count=Model->Coder.GetCurrentCount();
if (count>=(int)Model->Coder.SubRange.scale)
if (count>=Model->Coder.SubRange.scale)
return(false);
p=*(pps=ps);
if (count < HiCnt)
{
HiCnt=0;
while ((HiCnt += p->Freq) <= count)
{
pps++;
if (pps>=ps+ASIZE(ps)) // Extra safety check.
return false;
p=*pps;
}
p=*++pps;
Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
psee2c->update();
update2(Model,p);
@@ -535,15 +509,12 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
pps--;
do
{
pps++;
if (pps>=ps+ASIZE(ps)) // Extra safety check.
return false;
Model->CharMask[(*pps)->Symbol]=Model->EscCount;
Model->CharMask[(*++pps)->Symbol]=Model->EscCount;
} while ( --i );
psee2c->Summ += Model->Coder.SubRange.scale;
Model->NumMasked = NumStats;
}
return true;
return(true);
}
@@ -556,20 +527,10 @@ inline void ModelPPM::ClearMask()
// reset PPM variables after data error allowing safe resuming
// of further data processing
void ModelPPM::CleanUp()
{
SubAlloc.StopSubAllocator();
SubAlloc.StartSubAllocator(1);
StartModelRare(2);
}
bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
{
int MaxOrder=UnpackRead->GetChar();
bool Reset=(MaxOrder & 0x20)!=0;
bool Reset=MaxOrder & 0x20;
int MaxMB;
if (Reset)
+43 -34
View File
@@ -4,17 +4,16 @@
#include "coder.hpp"
#include "suballoc.hpp"
#ifdef ALLOW_MISALIGNED
const int MAX_O=64; /* maximum allowed model order */
const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
#ifndef STRICT_ALIGNMENT_REQUIRED
#pragma pack(1)
#endif
struct RARPPM_DEF
{
static const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
};
struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
struct SEE2_CONTEXT
{ // SEE-contexts for PPM-contexts with masked symbols
ushort Summ;
byte Shift, Count;
@@ -25,7 +24,7 @@ struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
}
uint getMean()
{
uint RetVal=GET_SHORT16(Summ) >> Shift;
uint RetVal=SHORT16(Summ) >> Shift;
Summ -= RetVal;
return RetVal+(RetVal == 0);
}
@@ -41,47 +40,45 @@ struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
class ModelPPM;
struct RARPPM_CONTEXT;
struct PPM_CONTEXT;
struct RARPPM_STATE
struct STATE
{
byte Symbol;
byte Freq;
RARPPM_CONTEXT* Successor;
PPM_CONTEXT* Successor;
};
struct FreqData
{
ushort SummFreq;
STATE _PACK_ATTR * Stats;
};
struct RARPPM_CONTEXT : RARPPM_DEF
struct PPM_CONTEXT
{
ushort NumStats;
struct FreqData
{
ushort SummFreq;
RARPPM_STATE RARPPM_PACK_ATTR * Stats;
};
union
{
FreqData U;
RARPPM_STATE OneState;
STATE OneState;
};
RARPPM_CONTEXT* Suffix;
PPM_CONTEXT* Suffix;
inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
inline bool decodeSymbol1(ModelPPM *Model); // other orders:
inline bool decodeSymbol2(ModelPPM *Model); // BCD context
inline void update1(ModelPPM *Model,RARPPM_STATE* p); // CD suffix
inline void update2(ModelPPM *Model,RARPPM_STATE* p); // BCDE successor
inline void update1(ModelPPM *Model,STATE* p); // CD suffix
inline void update2(ModelPPM *Model,STATE* p); // BCDE successor
void rescale(ModelPPM *Model);
inline RARPPM_CONTEXT* createChild(ModelPPM *Model,RARPPM_STATE* pStats,RARPPM_STATE& FirstState);
inline RARPPM_SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
};
#ifdef ALLOW_MISALIGNED
#ifndef STRICT_ALIGNMENT_REQUIRED
#ifdef _AIX
#pragma pack(pop)
#else
@@ -89,15 +86,28 @@ struct RARPPM_CONTEXT : RARPPM_DEF
#endif
#endif
class ModelPPM : RARPPM_DEF
const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK));
const uint FIXED_UNIT_SIZE=12;
/*
inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext):
NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; }
inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {}
*/
template <class T>
inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
class ModelPPM
{
private:
friend struct RARPPM_CONTEXT;
friend struct PPM_CONTEXT;
RARPPM_SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
_PACK_ATTR SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
struct RARPPM_CONTEXT *MinContext, *MedContext, *MaxContext;
RARPPM_STATE* FoundState; // found next state transition
struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
STATE* FoundState; // found next state transition
int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
byte EscCount, PrevSuccess, HiBitsFlag;
@@ -108,13 +118,12 @@ class ModelPPM : RARPPM_DEF
void RestartModelRare();
void StartModelRare(int MaxOrder);
inline RARPPM_CONTEXT* CreateSuccessors(bool Skip,RARPPM_STATE* p1);
inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);
inline void UpdateModel();
inline void ClearMask();
public:
ModelPPM();
void CleanUp(); // reset PPM variables after data error
bool DecodeInit(Unpack *UnpackRead,int &EscChar);
int DecodeChar();
};
+2532
View File
File diff suppressed because it is too large Load Diff
+7 -14
View File
@@ -8,8 +8,6 @@ RAROptions::RAROptions()
RAROptions::~RAROptions()
{
// It is important for security reasons, so we do not have the unnecessary
// password data left in memory.
memset(this,0,sizeof(RAROptions));
}
@@ -17,19 +15,14 @@ RAROptions::~RAROptions()
void RAROptions::Init()
{
memset(this,0,sizeof(RAROptions));
WinSize=0x2000000;
Overwrite=OVERWRITE_DEFAULT;
WinSize=0x400000;
Overwrite=OVERWRITE_ASK;
Method=3;
MsgStream=MSG_STDOUT;
ConvertNames=NAMES_ORIGINALCASE;
xmtime=EXTTIME_MAX;
FileSizeLess=INT64NDF;
FileSizeMore=INT64NDF;
HashType=HASH_CRC32;
#ifdef RAR_SMP
Threads=GetNumberOfThreads();
#endif
#ifdef USE_QOPEN
QOpenMode=QOPEN_AUTO;
#endif
ProcessEA=true;
xmtime=EXTTIME_HIGH3;
CurVolNum=0;
FileSizeLess=INT64ERR;
FileSizeMore=INT64ERR;
}
+57 -132
View File
@@ -1,78 +1,30 @@
#ifndef _RAR_OPTIONS_
#define _RAR_OPTIONS_
#define DEFAULT_RECOVERY -3
#define DEFAULT_RECOVERY -1
#define DEFAULT_RECVOLUMES -10
#define VOLSIZE_AUTO INT64NDF // Automatically detect the volume size.
enum PATH_EXCL_MODE {
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)
EXCL_ABSPATH // -ep3 (the full path with the disk letter)
enum PathExclMode {
EXCL_NONE,EXCL_BASEPATH,EXCL_SKIPWHOLEPATH,EXCL_SAVEFULLPATH,
EXCL_SKIPABSPATH,EXCL_ABSPATH
};
enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
SOLID_VOLUME_DEPENDENT=8,SOLID_VOLUME_INDEPENDENT=16};
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
enum {ARCTIME_NONE,ARCTIME_KEEP,ARCTIME_LATEST};
enum EXTTIME_MODE {
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_MAX
EXTTIME_NONE,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
};
enum {NAMES_ORIGINALCASE,NAMES_UPPERCASE,NAMES_LOWERCASE};
enum MESSAGE_TYPE {MSG_STDOUT,MSG_STDERR,MSG_ERRONLY,MSG_NULL};
enum OVERWRITE_MODE {
OVERWRITE_ASK,OVERWRITE_ALL,OVERWRITE_NONE,OVERWRITE_AUTORENAME
};
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
enum MESSAGE_TYPE {MSG_STDOUT=0,MSG_STDERR,MSG_ERRONLY,MSG_NULL};
enum RECURSE_MODE
{
RECURSE_NONE=0, // no recurse switches
RECURSE_DISABLE, // switch -r-
RECURSE_ALWAYS, // switch -r
RECURSE_WILDCARDS, // switch -r0
};
enum OVERWRITE_MODE
{
OVERWRITE_DEFAULT=0, // Ask when extracting, silently overwrite when archiving.
OVERWRITE_ALL,
OVERWRITE_NONE,
OVERWRITE_AUTORENAME,
OVERWRITE_FORCE_ASK
};
enum QOPEN_MODE { QOPEN_NONE, QOPEN_AUTO, QOPEN_ALWAYS };
enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE,RCH_UTF8 };
#define MAX_FILTER_TYPES 16
#define MAX_FILTERS 16
enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE};
enum SAVECOPY_MODE {
SAVECOPY_NONE=0, SAVECOPY_SILENT, SAVECOPY_LIST, SAVECOPY_LISTEXIT,
SAVECOPY_DUPLISTEXIT
};
enum APPENDARCNAME_MODE
{
APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNDIR
};
enum POWER_MODE {
POWERMODE_KEEP=0,POWERMODE_OFF,POWERMODE_HIBERNATE,POWERMODE_SLEEP,
POWERMODE_RESTART
};
// Need "forced off" state to turn off sound in GUI command line.
enum SOUND_NOTIFY_MODE {SOUND_NOTIFY_DEFAULT=0,SOUND_NOTIFY_ON,SOUND_NOTIFY_OFF};
struct FilterMode
{
FilterState State;
@@ -80,8 +32,6 @@ struct FilterMode
int Param2;
};
#define MAX_GENERATE_MASK 128
class RAROptions
{
@@ -92,120 +42,95 @@ class RAROptions
uint ExclFileAttr;
uint InclFileAttr;
// We handle -ed and -e+d with special flags instead of attribute mask,
// so it works with both Windows and Unix archives.
bool ExclDir;
bool InclDir;
bool InclAttrSet;
size_t WinSize;
wchar TempPath[NM];
wchar SFXModule[NM];
#ifdef USE_QOPEN
QOPEN_MODE QOpenMode;
#endif
bool ConfigDisabled; // Switch -cfg-.
wchar ExtrPath[NM];
wchar CommentFile[NM];
RAR_CHARSET CommentCharset;
RAR_CHARSET FilelistCharset;
RAR_CHARSET ErrlogCharset;
RAR_CHARSET RedirectCharset;
wchar ArcPath[NM];
SecPassword Password;
uint WinSize;
char TempPath[NM];
char SFXModule[NM];
char ExtrPath[NM];
wchar ExtrPathW[NM];
char CommentFile[NM];
bool UnicodeComment;
char ArcPath[NM];
char Password[MAXPASSWORD];
bool EncryptHeaders;
bool ManualPassword; // Password entered manually during operation, might need to clean for next archive.
wchar LogName[NM];
char LogName[NM];
MESSAGE_TYPE MsgStream;
SOUND_NOTIFY_MODE Sound;
bool Sound;
OVERWRITE_MODE Overwrite;
int Method;
HASH_TYPE HashType;
int Recovery;
int RecVolNumber;
bool DisablePercentage;
bool DisableCopyright;
bool DisableDone;
bool PrintVersion;
int Solid;
int SolidCount;
bool ClearArc;
bool AddArcOnly;
bool AV;
bool DisableComment;
bool FreshFiles;
bool UpdateFiles;
PATH_EXCL_MODE ExclPath;
RECURSE_MODE Recurse;
int64 VolSize;
Array<int64> NextVolSizes;
uint CurVolNum;
PathExclMode ExclPath;
int Recurse;
Int64 VolSize;
Array<Int64> NextVolSizes;
int CurVolNum;
bool AllYes;
bool MoreInfo; // -im, show more information, used only in "WinRAR t" now.
bool DisableViewAV;
bool DisableSortSolid;
int ArcTime;
int ConvertNames;
bool ProcessOwners;
bool SaveSymLinks;
bool SaveHardLinks;
bool AbsoluteLinks;
bool SaveLinks;
int Priority;
int SleepTime;
bool KeepBroken;
bool EraseDisk;
bool OpenShared;
bool ExclEmptyDir;
bool DeleteFiles;
#ifdef _WIN_ALL
bool AllowIncompatNames; // Allow names with trailing dots and spaces.
#endif
#ifndef SFX_MODULE
bool GenerateArcName;
wchar GenerateMask[MAX_GENERATE_MASK];
wchar DefGenerateMask[MAX_GENERATE_MASK];
#endif
bool SyncFiles;
bool GenerateArcName;
char GenerateMask[80];
bool ProcessEA;
bool SaveStreams;
bool SetCompressedAttr;
bool IgnoreGeneralAttr;
RarTime FileMtimeBefore,FileCtimeBefore,FileAtimeBefore;
bool FileMtimeBeforeOR,FileCtimeBeforeOR,FileAtimeBeforeOR;
RarTime FileMtimeAfter,FileCtimeAfter,FileAtimeAfter;
bool FileMtimeAfterOR,FileCtimeAfterOR,FileAtimeAfterOR;
int64 FileSizeLess;
int64 FileSizeMore;
uint FileTimeOlder;
uint FileTimeNewer;
RarTime FileTimeBefore;
RarTime FileTimeAfter;
Int64 FileSizeLess;
Int64 FileSizeMore;
bool OldNumbering;
bool Lock;
bool Test;
bool VolumePause;
FilterMode FilterModes[MAX_FILTER_TYPES];
wchar EmailTo[NM];
uint VersionControl;
APPENDARCNAME_MODE AppendArcNameToPath;
POWER_MODE Shutdown;
EXTTIME_MODE xmtime; // Extended time modes (time precision to store).
FilterMode FilterModes[MAX_FILTERS];
char EmailTo[NM];
int VersionControl;
bool NoEndBlock;
bool AppendArcNameToPath;
bool Shutdown;
EXTTIME_MODE xmtime;
EXTTIME_MODE xctime;
EXTTIME_MODE xatime;
bool PreserveAtime;
wchar CompressStdin[NM];
uint Threads; // We use it to init hash even if RAR_SMP is not defined.
EXTTIME_MODE xarctime;
char CompressStdin[NM];
#ifdef PACK_SMP
uint Threads;
#endif
#ifdef RARDLL
wchar DllDestName[NM];
char DllDestName[NM];
wchar DllDestNameW[NM];
int DllOpMode;
int DllError;
LPARAM UserData;
LONG UserData;
UNRARCALLBACK Callback;
CHANGEVOLPROC ChangeVolProc;
PROCESSDATAPROC ProcessDataProc;
+99 -128
View File
@@ -8,132 +8,139 @@
#define INCL_BASE
#endif
#if defined(RARDLL) && !defined(SILENT)
#define SILENT
#if defined(_WIN_32) || defined(_EMX)
#define ENABLE_BAD_ALLOC
#endif
#include <new>
#if defined(_WIN_ALL) || defined(_EMX)
#if defined(_WIN_32) || defined(_EMX)
#define LITTLE_ENDIAN
#define NM 2048
#define NM 1024
#ifdef _WIN_ALL
#ifdef _WIN_32
#define STRICT
#undef WINVER
#undef _WIN32_WINNT
#define WINVER 0x0400
#define _WIN32_WINNT 0x0300
// We got a report that just "#define STRICT" is incompatible with
// "#define STRICT 1" in Windows 10 SDK minwindef.h and depending on the order
// in which these statements are reached this may cause a compiler warning
// and build break for other projects incorporating this source.
// So we changed it to "#define STRICT 1".
#ifndef STRICT
#define STRICT 1
#endif
// 'ifndef' check here is needed for unrar.dll header to avoid macro
// re-definition warnings in third party projects.
#ifndef UNICODE
#define UNICODE
#endif
#undef WINVER
#undef _WIN32_WINNT
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#if !defined(ZIPSFX)
#define RAR_SMP
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <prsht.h>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <PowrProf.h>
#pragma comment(lib, "PowrProf.lib")
#include <shellapi.h>
#include <shlobj.h>
#include <winioctl.h>
#include <wincrypt.h>
#include <wchar.h>
#include <wctype.h>
#ifndef _WIN_CE
#include <winioctl.h>
#endif
#endif // _WIN_ALL
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <dos.h>
#ifndef _WIN_CE
#include <sys/types.h>
#include <sys/stat.h>
#include <dos.h>
#endif
#if !defined(_EMX) && !defined(_MSC_VER)
#if !defined(_EMX) && !defined(_MSC_VER) && !defined(_WIN_CE)
#include <dir.h>
#endif
#ifdef _MSC_VER
#if _MSC_VER<1500
#define for if (0) ; else for
#endif
#define for if (0) ; else for
#ifndef _WIN_CE
#include <direct.h>
#include <intrin.h>
#define USE_SSE
#define SSE_ALIGNMENT 16
#endif
#else
#include <dirent.h>
#endif // _MSC_VER
#endif
#ifndef _WIN_CE
#include <share.h>
#endif
#if defined(ENABLE_BAD_ALLOC) && !defined(_WIN_CE)
#include <new.h>
#endif
#ifdef _EMX
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#ifdef _DJGPP
#include <utime.h>
#else
#include <os2.h>
#include <sys/utime.h>
#include <emx/syscalls.h>
#endif
#else
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <exception>
#else
#include <except.h>
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <dos.h>
#include <io.h>
#include <time.h>
#include <signal.h>
#ifndef _WIN_CE
#include <fcntl.h>
#include <dos.h>
#include <io.h>
#include <time.h>
#include <signal.h>
#endif
#define SAVE_LINKS
/*
#ifdef _WIN_32
#pragma hdrstop
#endif
*/
#define ENABLE_ACCESS
#define DefConfigName L"rar.ini"
#define DefLogName L"rar.log"
#define DefConfigName "rar.ini"
#define DefLogName "rar.log"
#define SPATHDIVIDER L"\\"
#define PATHDIVIDER "\\"
#define PATHDIVIDERW L"\\"
#define CPATHDIVIDER '\\'
#define MASKALL L"*"
#define MASKALL "*"
#define MASKALLW L"*"
#define READBINARY "rb"
#define READTEXT "rt"
#define UPDATEBINARY "r+b"
#define CREATEBINARY "w+b"
#define WRITEBINARY "wb"
#define APPENDTEXT "at"
#if defined(_WIN_ALL)
#if defined(_WIN_32)
#ifdef _MSC_VER
#define _stdfunction __cdecl
#define _forceinline __forceinline
#else
#define _stdfunction _USERENTRY
#define _forceinline inline
#endif
#else
#define _stdfunction
#define _forceinline inline
#endif
#endif // defined(_WIN_ALL) || defined(_EMX)
#endif
#ifdef _UNIX
#define NM 2048
#define NM 1024
#ifdef _BEOS
#include <be/kernel/fs_info.h>
#include <be/kernel/fs_attr.h>
#endif
#include <unistd.h>
#include <sys/types.h>
@@ -142,16 +149,13 @@
#if defined(__QNXNTO__)
#include <sys/param.h>
#endif
#if defined(RAR_SMP) && defined(__APPLE__)
#include <sys/sysctl.h>
#endif
#ifndef SFX_MODULE
#include <sys/statvfs.h>
#if defined(__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__)
#include <sys/param.h>
#include <sys/mount.h>
#else
#endif
#include <pwd.h>
#include <grp.h>
#include <wchar.h>
#include <wctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -165,35 +169,29 @@
#include <utime.h>
#include <locale.h>
#ifdef S_IFLNK
#define SAVE_LINKS
#endif
#if defined(__linux) || defined(__FreeBSD__)
#include <sys/time.h>
#define USE_LUTIMES
#endif
#define ENABLE_ACCESS
#define DefConfigName L".rarrc"
#define DefLogName L".rarlog"
#define DefConfigName ".rarrc"
#define DefLogName ".rarlog"
#define SPATHDIVIDER L"/"
#define PATHDIVIDER "/"
#define PATHDIVIDERW L"/"
#define CPATHDIVIDER '/'
#define MASKALL L"*"
#define MASKALL "*"
#define MASKALLW L"*"
#define READBINARY "r"
#define READTEXT "r"
#define UPDATEBINARY "r+"
#define CREATEBINARY "w+"
#define WRITEBINARY "w"
#define APPENDTEXT "a"
#define _stdfunction
#define _forceinline inline
#ifdef _APPLE
#if defined(__BIG_ENDIAN__) && !defined(BIG_ENDIAN)
@@ -212,58 +210,31 @@
#endif
#endif
#if _POSIX_C_SOURCE >= 200809L
#define UNIX_TIME_NS // Nanosecond time precision in Unix.
#endif
#endif // _UNIX
#if 0
#define MSGID_INT
typedef int MSGID;
#else
typedef const wchar* MSGID;
#endif
#ifndef SSE_ALIGNMENT // No SSE use and no special data alignment is required.
#define SSE_ALIGNMENT 1
#endif
typedef const char* MSGID;
#define safebuf static
// Solaris defines _LITTLE_ENDIAN or _BIG_ENDIAN.
#if defined(_LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN)
#define LITTLE_ENDIAN
#endif
#if defined(_BIG_ENDIAN) && !defined(BIG_ENDIAN)
#define BIG_ENDIAN
#endif
#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#if defined(__i386) || defined(i386) || defined(__i386__) || defined(__x86_64)
#define LITTLE_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN || defined(__LITTLE_ENDIAN__)
#define LITTLE_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN || defined(__BIG_ENDIAN__)
#define BIG_ENDIAN
#else
#error "Neither LITTLE_ENDIAN nor BIG_ENDIAN are defined. Define one of them."
#endif
#endif
#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
#undef LITTLE_ENDIAN
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
#undef BIG_ENDIAN
#else
#error "Both LITTLE_ENDIAN and BIG_ENDIAN are defined. Undef one of them."
#error "Both LITTLE_ENDIAN and BIG_ENDIAN are defined. Undef something one"
#endif
#endif
#if !defined(BIG_ENDIAN) && defined(_WIN_ALL) || defined(__i386__) || defined(__x86_64__)
// Allow not aligned integer access, increases speed in some operations.
#define ALLOW_MISALIGNED
#if !defined(BIG_ENDIAN) && !defined(_WIN_CE) && defined(_WIN_32)
/* 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 */
#define STRICT_ALIGNMENT_REQUIRED
#endif
#endif // _RAR_OS_
+94
View File
@@ -0,0 +1,94 @@
#include <os2.h>
void ExtractOS2EA(Archive &Arc,char *FileName)
{
if (_osmode != OS2_MODE)
{
mprintf(St(MSkipEA));
return;
}
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
return;
}
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
{
Log(Arc.FileName,St(MEAUnknHeader),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
return;
}
struct StructEAOP2
{
char *GEAPtr;
char *FEAPtr;
unsigned long Error;
} EAOP2;
ComprDataIO DataIO;
Unpack Unpack(&DataIO);
Unpack.Init();
Array<unsigned char> UnpData(Arc.EAHead.UnpSize);
DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
DataIO.EnableShowProgress(false);
DataIO.SetFiles(&Arc,NULL);
Unpack.SetDestSize(Arc.EAHead.UnpSize);
Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
return;
}
EAOP2.FEAPtr=(char *)&UnpData[0];
EAOP2.GEAPtr=NULL;
if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
}
File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
mprintf(St(MShowEA));
}
void ExtractOS2EANew(Archive &Arc,char *FileName)
{
if (_osmode != OS2_MODE)
{
mprintf(St(MSkipEA));
return;
}
Array<byte> SubData;
if (!Arc.ReadSubData(&SubData,NULL))
return;
struct StructEAOP2
{
char *GEAPtr;
char *FEAPtr;
unsigned long Error;
} EAOP2;
EAOP2.FEAPtr=(char *)&SubData[0];
EAOP2.GEAPtr=NULL;
if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
}
File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
mprintf(St(MShowEA));
}
+340 -704
View File
File diff suppressed because it is too large Load Diff
+31 -63
View File
@@ -1,76 +1,44 @@
#ifndef _RAR_PATHFN_
#define _RAR_PATHFN_
char* PointToName(const char *Path);
wchar* PointToName(const wchar *Path);
wchar* PointToLastChar(const wchar *Path);
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize);
void SetName(wchar *FullName,const wchar *Name,size_t MaxSize);
void SetExt(wchar *Name,const wchar *NewExt,size_t MaxSize);
void SetSFXExt(wchar *SFXName,size_t MaxSize);
char* PointToLastChar(const char *Path);
char* ConvertPath(const char *SrcPath,char *DestPath);
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath);
void SetExt(char *Name,const char *NewExt);
void SetExt(wchar *Name,const wchar *NewExt);
void SetSFXExt(char *SFXName);
void SetSFXExt(wchar *SFXName);
char *GetExt(const char *Name);
wchar *GetExt(const wchar *Name);
bool CmpExt(const wchar *Name,const wchar *Ext);
bool IsWildcard(const wchar *Str);
bool CmpExt(const char *Name,const char *Ext);
bool IsWildcard(const char *Str,const wchar *StrW=NULL);
bool IsPathDiv(int Ch);
bool IsDriveDiv(int Ch);
bool IsDriveLetter(const wchar *Path);
int GetPathDisk(const wchar *Path);
void AddEndSlash(wchar *Path,size_t MaxLength);
void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize);
void GetFilePath(const wchar *FullName,wchar *Path,size_t MaxLength);
int GetPathDisk(const char *Path);
void AddEndSlash(char *Path);
void AddEndSlash(wchar *Path);
void GetFilePath(const char *FullName,char *Path);
void GetFilePath(const wchar *FullName,wchar *Path);
void RemoveNameFromPath(char *Path);
void RemoveNameFromPath(wchar *Path);
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
bool GetAppDataPath(wchar *Path,size_t MaxSize,bool Create);
void GetRarDataPath(wchar *Path,size_t MaxSize,bool Create);
#endif
#ifndef SFX_MODULE
bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create);
void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckExist,bool Create);
#endif
wchar* GetVolNumPart(const wchar *ArcName);
void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering);
bool IsNameUsable(const wchar *Name);
bool EnumConfigPaths(char *Path,int Number);
void GetConfigName(const char *Name,char *FullName,bool CheckExist);
char* GetVolNumPart(char *ArcName);
void NextVolumeName(char *ArcName,bool OldNumbering);
bool IsNameUsable(const char *Name);
void MakeNameUsable(char *Name,bool Extended);
void MakeNameUsable(wchar *Name,bool Extended);
char* UnixSlashToDos(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
char* DosSlashToUnix(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
bool IsFullPath(const char *Path);
bool IsDiskLetter(const char *Path);
void GetPathRoot(const char *Path,char *Root);
int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate);
char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering);
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW);
void UnixSlashToDos(const char *SrcName,char *DestName,size_t MaxLength);
void DosSlashToUnix(const char *SrcName,char *DestName,size_t MaxLength);
void UnixSlashToDos(const wchar *SrcName,wchar *DestName,size_t MaxLength);
void DosSlashToUnix(const wchar *SrcName,wchar *DestName,size_t MaxLength);
inline void SlashToNative(const char *SrcName,char *DestName,size_t MaxLength)
{
#ifdef _WIN_ALL
UnixSlashToDos(SrcName,DestName,MaxLength);
#else
DosSlashToUnix(SrcName,DestName,MaxLength);
#endif
}
inline void SlashToNative(const wchar *SrcName,wchar *DestName,size_t MaxLength)
{
#ifdef _WIN_ALL
UnixSlashToDos(SrcName,DestName,MaxLength);
#else
DosSlashToUnix(SrcName,DestName,MaxLength);
#endif
}
void ConvertNameToFull(const wchar *Src,wchar *Dest,size_t MaxSize);
bool IsFullPath(const wchar *Path);
bool IsFullRootPath(const wchar *Path);
void GetPathRoot(const wchar *Path,wchar *Root,size_t MaxSize);
int ParseVersionFileName(wchar *Name,bool Truncate);
wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,size_t MaxSize,bool NewNumbering);
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize);
#ifndef SFX_MODULE
void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,bool Archiving);
#endif
#ifdef _WIN_ALL
bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize);
void ConvertToPrecomposed(wchar *Name,size_t NameSize);
void MakeNameCompatible(wchar *Name);
#endif
inline char* GetOutputName(const char *Name) {return((char *)Name);};
#endif
-300
View File
@@ -1,300 +0,0 @@
#include "rar.hpp"
QuickOpen::QuickOpen()
{
Buf=NULL;
Init(NULL,false);
}
QuickOpen::~QuickOpen()
{
Close();
delete[] Buf;
}
void QuickOpen::Init(Archive *Arc,bool WriteMode)
{
if (Arc!=NULL) // Unless called from constructor.
Close();
QuickOpen::Arc=Arc;
QuickOpen::WriteMode=WriteMode;
ListStart=NULL;
ListEnd=NULL;
if (Buf==NULL)
Buf=new byte[MaxBufSize];
CurBufSize=0; // Current size of buffered data in write mode.
Loaded=false;
}
void QuickOpen::Close()
{
QuickOpenItem *Item=ListStart;
while (Item!=NULL)
{
QuickOpenItem *Next=Item->Next;
delete[] Item->Header;
delete Item;
Item=Next;
}
}
void QuickOpen::Load(uint64 BlockPos)
{
if (!Loaded)
{
// If loading for the first time, perform additional intialization.
SeekPos=Arc->Tell();
UnsyncSeekPos=false;
int64 SavePos=SeekPos;
Arc->Seek(BlockPos,SEEK_SET);
// If BlockPos points to original main header, we'll have the infinite
// recursion, because ReadHeader() for main header will attempt to load
// QOpen and call QuickOpen::Load again. If BlockPos points to long chain
// of other main headers, we'll have multiple recursive calls of this
// function wasting resources. So we prohibit QOpen temporarily to
// prevent this. ReadHeader() calls QOpen.Init and sets MainHead Locator
// and QOpenOffset fields, so we cannot use them to prohibit QOpen.
Arc->SetProhibitQOpen(true);
size_t ReadSize=Arc->ReadHeader();
Arc->SetProhibitQOpen(false);
if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||
!Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN))
{
Arc->Seek(SavePos,SEEK_SET);
return;
}
QOHeaderPos=Arc->CurBlockPos;
RawDataStart=Arc->Tell();
RawDataSize=Arc->SubHead.UnpSize;
Arc->Seek(SavePos,SEEK_SET);
Loaded=true; // Set only after all file processing calls like Tell, Seek, ReadHeader.
}
if (Arc->SubHead.Encrypted)
{
RAROptions *Cmd=Arc->GetRAROptions();
#ifndef RAR_NOCRYPT
if (Cmd->Password.IsSet())
Crypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,Arc->SubHead.Salt,
Arc->SubHead.InitV,Arc->SubHead.Lg2Count,
Arc->SubHead.HashKey,Arc->SubHead.PswCheck);
else
#endif
{
Loaded=false;
return;
}
}
RawDataPos=0;
ReadBufSize=0;
ReadBufPos=0;
LastReadHeader.Reset();
LastReadHeaderPos=0;
ReadBuffer();
}
bool QuickOpen::Read(void *Data,size_t Size,size_t &Result)
{
if (!Loaded)
return false;
// Find next suitable cached block.
while (LastReadHeaderPos+LastReadHeader.Size()<=SeekPos)
if (!ReadNext())
break;
if (!Loaded)
{
// If something wrong happened, let's set the correct file pointer
// and stop further quick open processing.
if (UnsyncSeekPos)
Arc->File::Seek(SeekPos,SEEK_SET);
return false;
}
if (SeekPos>=LastReadHeaderPos && SeekPos+Size<=LastReadHeaderPos+LastReadHeader.Size())
{
memcpy(Data,LastReadHeader+size_t(SeekPos-LastReadHeaderPos),Size);
Result=Size;
SeekPos+=Size;
UnsyncSeekPos=true;
}
else
{
if (UnsyncSeekPos)
{
Arc->File::Seek(SeekPos,SEEK_SET);
UnsyncSeekPos=false;
}
int ReadSize=Arc->File::Read(Data,Size);
if (ReadSize<0)
{
Loaded=false;
return false;
}
Result=ReadSize;
SeekPos+=ReadSize;
}
return true;
}
bool QuickOpen::Seek(int64 Offset,int Method)
{
if (!Loaded)
return false;
// Normally we process an archive sequentially from beginning to end,
// so we read quick open data sequentially. But some operations like
// archive updating involve several passes. So if we detect that file
// pointer is moved back, we reload quick open data from beginning.
if (Method==SEEK_SET && (uint64)Offset<SeekPos && (uint64)Offset<LastReadHeaderPos)
Load(QOHeaderPos);
if (Method==SEEK_SET)
SeekPos=Offset;
if (Method==SEEK_CUR)
SeekPos+=Offset;
UnsyncSeekPos=true;
if (Method==SEEK_END)
{
Arc->File::Seek(Offset,SEEK_END);
SeekPos=Arc->File::Tell();
UnsyncSeekPos=false;
}
return true;
}
bool QuickOpen::Tell(int64 *Pos)
{
if (!Loaded)
return false;
*Pos=SeekPos;
return true;
}
uint QuickOpen::ReadBuffer()
{
int64 SavePos=Arc->Tell();
Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET);
size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize);
if (Arc->SubHead.Encrypted)
SizeToRead &= ~CRYPT_BLOCK_MASK;
int ReadSize=0;
if (SizeToRead!=0)
{
ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
if (ReadSize<=0)
ReadSize=0;
else
{
#ifndef RAR_NOCRYPT
if (Arc->SubHead.Encrypted)
Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
#endif
RawDataPos+=ReadSize;
ReadBufSize+=ReadSize;
}
}
Arc->Seek(SavePos,SEEK_SET);
return ReadSize;
}
// Fill RawRead object from buffer.
bool QuickOpen::ReadRaw(RawRead &Raw)
{
if (MaxBufSize-ReadBufPos<0x100) // We are close to end of buffer.
{
// Ensure that we have enough data to read CRC and header size.
size_t DataLeft=ReadBufSize-ReadBufPos;
memcpy(Buf,Buf+ReadBufPos,DataLeft);
ReadBufPos=0;
ReadBufSize=DataLeft;
ReadBuffer();
}
const size_t FirstReadSize=7;
if (ReadBufPos+FirstReadSize>ReadBufSize)
return false;
Raw.Read(Buf+ReadBufPos,FirstReadSize);
ReadBufPos+=FirstReadSize;
uint SavedCRC=Raw.Get4();
uint SizeBytes=Raw.GetVSize(4);
uint64 BlockSize=Raw.GetV();
int SizeToRead=int(BlockSize);
SizeToRead-=FirstReadSize-SizeBytes-4; // Adjust overread size bytes if any.
if (SizeToRead<0 || SizeBytes==0 || BlockSize==0)
{
Loaded=false; // Invalid data.
return false;
}
// If rest of block data crosses Buf boundary, read it in loop.
while (SizeToRead>0)
{
size_t DataLeft=ReadBufSize-ReadBufPos;
size_t CurSizeToRead=Min(DataLeft,(size_t)SizeToRead);
Raw.Read(Buf+ReadBufPos,CurSizeToRead);
ReadBufPos+=CurSizeToRead;
SizeToRead-=int(CurSizeToRead);
if (SizeToRead>0) // We read the entire buffer and still need more data.
{
ReadBufPos=0;
ReadBufSize=0;
if (ReadBuffer()==0)
return false;
}
}
return SavedCRC==Raw.GetCRC50();
}
// Read next cached header.
bool QuickOpen::ReadNext()
{
RawRead Raw(NULL);
if (!ReadRaw(Raw)) // Read internal quick open header preceding stored block.
return false;
uint Flags=(uint)Raw.GetV();
uint64 Offset=Raw.GetV();
size_t HeaderSize=(size_t)Raw.GetV();
if (HeaderSize>MAX_HEADER_SIZE_RAR5)
return false;
LastReadHeader.Alloc(HeaderSize);
Raw.GetB(&LastReadHeader[0],HeaderSize);
// Calculate the absolute position as offset from quick open service header.
LastReadHeaderPos=QOHeaderPos-Offset;
return true;
}

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