From 6aae06fc1521dab48a407749b0abcc7128d3da45 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 17 May 2005 16:24:10 +0000 Subject: [PATCH] Added RAR archive plugin. --- CHANGES | 2 + Makefile.in | 30 +- configure.in | 17 + plugins/plugindefs.h | 6 + plugins/rar.c | 282 +++++ unrar/README.loki_setup | 25 + unrar/arccmt.cpp | 183 +++ unrar/archive.cpp | 241 ++++ unrar/archive.hpp | 130 ++ unrar/arcread.cpp | 653 ++++++++++ unrar/array.hpp | 121 ++ unrar/beosea.cpp | 113 ++ unrar/cmddata.cpp | 1147 ++++++++++++++++++ unrar/cmddata.hpp | 56 + unrar/coder.cpp | 47 + unrar/coder.hpp | 24 + unrar/compress.hpp | 36 + unrar/consio.cpp | 291 +++++ unrar/consio.hpp | 42 + unrar/crc.cpp | 61 + unrar/crc.hpp | 10 + unrar/crypt.cpp | 379 ++++++ unrar/crypt.hpp | 60 + unrar/dll.cpp | 354 ++++++ unrar/dll.def | 12 + unrar/dll.hpp | 137 +++ unrar/encname.cpp | 57 + unrar/encname.hpp | 20 + unrar/errhnd.cpp | 352 ++++++ unrar/errhnd.hpp | 61 + unrar/extinfo.cpp | 76 ++ unrar/extinfo.hpp | 8 + unrar/extract.cpp | 821 +++++++++++++ unrar/extract.hpp | 40 + unrar/filcreat.cpp | 204 ++++ unrar/filcreat.hpp | 12 + unrar/file.cpp | 682 +++++++++++ unrar/file.hpp | 100 ++ unrar/filefn.cpp | 540 +++++++++ unrar/filefn.hpp | 39 + unrar/filestr.cpp | 139 +++ unrar/filestr.hpp | 8 + unrar/find.cpp | 287 +++++ unrar/find.hpp | 48 + unrar/getbits.cpp | 24 + unrar/getbits.hpp | 37 + unrar/global.cpp | 4 + unrar/global.hpp | 14 + unrar/headers.hpp | 304 +++++ unrar/int64.cpp | 274 +++++ unrar/int64.hpp | 86 ++ unrar/isnt.cpp | 17 + unrar/isnt.hpp | 6 + unrar/license.txt | 41 + unrar/list.cpp | 380 ++++++ unrar/list.hpp | 6 + unrar/loclang.hpp | 340 ++++++ unrar/log.cpp | 24 + unrar/log.hpp | 18 + unrar/makefile.bcc | 500 ++++++++ unrar/makefile.cygmin | 55 + unrar/makefile.dmc | 54 + unrar/makefile.msc | 564 +++++++++ unrar/makefile.unix | 119 ++ unrar/match.cpp | 250 ++++ unrar/match.hpp | 16 + unrar/model.cpp | 598 +++++++++ unrar/model.hpp | 126 ++ unrar/msc.dep | 2532 +++++++++++++++++++++++++++++++++++++++ unrar/options.cpp | 26 + unrar/options.hpp | 129 ++ unrar/os.hpp | 229 ++++ unrar/os2ea.cpp | 94 ++ unrar/pathfn.cpp | 633 ++++++++++ unrar/pathfn.hpp | 44 + unrar/rar.cpp | 132 ++ unrar/rar.hpp | 80 ++ unrar/rardefs.hpp | 21 + unrar/rarfn.hpp | 7 + unrar/rarlang.hpp | 10 + unrar/raros.hpp | 41 + unrar/rartypes.hpp | 21 + unrar/rarvm.cpp | 1048 ++++++++++++++++ unrar/rarvm.hpp | 110 ++ unrar/rarvmtbl.cpp | 53 + unrar/rawread.cpp | 101 ++ unrar/rawread.hpp | 32 + unrar/rdwrfn.cpp | 260 ++++ unrar/rdwrfn.hpp | 83 ++ unrar/readme.txt | 64 + unrar/recvol.cpp | 377 ++++++ unrar/recvol.hpp | 16 + unrar/resource.cpp | 12 + unrar/resource.hpp | 14 + unrar/rijndael.cpp | 298 +++++ unrar/rijndael.hpp | 37 + unrar/rs.cpp | 143 +++ unrar/rs.hpp | 32 + unrar/savepos.cpp | 15 + unrar/savepos.hpp | 15 + unrar/scantree.cpp | 279 +++++ unrar/scantree.hpp | 52 + unrar/sha1.cpp | 227 ++++ unrar/sha1.hpp | 16 + unrar/smallfn.cpp | 17 + unrar/smallfn.hpp | 7 + unrar/strfn.cpp | 143 +++ unrar/strfn.hpp | 24 + unrar/strlist.cpp | 191 +++ unrar/strlist.hpp | 39 + unrar/suballoc.cpp | 241 ++++ unrar/suballoc.hpp | 81 ++ unrar/system.cpp | 79 ++ unrar/system.hpp | 10 + unrar/timefn.cpp | 288 +++++ unrar/timefn.hpp | 57 + unrar/ulinks.cpp | 32 + unrar/ulinks.hpp | 9 + unrar/unicode.cpp | 450 +++++++ unrar/unicode.hpp | 82 ++ unrar/unios2.cpp | 128 ++ unrar/unpack.cpp | 931 ++++++++++++++ unrar/unpack.hpp | 205 ++++ unrar/unpack15.cpp | 507 ++++++++ unrar/unpack20.cpp | 368 ++++++ unrar/uowners.cpp | 68 ++ unrar/version.hpp | 6 + unrar/volume.cpp | 178 +++ unrar/volume.hpp | 11 + unrar/win32acl.cpp | 127 ++ unrar/win32stm.cpp | 138 +++ 131 files changed, 23497 insertions(+), 13 deletions(-) create mode 100644 plugins/rar.c create mode 100644 unrar/README.loki_setup create mode 100644 unrar/arccmt.cpp create mode 100644 unrar/archive.cpp create mode 100644 unrar/archive.hpp create mode 100644 unrar/arcread.cpp create mode 100644 unrar/array.hpp create mode 100644 unrar/beosea.cpp create mode 100644 unrar/cmddata.cpp create mode 100644 unrar/cmddata.hpp create mode 100644 unrar/coder.cpp create mode 100644 unrar/coder.hpp create mode 100644 unrar/compress.hpp create mode 100644 unrar/consio.cpp create mode 100644 unrar/consio.hpp create mode 100644 unrar/crc.cpp create mode 100644 unrar/crc.hpp create mode 100644 unrar/crypt.cpp create mode 100644 unrar/crypt.hpp create mode 100644 unrar/dll.cpp create mode 100644 unrar/dll.def create mode 100644 unrar/dll.hpp create mode 100644 unrar/encname.cpp create mode 100644 unrar/encname.hpp create mode 100644 unrar/errhnd.cpp create mode 100644 unrar/errhnd.hpp create mode 100644 unrar/extinfo.cpp create mode 100644 unrar/extinfo.hpp create mode 100644 unrar/extract.cpp create mode 100644 unrar/extract.hpp create mode 100644 unrar/filcreat.cpp create mode 100644 unrar/filcreat.hpp create mode 100644 unrar/file.cpp create mode 100644 unrar/file.hpp create mode 100644 unrar/filefn.cpp create mode 100644 unrar/filefn.hpp create mode 100644 unrar/filestr.cpp create mode 100644 unrar/filestr.hpp create mode 100644 unrar/find.cpp create mode 100644 unrar/find.hpp create mode 100644 unrar/getbits.cpp create mode 100644 unrar/getbits.hpp create mode 100644 unrar/global.cpp create mode 100644 unrar/global.hpp create mode 100644 unrar/headers.hpp create mode 100644 unrar/int64.cpp create mode 100644 unrar/int64.hpp create mode 100644 unrar/isnt.cpp create mode 100644 unrar/isnt.hpp create mode 100644 unrar/license.txt create mode 100644 unrar/list.cpp create mode 100644 unrar/list.hpp create mode 100644 unrar/loclang.hpp create mode 100644 unrar/log.cpp create mode 100644 unrar/log.hpp create mode 100644 unrar/makefile.bcc create mode 100644 unrar/makefile.cygmin create mode 100644 unrar/makefile.dmc create mode 100644 unrar/makefile.msc create mode 100644 unrar/makefile.unix create mode 100644 unrar/match.cpp create mode 100644 unrar/match.hpp create mode 100644 unrar/model.cpp create mode 100644 unrar/model.hpp create mode 100644 unrar/msc.dep create mode 100644 unrar/options.cpp create mode 100644 unrar/options.hpp create mode 100644 unrar/os.hpp create mode 100644 unrar/os2ea.cpp create mode 100644 unrar/pathfn.cpp create mode 100644 unrar/pathfn.hpp create mode 100644 unrar/rar.cpp create mode 100644 unrar/rar.hpp create mode 100644 unrar/rardefs.hpp create mode 100644 unrar/rarfn.hpp create mode 100644 unrar/rarlang.hpp create mode 100644 unrar/raros.hpp create mode 100644 unrar/rartypes.hpp create mode 100644 unrar/rarvm.cpp create mode 100644 unrar/rarvm.hpp create mode 100644 unrar/rarvmtbl.cpp create mode 100644 unrar/rawread.cpp create mode 100644 unrar/rawread.hpp create mode 100644 unrar/rdwrfn.cpp create mode 100644 unrar/rdwrfn.hpp create mode 100644 unrar/readme.txt create mode 100644 unrar/recvol.cpp create mode 100644 unrar/recvol.hpp create mode 100644 unrar/resource.cpp create mode 100644 unrar/resource.hpp create mode 100644 unrar/rijndael.cpp create mode 100644 unrar/rijndael.hpp create mode 100644 unrar/rs.cpp create mode 100644 unrar/rs.hpp create mode 100644 unrar/savepos.cpp create mode 100644 unrar/savepos.hpp create mode 100644 unrar/scantree.cpp create mode 100644 unrar/scantree.hpp create mode 100644 unrar/sha1.cpp create mode 100644 unrar/sha1.hpp create mode 100644 unrar/smallfn.cpp create mode 100644 unrar/smallfn.hpp create mode 100644 unrar/strfn.cpp create mode 100644 unrar/strfn.hpp create mode 100644 unrar/strlist.cpp create mode 100644 unrar/strlist.hpp create mode 100644 unrar/suballoc.cpp create mode 100644 unrar/suballoc.hpp create mode 100644 unrar/system.cpp create mode 100644 unrar/system.hpp create mode 100644 unrar/timefn.cpp create mode 100644 unrar/timefn.hpp create mode 100644 unrar/ulinks.cpp create mode 100644 unrar/ulinks.hpp create mode 100644 unrar/unicode.cpp create mode 100644 unrar/unicode.hpp create mode 100644 unrar/unios2.cpp create mode 100644 unrar/unpack.cpp create mode 100644 unrar/unpack.hpp create mode 100644 unrar/unpack15.cpp create mode 100644 unrar/unpack20.cpp create mode 100644 unrar/uowners.cpp create mode 100644 unrar/version.hpp create mode 100644 unrar/volume.cpp create mode 100644 unrar/volume.hpp create mode 100644 unrar/win32acl.cpp create mode 100644 unrar/win32stm.cpp diff --git a/CHANGES b/CHANGES index 0894b7e..585c1f9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ Current: +Ryan C. Gordon (icculus.org) - Tue May 17 12:21:23 EDT 2005 + * Added .rar archive plugin. Ryan C. Gordon (icculus.org) - Sat Nov 20 08:42:16 EST 2004 * Minor carbon_ui tweaks and corrections to update function. Ludwig Nussel - Wed Nov 10 14:21:21 PST 2004 diff --git a/Makefile.in b/Makefile.in index 3b064a7..60a003a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -14,6 +14,7 @@ BRANDELF = @BRANDELF@ UNINSTALL_VERSION = 1.0.4 CC = @CC@ +CXX = @CXX@ # This indicates where the 'setupdb' CVS module is checked out SETUPDB = @SETUPDB@ @@ -26,6 +27,7 @@ CONVERT_IMAGE = /loki/patch-tools/convert-image # The supported locales so far LOCALES = fr de es sv it nl ru en_GB +LD = @LD@ OPTIMIZE = @CFLAGS@ LDFLAGS = @LDFLAGS@ BDYNAMIC = @BDYNAMIC@ @@ -38,6 +40,7 @@ OPTIONS = -DSTUB_UI -DSETUP_VERSION_MAJOR=@SETUP_VERSION_MAJOR@ \ -DDATADIR=\"$(DATADIR)\" -DLOCALEDIR=\"$(LOCALEDIR)\" -DLOKI_PREFIX=\"$(BRAND)\" CFLAGS += $(OPTIMIZE) $(HEADERS) $(OPTIONS) +CXXFLAGS = $(CFLAGS) COMMON_OBJS = log.o install_log.o CORE_OBJS = detect.o plugins.o network.o install.o copy.o file.o loki_launchurl.o @@ -68,32 +71,32 @@ CONSOLE_LIBS = $(LIBS) @CONSOLE_LIBS@ all: do-plugins @DO_DIALOG@ setup setup.gtk uninstall xsu testxml: testxml.o - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) loki_uninstall.o: uninstall.c - $(CC) $(LDFLAGS) -c -o $@ $^ $(CFLAGS) -DUNINSTALL_UI -DVERSION=\"$(UNINSTALL_VERSION)\" + $(LD) $(LDFLAGS) -c -o $@ $^ $(CFLAGS) -DUNINSTALL_UI -DVERSION=\"$(UNINSTALL_VERSION)\" loki_uninstall: $(LOKI_UNINSTALL_OBJS) $(SETUPDB)/$(arch)/libsetupdb.a - $(CC) $(LDFLAGS) -o $@ $(LOKI_UNINSTALL_OBJS) $(GUI_LIBS) + $(LD) $(LDFLAGS) -o $@ $(LOKI_UNINSTALL_OBJS) $(GUI_LIBS) carbon_uninstall.o: uninstall.c - $(CC) $(LDFLAGS) -c -o $@ $^ $(CFLAGS) -DUNINSTALL_CARBONUI -DUNINSTALL_UI -DVERSION=\"$(UNINSTALL_VERSION)\" + $(LD) $(LDFLAGS) -c -o $@ $^ $(CFLAGS) -DUNINSTALL_CARBONUI -DUNINSTALL_UI -DVERSION=\"$(UNINSTALL_VERSION)\" carbon_uninstall: $(CARBON_UNINSTALL_OBJS) $(SETUPDB)/$(arch)/libsetupdb.a - $(CC) $(LDFLAGS) -o $@ $(CARBON_UNINSTALL_OBJS) $(CARBON_LIBS) + $(LD) $(LDFLAGS) -o $@ $(CARBON_UNINSTALL_OBJS) $(CARBON_LIBS) rm -f -R ./uninstall.APP cp -R ./setup.APP ./uninstall.APP cp ./carbon/Info.plist.uninstall ./uninstall.APP/Contents/Info.plist rm -f ./uninstall.APP/Contents/MacOS/setup.carbon cp ./carbon_uninstall ./uninstall.APP/Contents/MacOS uninstall: $(UNINSTALL_OBJS) $(COMMON_LIBS) - $(CC) $(LDFLAGS) -o $@ $(UNINSTALL_OBJS) $(CONSOLE_LIBS) @STATIC@ + $(LD) $(LDFLAGS) -o $@ $(UNINSTALL_OBJS) $(CONSOLE_LIBS) @STATIC@ check: $(CHECK_OBJS) $(COMMON_LIBS) - $(CC) $(LDFLAGS) -o $@ $(CHECK_OBJS) $(GUI_LIBS) + $(LD) $(LDFLAGS) -o $@ $(CHECK_OBJS) $(GUI_LIBS) check.carbon: $(CHECK_CARBON_OBJS) $(COMMON_LIBS) - $(CC) $(LDFLAGS) -o $@ $(CHECK_CARBON_OBJS) $(CARBON_LIBS) + $(LD) $(LDFLAGS) -o $@ $(CHECK_CARBON_OBJS) $(CARBON_LIBS) rm -f -R ./check.APP cp -R ./setup.APP ./check.APP cp ./carbon/Info.plist.check ./check.APP/Contents/Info.plist @@ -101,23 +104,23 @@ check.carbon: $(CHECK_CARBON_OBJS) $(COMMON_LIBS) cp ./check.carbon ./check.APP/Contents/MacOS testcd: testcd.o $(CORE_OBJS) $(COMMON_OBJS) $(COMMON_LIBS) - $(CC) $(LDFLAGS) -o $@ $^ @LIBS@ @CONSOLE_LIBS@ @STATIC@ + $(LD) $(LDFLAGS) -o $@ $^ @LIBS@ @CONSOLE_LIBS@ @STATIC@ setup: do-plugins @DO_DIALOG@ $(CONSOLE_OBJS) $(COMMON_LIBS) - $(CC) $(LDFLAGS) -o $@ $(CONSOLE_OBJS) $(CONSOLE_LIBS) @STATIC@ + $(LD) $(LDFLAGS) -o $@ $(CONSOLE_OBJS) $(CONSOLE_LIBS) @STATIC@ setup.gtk: $(GUI_OBJS) $(COMMON_LIBS) - $(CC) $(LDFLAGS) -o $@ $(GUI_OBJS) $(GUI_LIBS) + $(LD) $(LDFLAGS) -o $@ $(GUI_OBJS) $(GUI_LIBS) #!!!TODO - Take dependency of dialog libs out of carbon #!!!TODO - Should we include setup.carbon as part of "all", "install", etc...? # Carbon needs to be a target all its own setup.carbon: do-plugins @DO_DIALOG@ $(CARBON_OBJS) $(COMMON_LIBS) - $(CC) $(LDFLAGS) -o $@ $(CARBON_OBJS) $(CARBON_LIBS) + $(LD) $(LDFLAGS) -o $@ $(CARBON_OBJS) $(CARBON_LIBS) cp setup.carbon setup.APP/Contents/MacOS xsu: $(XSU_OBJS) - $(CC) $(LDFLAGS) -o $@ $^ @GTK_LIBS@ @LIBUTIL@ @X11_LIBS@ @LIBINTL@ @EXTRA_LIBS@ + $(LD) $(LDFLAGS) -o $@ $^ @GTK_LIBS@ @LIBUTIL@ @X11_LIBS@ @LIBINTL@ @EXTRA_LIBS@ do-plugins: $(MAKE) -C plugins all @@ -250,6 +253,7 @@ clean: $(MAKE) -C dialog clean rm -f foo.xml core tags *.o rm -f carbon/*.o + rm -f unrar/*.o distclean: clean rm -f Makefile config.cache config.status config.log diff --git a/configure.in b/configure.in index 2ad96d2..e2fd4cf 100644 --- a/configure.in +++ b/configure.in @@ -16,6 +16,7 @@ AC_CANONICAL_HOST AC_CANONICAL_TARGET AC_PROG_CC +AC_PROG_CXX AC_PROG_RANLIB AC_PROG_MAKE_SET AC_PROG_INSTALL @@ -64,6 +65,7 @@ AC_PATH_PROG(MOUNT_PATH, mount, /sbin/mount, $PATH:/usr/sbin:/sbin) AC_PATH_PROG(UMOUNT_PATH, umount, /sbin/umount, $PATH:/usr/sbin:/sbin) AC_PATH_PROG(BRANDELF, brandelf, true) +LD="$CC" CFLAGS="-fsigned-char -funroll-loops -Wall -g -O2 -I. $X_CFLAGS" CONSOLE_LIBS="" if test -d /usr/codehost/lib; then @@ -465,6 +467,18 @@ if test x$enable_uz2 = xyes; then AC_DEFINE(ENABLE_UZ2, 1, UZ2 support.) fi +dnl enable RAR support +AC_ARG_ENABLE(rar, +[ --enable-rar enable RAR archives support [default=no]], + , enable_rar=no) +if test x$enable_rar = xyes; then + PLUGINS="$PLUGINS rar.c" + LD="$CXX" + CFLAGS="$CFLAGS -DRAR_SUPPORT -DRARDLL -DSILENT" + COMMON_LIBS="$COMMON_LIBS unrar/filestr.o unrar/scantree.o unrar/dll.o unrar/rar.o unrar/strlist.o unrar/strfn.o unrar/pathfn.o unrar/int64.o unrar/savepos.o unrar/global.o unrar/file.o unrar/filefn.o unrar/filcreat.o unrar/archive.o unrar/arcread.o unrar/unicode.o unrar/system.o unrar/isnt.o unrar/crypt.o unrar/crc.o unrar/rawread.o unrar/encname.o unrar/resource.o unrar/match.o unrar/timefn.o unrar/rdwrfn.o unrar/consio.o unrar/options.o unrar/ulinks.o unrar/errhnd.o unrar/rarvm.o unrar/rijndael.o unrar/getbits.o unrar/sha1.o unrar/extinfo.o unrar/extract.o unrar/volume.o unrar/list.o unrar/find.o unrar/unpack.o unrar/cmddata.o" + AC_DEFINE(ENABLE_RAR, 1, RAR support.) +fi + dnl enable RPM support AC_ARG_ENABLE(rpm, [ --enable-rpm enable RPM archives support [default=no]], @@ -585,6 +599,8 @@ BRAND="$with_vendor" OS=`uname -s` +CXXFLAGS="$CFLAGS" + AC_SUBST(SETUPDB) AC_SUBST(PLUGINS) AC_SUBST(DYN_PLUGINS) @@ -614,6 +630,7 @@ AC_SUBST(DO_DIALOG) AC_SUBST(IMAGE) AC_SUBST(BRAND) AC_SUBST(BDYNAMIC) +AC_SUBST(LD) AC_OUTPUT(Makefile plugins/Makefile dialog/Makefile) diff --git a/plugins/plugindefs.h b/plugins/plugindefs.h index 0a6f1f6..0597ea4 100644 --- a/plugins/plugindefs.h +++ b/plugins/plugindefs.h @@ -17,6 +17,9 @@ extern SetupPlugin zip_plugin; #ifdef UZ2_SUPPORT extern SetupPlugin uz2_plugin; #endif +#ifdef RAR_SUPPORT +extern SetupPlugin rar_plugin; +#endif #endif /* !DYNAMIC_PLUGINS */ extern SetupPlugin cpio_plugin; @@ -36,6 +39,9 @@ SetupPlugin *static_plugins[] = { #ifdef UZ2_SUPPORT &uz2_plugin, #endif +#ifdef RAR_SUPPORT + &rar_plugin, +#endif #ifdef OUTRAGE_SUPPORT &opkg_plugin, #endif diff --git a/plugins/rar.c b/plugins/rar.c new file mode 100644 index 0000000..35bf7ad --- /dev/null +++ b/plugins/rar.c @@ -0,0 +1,282 @@ +/* RAR files (.rar) plugin for setup, using unrar's library version. */ +/* $Id: rar.c,v 1.1 2005-05-17 16:24:10 icculus Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "plugins.h" +#include "file.h" +#include "install_log.h" + +/* define _UNIX if needed, since unrar expects it... */ +#ifndef WIN32 +#ifndef _UNIX +#define _UNIX 1 +#endif +#endif +#include "../unrar/dll.hpp" + +/* Initialize the plugin */ +static int RARInitPlugin(void) +{ + return 1; +} + +/* Free the plugin */ +static int RARFreePlugin(void) +{ + return 1; +} + +static const char *rar_strerror(unsigned int e) +{ + switch (e) + { + case ERAR_END_ARCHIVE: return "end of archive"; + case ERAR_NO_MEMORY: return "out of memory"; + case ERAR_BAD_DATA: return "bad data"; + case ERAR_BAD_ARCHIVE: return "bad archive"; + case ERAR_UNKNOWN_FORMAT: return "unknown format"; + case ERAR_EOPEN: return "opening error (file missing?)"; + case ERAR_ECREATE: return "creation error"; + case ERAR_ECLOSE: return "close error"; + case ERAR_EREAD: return "read error"; + case ERAR_EWRITE: return "write error"; + case ERAR_SMALL_BUF: return "too small buffer"; + } /* switch */ + + return "unknown error"; +} /* rar_strerror */ + +static int rar_list_callback(UINT msg,LONG UserData,LONG P1,LONG P2) +{ + switch (msg) + { + case UCM_PROCESSDATA: + return 1; + + case UCM_CHANGEVOLUME: + if (P2 == RAR_VOL_NOTIFY) + return(1); /* just a notification...keep processing. */ + else if (P2 == RAR_VOL_ASK) + return(-1); + break; + + case UCM_NEEDPASSWORD: + return(-1); + } /* switch */ + + return 0; /* don't know what this message is! */ +} /* rar_list_callback */ + + +/* Get the size of the file */ +static size_t RARSize(install_info *info, const char *path) +{ + size_t retval = 0; + int rc = 0; + HANDLE h; + struct RAROpenArchiveData raroad; + struct RARHeaderDataEx rarhdx; + memset(&raroad, '\0', sizeof (raroad)); + memset(&rarhdx, '\0', sizeof (rarhdx)); + + raroad.ArcName = (char *) path; + raroad.OpenMode = RAR_OM_LIST; + h = RAROpenArchive(&raroad); + if (!h) + return(0); + + RARSetCallback(h, rar_list_callback, 0); + while ((rc = RARReadHeaderEx(h, &rarhdx)) == 0) + { + retval += rarhdx.UnpSize; + RARProcessFile(h, RAR_SKIP, NULL, NULL); + } + + RARCloseArchive(h); + return(retval); +} + + +typedef struct +{ + size_t bw; + install_info *info; + stream *out; + const char *final; + struct RARHeaderDataEx *rarhdx; + const char *current_option; + UIUpdateFunc update; +} ExtractCallbackData; + +static int rar_extract_callback(UINT msg,LONG UserData,LONG P1,LONG P2) +{ + ExtractCallbackData *ecd = (ExtractCallbackData *) UserData; + int w = 0; + switch (msg) + { + case UCM_PROCESSDATA: + if (ecd->out == NULL) /* skipping ahead? */ + return(1); + + w = file_write(ecd->info, (void *) P1, P2, ecd->out); + ecd->bw += w; + ecd->update(ecd->info, ecd->final, ecd->bw, + ecd->rarhdx->UnpSize, ecd->current_option); + ecd->info->installed_bytes += w; + return((w != P2) ? -1 : 1); + + case UCM_CHANGEVOLUME: + if (P2 == RAR_VOL_NOTIFY) + return(1); /* just a notification...keep processing. */ + else if (P2 == RAR_VOL_ASK) + return(-1); + break; + + case UCM_NEEDPASSWORD: + return(-1); + } /* switch */ + + return 0; /* don't know what this message is! */ +} /* rar_extract_callback */ + + + +/* Extract the file */ +static size_t RARCopy(install_info *info, const char *path, const char *dest, const char *current_option, + xmlNodePtr node, + UIUpdateFunc update) +{ + char final[PATH_MAX]; + size_t retval = 0; + stream *out = NULL; + int rc = 0; + HANDLE h; + unsigned int user_mode = 0; + struct RAROpenArchiveData raroad; + struct RARHeaderDataEx rarhdx; + ExtractCallbackData ecd; + + /* Optional MD5 sum can be specified in the XML file */ + const char *md5 = xmlGetProp(node, "md5sum"); + const char *mut = xmlGetProp(node, "mutable"); + const char *mode_str = xmlGetProp(node, "mode"); + + if ( mode_str ) { + user_mode = (unsigned int) strtol(mode_str, NULL, 8); + } + + log_debug("RAR: Copy %s -> %s", path, dest); + + memset(&ecd, '\0', sizeof (ExtractCallbackData)); + memset(&rarhdx, '\0', sizeof (rarhdx)); + memset(&raroad, '\0', sizeof (raroad)); + raroad.ArcName = (char *) path; + raroad.OpenMode = RAR_OM_EXTRACT; + h = RAROpenArchive(&raroad); + if (!h) + { + log_debug("RAR: failed to open archive %s: %s", + path, rar_strerror(raroad.OpenResult)); + return(0); + } + + ecd.bw = 0; + ecd.info = info; + ecd.out = NULL; + ecd.final = final; + ecd.rarhdx = &rarhdx; + ecd.current_option = current_option; + ecd.update = update; + + RARSetCallback(h, rar_extract_callback, (LONG) &ecd); + while ((rc = RARReadHeaderEx(h, &rarhdx)) == 0) + { + /* + * We use RAR_TEST so that the unrar library doesn't try to write + * the file itself...it will pass the decoded data to + * rar_extract_callback, where we can do as we please with it. + */ + int operation = RAR_TEST; + + snprintf(final, sizeof(final), "%s/%s", dest, rarhdx.FileName); + update(info, final, 0, rarhdx.UnpSize, current_option); + file_create_hierarchy(info, final); + out = file_open_install(info, final, (mut && *mut=='y') ? "wm" : "wb"); + + ecd.bw = 0; + ecd.out = out; + + if (!out) + { + log_debug("RAR: failed to open [%s] for write.", final); + operation = RAR_SKIP; + } /* if */ + + if ((rc = RARProcessFile(h, operation, NULL, NULL)) != 0) + { + log_debug("RAR: Failed to process %s in archive %s: %s", + rarhdx.FileName, path, rar_strerror(rc)); + } + + if (out) + file_close(info, out); + + if ((!out) || (rc)) + unlink(final); + else + retval += rarhdx.UnpSize; + + if (out) + { + if ( user_mode ) + file_chmod(info, final, user_mode); + + if ( md5 ) /* Verify the output file */ + { + char sum[CHECKSUM_SIZE+1]; + strcpy(sum, get_md5(out->md5.buf)); + if ( strcasecmp(md5, sum) ) + log_fatal(_("File '%s' has an invalid checksum! Aborting."), final); + } + } + + ecd.bw = 0; + ecd.out = NULL; + } + + RARCloseArchive(h); + + if (rc != ERAR_END_ARCHIVE) + log_debug("RAR: Failed to fully decompress all files in archive %s: %s", path, rar_strerror(rc)); + + return(retval); +} + + +#ifdef DYNAMIC_PLUGINS +static +#endif +SetupPlugin rar_plugin = { + "RAR archives plugin", + "1.0", + "Ryan C. Gordon ", + 1, {".rar"}, + RARInitPlugin, RARFreePlugin, + RARSize, RARCopy +}; + +#ifdef DYNAMIC_PLUGINS +SetupPlugin *GetSetupPlugin(void) +{ + return &rar_plugin; +} +#endif diff --git a/unrar/README.loki_setup b/unrar/README.loki_setup new file mode 100644 index 0000000..9017d38 --- /dev/null +++ b/unrar/README.loki_setup @@ -0,0 +1,25 @@ + +These are the unrar 3.5.2 sources (unrarsrc-3.5.2.tar.gz) from rarlabs.com. + They are completely unmodified in this directory, except for the addition of + this file. loki_setup builds these through their makefiles and ignores the + build system from unrar. + +These are built with RARDLL defined, so that we get an external API for + decompressing .rar files without having to dig into the guts of these files. + +Basically, as long as their API doesn't change, you can just replace this + whole directory with the latest unrar sources, if you need bugfixes or + whatnot, and it shouldn't affect loki_setup. + +The .o files are statically linked to the loki_setup binaries. You can enable + the .rar plugin by specifying --enable-rar on the loki_setup ./configure + command line...RAR support is disabled by default, since it bloats the + binary with functionality that most people don't need, but it is known to + work on at least x86 linux and 32-bit PowerPC MacOS X, and probably just + about anywhere else. + +Please see license.txt in this directory for unrar-specific licensing details. + The unrar code may not be used to develop a RAR (WinRAR) compatible archiver. + +--ryan. + diff --git a/unrar/arccmt.cpp b/unrar/arccmt.cpp new file mode 100644 index 0000000..9273394 --- /dev/null +++ b/unrar/arccmt.cpp @@ -0,0 +1,183 @@ +bool Archive::GetComment(Array &CmtData) +{ + if (!MainComment) + return(false); + SaveFilePos SavePos(*this); + + ushort CmtLength; +#ifndef SFX_MODULE + if (OldFormat) + { + Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET); + CmtLength=GetByte()+(GetByte()<<8); + } + else +#endif + { + if (NewMhd.Flags & MHD_COMMENT) + { + Seek(SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD,SEEK_SET); + ReadHeader(); + } + else + { + Seek(SFXSize+SIZEOF_MARKHEAD+NewMhd.HeadSize,SEEK_SET); + return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData)!=0); + } +#ifndef SFX_MODULE + if (CommHead.HeadCRC!=HeaderCRC) + { + Log(FileName,St(MLogCommHead)); + Alarm(); + return(false); + } + CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD; +#endif + } +#ifndef SFX_MODULE + if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT) || !OldFormat && CommHead.Method!=0x30) + { + if (!OldFormat && (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER || CommHead.Method > 0x35)) + return(false); + ComprDataIO DataIO; + Unpack Unpack(&DataIO); + Unpack.Init(); + DataIO.SetTestMode(true); + uint UnpCmtLength; + if (OldFormat) + { + UnpCmtLength=GetByte()+(GetByte()<<8); + CmtLength-=2; + DataIO.SetCmt13Encryption(); + } + else + UnpCmtLength=CommHead.UnpSize; + DataIO.SetFiles(this,NULL); + DataIO.EnableShowProgress(false); + DataIO.SetPackedSizeToRead(CmtLength); + Unpack.SetDestSize(UnpCmtLength); + Unpack.DoUnpack(CommHead.UnpVer,false); + + if (!OldFormat && ((~DataIO.UnpFileCRC)&0xffff)!=CommHead.CommCRC) + { + Log(FileName,St(MLogCommBrk)); + Alarm(); + return(false); + } + else + { + unsigned char *UnpData; + uint UnpDataSize; + DataIO.GetUnpackedData(&UnpData,&UnpDataSize); + CmtData.Alloc(UnpDataSize); + memcpy(&CmtData[0],UnpData,UnpDataSize); + } + } + else + { + CmtData.Alloc(CmtLength); + + Read(&CmtData[0],CmtLength); + if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&CmtData[0],CmtLength)&0xffff)) + { + Log(FileName,St(MLogCommBrk)); + Alarm(); + CmtData.Reset(); + return(false); + } + } +#endif +#if defined(_WIN_32) && !defined(_WIN_CE) + if (CmtData.Size()>0) + OemToCharBuff((char*)&CmtData[0],(char*)&CmtData[0],CmtData.Size()); +#endif + return(CmtData.Size()>0); +} + + +int Archive::ReadCommentData(Array &CmtData) +{ + bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE; + if (!ReadSubData(&CmtData,NULL)) + return(0); + int CmtSize=CmtData.Size(); + if (Unicode) + { + CmtSize/=2; + Array CmtDataW(CmtSize+1); + RawToWide(&CmtData[0],&CmtDataW[0],CmtSize); + CmtDataW[CmtSize]=0; + CmtData.Alloc(CmtSize*2); + WideToChar(&CmtDataW[0],(char *)&CmtData[0]); + CmtSize=strlen((char *)&CmtData[0]); + CmtData.Alloc(CmtSize); + } + return(CmtSize); +} + + +void Archive::ViewComment() +{ +#ifndef GUI + if (Cmd->DisableComment) + return; + Array CmtBuf; + if (GetComment(CmtBuf)) + { + int CmtSize=CmtBuf.Size(); + char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize); + if (ChPtr!=NULL) + 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 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 diff --git a/unrar/archive.cpp b/unrar/archive.cpp new file mode 100644 index 0000000..8e527e2 --- /dev/null +++ b/unrar/archive.cpp @@ -0,0 +1,241 @@ +#include "rar.hpp" + +#ifndef SHELL_EXT +#include "arccmt.cpp" +#endif + + +Archive::Archive(RAROptions *InitCmd) +{ + Cmd=InitCmd==NULL ? &DummyCmd:InitCmd; + OpenShared=Cmd->OpenShared; + OldFormat=false; + Solid=false; + Volume=false; + MainComment=false; + Locked=false; + Signed=false; + NotFirstVolume=false; + SFXSize=0; + LatestTime.Reset(); + Protected=false; + Encrypted=false; + BrokenFileHeader=false; + LastReadBlock=0; + + CurBlockPos=0; + NextBlockPos=0; + + RecoveryPos=SIZEOF_MARKHEAD; + RecoverySectors=-1; + + 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; +} + + +#ifndef SHELL_EXT +void Archive::CheckArc(bool EnableBroken) +{ + if (!IsArchive(EnableBroken)) + { + Log(FileName,St(MBadArc),FileName); + ErrHandler.Exit(FATAL_ERROR); + } +} +#endif + + +#if !defined(SHELL_EXT) && !defined(SFX_MODULE) +void Archive::CheckOpen(char *Name,wchar *NameW) +{ + TOpen(Name,NameW); + CheckArc(false); +} +#endif + + +bool Archive::WCheckOpen(char *Name,wchar *NameW) +{ + if (!WOpen(Name,NameW)) + return(false); + if (!IsArchive(false)) + { +#ifndef SHELL_EXT + Log(FileName,St(MNotRAR),FileName); +#endif + Close(); + return(false); + } + return(true); +} + + +bool Archive::IsSignature(byte *D) +{ + bool Valid=false; + if (D[0]==0x52) +#ifndef SFX_MODULE + if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e) + { + OldFormat=true; + Valid=true; + } + else +#endif + if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00) + { + OldFormat=false; + Valid=true; + } + return(Valid); +} + + +bool Archive::IsArchive(bool EnableBroken) +{ + Encrypted=false; +#ifndef SFX_MODULE + if (IsDevice()) + { +#ifndef SHELL_EXT + Log(FileName,St(MInvalidName),FileName); +#endif + return(false); + } +#endif + if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) + return(false); + SFXSize=0; + if (IsSignature(MarkHead.Mark)) + { + if (OldFormat) + Seek(0,SEEK_SET); + } + else + { + Array Buffer(0x80000); + long CurPos=int64to32(Tell()); + int ReadSize=Read(&Buffer[0],Buffer.Size()-16); + for (int I=0;I0 && CurPos<28 && ReadSize>31) + { + char *D=&Buffer[28-CurPos]; + if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58) + continue; + } + SFXSize=CurPos+I; + Seek(SFXSize,SEEK_SET); + if (!OldFormat) + Read(MarkHead.Mark,SIZEOF_MARKHEAD); + break; + } + if (SFXSize==0) + return(false); + } + ReadHeader(); + SeekToNext(); +#ifndef SFX_MODULE + if (OldFormat) + { + NewMhd.Flags=OldMhd.Flags & 0x3f; + NewMhd.HeadSize=OldMhd.HeadSize; + } + else +#endif + { + if (HeaderCRC!=NewMhd.HeadCRC) + { +#ifndef SHELL_EXT + Log(FileName,St(MLogMainHead)); +#endif + Alarm(); + if (!EnableBroken) + return(false); + } + } + Volume=(NewMhd.Flags & MHD_VOLUME); + Solid=(NewMhd.Flags & MHD_SOLID)!=0; + MainComment=(NewMhd.Flags & MHD_COMMENT)!=0; + Locked=(NewMhd.Flags & MHD_LOCK)!=0; + Signed=(NewMhd.PosAV!=0); + Protected=(NewMhd.Flags & MHD_PROTECT)!=0; + Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0; + +#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 (SubHead.CmpName(SUBHEAD_TYPE_CMT)) + MainComment=true; + if ((SubHead.Flags & LHD_SPLIT_BEFORE) || + Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0) + NotFirstVolume=true; + } + else + { + 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; + } + return(true); +} + + + + +void Archive::SeekToNext() +{ + Seek(NextBlockPos,SEEK_SET); +} + + +#ifndef SFX_MODULE +int Archive::GetRecoverySize(bool Required) +{ + if (!Protected) + return(0); + if (RecoverySectors!=-1 || !Required) + return(RecoverySectors); + SaveFilePos SavePos(*this); + Seek(SFXSize,SEEK_SET); + SearchSubBlock(SUBHEAD_TYPE_RR); + return(RecoverySectors); +} +#endif + + diff --git a/unrar/archive.hpp b/unrar/archive.hpp new file mode 100644 index 0000000..2ce92c5 --- /dev/null +++ b/unrar/archive.hpp @@ -0,0 +1,130 @@ +#ifndef _RAR_ARCHIVE_ +#define _RAR_ARCHIVE_ + +class Pack; + +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 ConvertUnknownHeader(); + bool AddArcComment(char *NameToShow); + int ReadOldHeader(); + void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array &TimeData); + +#if !defined(SHELL_EXT) && !defined(NOCRYPT) + CryptData HeadersCrypt; + byte HeadersSalt[SALT_SIZE]; +#endif +#ifndef SHELL_EXT + ComprDataIO SubDataIO; + byte SubDataSalt[SALT_SIZE]; +#endif + RAROptions *Cmd,DummyCmd; + + MarkHeader MarkHead; + OldMainHeader OldMhd; + + int RecoverySectors; + Int64 RecoveryPos; + + RarTime LatestTime; + int LastReadBlock; + int CurHeaderType; + + bool SilentOpen; + public: + Archive(RAROptions *InitCmd=NULL); + bool IsArchive(bool EnableBroken); + 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(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 &CmtData); + void ViewComment(); + void ViewFileComment(); + void SetLatestTime(RarTime *NewTime); + void SeekToNext(); + bool CheckAccess(); + bool IsArcDir(); + bool IsArcLabel(); + void ConvertAttributes(); + int LhdSize(); + int LhdExtraSize(); + int GetRecoverySize(bool Required); + void VolSubtractHeaderSize(int SubSize); + void AddSubData(byte *SrcData,int DataSize,File *SrcFile,char *Name,bool AllowSplit); + bool ReadSubData(Array *UnpData,File *DestFile); + int GetHeaderType() {return(CurHeaderType);}; + int ReadCommentData(Array &CmtData); + void WriteCommentData(byte *Data,int DataSize,bool FileComment); + RAROptions* GetRAROptions() {return(Cmd);} + void SetSilentOpen(bool Mode) {SilentOpen=Mode;} + + BaseBlock ShortBlock; + 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; + + bool OldFormat; + bool Solid; + bool Volume; + bool MainComment; + bool Locked; + bool Signed; + bool NotFirstVolume; + bool Protected; + bool Encrypted; + uint SFXSize; + bool BrokenFileHeader; + + bool Splitting; + + ushort HeaderCRC; + + Int64 VolWrite; + Int64 AddingFilesSize; + uint AddingHeadersSize; + + bool NewArchive; + + char FirstVolumeName[NM]; + wchar FirstVolumeNameW[NM]; +}; + +#endif diff --git a/unrar/arcread.cpp b/unrar/arcread.cpp new file mode 100644 index 0000000..78a89b6 --- /dev/null +++ b/unrar/arcread.cpp @@ -0,0 +1,653 @@ +#include "rar.hpp" + +int Archive::SearchBlock(int BlockType) +{ + int Size,Count=0; + while ((Size=ReadHeader())!=0 && + (BlockType==ENDARC_HEAD || GetHeaderType()!=ENDARC_HEAD)) + { + if ((++Count & 127)==0) + Wait(); + if (GetHeaderType()==BlockType) + return(Size); + SeekToNext(); + } + return(0); +} + + +int Archive::SearchSubBlock(const char *Type) +{ + int Size; + while ((Size=ReadHeader())!=0 && GetHeaderType()!=ENDARC_HEAD) + { + if (GetHeaderType()==NEWSUB_HEAD && SubHead.CmpName(Type)) + return(Size); + SeekToNext(); + } + return(0); +} + + +int Archive::ReadHeader() +{ + CurBlockPos=Tell(); + +#ifndef SFX_MODULE + if (OldFormat) + return(ReadOldHeader()); +#endif + + RawRead Raw(this); + + bool Decrypt=Encrypted && CurBlockPos>=SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD; + + if (Decrypt) + { +#if defined(SHELL_EXT) || defined(NOCRYPT) + return(0); +#else + if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE) + return(0); + if (*Cmd->Password==0) +#ifdef RARDLL + if (Cmd->Callback==NULL || + Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1) + { + Close(); + ErrHandler.Exit(USER_BREAK); + } + +#else + if (!GetPassword(PASSWORD_ARCHIVE,FileName,Cmd->Password,sizeof(Cmd->Password))) + { + Close(); + ErrHandler.Exit(USER_BREAK); + } +#endif + HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false); + Raw.SetCrypt(&HeadersCrypt); +#endif + } + + Raw.Read(SIZEOF_SHORTBLOCKHEAD); + if (Raw.Size()==0) + { + Int64 ArcSize=FileLength(); + if (CurBlockPos>ArcSize || NextBlockPos>ArcSize) + { + #ifndef SHELL_EXT + Log(FileName,St(MLogUnexpEOF)); + #endif + ErrHandler.SetErrorCode(WARNING); + } + return(0); + } + + Raw.Get(ShortBlock.HeadCRC); + byte HeadType; + Raw.Get(HeadType); + ShortBlock.HeadType=(HEADER_TYPE)HeadType; + Raw.Get(ShortBlock.Flags); + Raw.Get(ShortBlock.HeadSize); + if (ShortBlock.HeadSizePackSize); + Raw.Get(hd->UnpSize); + Raw.Get(hd->HostOS); + Raw.Get(hd->FileCRC); + Raw.Get(hd->FileTime); + Raw.Get(hd->UnpVer); + Raw.Get(hd->Method); + Raw.Get(hd->NameSize); + Raw.Get(hd->FileAttr); + if (hd->Flags & LHD_LARGE) + { + Raw.Get(hd->HighPackSize); + Raw.Get(hd->HighUnpSize); + } + else + { + hd->HighPackSize=hd->HighUnpSize=0; + if (hd->UnpSize==0xffffffff) + { + hd->UnpSize=int64to32(INT64MAX); + hd->HighUnpSize=int64to32(INT64MAX>>32); + } + } + hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize); + hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize); + + char FileName[NM*4]; + int NameSize=Min(hd->NameSize,sizeof(FileName)-1); + Raw.Get((byte *)FileName,NameSize); + FileName[NameSize]=0; + + strncpy(hd->FileName,FileName,sizeof(hd->FileName)); + hd->FileName[sizeof(hd->FileName)-1]=0; + + if (hd->HeadType==NEWSUB_HEAD) + { + int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD; + if (hd->Flags & LHD_SALT) + DataSize-=SALT_SIZE; + if (DataSize>0) + { + hd->SubData.Alloc(DataSize); + Raw.Get(&hd->SubData[0],DataSize); + if (hd->CmpName(SUBHEAD_TYPE_RR)) + { + byte *D=&hd->SubData[8]; + RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24); + } + } + } + else + if (hd->HeadType==FILE_HEAD) + { + if (hd->Flags & LHD_UNICODE) + { + EncodeFileName NameCoder; + int Length=strlen(FileName)+1; + NameCoder.Decode(FileName,(byte *)FileName+Length, + hd->NameSize-Length,hd->FileNameW, + sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])); + if (*hd->FileNameW==0) + hd->Flags &= ~LHD_UNICODE; + } + else + *hd->FileNameW=0; +#ifndef SFX_MODULE + ConvertNameCase(hd->FileName); + ConvertNameCase(hd->FileNameW); +#endif + ConvertUnknownHeader(); + } + if (hd->Flags & LHD_SALT) + Raw.Get(hd->Salt,SALT_SIZE); + hd->mtime.SetDos(hd->FileTime); + hd->ctime.Reset(); + hd->atime.Reset(); + hd->arctime.Reset(); + if (hd->Flags & LHD_EXTTIME) + { + ushort Flags; + Raw.Get(Flags); + RarTime *tbl[4]; + tbl[0]=&NewLhd.mtime; + tbl[1]=&NewLhd.ctime; + tbl[2]=&NewLhd.atime; + tbl[3]=&NewLhd.arctime; + for (int I=0;I<4;I++) + { + RarTime *CurTime=tbl[I]; + uint rmode=Flags>>(3-I)*4; + if ((rmode & 8)==0) + continue; + if (I!=0) + { + uint DosTime; + Raw.Get(DosTime); + CurTime->SetDos(DosTime); + } + RarLocalTime rlt; + CurTime->GetLocal(&rlt); + if (rmode & 4) + rlt.Second++; + rlt.Reminder=0; + int count=rmode&3; + for (int J=0;JSetLocal(&rlt); + } + } + NextBlockPos+=hd->FullPackSize; + bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0; + HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff; + if (hd->HeadCRC!=HeaderCRC) + { + if (hd->HeadType==NEWSUB_HEAD) + strcat(hd->FileName,"- ???"); + BrokenFileHeader=true; + ErrHandler.SetErrorCode(WARNING); +#ifndef SHELL_EXT + Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName)); + Alarm(); +#endif + } + } + break; +#ifndef SFX_MODULE + case COMM_HEAD: + *(BaseBlock *)&CommHead=ShortBlock; + Raw.Get(CommHead.UnpSize); + Raw.Get(CommHead.UnpVer); + Raw.Get(CommHead.Method); + Raw.Get(CommHead.CommCRC); + break; + case SIGN_HEAD: + *(BaseBlock *)&SignHead=ShortBlock; + Raw.Get(SignHead.CreationTime); + Raw.Get(SignHead.ArcNameSize); + Raw.Get(SignHead.UserNameSize); + break; + case AV_HEAD: + *(BaseBlock *)&AVHead=ShortBlock; + Raw.Get(AVHead.UnpVer); + Raw.Get(AVHead.Method); + Raw.Get(AVHead.AVVer); + Raw.Get(AVHead.AVInfoCRC); + break; + case PROTECT_HEAD: + *(BaseBlock *)&ProtectHead=ShortBlock; + Raw.Get(ProtectHead.DataSize); + Raw.Get(ProtectHead.Version); + Raw.Get(ProtectHead.RecSectors); + Raw.Get(ProtectHead.TotalBlocks); + Raw.Get(ProtectHead.Mark,8); + NextBlockPos+=ProtectHead.DataSize; + RecoverySectors=ProtectHead.RecSectors; + break; + case SUB_HEAD: + *(BaseBlock *)&SubBlockHead=ShortBlock; + Raw.Get(SubBlockHead.DataSize); + NextBlockPos+=SubBlockHead.DataSize; + Raw.Get(SubBlockHead.SubType); + Raw.Get(SubBlockHead.Level); + switch(SubBlockHead.SubType) + { + case UO_HEAD: + *(SubBlockHeader *)&UOHead=SubBlockHead; + Raw.Get(UOHead.OwnerNameSize); + Raw.Get(UOHead.GroupNameSize); + if (UOHead.OwnerNameSize>NM-1) + UOHead.OwnerNameSize=NM-1; + if (UOHead.GroupNameSize>NM-1) + UOHead.GroupNameSize=NM-1; + Raw.Get((byte *)UOHead.OwnerName,UOHead.OwnerNameSize); + Raw.Get((byte *)UOHead.GroupName,UOHead.GroupNameSize); + UOHead.OwnerName[UOHead.OwnerNameSize]=0; + UOHead.GroupName[UOHead.GroupNameSize]=0; + break; + case MAC_HEAD: + *(SubBlockHeader *)&MACHead=SubBlockHead; + Raw.Get(MACHead.fileType); + Raw.Get(MACHead.fileCreator); + break; + case EA_HEAD: + case BEEA_HEAD: + case NTACL_HEAD: + *(SubBlockHeader *)&EAHead=SubBlockHead; + Raw.Get(EAHead.UnpSize); + Raw.Get(EAHead.UnpVer); + Raw.Get(EAHead.Method); + Raw.Get(EAHead.EACRC); + break; + case STREAM_HEAD: + *(SubBlockHeader *)&StreamHead=SubBlockHead; + Raw.Get(StreamHead.UnpSize); + Raw.Get(StreamHead.UnpVer); + Raw.Get(StreamHead.Method); + Raw.Get(StreamHead.StreamCRC); + Raw.Get(StreamHead.StreamNameSize); + if (StreamHead.StreamNameSize>NM-1) + StreamHead.StreamNameSize=NM-1; + Raw.Get((byte *)StreamHead.StreamName,StreamHead.StreamNameSize); + StreamHead.StreamName[StreamHead.StreamNameSize]=0; + break; + } + break; +#endif + default: + if (ShortBlock.Flags & LONG_BLOCK) + { + uint DataSize; + Raw.Get(DataSize); + NextBlockPos+=DataSize; + } + break; + } + HeaderCRC=~Raw.GetCRC(false)&0xffff; + CurHeaderType=ShortBlock.HeadType; + if (Decrypt) + { + NextBlockPos+=Raw.PaddedSize()+SALT_SIZE; + + if (ShortBlock.HeadCRC!=HeaderCRC) + { + bool Recovered=false; + if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0) + { + SaveFilePos SavePos(*this); + Int64 Length=Tell(); + Seek(Length-7,SEEK_SET); + Recovered=true; + for (int J=0;J<7;J++) + if (GetByte()!=0) + Recovered=false; + } + if (!Recovered) + { +#ifndef SILENT + Log(FileName,St(MEncrBadCRC),FileName); +#endif + Close(); + + BrokenFileHeader=true; + ErrHandler.SetErrorCode(CRC_ERROR); + return(0); +// ErrHandler.Exit(CRC_ERROR); + } + } + } + + if (NextBlockPos<=CurBlockPos) + { +#ifndef SHELL_EXT + Log(FileName,St(MLogFileHead),"???"); +#endif + BrokenFileHeader=true; + ErrHandler.SetErrorCode(CRC_ERROR); + return(0); + } + return(Raw.Size()); +} + + +#ifndef SFX_MODULE +int Archive::ReadOldHeader() +{ + RawRead Raw(this); + if (CurBlockPos<=SFXSize) + { + Raw.Read(SIZEOF_OLDMHD); + Raw.Get(OldMhd.Mark,4); + Raw.Get(OldMhd.HeadSize); + Raw.Get(OldMhd.Flags); + NextBlockPos=CurBlockPos+OldMhd.HeadSize; + CurHeaderType=MAIN_HEAD; + } + else + { + OldFileHeader OldLhd; + Raw.Read(SIZEOF_OLDLHD); + NewLhd.HeadType=FILE_HEAD; + Raw.Get(NewLhd.PackSize); + Raw.Get(NewLhd.UnpSize); + Raw.Get(OldLhd.FileCRC); + Raw.Get(NewLhd.HeadSize); + Raw.Get(NewLhd.FileTime); + Raw.Get(OldLhd.FileAttr); + Raw.Get(OldLhd.Flags); + Raw.Get(OldLhd.UnpVer); + Raw.Get(OldLhd.NameSize); + Raw.Get(OldLhd.Method); + + NewLhd.Flags=OldLhd.Flags|LONG_BLOCK; + NewLhd.UnpVer=(OldLhd.UnpVer==2) ? 13 : 10; + NewLhd.Method=OldLhd.Method+0x30; + NewLhd.NameSize=OldLhd.NameSize; + NewLhd.FileAttr=OldLhd.FileAttr; + NewLhd.FileCRC=OldLhd.FileCRC; + NewLhd.FullPackSize=NewLhd.PackSize; + NewLhd.FullUnpSize=NewLhd.UnpSize; + + NewLhd.mtime.SetDos(NewLhd.FileTime); + NewLhd.ctime.Reset(); + NewLhd.atime.Reset(); + NewLhd.arctime.Reset(); + + Raw.Read(OldLhd.NameSize); + Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize); + NewLhd.FileName[OldLhd.NameSize]=0; + ConvertNameCase(NewLhd.FileName); + *NewLhd.FileNameW=0; + + if (Raw.Size()!=0) + NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize; + CurHeaderType=FILE_HEAD; + } + return(NextBlockPos>CurBlockPos ? Raw.Size():0); +} +#endif + + +void Archive::ConvertNameCase(char *Name) +{ + if (Cmd->ConvertNames==NAMES_UPPERCASE) + { + IntToExt(Name,Name); + strupper(Name); + ExtToInt(Name,Name); + } + if (Cmd->ConvertNames==NAMES_LOWERCASE) + { + IntToExt(Name,Name); + strlower(Name); + ExtToInt(Name,Name); + } +} + + +#ifndef SFX_MODULE +void Archive::ConvertNameCase(wchar *Name) +{ + if (Cmd->ConvertNames==NAMES_UPPERCASE) + strupperw(Name); + if (Cmd->ConvertNames==NAMES_LOWERCASE) + strlowerw(Name); +} +#endif + + +bool Archive::IsArcDir() +{ + return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY); +} + + +bool Archive::IsArcLabel() +{ + return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8)); +} + + +void Archive::ConvertAttributes() +{ +#if defined(_WIN_32) || defined(_EMX) + switch(NewLhd.HostOS) + { + case HOST_MSDOS: + case HOST_OS2: + case HOST_WIN32: + break; + case HOST_UNIX: + case HOST_BEOS: + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x10; + else + NewLhd.FileAttr=0x20; + break; + default: + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x10; + else + NewLhd.FileAttr=0x20; + break; + } +#endif +#ifdef _UNIX + static mode_t mask = (mode_t) -1; + + if (mask == (mode_t) -1) + { + mask = umask(022); + umask(mask); + } + switch(NewLhd.HostOS) + { + case HOST_MSDOS: + case HOST_OS2: + case HOST_WIN32: + if (NewLhd.FileAttr & 0x10) + NewLhd.FileAttr=0x41ff & ~mask; + else + if (NewLhd.FileAttr & 1) + NewLhd.FileAttr=0x8124 & ~mask; + else + NewLhd.FileAttr=0x81b6 & ~mask; + break; + case HOST_UNIX: + case HOST_BEOS: + break; + default: + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x41ff & ~mask; + else + NewLhd.FileAttr=0x81b6 & ~mask; + break; + } +#endif +} + + +void Archive::ConvertUnknownHeader() +{ + if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10)) + NewLhd.Flags|=LHD_DIRECTORY; + if (NewLhd.HostOS>=HOST_MAX) + { + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x10; + else + NewLhd.FileAttr=0x20; + } + for (char *s=NewLhd.FileName;*s!=0;s=charnext(s)) + { + if (*s=='/' || *s=='\\') + *s=CPATHDIVIDER; +#if defined(_APPLE) && !defined(UNICODE_SUPPORTED) + if ((byte)*s<32 || (byte)*s>127) + *s='_'; +#endif + } + for (wchar *s=NewLhd.FileNameW;*s!=0;s++) + if (*s=='/' || *s=='\\') + *s=CPATHDIVIDER; +} + + +int Archive::LhdSize() +{ + return((NewLhd.Flags & LHD_LARGE) ? SIZEOF_NEWLHD+8:SIZEOF_NEWLHD); +} + + +int Archive::LhdExtraSize() +{ + return(NewLhd.HeadSize-NewLhd.NameSize-LhdSize()); +} + + +#ifndef SHELL_EXT +bool Archive::ReadSubData(Array *UnpData,File *DestFile) +{ + if (HeaderCRC!=SubHead.HeadCRC) + { +#ifndef SHELL_EXT + Log(FileName,St(MSubHeadCorrupt)); +#endif + ErrHandler.SetErrorCode(CRC_ERROR); + return(false); + } + if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>PACK_VER) + { +#ifndef SHELL_EXT + Log(FileName,St(MSubHeadUnknown)); +#endif + return(false); + } + + if (SubHead.PackSize==0 && (SubHead.Flags & LHD_SPLIT_AFTER)==0) + return(true); + + SubDataIO.Init(); + Unpack Unpack(&SubDataIO); + Unpack.Init(); + + if (DestFile==NULL) + { + UnpData->Alloc(SubHead.UnpSize); + SubDataIO.SetUnpackToMemory(&(*UnpData)[0],SubHead.UnpSize); + } + if (SubHead.Flags & LHD_PASSWORD) + if (*Cmd->Password) + SubDataIO.SetEncryption(SubHead.UnpVer,Cmd->Password, + (SubHead.Flags & LHD_SALT) ? SubHead.Salt:NULL,false); + else + return(false); + SubDataIO.SetPackedSizeToRead(SubHead.PackSize); + SubDataIO.EnableShowProgress(false); + SubDataIO.SetFiles(this,DestFile); + SubDataIO.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER); + SubDataIO.SetSubHeader(&SubHead,NULL); + Unpack.SetDestSize(SubHead.UnpSize); + if (SubHead.Method==0x30) + CmdExtract::UnstoreFile(SubDataIO,SubHead.UnpSize); + else + Unpack.DoUnpack(SubHead.UnpVer,false); + + if (SubHead.FileCRC!=~SubDataIO.UnpFileCRC) + { +#ifndef SHELL_EXT + Log(FileName,St(MSubHeadDataCRC),SubHead.FileName); +#endif + ErrHandler.SetErrorCode(CRC_ERROR); + if (UnpData!=NULL) + UnpData->Reset(); + return(false); + } + return(true); +} +#endif diff --git a/unrar/array.hpp b/unrar/array.hpp new file mode 100644 index 0000000..3afec70 --- /dev/null +++ b/unrar/array.hpp @@ -0,0 +1,121 @@ +#ifndef _RAR_ARRAY_ +#define _RAR_ARRAY_ + +extern ErrorHandler ErrHandler; + +template class Array +{ + private: + T *Buffer; + int BufSize; + int AllocSize; + public: + Array(); + Array(int Size); + ~Array(); + inline void CleanData(); + inline T& operator [](int Item); + inline int Size(); + void Add(int Items); + void Alloc(int Items); + void Reset(); + void operator = (Array &Src); + void Push(T Item); +}; + +template void Array::CleanData() +{ + Buffer=NULL; + BufSize=0; + AllocSize=0; +} + + +template Array::Array() +{ + CleanData(); +} + + +template Array::Array(int Size) +{ + Buffer=(T *)rarmalloc(sizeof(T)*Size); + if (Buffer==NULL && Size!=0) + ErrHandler.MemoryError(); + + AllocSize=BufSize=Size; +} + + +template Array::~Array() +{ + if (Buffer!=NULL) + rarfree(Buffer); +} + + +template inline T& Array::operator [](int Item) +{ + return(Buffer[Item]); +} + + +template inline int Array::Size() +{ + return(BufSize); +} + + +template void Array::Add(int Items) +{ + BufSize+=Items; + if (BufSize>AllocSize) + { + int Suggested=AllocSize+AllocSize/4+32; + int NewSize=Max(BufSize,Suggested); + + Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T)); + if (Buffer==NULL) + ErrHandler.MemoryError(); + AllocSize=NewSize; + } +} + + +template void Array::Alloc(int Items) +{ + if (Items>AllocSize) + Add(Items-BufSize); + else + BufSize=Items; +} + + +template void Array::Reset() +{ + if (Buffer!=NULL) + { + rarfree(Buffer); + Buffer=NULL; + } + BufSize=0; + AllocSize=0; +} + + +template void Array::operator =(Array &Src) +{ + Reset(); + Alloc(Src.BufSize); + if (Src.BufSize!=0) + memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T)); +} + + +template void Array::Push(T Item) +{ + Add(1); + (*this)[Size()-1]=Item; +} + +#endif diff --git a/unrar/beosea.cpp b/unrar/beosea.cpp new file mode 100644 index 0000000..86eb7d4 --- /dev/null +++ b/unrar/beosea.cpp @@ -0,0 +1,113 @@ + + +void ExtractBeEA(Archive &Arc,char *FileName) +{ + if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC) + { + Log(Arc.FileName,St(MEABroken),FileName); + ErrHandler.SetErrorCode(CRC_ERROR); + return; + } + if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER) + { + Log(Arc.FileName,St(MEAUnknHeader),FileName); + return; + } + + ComprDataIO DataIO; + Unpack Unpack(&DataIO); + Unpack.Init(); + + Array UnpData(Arc.EAHead.UnpSize); + DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize); + DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize); + DataIO.EnableShowProgress(false); + DataIO.SetFiles(&Arc,NULL); + Unpack.SetDestSize(Arc.EAHead.UnpSize); + Unpack.DoUnpack(Arc.EAHead.UnpVer,false); + + if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC) + { + Log(Arc.FileName,St(MEABroken),FileName); + ErrHandler.SetErrorCode(CRC_ERROR); + return; + } + int fd = open(FileName,O_WRONLY); + if (fd==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + return; + } + + int AttrPos=0; + while (AttrPos=sizeof(Name)) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + memcpy(Name,CurItem+10,NameSize); + Name[NameSize]=0; + if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + AttrPos+=10+NameSize+Size; + } + close(fd); + mprintf(St(MShowEA)); +} + + +void ExtractBeEANew(Archive &Arc,char *FileName) +{ + Array SubData; + if (!Arc.ReadSubData(&SubData,NULL)) + return; + + int fd = open(FileName,O_WRONLY); + if (fd==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + return; + } + + int AttrPos=0; + while (AttrPos=sizeof(Name)) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + memcpy(Name,CurItem+10,NameSize); + Name[NameSize]=0; + if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + AttrPos+=10+NameSize+Size; + } + close(fd); + mprintf(St(MShowEA)); +} + diff --git a/unrar/cmddata.cpp b/unrar/cmddata.cpp new file mode 100644 index 0000000..890ec40 --- /dev/null +++ b/unrar/cmddata.cpp @@ -0,0 +1,1147 @@ +#include "rar.hpp" + +CommandData::CommandData() +{ + FileArgs=ExclArgs=InclArgs=StoreArgs=ArcNames=NULL; + Init(); +} + + +CommandData::~CommandData() +{ + Close(); +} + + +void CommandData::Init() +{ + Close(); + + *Command=0; + *ArcName=0; + *ArcNameW=0; + FileLists=false; + NoMoreSwitches=false; + TimeConverted=false; + + FileArgs=new StringList; + ExclArgs=new StringList; + InclArgs=new StringList; + StoreArgs=new StringList; + ArcNames=new StringList; +} + + +void CommandData::Close() +{ + delete FileArgs; + delete ExclArgs; + delete InclArgs; + delete StoreArgs; + delete ArcNames; + FileArgs=ExclArgs=InclArgs=StoreArgs=ArcNames=NULL; + NextVolSizes.Reset(); +} + + +#if !defined(SFX_MODULE) && !defined(_WIN_CE) +void CommandData::ParseArg(char *Arg,wchar *ArgW) +{ + if (IsSwitch(*Arg) && !NoMoreSwitches) + if (Arg[1]=='-') + NoMoreSwitches=true; + else + ProcessSwitch(&Arg[1]); + else + if (*Command==0) + { + strncpy(Command,Arg,sizeof(Command)); + if (ArgW!=NULL) + strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0])); + if (toupper(*Command)=='S') + { + const char *SFXName=Command[1] ? Command+1:DefSFXName; + if (PointToName(SFXName)!=SFXName || FileExist(SFXName)) + strcpy(SFXModule,SFXName); + else + GetConfigName(SFXName,SFXModule,true); + } +#ifndef GUI + *Command=toupper(*Command); + if (*Command!='I' && *Command!='S') + strupper(Command); +#endif + } + else + if (*ArcName==0) + { + strncpy(ArcName,Arg,sizeof(ArcName)); + if (ArgW!=NULL) + strncpyw(ArcNameW,ArgW,sizeof(ArcNameW)/sizeof(ArcNameW[0])); + } + else + { + int Length=strlen(Arg); + char EndChar=Arg[Length-1]; + char CmdChar=toupper(*Command); + bool Add=strchr("AFUM",CmdChar)!=NULL; + bool Extract=CmdChar=='X' || CmdChar=='E'; + if ((IsDriveDiv(EndChar) || IsPathDiv(EndChar)) && !Add) + strcpy(ExtrPath,Arg); + else + if ((Add || CmdChar=='T') && *Arg!='@') + FileArgs->AddString(Arg); + else + { + struct FindData FileData; + bool Found=FindFile::FastFind(Arg,NULL,&FileData); + if (!Found && *Arg=='@' && !IsWildcard(Arg)) + { + ReadTextFile(Arg+1,FileArgs,false,true,true,true,true); + FileLists=true; + } + else + if (Found && FileData.IsDir && Extract && *ExtrPath==0) + { + strcpy(ExtrPath,Arg); + AddEndSlash(ExtrPath); + } + else + FileArgs->AddString(Arg); + } + } +} +#endif + + +void CommandData::ParseDone() +{ + if (FileArgs->ItemsCount()==0 && !FileLists) + FileArgs->AddString(MASKALL); + char CmdChar=toupper(*Command); + bool Extract=CmdChar=='X' || CmdChar=='E'; + if (Test && Extract) + Test=false; + BareOutput=(CmdChar=='L' || CmdChar=='V') && Command[1]=='B'; +} + + +#if !defined(SFX_MODULE) && !defined(_WIN_CE) +void CommandData::ParseEnvVar() +{ + char *EnvStr=getenv("RAR"); + if (EnvStr!=NULL) + ProcessSwitchesString(EnvStr); +} +#endif + + +#if !defined(GUI) && !defined(SFX_MODULE) +bool CommandData::IsConfigEnabled(int argc,char *argv[]) +{ + bool ConfigEnabled=true; + for (int I=1;I='0' && Switch[2]<='4'; + if (CommonMode) + Mode=(EXTTIME_MODE)(Switch[2]-'0'); + if (Switch[2]=='-') + Mode=EXTTIME_NONE; + if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0) + xmtime=xctime=xatime=Mode; + else + { + if (Switch[3]>='0' && Switch[3]<='4') + Mode=(EXTTIME_MODE)(Switch[3]-'0'); + if (Switch[3]=='-') + Mode=EXTTIME_NONE; + switch(toupper(Switch[2])) + { + case 'M': + xmtime=Mode; + break; + case 'C': + xctime=Mode; + break; + case 'A': + xatime=Mode; + break; + case 'R': + xarctime=Mode; + break; + } + } + } + break; + case '-': + Test=false; + break; + case 0: + Test=true; + break; + default: + BadSwitch(Switch); + break; + } + break; + case 'A': + switch(toupper(Switch[1])) + { + case 'C': + ClearArc=true; + break; + case 'D': + AppendArcNameToPath=true; + break; + case 'G': + if (Switch[2]=='-' && Switch[3]==0) + GenerateArcName=0; + else + { + GenerateArcName=true; + strncpy(GenerateMask,Switch+2,sizeof(GenerateMask)); + } + break; + case 'N': //reserved for archive name + break; + case 'O': + AddArcOnly=true; + break; + case 'P': + strcpy(ArcPath,Switch+2); + break; + case 'S': + SyncFiles=true; + break; + } + break; + case 'D': + if (Switch[2]==0) + switch(toupper(Switch[1])) + { + case 'S': + DisableSortSolid=true; + break; + case 'H': + OpenShared=true; + break; + case 'F': + DeleteFiles=true; + break; + } + break; + case 'O': + switch(toupper(Switch[1])) + { + case '+': + Overwrite=OVERWRITE_ALL; + break; + case '-': + Overwrite=OVERWRITE_NONE; + break; + case 'W': + ProcessOwners=true; + break; +#ifdef SAVE_LINKS + case 'L': + SaveLinks=true; + break; +#endif +#ifdef _WIN_32 + case 'S': + SaveStreams=true; + break; + case 'C': + SetCompressedAttr=true; + break; +#endif + default : + BadSwitch(Switch); + break; + } + break; + case 'R': + switch(toupper(Switch[1])) + { + case 0: + Recurse=RECURSE_ALWAYS; + break; + case '-': + Recurse=0; + break; + case '0': + Recurse=RECURSE_WILDCARDS; + break; + case 'I': + { + Priority=atoi(Switch+2); + char *ChPtr=strchr(Switch+2,':'); + if (ChPtr!=NULL) + { + SleepTime=atoi(ChPtr+1); + InitSystemOptions(SleepTime); + } + SetPriority(Priority); + } + break; + } + break; + case 'Y': + AllYes=true; + break; + case 'N': + case 'X': + if (Switch[1]!=0) + { + StringList *Args=toupper(Switch[0])=='N' ? InclArgs:ExclArgs; + if (Switch[1]=='@' && !IsWildcard(Switch)) + ReadTextFile(Switch+2,Args,false,true,true,true,true); + else + Args->AddString(Switch+1); + } + break; + case 'E': + switch(toupper(Switch[1])) + { + case 'P': + switch(Switch[2]) + { + case 0: + ExclPath=EXCL_SKIPWHOLEPATH; + break; + case '1': + ExclPath=EXCL_BASEPATH; + break; + case '2': + ExclPath=EXCL_SAVEFULLPATH; + break; + case '3': + ExclPath=EXCL_ABSPATH; + break; + } + break; + case 'D': + ExclEmptyDir=true; + break; + case 'E': + ProcessEA=false; + break; + case 'N': + NoEndBlock=true; + break; + default: + if (Switch[1]=='+') + { + InclFileAttr=GetExclAttr(&Switch[2]); + InclAttrSet=true; + } + else + ExclFileAttr=GetExclAttr(&Switch[1]); + break; + } + break; + case 'P': + if (Switch[1]==0) + { + GetPassword(PASSWORD_GLOBAL,NULL,Password,sizeof(Password)); + eprintf("\n"); + } + else + strncpy(Password,Switch+1,sizeof(Password)); + break; + case 'H': + if (toupper(Switch[1])=='P') + { + EncryptHeaders=true; + if (Switch[2]!=0) + strncpy(Password,Switch+2,sizeof(Password)); + else + if (*Password==0) + { + GetPassword(PASSWORD_GLOBAL,NULL,Password,sizeof(Password)); + eprintf("\n"); + } + } + break; + case 'Z': + strncpy(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",sizeof(CommentFile)); + break; + case 'M': + switch(toupper(Switch[1])) + { + case 'C': + { + char *Str=Switch+2; + if (*Str=='-') + for (int I=0;IAddString(Mask); + if (End==NULL) + break; + Names=End+1; + } + } + break; + default: + Method=Switch[1]-'0'; + if (Method>5 || Method<0) + BadSwitch(Switch); + break; + } + break; + case 'V': + switch(toupper(Switch[1])) + { +#ifdef _WIN_32 + case 'D': + EraseDisk=true; + break; +#endif + case 'N': + OldNumbering=true; + break; + case 'P': + VolumePause=true; + break; + case 'E': + if (toupper(Switch[2])=='R') + VersionControl=atoi(Switch+3)+1; + break; + case '-': + VolSize=0; + break; + default: + { + Int64 NewVolSize=atoil(&Switch[1]); + + if (NewVolSize==0) + NewVolSize=INT64ERR; + else + switch (Switch[strlen(Switch)-1]) + { + case 'f': + case 'F': + switch(int64to32(NewVolSize)) + { + case 360: + NewVolSize=362496; + break; + case 720: + NewVolSize=730112; + break; + case 1200: + NewVolSize=1213952; + break; + case 1440: + NewVolSize=1457664; + break; + case 2880: + NewVolSize=2915328; + break; + } + break; + case 'k': + NewVolSize*=1024; + break; + case 'm': + NewVolSize*=1024*1024; + break; + case 'M': + NewVolSize*=1000*1000; + break; + case 'g': + NewVolSize*=1024*1024; + NewVolSize*=1024; + break; + case 'G': + NewVolSize*=1000*1000; + NewVolSize*=1000; + break; + case 'b': + case 'B': + break; + default: + NewVolSize*=1000; + break; + } + if (VolSize==0) + VolSize=NewVolSize; + else + NextVolSizes.Push(NewVolSize); + } + break; + } + break; + case 'F': + if (Switch[1]==0) + FreshFiles=true; + break; + case 'U': + if (Switch[1]==0) + UpdateFiles=true; + break; + case 'W': + strncpy(TempPath,&Switch[1],sizeof(TempPath)-1); + AddEndSlash(TempPath); + break; + case 'S': + if (strnicomp(Switch,"SFX",3)==0) + { + const char *SFXName=Switch[3] ? Switch+3:DefSFXName; + if (PointToName(SFXName)!=SFXName || FileExist(SFXName)) + strcpy(SFXModule,SFXName); + else + GetConfigName(SFXName,SFXModule,true); + } + if (isdigit(Switch[1])) + { + Solid|=SOLID_COUNT; + SolidCount=atoi(&Switch[1]); + } + else + switch(toupper(Switch[1])) + { + case 0: + Solid|=SOLID_NORMAL; + break; + case '-': + Solid=SOLID_NONE; + break; + case 'E': + Solid|=SOLID_FILEEXT; + break; + case 'V': + Solid|=Switch[2]=='-' ? SOLID_VOLUME_DEPENDENT:SOLID_VOLUME_INDEPENDENT; + break; + case 'D': + Solid|=SOLID_VOLUME_DEPENDENT; + break; + } + break; + case 'C': + if (Switch[2]==0) + switch(toupper(Switch[1])) + { + case '-': + DisableComment=true; + break; + case 'U': + ConvertNames=NAMES_UPPERCASE; + break; + case 'L': + ConvertNames=NAMES_LOWERCASE; + break; + } + break; + case 'K': + switch(toupper(Switch[1])) + { + case 'B': + KeepBroken=true; + break; + case 0: + Lock=true; + break; + } + break; +#ifndef GUI + case '?' : + OutHelp(); + break; +#endif + default : + BadSwitch(Switch); + break; + } +} +#endif + + +#if !defined(SFX_MODULE) && !defined(_WIN_CE) +void CommandData::BadSwitch(char *Switch) +{ + mprintf(St(MUnknownOption),Switch); + ErrHandler.Exit(USER_ERROR); +} +#endif + + +#ifndef GUI +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; + char Version[50]; + int Beta=RARVER_BETA; + if (Beta!=0) + sprintf(Version,"%d.%02d %s %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA); + else + sprintf(Version,"%d.%02d",RARVER_MAJOR,RARVER_MINOR); +#ifdef UNRAR + mprintf(St(MUCopyright),Version,RARVER_YEAR); +#else +#endif +#endif +#endif +} +#endif + + +void CommandData::OutHelp() +{ +#if !defined(GUI) && !defined(SILENT) + OutTitle(); + static MSGID Help[]={ +#ifdef SFX_MODULE + MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV +#elif defined(UNRAR) + MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,MCHelpCmdP, + MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,MCHelpSwAC,MCHelpSwAD, + MCHelpSwAP,MCHelpSwAVm,MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU, + MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR, + MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal, + MCHelpSwOp,MCHelpSwOm,MCHelpSwOC,MCHelpSwOW,MCHelpSwP,MCHelpSwPm, + MCHelpSwR,MCHelpSwRI,MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO, + MCHelpSwTS,MCHelpSwU,MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX, + MCHelpSwXa,MCHelpSwXal,MCHelpSwY +#else + MRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdA,MCHelpCmdC,MCHelpCmdCF, + MCHelpCmdCW,MCHelpCmdD,MCHelpCmdE,MCHelpCmdF,MCHelpCmdI,MCHelpCmdK, + MCHelpCmdL,MCHelpCmdM,MCHelpCmdP,MCHelpCmdR,MCHelpCmdRC,MCHelpCmdRN, + MCHelpCmdRR,MCHelpCmdRV,MCHelpCmdS,MCHelpCmdT,MCHelpCmdU,MCHelpCmdV, + MCHelpCmdX,MCHelpSw,MCHelpSwm,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG, + MCHelpSwAO,MCHelpSwAP,MCHelpSwAS,MCHelpSwAV,MCHelpSwAVm,MCHelpSwCm, + MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,MCHelpSwDF,MCHelpSwDH,MCHelpSwDS, + MCHelpSwEa,MCHelpSwED,MCHelpSwEE,MCHelpSwEN,MCHelpSwEP,MCHelpSwEP1, + MCHelpSwEP2,MCHelpSwEP3,MCHelpSwF,MCHelpSwHP,MCHelpSwIDP,MCHelpSwIEML, + MCHelpSwIERR,MCHelpSwILOG,MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwISND, + MCHelpSwK,MCHelpSwKB,MCHelpSwMn,MCHelpSwMC,MCHelpSwMD,MCHelpSwMS, + MCHelpSwN,MCHelpSwNa,MCHelpSwNal,MCHelpSwOp,MCHelpSwOm,MCHelpSwOC, + MCHelpSwOL,MCHelpSwOS,MCHelpSwOW,MCHelpSwP,MCHelpSwPm,MCHelpSwR, + MCHelpSwR0,MCHelpSwRI,MCHelpSwRR,MCHelpSwRV,MCHelpSwS,MCHelpSwSm, + MCHelpSwSFX,MCHelpSwSI,MCHelpSwT,MCHelpSwTA,MCHelpSwTB,MCHelpSwTK, + MCHelpSwTL,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwV, + MCHelpSwVn,MCHelpSwVD,MCHelpSwVER,MCHelpSwVN,MCHelpSwVP,MCHelpSwW, + MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY,MCHelpSwZ +#endif + }; + + for (int I=0;IRewind(); + while ((CurName=Args->GetString())!=NULL) +#ifndef SFX_MODULE + if (CheckFullPath && IsFullPath(CurName)) + { + if (*FullName==0) + ConvertNameToFull(CheckName,FullName); + if (CmpName(CurName,FullName,MATCH_WILDSUBPATH)) + return(true); + } + else +#endif + if (CmpName(ConvertPath(CurName,NULL),Name,MATCH_WILDSUBPATH)) + return(true); + return(false); +} + + +bool CommandData::ExclCheck(char *CheckName,bool CheckFullPath) +{ + if (ExclCheckArgs(ExclArgs,CheckName,CheckFullPath)) + return(true); + if (InclArgs->ItemsCount()==0) + return(false); + if (ExclCheckArgs(InclArgs,CheckName,CheckFullPath)) + return(false); + return(true); +} + + + + +#ifndef SFX_MODULE +bool CommandData::TimeCheck(RarTime &ft) +{ + if (FileTimeBefore.IsSet() && ft>=FileTimeBefore) + return(true); + if (FileTimeAfter.IsSet() && ft<=FileTimeAfter) + return(true); +/* + if (FileTimeOlder!=0 || FileTimeNewer!=0) + { + if (!TimeConverted) + { + if (FileTimeOlder!=0) + FileTimeOlder=SecondsToDosTime(FileTimeOlder); + if (FileTimeNewer!=0) + FileTimeNewer=SecondsToDosTime(FileTimeNewer); + TimeConverted=true; + } + if (FileTimeOlder!=0 && ft>=FileTimeOlder) + return(true); + if (FileTimeNewer!=0 && ft<=FileTimeNewer) + return(true); + + } +*/ + return(false); +} +#endif + + +int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType) +{ + if (strlen(NewLhd.FileName)>=NM || strlenw(NewLhd.FileNameW)>=NM) + return(0); + if (ExclCheck(NewLhd.FileName,false)) + return(0); +#ifndef SFX_MODULE + if (TimeCheck(NewLhd.mtime)) + return(0); +#endif + char *ArgName; + wchar *ArgNameW; + FileArgs->Rewind(); + for (int StringCount=1;FileArgs->GetString(&ArgName,&ArgNameW);StringCount++) + { +#ifndef SFX_MODULE + bool Unicode=(NewLhd.Flags & LHD_UNICODE) || ArgNameW!=NULL; + if (Unicode) + { + wchar NameW[NM],ArgW[NM],*NamePtr=NewLhd.FileNameW; + if (ArgNameW==NULL) + { + CharToWide(ArgName,ArgW); + ArgNameW=ArgW; + } + if ((NewLhd.Flags & LHD_UNICODE)==0) + { + CharToWide(NewLhd.FileName,NameW); + NamePtr=NameW; + } + if (CmpName(ArgNameW,NamePtr,MatchType)) + { + if (ExactMatch!=NULL) + *ExactMatch=stricompcw(ArgNameW,NamePtr)==0; + return(StringCount); + } + continue; + } +#endif + if (CmpName(ArgName,NewLhd.FileName,MatchType)) + { + if (ExactMatch!=NULL) + *ExactMatch=stricompc(ArgName,NewLhd.FileName)==0; + return(StringCount); + } + } + return(0); +} + + +#ifndef _WIN_CE +void CommandData::ProcessCommand() +{ +#ifndef SFX_MODULE + if (Command[1] && strchr("FUADPXETK",*Command)!=NULL || *ArcName==0) + OutHelp(); + +#ifdef _UNIX + if (GetExt(ArcName)==NULL && (!FileExist(ArcName) || IsDir(GetFileAttr(ArcName)))) + strcat(ArcName,".rar"); +#else + if (GetExt(ArcName)==NULL) + strcat(ArcName,".rar"); +#endif + + if (strchr("AFUMD",*Command)==NULL) + { + StringList ArcMasks; + ArcMasks.AddString(ArcName); + ScanTree Scan(&ArcMasks,Recurse,SaveLinks,SCAN_SKIPDIRS); + FindData FindData; + while (Scan.GetNext(&FindData)==SCAN_SUCCESS) + AddArcName(FindData.Name,FindData.NameW); + } + else + AddArcName(ArcName,NULL); +#endif + + switch(Command[0]) + { + case 'P': + case 'X': + case 'E': + case 'T': + case 'I': + { + CmdExtract Extract; + Extract.DoExtract(this); + } + break; +#if !defined(GUI) && !defined(SILENT) + case 'V': + case 'L': + ListArchive(this); + break; + default: + OutHelp(); +#endif + } +#ifndef GUI + if (!BareOutput) + mprintf("\n"); +#endif +} +#endif + + +void CommandData::AddArcName(char *Name,wchar *NameW) +{ + ArcNames->AddString(Name,NameW); +} + + +bool CommandData::GetArcName(char *Name,wchar *NameW,int MaxSize) +{ + if (!ArcNames->GetString(Name,NameW,NM)) + return(false); + return(true); +} + + +bool CommandData::IsSwitch(int Ch) +{ +#if defined(_WIN_32) || defined(_EMX) + return(Ch=='-' || Ch=='/'); +#else + return(Ch=='-'); +#endif +} + + +#ifndef SFX_MODULE +uint CommandData::GetExclAttr(char *Str) +{ + if (isdigit(*Str)) + return(strtol(Str,NULL,0)); + else + { + uint Attr; + for (Attr=0;*Str;Str++) + switch(toupper(*Str)) + { +#ifdef _UNIX + case 'D': + Attr|=S_IFDIR; + break; + case 'V': + Attr|=S_IFCHR; + break; +#elif defined(_WIN_32) || defined(_EMX) + case 'R': + Attr|=0x1; + break; + case 'H': + Attr|=0x2; + break; + case 'S': + Attr|=0x4; + break; + case 'D': + Attr|=0x10; + break; + case 'A': + Attr|=0x20; + break; +#endif + } + return(Attr); + } +} +#endif + + + + +#ifndef SFX_MODULE +bool CommandData::CheckWinSize() +{ + static int ValidSize[]={ + 0x10000,0x20000,0x40000,0x80000,0x100000,0x200000,0x400000 + }; + for (int I=0;IGetChar()); +} + + +void RangeCoder::InitDecoder(Unpack *UnpackRead) +{ + RangeCoder::UnpackRead=UnpackRead; + + low=code=0; + range=uint(-1); + for (int i=0;i < 4;i++) + code=(code << 8) | GetChar(); +} + + +#define ARI_DEC_NORMALIZE(code,low,range,read) \ +{ \ + while ((low^(low+range))GetChar(); \ + range <<= 8; \ + low <<= 8; \ + } \ +} + + +inline int RangeCoder::GetCurrentCount() +{ + return (code-low)/(range /= SubRange.scale); +} + + +inline uint RangeCoder::GetCurrentShiftCount(uint SHIFT) +{ + return (code-low)/(range >>= SHIFT); +} + + +inline void RangeCoder::Decode() +{ + low += range*SubRange.LowCount; + range *= SubRange.HighCount-SubRange.LowCount; +} diff --git a/unrar/coder.hpp b/unrar/coder.hpp new file mode 100644 index 0000000..f09f911 --- /dev/null +++ b/unrar/coder.hpp @@ -0,0 +1,24 @@ +/**************************************************************************** + * Contents: 'Carryless rangecoder' by Dmitry Subbotin * + ****************************************************************************/ + +const uint TOP=1 << 24, BOT=1 << 15; + +class RangeCoder +{ + public: + void InitDecoder(Unpack *UnpackRead); + inline int GetCurrentCount(); + inline uint GetCurrentShiftCount(uint SHIFT); + inline void Decode(); + inline void PutChar(unsigned int c); + inline unsigned int GetChar(); + + uint low, code, range; + struct SUBRANGE + { + uint LowCount, HighCount, scale; + } SubRange; + + Unpack *UnpackRead; +}; diff --git a/unrar/compress.hpp b/unrar/compress.hpp new file mode 100644 index 0000000..2ba7b23 --- /dev/null +++ b/unrar/compress.hpp @@ -0,0 +1,36 @@ +#ifndef _RAR_COMPRESS_ +#define _RAR_COMPRESS_ + +class ComprDataIO; +class PackingFileTable; + +#define CODEBUFSIZE 0x4000 +#define MAXWINSIZE 0x400000 +#define MAXWINMASK (MAXWINSIZE-1) + +#define LOW_DIST_REP_COUNT 16 + +#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 + +#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */ +#define DC20 48 +#define RC20 28 +#define BC20 19 +#define MC20 257 + +enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ, + CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA}; + + +enum FilterType { + FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9, + FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA, + FILTER_ITANIUM, FILTER_E8E9V2 +}; + +#endif diff --git a/unrar/consio.cpp b/unrar/consio.cpp new file mode 100644 index 0000000..a792e0d --- /dev/null +++ b/unrar/consio.cpp @@ -0,0 +1,291 @@ +#include "rar.hpp" + +#ifndef GUI +#include "log.cpp" +#endif + +static void RawPrint(char *Msg,MESSAGE_TYPE MessageType); + +static MESSAGE_TYPE MsgStream=MSG_STDOUT; +static bool Sound=false; +const int MaxMsgSize=2*NM+2048; + +void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound) +{ + ::MsgStream=MsgStream; + ::Sound=Sound; +} + +#if !defined(GUI) && !defined(SILENT) +void mprintf(const char *fmt,...) +{ + if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY) + return; + safebuf char Msg[MaxMsgSize]; + va_list argptr; + va_start(argptr,fmt); + vsprintf(Msg,fmt,argptr); + RawPrint(Msg,MsgStream); + va_end(argptr); +} +#endif + + +#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 + + +#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 +void Alarm() +{ +#ifndef SFX_MODULE + if (Sound) + putchar('\007'); +#endif +} +#endif + + +#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) + fgets(Str,MaxLength-1,stdin); +#else + strncpy(Str,getpass(""),MaxLength-1); +#endif + RemoveLF(Str); +} +#endif +#endif + + +#if !defined(GUI) && !defined(SILENT) +unsigned int GetKey() +{ +#ifdef SILENT + return(0); +#else + char Str[80]; +#ifdef __GNUC__ + fgets(Str,sizeof(Str),stdin); + return(Str[0]); +#else + File SrcFile; + SrcFile.SetHandleType(FILE_HANDLESTD); + SrcFile.Read(Str,sizeof(Str)); + return(Str[0]); +#endif +#endif +} +#endif + + +#ifndef SILENT +bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength) +{ + Alarm(); + while (true) + { + char PromptStr[256]; +#if defined(_EMX) || defined(_BEOS) + strcpy(PromptStr,St(MAskPswEcho)); +#else + strcpy(PromptStr,St(MAskPsw)); +#endif + if (Type!=PASSWORD_GLOBAL) + { + 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) + { + strcpy(PromptStr,St(MNotMatchPsw)); +/* +#ifdef _WIN_32 + CharToOem(PromptStr,PromptStr); +#endif +*/ + eprintf(PromptStr); + memset(Password,0,MaxLength); + memset(CmpStr,0,sizeof(CmpStr)); + continue; + } + memset(CmpStr,0,sizeof(CmpStr)); + } + break; + } + return(true); +} +#endif + + +#if !defined(GUI) && !defined(SILENT) +int Ask(const char *AskStr) +{ + const int MaxItems=10; + char Item[MaxItems][40]; + int ItemKeyPos[MaxItems],NumItems=0; + + for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_')) + { + char *CurItem=Item[NumItems]; + strncpy(CurItem,NextItem+1,sizeof(Item[0])); + char *EndItem=strchr(CurItem,'_'); + if (EndItem!=NULL) + *EndItem=0; + int KeyPos=0,CurKey; + while ((CurKey=CurItem[KeyPos])!=0) + { + bool Found=false; + for (int I=0;I4 ? "\n":" "):", "); + int KeyPos=ItemKeyPos[I]; + for (int J=0;J>1)^0xEDB88320L : (C>>1); + CRCTab[I]=C; + } +} + + +uint CRC(uint StartCRC,const void *Addr,uint Size) +{ + if (CRCTab[1]==0) + InitCRC(); + byte *Data=(byte *)Addr; +#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) + while (Size>0 && ((long)Data & 7)) + { + StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8); + Size--; + Data++; + } + while (Size>=8) + { + StartCRC^=*(uint32 *)Data; + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC^=*(uint32 *)(Data+4); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); + Data+=8; + Size-=8; + } +#endif + for (int I=0;I>8); + return(StartCRC); +} + +#ifndef SFX_MODULE +ushort OldCRC(ushort StartCRC,const void *Addr,uint Size) +{ + byte *Data=(byte *)Addr; + for (int I=0;I>15))&0xffff; + } + return(StartCRC); +} +#endif diff --git a/unrar/crc.hpp b/unrar/crc.hpp new file mode 100644 index 0000000..47ee7e2 --- /dev/null +++ b/unrar/crc.hpp @@ -0,0 +1,10 @@ +#ifndef _RAR_CRC_ +#define _RAR_CRC_ + +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 diff --git a/unrar/crypt.cpp b/unrar/crypt.cpp new file mode 100644 index 0000000..90a7936 --- /dev/null +++ b/unrar/crypt.cpp @@ -0,0 +1,379 @@ +#include "rar.hpp" + +#ifndef SFX_MODULE +extern uint CRCTab[256]; +#endif + +#define NROUNDS 32 + +#define rol(x,n,xsize) (((x)<<(n)) | ((x)>>(xsize-(n)))) +#define ror(x,n,xsize) (((x)>>(n)) | ((x)<<(xsize-(n)))) + +#define substLong(t) ( (uint)SubstTable[(uint)t&255] | \ + ((uint)SubstTable[(int)(t>> 8)&255]<< 8) | \ + ((uint)SubstTable[(int)(t>>16)&255]<<16) | \ + ((uint)SubstTable[(int)(t>>24)&255]<<24) ) + +CryptKeyCacheItem CryptData::Cache[4]; +int CryptData::CachePos=0; + + +#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) +{ + rin.blockDecrypt(Buf,Size,Buf); +} + + +#ifndef SFX_MODULE +void CryptData::EncryptBlock20(byte *Buf) +{ + uint A,B,C,D,T,TA,TB; +#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT) + A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0]; + B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1]; + C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2]; + D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3]; +#else + uint32 *BufPtr=(uint32 *)Buf; + A=BufPtr[0]^Key[0]; + B=BufPtr[1]^Key[1]; + C=BufPtr[2]^Key[2]; + D=BufPtr[3]^Key[3]; +#endif + for(int I=0;I>8); + Buf[2]=(byte)(C>>16); + Buf[3]=(byte)(C>>24); + D^=Key[1]; + Buf[4]=(byte)D; + Buf[5]=(byte)(D>>8); + Buf[6]=(byte)(D>>16); + Buf[7]=(byte)(D>>24); + A^=Key[2]; + Buf[8]=(byte)A; + Buf[9]=(byte)(A>>8); + Buf[10]=(byte)(A>>16); + Buf[11]=(byte)(A>>24); + B^=Key[3]; + Buf[12]=(byte)B; + Buf[13]=(byte)(B>>8); + Buf[14]=(byte)(B>>16); + Buf[15]=(byte)(B>>24); +#else + BufPtr[0]=C^Key[0]; + BufPtr[1]=D^Key[1]; + BufPtr[2]=A^Key[2]; + BufPtr[3]=B^Key[3]; +#endif + UpdKeys(Buf); +} + + +void CryptData::DecryptBlock20(byte *Buf) +{ + byte InBuf[16]; + uint A,B,C,D,T,TA,TB; +#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT) + A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0]; + B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1]; + C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2]; + D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3]; +#else + uint32 *BufPtr=(uint32 *)Buf; + A=BufPtr[0]^Key[0]; + B=BufPtr[1]^Key[1]; + C=BufPtr[2]^Key[2]; + D=BufPtr[3]^Key[3]; +#endif + memcpy(InBuf,Buf,sizeof(InBuf)); + for(int I=NROUNDS-1;I>=0;I--) + { + T=((C+rol(D,11,32))^Key[I&3]); + TA=A^substLong(T); + T=((D^rol(C,17,32))+Key[I&3]); + TB=B^substLong(T); + A=C; + B=D; + C=TA; + D=TB; + } +#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT) + C^=Key[0]; + Buf[0]=(byte)C; + Buf[1]=(byte)(C>>8); + Buf[2]=(byte)(C>>16); + Buf[3]=(byte)(C>>24); + D^=Key[1]; + Buf[4]=(byte)D; + Buf[5]=(byte)(D>>8); + Buf[6]=(byte)(D>>16); + Buf[7]=(byte)(D>>24); + A^=Key[2]; + Buf[8]=(byte)A; + Buf[9]=(byte)(A>>8); + Buf[10]=(byte)(A>>16); + Buf[11]=(byte)(A>>24); + B^=Key[3]; + Buf[12]=(byte)B; + Buf[13]=(byte)(B>>8); + Buf[14]=(byte)(B>>16); + Buf[15]=(byte)(B>>24); +#else + BufPtr[0]=C^Key[0]; + BufPtr[1]=D^Key[1]; + BufPtr[2]=A^Key[2]; + BufPtr[3]=B^Key[3]; +#endif + UpdKeys(InBuf); +} + + +void CryptData::UpdKeys(byte *Buf) +{ + for (int I=0;I<16;I+=4) + { + Key[0]^=CRCTab[Buf[I]]; + Key[1]^=CRCTab[Buf[I+1]]; + Key[2]^=CRCTab[Buf[I+2]]; + Key[3]^=CRCTab[Buf[I+3]]; + } +} + + +void CryptData::Swap(byte *Ch1,byte *Ch2) +{ + byte Ch=*Ch1; + *Ch1=*Ch2; + *Ch2=Ch; +} +#endif + + +void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly) +{ + if (*Password==0) + return; + if (OldOnly) + { +#ifndef SFX_MODULE + 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 + int PswLength=strlen(Password); + memcpy(SubstTable,InitSubstTable,sizeof(SubstTable)); + for (int J=0;J<256;J++) + for (int I=0;I>8); + PswNum[2]=(byte)(I>>16); + hash_process( &c, PswNum, 3); + if (I%(HashRounds/16)==0) + { + hash_context tempc=c; + uint32 digest[5]; + hash_final( &tempc, digest); + AESInit[I/(HashRounds/16)]=(byte)digest[4]; + } + } + uint32 digest[5]; + hash_final( &c, digest); + for (int I=0;I<4;I++) + for (int J=0;J<4;J++) + AESKey[I*4+J]=(byte)(digest[I]>>(J*8)); + + strcpy(Cache[CachePos].Password,Password); + if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true) + memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE); + memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey)); + memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit)); + CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0])); + } + rin.init(Encrypt ? Rijndael::Encrypt : Rijndael::Decrypt,AESKey,AESInit); +} + + +#ifndef SFX_MODULE +void CryptData::SetOldKeys(char *Password) +{ + uint PswCRC=CRC(0xffffffff,Password,strlen(Password)); + OldKey[0]=PswCRC&0xffff; + OldKey[1]=(PswCRC>>16)&0xffff; + OldKey[2]=OldKey[3]=0; + PN1=PN2=PN3=0; + byte Ch; + while ((Ch=*Password)!=0) + { + PN1+=Ch; + PN2^=Ch; + PN3+=Ch; + PN3=(byte)rol(PN3,1,8); + OldKey[2]^=Ch^CRCTab[Ch]; + OldKey[3]+=Ch+(CRCTab[Ch]>>16); + Password++; + } +} + + +void CryptData::SetAV15Encryption() +{ + OldKey[0]=0x4765; + OldKey[1]=0x9021; + OldKey[2]=0x7382; + OldKey[3]=0x5215; +} + + +void CryptData::SetCmt13Encryption() +{ + PN1=0; + PN2=7; + PN3=77; +} + + +void CryptData::Crypt(byte *Data,uint Count,int Method) +{ + if (Method==OLD_DECODE) + Decode13(Data,Count); + else + if (Method==OLD_ENCODE) + Encode13(Data,Count); + else + Crypt15(Data,Count); +} + + +void CryptData::Encode13(byte *Data,uint Count) +{ + while (Count--) + { + PN2+=PN3; + PN1+=PN2; + *Data+=PN1; + Data++; + } +} + + +void CryptData::Decode13(byte *Data,uint Count) +{ + while (Count--) + { + PN2+=PN3; + PN1+=PN2; + *Data-=PN1; + Data++; + } +} + + +void CryptData::Crypt15(byte *Data,uint Count) +{ + while (Count--) + { + OldKey[0]+=0x1234; + OldKey[1]^=CRCTab[(OldKey[0] & 0x1fe)>>1]; + OldKey[2]-=CRCTab[(OldKey[0] & 0x1fe)>>1]>>16; + OldKey[0]^=OldKey[2]; + OldKey[3]=ror(OldKey[3]&0xffff,1,16)^OldKey[1]; + OldKey[3]=ror(OldKey[3]&0xffff,1,16); + OldKey[0]^=OldKey[3]; + *Data^=(byte)(OldKey[0]>>8); + Data++; + } +} +#endif + + diff --git a/unrar/crypt.hpp b/unrar/crypt.hpp new file mode 100644 index 0000000..809d76a --- /dev/null +++ b/unrar/crypt.hpp @@ -0,0 +1,60 @@ +#ifndef _RAR_CRYPT_ +#define _RAR_CRYPT_ + +enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 }; + +struct CryptKeyCacheItem +{ +#ifndef _SFX_RTL_ + CryptKeyCacheItem() + { + *Password=0; + } + + ~CryptKeyCacheItem() + { + memset(AESKey,0,sizeof(AESKey)); + memset(AESInit,0,sizeof(AESInit)); + memset(Password,0,sizeof(Password)); + } +#endif + byte AESKey[16],AESInit[16]; + char Password[MAXPASSWORD]; + bool SaltPresent; + byte Salt[SALT_SIZE]; +}; + +class CryptData +{ + private: + void Encode13(byte *Data,uint Count); + void Decode13(byte *Data,uint Count); + void Crypt15(byte *Data,uint Count); + void UpdKeys(byte *Buf); + void Swap(byte *Ch1,byte *Ch2); + void SetOldKeys(char *Password); + + Rijndael rin; + + byte SubstTable[256]; + uint Key[4]; + ushort OldKey[4]; + byte PN1,PN2,PN3; + + byte AESKey[16],AESInit[16]; + + static CryptKeyCacheItem Cache[4]; + static int CachePos; + public: + void SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly=false); + void SetAV15Encryption(); + void SetCmt13Encryption(); + void EncryptBlock20(byte *Buf); + void DecryptBlock20(byte *Buf); + void EncryptBlock(byte *Buf,int Size); + void DecryptBlock(byte *Buf,int Size); + void Crypt(byte *Data,uint Count,int Method); + static void SetSalt(byte *Salt,int SaltSize); +}; + +#endif diff --git a/unrar/dll.cpp b/unrar/dll.cpp new file mode 100644 index 0000000..b879a4b --- /dev/null +++ b/unrar/dll.cpp @@ -0,0 +1,354 @@ +#include "rar.hpp" +#include "dll.hpp" + +static int RarErrorToDll(int ErrCode); + +struct DataSet +{ + CommandData Cmd; + CmdExtract Extract; + Archive Arc; + int OpenMode; + int HeaderSize; + + DataSet():Arc(&Cmd) {}; +}; + + +HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r) +{ + RAROpenArchiveDataEx rx; + memset(&rx,0,sizeof(rx)); + rx.ArcName=r->ArcName; + rx.OpenMode=r->OpenMode; + rx.CmtBuf=r->CmtBuf; + rx.CmtBufSize=r->CmtBufSize; + HANDLE hArc=RAROpenArchiveEx(&rx); + r->OpenResult=rx.OpenResult; + r->CmtSize=rx.CmtSize; + r->CmtState=rx.CmtState; + return(hArc); +} + + +HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) +{ + try + { + r->OpenResult=0; + DataSet *Data=new DataSet; + Data->OpenMode=r->OpenMode; + Data->Cmd.FileArgs->AddString("*"); + + char an[NM]; + if (r->ArcName==NULL && r->ArcNameW!=NULL) + { + WideToChar(r->ArcNameW,an,NM); + r->ArcName=an; + } + + Data->Cmd.AddArcName(r->ArcName,r->ArcNameW); + Data->Cmd.Overwrite=OVERWRITE_ALL; + Data->Cmd.VersionControl=1; + if (!Data->Arc.Open(r->ArcName,r->ArcNameW)) + { + delete Data; + r->OpenResult=ERAR_EOPEN; + return(NULL); + } + if (!Data->Arc.IsArchive(false)) + { + delete Data; + r->OpenResult=ERAR_BAD_ARCHIVE; + return(NULL); + } + r->Flags=Data->Arc.NewMhd.Flags; + Array CmtData; + if (r->CmtBufSize!=0 && Data->Arc.GetComment(CmtData)) + { + 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; + if (Data->Arc.Signed) + r->Flags|=0x20; + Data->Extract.ExtractArchiveInit(&Data->Cmd,Data->Arc); + return((HANDLE)Data); + } + catch (int ErrCode) + { + r->OpenResult=RarErrorToDll(ErrCode); + return(NULL); + } +} + + +int PASCAL RARCloseArchive(HANDLE hArcData) +{ + DataSet *Data=(DataSet *)hArcData; + bool Success=Data==NULL ? false:Data->Arc.Close(); + delete Data; + return(Success ? 0:ERAR_ECLOSE); +} + + +int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D) +{ + 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)) + { + if (RARProcessFile(hArcData,RAR_SKIP,NULL,NULL)==0) + return(RARReadHeader(hArcData,D)); + } + 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); +} + + +int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D) +{ + 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(RARReadHeaderEx(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)) + { + if (RARProcessFile(hArcData,RAR_SKIP,NULL,NULL)==0) + return(RARReadHeaderEx(hArcData,D)); + } + 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=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; + } + catch (int ErrCode) + { + return(RarErrorToDll(ErrCode)); + } + return(0); +} + + +int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW) +{ + DataSet *Data=(DataSet *)hArcData; + try + { + Data->Cmd.DllError=0; + if (Data->OpenMode==RAR_OM_LIST || Operation==RAR_SKIP && !Data->Arc.Solid) + { + 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(0); + } + else + return(ERAR_EOPEN); + Data->Arc.SeekToNext(); + } + else + { + Data->Cmd.DllOpMode=Operation; + + if (DestPath!=NULL || DestName!=NULL) + { +#ifdef _WIN_32 + OemToChar(NullToEmpty(DestPath),Data->Cmd.ExtrPath); +#else + strcpy(Data->Cmd.ExtrPath,NullToEmpty(DestPath)); +#endif + AddEndSlash(Data->Cmd.ExtrPath); +#ifdef _WIN_32 + OemToChar(NullToEmpty(DestName),Data->Cmd.DllDestName); +#else + strcpy(Data->Cmd.DllDestName,NullToEmpty(DestName)); +#endif + } + else + { + *Data->Cmd.ExtrPath=0; + *Data->Cmd.DllDestName=0; + } + + 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; + } + + strcpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? "X":"T"); + Data->Cmd.Test=Operation!=RAR_EXTRACT; + bool Repeat=false; + Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat); + + while (Data->Arc.ReadHeader()!=0 && Data->Arc.GetHeaderType()==NEWSUB_HEAD) + { + Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat); + Data->Arc.SeekToNext(); + } + Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET); + } + } + catch (int ErrCode) + { + return(RarErrorToDll(ErrCode)); + } + return(Data->Cmd.DllError); +} + + +int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName) +{ + 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)); +} + + +void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc) +{ + DataSet *Data=(DataSet *)hArcData; + Data->Cmd.ChangeVolProc=ChangeVolProc; +} + + +void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData) +{ + DataSet *Data=(DataSet *)hArcData; + Data->Cmd.Callback=Callback; + Data->Cmd.UserData=UserData; +} + + +void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc) +{ + DataSet *Data=(DataSet *)hArcData; + Data->Cmd.ProcessDataProc=ProcessDataProc; +} + + +void PASCAL RARSetPassword(HANDLE hArcData,char *Password) +{ + DataSet *Data=(DataSet *)hArcData; + strncpy(Data->Cmd.Password,Password,sizeof(Data->Cmd.Password)); +} + + +int PASCAL RARGetDllVersion() +{ + return(RAR_DLL_VERSION); +} + + +static int RarErrorToDll(int ErrCode) +{ + switch(ErrCode) + { + case FATAL_ERROR: + return(ERAR_EREAD); + case CRC_ERROR: + return(ERAR_BAD_DATA); + case WRITE_ERROR: + return(ERAR_EWRITE); + case OPEN_ERROR: + return(ERAR_EOPEN); + case CREATE_ERROR: + return(ERAR_ECREATE); + case MEMORY_ERROR: + return(ERAR_NO_MEMORY); + case SUCCESS: + return(0); + default: + return(ERAR_UNKNOWN); + } +} diff --git a/unrar/dll.def b/unrar/dll.def new file mode 100644 index 0000000..660f69b --- /dev/null +++ b/unrar/dll.def @@ -0,0 +1,12 @@ +EXPORTS + RAROpenArchive + RAROpenArchiveEx + RARCloseArchive + RARReadHeader + RARReadHeaderEx + RARProcessFile + RARSetCallback + RARSetChangeVolProc + RARSetProcessDataProc + RARSetPassword + RARGetDllVersion diff --git a/unrar/dll.hpp b/unrar/dll.hpp new file mode 100644 index 0000000..6b3a26d --- /dev/null +++ b/unrar/dll.hpp @@ -0,0 +1,137 @@ +#ifndef _UNRAR_DLL_ +#define _UNRAR_DLL_ + +#define ERAR_END_ARCHIVE 10 +#define ERAR_NO_MEMORY 11 +#define ERAR_BAD_DATA 12 +#define ERAR_BAD_ARCHIVE 13 +#define ERAR_UNKNOWN_FORMAT 14 +#define ERAR_EOPEN 15 +#define ERAR_ECREATE 16 +#define ERAR_ECLOSE 17 +#define ERAR_EREAD 18 +#define ERAR_EWRITE 19 +#define ERAR_SMALL_BUF 20 +#define ERAR_UNKNOWN 21 + +#define RAR_OM_LIST 0 +#define RAR_OM_EXTRACT 1 + +#define RAR_SKIP 0 +#define RAR_TEST 1 +#define RAR_EXTRACT 2 + +#define RAR_VOL_ASK 0 +#define RAR_VOL_NOTIFY 1 + +#define RAR_DLL_VERSION 4 + +#ifdef _UNIX +#define CALLBACK +#define PASCAL +#define LONG long +#define HANDLE void * +#define UINT unsigned int +#endif + +struct RARHeaderData +{ + char ArcName[260]; + char FileName[260]; + unsigned int Flags; + unsigned int PackSize; + unsigned int UnpSize; + unsigned int HostOS; + unsigned int FileCRC; + unsigned int FileTime; + unsigned int UnpVer; + unsigned int Method; + unsigned int FileAttr; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; +}; + + +struct RARHeaderDataEx +{ + char ArcName[1024]; + wchar_t ArcNameW[1024]; + char FileName[1024]; + wchar_t FileNameW[1024]; + unsigned int Flags; + unsigned int PackSize; + unsigned int PackSizeHigh; + unsigned int UnpSize; + unsigned int UnpSizeHigh; + unsigned int HostOS; + unsigned int FileCRC; + unsigned int FileTime; + unsigned int UnpVer; + unsigned int Method; + unsigned int FileAttr; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; + unsigned int Reserved[1024]; +}; + + +struct RAROpenArchiveData +{ + char *ArcName; + unsigned int OpenMode; + unsigned int OpenResult; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; +}; + +struct RAROpenArchiveDataEx +{ + char *ArcName; + wchar_t *ArcNameW; + unsigned int OpenMode; + unsigned int OpenResult; + char *CmtBuf; + 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 +}; + +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); + +#ifdef __cplusplus +extern "C" { +#endif + +HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData); +HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData); +int PASCAL RARCloseArchive(HANDLE hArcData); +int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData); +int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData); +int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName); +int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName); +void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData); +void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc); +void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc); +void PASCAL RARSetPassword(HANDLE hArcData,char *Password); +int PASCAL RARGetDllVersion(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/unrar/encname.cpp b/unrar/encname.cpp new file mode 100644 index 0000000..6f57cd9 --- /dev/null +++ b/unrar/encname.cpp @@ -0,0 +1,57 @@ +#include "rar.hpp" + +EncodeFileName::EncodeFileName() +{ + Flags=0; + FlagBits=0; + FlagsPos=0; + DestSize=0; +} + + + + +void EncodeFileName::Decode(char *Name,byte *EncName,int EncSize,wchar *NameW, + int MaxDecSize) +{ + int EncPos=0,DecPos=0; + byte HighByte=EncName[EncPos++]; + while (EncPos>6) + { + case 0: + NameW[DecPos++]=EncName[EncPos++]; + break; + case 1: + NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8); + break; + case 2: + NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8); + EncPos+=2; + break; + case 3: + { + int Length=EncName[EncPos++]; + if (Length & 0x80) + { + byte Correction=EncName[EncPos++]; + for (Length=(Length&0x7f)+2;Length>0 && DecPos0 && DecPosMAXPATH) + { + Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAXPATH); + } + } +#endif + SysErrMsg(); +#endif +} + + +void ErrorHandler::ReadErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + ErrMsg(ArcName,St(MErrRead),FileName); + SysErrMsg(); +#endif +} + + +void ErrorHandler::WriteErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + ErrMsg(ArcName,St(MErrWrite),FileName); + SysErrMsg(); +#endif +} + + +void ErrorHandler::Exit(int ExitCode) +{ +#ifndef SFX_MODULE + Alarm(); +#endif + Throw(ExitCode); +} + + +#ifndef GUI +void ErrorHandler::ErrMsg(const char *ArcName,const char *fmt,...) +{ + safebuf char Msg[NM+1024]; + va_list argptr; + va_start(argptr,fmt); + vsprintf(Msg,fmt,argptr); + va_end(argptr); +#ifdef _WIN_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 WARNING: + case USER_BREAK: + if (ExitCode==SUCCESS) + ExitCode=Code; + break; + case FATAL_ERROR: + if (ExitCode==SUCCESS || ExitCode==WARNING) + ExitCode=FATAL_ERROR; + break; + default: + ExitCode=Code; + break; + } + ErrCount++; +} + + +#if !defined(GUI) && !defined(_SFX_RTL_) +#ifdef _WIN_32 +BOOL __stdcall ProcessSignal(DWORD SigType) +#else +#if defined(__sun) +extern "C" +#endif +void _stdfunction ProcessSignal(int SigType) +#endif +{ +#ifdef _WIN_32 + if (SigType==CTRL_LOGOFF_EVENT) + return(TRUE); +#endif + UserBreak=true; + mprintf(St(MBreak)); + for (int I=0;!File::RemoveCreated() && I<3;I++) + { +#ifdef _WIN_32 + Sleep(100); +#endif + } +#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE) + ExtRes.UnloadDLL(); +#endif + exit(USER_BREAK); +#ifdef _WIN_32 + return(TRUE); +#endif +} +#endif + + +void ErrorHandler::SetSignalHandlers(bool Enable) +{ + EnableBreak=Enable; +#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(int Code) +{ + if (Code==USER_BREAK && !EnableBreak) + return; + ErrHandler.SetErrorCode(Code); +#ifdef ALLOW_EXCEPTIONS + throw Code; +#else + File::RemoveCreated(); + exit(Code); +#endif +} + + +void ErrorHandler::SysErrMsg() +{ +#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SILENT) + #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)) + { + ERRCHAR *CurMsg=lpMsgBuf; + while (CurMsg!=NULL) + { + 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; + } + } + LocalFree( lpMsgBuf ); +#endif +} diff --git a/unrar/errhnd.hpp b/unrar/errhnd.hpp new file mode 100644 index 0000000..9e27622 --- /dev/null +++ b/unrar/errhnd.hpp @@ -0,0 +1,61 @@ +#ifndef _RAR_ERRHANDLER_ +#define _RAR_ERRHANDLER_ + +#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 { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR, + OPEN_ERROR,USER_ERROR,MEMORY_ERROR,CREATE_ERROR,USER_BREAK=255}; + +class ErrorHandler +{ + private: + void ErrMsg(const char *ArcName,const char *fmt,...); + + int ExitCode; + int ErrCount; + bool EnableBreak; + bool Silent; + bool DoShutdown; + public: + ErrorHandler(); + void Clean(); + void MemoryError(); + 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 MemoryErrorMsg(); + 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(int Code); + void SetSilent(bool Mode) {Silent=Mode;}; + void SetShutdown(bool Mode) {DoShutdown=Mode;}; + void SysErrMsg(); +}; + +#endif diff --git a/unrar/extinfo.cpp b/unrar/extinfo.cpp new file mode 100644 index 0000000..13239fe --- /dev/null +++ b/unrar/extinfo.cpp @@ -0,0 +1,76 @@ +#include "rar.hpp" + +#ifdef _WIN_32 +#include "win32acl.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" +#endif + + + +#ifndef SFX_MODULE +void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW) +{ + switch(Arc.SubBlockHead.SubType) + { +#if defined(_EMX) && !defined(_DJGPP) + case EA_HEAD: + if (Cmd->ProcessEA) + ExtractOS2EA(Arc,Name); + break; +#endif +#ifdef _UNIX + case UO_HEAD: + if (Cmd->ProcessOwners) + ExtractUnixOwner(Arc,Name); + break; +#endif +#ifdef _BEOS + case BEEA_HEAD: + if (Cmd->ProcessEA) + ExtractBeEA(Arc,Name); + break; +#endif +#ifdef _WIN_32 + case NTACL_HEAD: + if (Cmd->ProcessOwners) + ExtractACL(Arc,Name,NameW); + break; + case STREAM_HEAD: + ExtractStreams(Arc,Name,NameW); + break; +#endif + } +} +#endif + + +void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW) +{ +#if defined(_EMX) && !defined(_DJGPP) + if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_OS2EA)) + ExtractOS2EANew(Arc,Name); +#endif +#ifdef _UNIX + if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER)) + ExtractUnixOwnerNew(Arc,Name); +#endif +#ifdef _BEOS + if (Cmd->ProcessEA && Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER)) + ExtractUnixOwnerNew(Arc,Name); +#endif +#ifdef _WIN_32 + if (Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL)) + ExtractACLNew(Arc,Name,NameW); + if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM)) + ExtractStreamsNew(Arc,Name,NameW); +#endif +} diff --git a/unrar/extinfo.hpp b/unrar/extinfo.hpp new file mode 100644 index 0000000..db7cea5 --- /dev/null +++ b/unrar/extinfo.hpp @@ -0,0 +1,8 @@ +#ifndef _RAR_EXTINFO_ +#define _RAR_EXTINFO_ + + +void SetExtraInfo(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW); +void SetExtraInfoNew(CommandData *Cmd,Archive &Arc,char *Name,wchar *NameW); + +#endif diff --git a/unrar/extract.cpp b/unrar/extract.cpp new file mode 100644 index 0000000..c94967a --- /dev/null +++ b/unrar/extract.cpp @@ -0,0 +1,821 @@ +#include "rar.hpp" + +CmdExtract::CmdExtract() +{ + TotalFileCount=0; + *Password=0; + Unp=new Unpack(&DataIO); + Unp->Init(NULL); +} + + +CmdExtract::~CmdExtract() +{ + delete Unp; + memset(Password,0,sizeof(Password)); +} + + +void CmdExtract::DoExtract(CommandData *Cmd) +{ + PasswordCancelled=false; + DataIO.SetCurrentCommand(*Cmd->Command); + + struct FindData FD; + while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName))) + if (FindFile::FastFind(ArcName,ArcNameW,&FD)) + DataIO.TotalArcSize+=FD.Size; + Cmd->ArcNames->Rewind(); + while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName))) + { + while (ExtractArchive(Cmd)==EXTRACT_ARC_REPEAT) + ; + if (FindFile::FastFind(ArcName,ArcNameW,&FD)) + DataIO.ProcessedArcSize+=FD.Size; + } + + if (TotalFileCount==0 && *Cmd->Command!='I') + { + if (!PasswordCancelled) + { + mprintf(St(MExtrNoFiles)); + } + ErrHandler.SetErrorCode(WARNING); + } +#ifndef GUI + else + if (!Cmd->DisableDone) + if (*Cmd->Command=='I') + mprintf(St(MDone)); + else + if (ErrHandler.GetErrorCount()==0) + mprintf(St(MExtrAllOk)); + else + mprintf(St(MExtrTotalErr),ErrHandler.GetErrorCount()); +#endif +} + + +void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc) +{ + DataIO.UnpArcSize=Arc.FileLength(); + + FileCount=0; + MatchedArgs=0; +#ifndef SFX_MODULE + FirstFile=true; +#endif + + if (*Cmd->Password!=0) + strcpy(Password,Cmd->Password); + PasswordAll=(*Cmd->Password!=0); + + DataIO.UnpVolume=false; + + PrevExtracted=false; + SignatureFound=false; + AllMatchesExact=true; + ReconstructDone=false; +} + + +EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd) +{ + Archive Arc(Cmd); + if (!Arc.WOpen(ArcName,ArcNameW)) + { + ErrHandler.SetErrorCode(OPEN_ERROR); + return(EXTRACT_ARC_NEXT); + } + + if (!Arc.IsArchive(true)) + { +#ifndef GUI + mprintf(St(MNotRAR),ArcName); +#endif + if (CmpExt(ArcName,"rar")) + ErrHandler.SetErrorCode(WARNING); + return(EXTRACT_ARC_NEXT); + } + + if (!Arc.IsOpened()) + return(EXTRACT_ARC_NEXT); + +#ifndef SFX_MODULE + if (Arc.Volume && Arc.NotFirstVolume) + { + char FirstVolName[NM]; + + VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)); + if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) && + Cmd->ArcNames->Search(FirstVolName,NULL,false)) + return(EXTRACT_ARC_NEXT); + } +#endif + ExtractArchiveInit(Cmd,Arc); + + if (*Cmd->Command=='T' || *Cmd->Command=='I') + Cmd->Test=true; + +#ifndef GUI + if (*Cmd->Command=='I') + Cmd->DisablePercentage=true; + else + if (Cmd->Test) + mprintf(St(MExtrTest),ArcName); + else + mprintf(St(MExtracting),ArcName); +#endif + + Arc.ViewComment(); + + while (1) + { + int Size=Arc.ReadHeader(); + bool Repeat=false; + if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat)) + if (Repeat) + { + return(EXTRACT_ARC_REPEAT); + } + else + break; + } + return(EXTRACT_ARC_NEXT); +} + + +bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,bool &Repeat) +{ + char Command=*Cmd->Command; + if (HeaderSize<=0) + if (DataIO.UnpVolume) + { +#ifdef NOVOLUME + return(false); +#else + if (!MergeArchive(Arc,NULL,false,Command)) + { + ErrHandler.SetErrorCode(WARNING); + return(false); + } + SignatureFound=false; +#endif + } + else + return(false); + int HeadType=Arc.GetHeaderType(); + if (HeadType!=FILE_HEAD) + { + if (HeadType==AV_HEAD || HeadType==SIGN_HEAD) + SignatureFound=true; +#if !defined(SFX_MODULE) && !defined(_WIN_CE) + if (HeadType==SUB_HEAD && PrevExtracted) + SetExtraInfo(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL); +#endif + if (HeadType==NEWSUB_HEAD) + { + if (Arc.SubHead.CmpName(SUBHEAD_TYPE_AV)) + SignatureFound=true; +#if !defined(NOSUBBLOCKS) && !defined(_WIN_CE) + if (PrevExtracted) + SetExtraInfoNew(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL); +#endif + } + if (HeadType==ENDARC_HEAD) + if (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME) + { +#ifndef NOVOLUME + if (!MergeArchive(Arc,NULL,false,Command)) + { + ErrHandler.SetErrorCode(WARNING); + return(false); + } + SignatureFound=false; +#endif + Arc.Seek(Arc.CurBlockPos,SEEK_SET); + return(true); + } + else + return(false); + Arc.SeekToNext(); + return(true); + } + PrevExtracted=false; + + if (SignatureFound || + !Cmd->Recurse && MatchedArgs>=Cmd->FileArgs->ItemsCount() && + AllMatchesExact) + return(false); + + char ArcFileName[NM]; + IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName); + strcpy(ArcFileName,Arc.NewLhd.FileName); + + wchar ArcFileNameW[NM]; + *ArcFileNameW=0; + + int MatchType=MATCH_WILDSUBPATH; + + bool EqualNames=false; + int MatchNumber=Cmd->IsProcessFile(Arc.NewLhd,&EqualNames,MatchType); + bool ExactMatch=MatchNumber!=0; +#if !defined(SFX_MODULE) && !defined(_WIN_CE) + if (Cmd->ExclPath==EXCL_BASEPATH) + { + *Cmd->ArcPath=0; + if (ExactMatch) + { + Cmd->FileArgs->Rewind(); + if (Cmd->FileArgs->GetString(Cmd->ArcPath,NULL,sizeof(Cmd->ArcPath),MatchNumber-1)) + *PointToName(Cmd->ArcPath)=0; + } + } +#endif + if (ExactMatch && !EqualNames) + AllMatchesExact=false; + +#ifdef UNICODE_SUPPORTED + bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled(); +#else + bool WideName=false; +#endif + +#ifdef _APPLE + if (WideName) + { + WideToUtf(Arc.NewLhd.FileNameW,ArcFileName,sizeof(ArcFileName)); + WideName=false; + } +#endif + + wchar *DestNameW=WideName ? DestFileNameW:NULL; + +#ifdef UNICODE_SUPPORTED + if (WideName) + { + ConvertPath(Arc.NewLhd.FileNameW,ArcFileNameW); + char Name[NM]; + if (WideToChar(ArcFileNameW,Name) && IsNameUsable(Name)) + strcpy(ArcFileName,Name); + } +#endif + + ConvertPath(ArcFileName,ArcFileName); + + if (Arc.IsArcLabel()) + return(true); + + if (Arc.NewLhd.Flags & LHD_VERSION) + { + if (Cmd->VersionControl!=1 && !EqualNames) + { + if (Cmd->VersionControl==0) + ExactMatch=false; + int Version=ParseVersionFileName(ArcFileName,ArcFileNameW,false); + if (Cmd->VersionControl-1==Version) + ParseVersionFileName(ArcFileName,ArcFileNameW,true); + else + ExactMatch=false; + } + } + else + if (!Arc.IsArcDir() && Cmd->VersionControl>1) + ExactMatch=false; + + Arc.ConvertAttributes(); + +#ifndef SFX_MODULE + if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile) + { + char CurVolName[NM]; + strcpy(CurVolName,ArcName); + + VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)); + if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName)) + { + *ArcNameW=0; + Repeat=true; + return(false); + } +#if !defined(RARDLL) && !defined(_WIN_CE) + if (!ReconstructDone) + { + ReconstructDone=true; + + RecVolumes RecVol; + if (RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true)) + { + Repeat=true; + return(false); + } + } +#endif + strcpy(ArcName,CurVolName); + } +#endif + DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER); + DataIO.NextVolumeMissing=false; + + Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET); + + bool TestMode=false; + bool ExtrFile=false; + bool SkipSolid=false; + +#ifndef SFX_MODULE + if (FirstFile && (ExactMatch || Arc.Solid) && (Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/))!=0) + { + if (ExactMatch) + { + Log(Arc.FileName,St(MUnpCannotMerge),ArcFileName); +#ifdef RARDLL + Cmd->DllError=ERAR_BAD_DATA; +#endif + } + ExactMatch=false; + } + + FirstFile=false; +#endif + + if (ExactMatch || (SkipSolid=Arc.Solid)!=0) + { + if (Arc.NewLhd.Flags & LHD_PASSWORD) +#ifndef RARDLL + if (*Password==0) +#endif + { +#ifdef RARDLL + if (*Cmd->Password==0) + if (Cmd->Callback==NULL || + Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1) + return(false); + strcpy(Password,Cmd->Password); + +#else + if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password))) + { + PasswordCancelled=true; + return(false); + } +#endif + } +#if !defined(GUI) && !defined(SILENT) + else + if (!PasswordAll && (!Arc.Solid || Arc.NewLhd.UnpVer>=20 && (Arc.NewLhd.Flags & LHD_SOLID)==0)) + { + eprintf(St(MUseCurPsw),ArcFileName); + switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll))) + { + case -1: + ErrHandler.Exit(USER_BREAK); + case 2: + if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password))) + { + return(false); + } + break; + case 3: + PasswordAll=true; + break; + } + } +#endif + +#ifndef SFX_MODULE + if (*Cmd->ExtrPath==0 && *Cmd->ExtrPathW!=0) + WideToChar(Cmd->ExtrPathW,DestFileName); + else +#endif + strcpy(DestFileName,Cmd->ExtrPath); + + +#ifndef SFX_MODULE + if (Cmd->AppendArcNameToPath) + { + strcat(DestFileName,PointToName(Arc.FileName)); + SetExt(DestFileName,NULL); + AddEndSlash(DestFileName); + } +#endif + + char *ExtrName=ArcFileName; + + bool EmptyName=false; +#ifndef SFX_MODULE + int Length=strlen(Cmd->ArcPath); + if (Length>1 && IsPathDiv(Cmd->ArcPath[Length-1]) && + strlen(ArcFileName)==Length-1) + Length--; + if (Length>0 && strnicomp(Cmd->ArcPath,ArcFileName,Length)==0) + { + ExtrName+=Length; + while (*ExtrName==CPATHDIVIDER) + ExtrName++; + if (*ExtrName==0) + EmptyName=true; + } +#endif + + bool AbsPaths=Cmd->ExclPath==EXCL_ABSPATH && Command=='X' && IsDriveDiv(':'); + if (AbsPaths) + *DestFileName=0; + + if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH) + strcat(DestFileName,PointToName(ExtrName)); + else + strcat(DestFileName,ExtrName); + + if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2])) + DestFileName[1]=':'; + +#ifndef SFX_MODULE + if (!WideName && *Cmd->ExtrPathW!=0) + { + DestNameW=DestFileNameW; + WideName=true; + CharToWide(ArcFileName,ArcFileNameW); + } +#endif + + if (WideName) + { + if (*Cmd->ExtrPathW!=0) + strcpyw(DestFileNameW,Cmd->ExtrPathW); + else + CharToWide(Cmd->ExtrPath,DestFileNameW); + +#ifndef SFX_MODULE + if (Cmd->AppendArcNameToPath) + { + wchar FileNameW[NM]; + if (*Arc.FileNameW!=0) + strcpyw(FileNameW,Arc.FileNameW); + else + CharToWide(Arc.FileName,FileNameW); + strcatw(DestFileNameW,PointToName(FileNameW)); + SetExt(DestFileNameW,NULL); + AddEndSlash(DestFileNameW); + } +#endif + wchar *ExtrNameW=ArcFileNameW; +#ifndef SFX_MODULE + if (Length>0) + { + wchar ArcPathW[NM]; + CharToWide(Cmd->ArcPath,ArcPathW); + Length=strlenw(ArcPathW); + } + ExtrNameW+=Length; + while (*ExtrNameW==CPATHDIVIDER) + ExtrNameW++; +#endif + + if (AbsPaths) + *DestFileNameW=0; + + if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH) + strcatw(DestFileNameW,PointToName(ExtrNameW)); + else + strcatw(DestFileNameW,ExtrNameW); + + if (AbsPaths && DestFileNameW[1]=='_' && IsPathDiv(DestFileNameW[2])) + DestFileNameW[1]=':'; + } + else + *DestFileNameW=0; + + ExtrFile=!SkipSolid && !EmptyName/* && *ExtrName*/; + if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X')) + { + struct FindData FD; + if (FindFile::FastFind(DestFileName,DestNameW,&FD)) + { + if (FD.mtime >= Arc.NewLhd.mtime) + ExtrFile=false; + } + else + if (Cmd->FreshFiles) + ExtrFile=false; + } + +#ifdef RARDLL + if (*Cmd->DllDestName) + { + strncpy(DestFileName,Cmd->DllDestName,sizeof(DestFileName)); + *DestFileNameW=0; + if (Cmd->DllOpMode!=RAR_EXTRACT) + ExtrFile=false; + } + if (*Cmd->DllDestNameW) + { + strncpyw(DestFileNameW,Cmd->DllDestNameW,sizeof(DestFileNameW)/sizeof(DestFileNameW[0])); + DestNameW=DestFileNameW; + if (Cmd->DllOpMode!=RAR_EXTRACT) + ExtrFile=false; + } +#endif + +#ifdef SFX_MODULE + if (Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.Method!=0x30) +#else + if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER) +#endif + { +#ifndef SILENT + Log(Arc.FileName,St(MUnknownMeth),ArcFileName); +#ifndef SFX_MODULE + Log(Arc.FileName,St(MVerRequired),Arc.NewLhd.UnpVer/10,Arc.NewLhd.UnpVer%10); +#endif +#endif + ExtrFile=false; + ErrHandler.SetErrorCode(WARNING); +#ifdef RARDLL + Cmd->DllError=ERAR_UNKNOWN_FORMAT; +#endif + } + + File CurFile; + + if (!IsLink(Arc.NewLhd.FileAttr)) + if (Arc.IsArcDir()) + { + if (!ExtrFile || Command=='P' || Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH) + return(true); + if (SkipSolid) + { +#ifndef GUI + mprintf(St(MExtrSkipFile),ArcFileName); +#endif + return(true); + } + TotalFileCount++; + if (Cmd->Test) + { +#ifndef GUI + mprintf(St(MExtrTestFile),ArcFileName); + mprintf(" %s",St(MOk)); +#endif + return(true); + } + MKDIR_CODE MDCode=MakeDir(DestFileName,DestNameW,Arc.NewLhd.FileAttr); + bool DirExist=false; + if (MDCode!=MKDIR_SUCCESS) + { + DirExist=FileExist(DestFileName,DestNameW); + if (DirExist && !IsDir(GetFileAttr(DestFileName,DestNameW))) + { + bool UserReject; + FileCreate(Cmd,NULL,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime); + DirExist=false; + } + CreatePath(DestFileName,DestNameW,true); + MDCode=MakeDir(DestFileName,DestNameW,Arc.NewLhd.FileAttr); + } + if (MDCode==MKDIR_SUCCESS) + { +#ifndef GUI + mprintf(St(MCreatDir),DestFileName); + mprintf(" %s",St(MOk)); +#endif + PrevExtracted=true; + } + else + if (DirExist) + { + SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr); + PrevExtracted=true; + } + else + { + Log(Arc.FileName,St(MExtrErrMkDir),DestFileName); + ErrHandler.SysErrMsg(); +#ifdef RARDLL + Cmd->DllError=ERAR_ECREATE; +#endif + ErrHandler.SetErrorCode(CREATE_ERROR); + } + if (PrevExtracted) + { +#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) + if (Cmd->SetCompressedAttr && + (Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()) + SetFileCompression(DestFileName,DestFileNameW,true); +#endif + SetDirTime(DestFileName, + Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime, + Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime, + Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime); + } + return(true); + } + else + { + if (Cmd->Test && ExtrFile) + TestMode=true; +#if !defined(GUI) && !defined(SFX_MODULE) + if (Command=='P' && ExtrFile) + CurFile.SetHandleType(FILE_HANDLESTD); +#endif + if ((Command=='E' || Command=='X') && ExtrFile && !Cmd->Test) + { + bool UserReject; + if (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime)) + { + ExtrFile=false; + if (!UserReject) + { + ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName); + ErrHandler.SetErrorCode(CREATE_ERROR); +#ifdef RARDLL + Cmd->DllError=ERAR_ECREATE; +#endif + if (!IsNameUsable(DestFileName)) + { + Log(Arc.FileName,St(MCorrectingName)); + MakeNameUsable(DestFileName,true); + CreatePath(DestFileName,NULL,true); + if (FileCreate(Cmd,&CurFile,DestFileName,NULL,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime)) + ExtrFile=true; + else + ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName); + } + } + } + } + } + + if (!ExtrFile && Arc.Solid) + { + SkipSolid=true; + TestMode=true; + ExtrFile=true; + } + if (ExtrFile) + { + if (!SkipSolid) + { + if (!TestMode && Command!='P' && CurFile.IsDevice()) + { + Log(Arc.FileName,St(MInvalidName),DestFileName); + ErrHandler.WriteError(Arc.FileName,DestFileName); + } + TotalFileCount++; + } + FileCount++; +#ifndef GUI + if (Command!='I') + if (SkipSolid) + mprintf(St(MExtrSkipFile),ArcFileName); + else + switch(Cmd->Test ? 'T':Command) + { + case 'T': + mprintf(St(MExtrTestFile),ArcFileName); + break; +#ifndef SFX_MODULE + case 'P': + mprintf(St(MExtrPrinting),ArcFileName); + break; +#endif + case 'X': + case 'E': + mprintf(St(MExtrFile),DestFileName); + break; + } + if (!Cmd->DisablePercentage) + mprintf(" "); +#endif + DataIO.CurUnpRead=0; + DataIO.CurUnpWrite=0; + DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff; + DataIO.PackedCRC=0xffffffff; + DataIO.SetEncryption( + (Arc.NewLhd.Flags & LHD_PASSWORD) ? Arc.NewLhd.UnpVer:0,Password, + (Arc.NewLhd.Flags & LHD_SALT) ? Arc.NewLhd.Salt:NULL,false); + DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize); + DataIO.SetFiles(&Arc,&CurFile); + DataIO.SetTestMode(TestMode); + DataIO.SetSkipUnpCRC(SkipSolid); +#ifndef _WIN_CE + if (!TestMode && !Arc.BrokenFileHeader && + (Arc.NewLhd.FullPackSize<<11)>Arc.NewLhd.FullUnpSize && + (Arc.NewLhd.FullUnpSize<100000000 || Arc.FileLength()>Arc.NewLhd.FullPackSize)) + CurFile.Prealloc(Arc.NewLhd.FullUnpSize); +#endif + + CurFile.SetAllowDelete(!Cmd->KeepBroken); + + if (!ExtractLink(DataIO,Arc,DestFileName,DataIO.UnpFileCRC,!TestMode && !SkipSolid) && + (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0) + if (Arc.NewLhd.Method==0x30) + UnstoreFile(DataIO,Arc.NewLhd.FullUnpSize); + else + { + Unp->SetDestSize(Arc.NewLhd.FullUnpSize); +#ifndef SFX_MODULE + if (Arc.NewLhd.UnpVer<=15) + Unp->DoUnpack(15,FileCount>1 && Arc.Solid); + else +#endif + Unp->DoUnpack(Arc.NewLhd.UnpVer,Arc.NewLhd.Flags & LHD_SOLID); + } + + if (Arc.IsOpened()) + Arc.SeekToNext(); + + bool BrokenFile=false; + if (!SkipSolid) + { + if (Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC) || + !Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff)) + { +#ifndef GUI + if (Command!='P' && Command!='I') + mprintf("%s%s ",Cmd->DisablePercentage ? " ":"\b\b\b\b\b ",St(MOk)); +#endif + } + else + { + char *BadArcName=(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE) ? NULL:Arc.FileName; + if (Arc.NewLhd.Flags & LHD_PASSWORD) + { + Log(BadArcName,St(MEncrBadCRC),ArcFileName); + } + else + { + Log(BadArcName,St(MCRCFailed),ArcFileName); + } + BrokenFile=true; + ErrHandler.SetErrorCode(CRC_ERROR); +#ifdef RARDLL + Cmd->DllError=ERAR_BAD_DATA; +#endif + Alarm(); + } + } +#ifndef GUI + else + mprintf("\b\b\b\b\b "); +#endif + + if (!TestMode && (Command=='X' || Command=='E') && + !IsLink(Arc.NewLhd.FileAttr)) + { +#if defined(_WIN_32) || defined(_EMX) + if (Cmd->ClearArc) + Arc.NewLhd.FileAttr&=~FA_ARCH; +#endif + if (!BrokenFile || Cmd->KeepBroken) + { + if (BrokenFile) + CurFile.Truncate(); + CurFile.SetOpenFileStat( + Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime, + Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime, + Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime); + CurFile.Close(); +#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) + if (Cmd->SetCompressedAttr && + (Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()) + SetFileCompression(CurFile.FileName,CurFile.FileNameW,true); +#endif + CurFile.SetCloseFileStat( + Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime, + Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime, + Arc.NewLhd.FileAttr); + PrevExtracted=true; + } + } + } + } + if (ExactMatch) + MatchedArgs++; + if (DataIO.NextVolumeMissing || !Arc.IsOpened()) + return(false); + if (!ExtrFile) + if (!Arc.Solid) + Arc.SeekToNext(); + else + if (!SkipSolid) + return(false); + return(true); +} + + +void CmdExtract::UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize) +{ + Array Buffer(0x10000); + while (1) + { + unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size()); + if (Code==0 || (int)Code==-1) + break; + Code=Code=0) + DestUnpSize-=Code; + } +} + diff --git a/unrar/extract.hpp b/unrar/extract.hpp new file mode 100644 index 0000000..b78c988 --- /dev/null +++ b/unrar/extract.hpp @@ -0,0 +1,40 @@ +#ifndef _RAR_EXTRACT_ +#define _RAR_EXTRACT_ + +enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT}; + +class CmdExtract +{ + private: + ComprDataIO DataIO; + Unpack *Unp; + long TotalFileCount; + + long FileCount; + long MatchedArgs; + bool FirstFile; + bool AllMatchesExact; + bool ReconstructDone; + + char ArcName[NM]; + wchar ArcNameW[NM]; + + char Password[MAXPASSWORD]; + bool PasswordAll; + bool PrevExtracted; + bool SignatureFound; + char DestFileName[NM]; + wchar DestFileNameW[NM]; + bool PasswordCancelled; + public: + CmdExtract(); + ~CmdExtract(); + void DoExtract(CommandData *Cmd); + void ExtractArchiveInit(CommandData *Cmd,Archive &Arc); + EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd); + bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize, + bool &Repeat); + static void UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize); +}; + +#endif diff --git a/unrar/filcreat.cpp b/unrar/filcreat.cpp new file mode 100644 index 0000000..d202b39 --- /dev/null +++ b/unrar/filcreat.cpp @@ -0,0 +1,204 @@ +#include "rar.hpp" + +bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW, + OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize, + uint FileTime) +{ + if (UserReject!=NULL) + *UserReject=false; +#if defined(_WIN_32) && !defined(_WIN_CE) + bool ShortNameChanged=false; +#endif + while (FileExist(Name,NameW)) + { +#if defined(_WIN_32) && !defined(_WIN_CE) + if (!ShortNameChanged) + { + ShortNameChanged=true; + if (UpdateExistingShortName(Name,NameW)) + continue; + } +#endif + if (Mode==OVERWRITE_NONE) + { + if (UserReject!=NULL) + *UserReject=true; + 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,NM); + 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(USER_BREAK); + } + } + 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)); +} + + +#if defined(_WIN_32) && !defined(_WIN_CE) +bool UpdateExistingShortName(char *Name,wchar *NameW) +{ + 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); + + char NewName[NM]; + for (int I=0;I<10000;I+=123) + { + strncpy(NewName,Name,sizeof(NewName)); + sprintf(PointToName(NewName),"rtmp%d",I); + if (!FileExist(NewName)) + break; + } + 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); + File KeepShortFile; + bool Created=false; + if (!FileExist(Name)) + Created=KeepShortFile.Create(Name); + MoveFile(NewName,FullName); + if (Created) + { + KeepShortFile.Close(); + KeepShortFile.Delete(); + } + 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 diff --git a/unrar/filcreat.hpp b/unrar/filcreat.hpp new file mode 100644 index 0000000..fa1fddd --- /dev/null +++ b/unrar/filcreat.hpp @@ -0,0 +1,12 @@ +#ifndef _RAR_FILECREATE_ +#define _RAR_FILECREATE_ + +bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW, + OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize=INT64ERR, + uint FileTime=0); + +#if defined(_WIN_32) && !defined(_WIN_CE) +bool UpdateExistingShortName(char *Name,wchar *NameW); +#endif + +#endif diff --git a/unrar/file.cpp b/unrar/file.cpp new file mode 100644 index 0000000..185b5a7 --- /dev/null +++ b/unrar/file.cpp @@ -0,0 +1,682 @@ +#include "rar.hpp" + +static File *CreatedFiles[256]; +static int RemoveCreatedActive=0; + +File::File() +{ + hFile=BAD_HANDLE; + *FileName=0; + *FileNameW=0; + NewFile=false; + LastWrite=false; + HandleType=FILE_HANDLENORMAL; + SkipClose=false; + IgnoreReadErrors=false; + ErrorType=FILE_SUCCESS; + OpenShared=false; + AllowDelete=true; + CloseCount=0; + AllowExceptions=true; +#ifdef _WIN_32 + NoSequentialRead=false; +#endif +} + + +File::~File() +{ + if (hFile!=BAD_HANDLE && !SkipClose) + if (NewFile) + Delete(); + else + Close(); +} + + +void File::operator = (File &SrcFile) +{ + hFile=SrcFile.hFile; + strcpy(FileName,SrcFile.FileName); + NewFile=SrcFile.NewFile; + LastWrite=SrcFile.LastWrite; + HandleType=SrcFile.HandleType; + SrcFile.SkipClose=true; +} + + +bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update) +{ + ErrorType=FILE_SUCCESS; + FileHandle hNewFile; + if (File::OpenShared) + OpenShared=true; +#ifdef _WIN_32 + uint Access=GENERIC_READ; + if (Update) + Access|=GENERIC_WRITE; + uint ShareMode=FILE_SHARE_READ; + if (OpenShared) + ShareMode|=FILE_SHARE_WRITE; + uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN; + if (WinNT() && NameW!=NULL && *NameW!=0) + hNewFile=CreateFileW(NameW,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); + else + hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); + + if (hNewFile==BAD_HANDLE && GetLastError()==ERROR_FILE_NOT_FOUND) + ErrorType=FILE_NOTFOUND; +#else + int flags=Update ? O_RDWR:O_RDONLY; +#ifdef O_BINARY + flags|=O_BINARY; +#if defined(_AIX) && defined(_LARGE_FILE_API) + flags|=O_LARGEFILE; +#endif +#endif +#if defined(_EMX) && !defined(_DJGPP) + int sflags=OpenShared ? SH_DENYNO:SH_DENYWR; + int handle=sopen(Name,flags,sflags); +#else + int handle=open(Name,flags); +#ifdef LOCK_EX + if (!OpenShared && Update && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1) + { + close(handle); + return(false); + } +#endif +#endif + hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,Update ? UPDATEBINARY:READBINARY); + if (hNewFile==BAD_HANDLE && errno==ENOENT) + ErrorType=FILE_NOTFOUND; +#endif + NewFile=false; + HandleType=FILE_HANDLENORMAL; + SkipClose=false; + bool Success=hNewFile!=BAD_HANDLE; + if (Success) + { + hFile=hNewFile; + if (NameW!=NULL) + strcpyw(FileNameW,NameW); + else + *FileNameW=0; + if (Name!=NULL) + strcpy(FileName,Name); + else + WideToChar(NameW,FileName); + AddFileToList(hFile); + } + return(Success); +} + + +#if !defined(SHELL_EXT) && !defined(SFX_MODULE) +void File::TOpen(const char *Name,const wchar *NameW) +{ + if (!WOpen(Name,NameW)) + ErrHandler.Exit(OPEN_ERROR); +} +#endif + + +bool File::WOpen(const char *Name,const wchar *NameW) +{ + if (Open(Name,NameW)) + return(true); + ErrHandler.OpenErrorMsg(Name); + return(false); +} + + +bool File::Create(const char *Name,const wchar *NameW) +{ +#ifdef _WIN_32 + if (WinNT() && NameW!=NULL && *NameW!=0) + hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL, + CREATE_ALWAYS,0,NULL); + else + hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL, + CREATE_ALWAYS,0,NULL); +#else + hFile=fopen(Name,CREATEBINARY); +#endif + NewFile=true; + HandleType=FILE_HANDLENORMAL; + SkipClose=false; + if (NameW!=NULL) + strcpyw(FileNameW,NameW); + else + *FileNameW=0; + if (Name!=NULL) + strcpy(FileName,Name); + else + WideToChar(NameW,FileName); + AddFileToList(hFile); + return(hFile!=BAD_HANDLE); +} + + +void File::AddFileToList(FileHandle hFile) +{ + if (hFile!=BAD_HANDLE) + for (int I=0;ISize && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff) + ErrHandler.WriteErrorFAT(FileName); +#endif + if (ErrHandler.AskRepeatWrite(FileName)) + { +#ifndef _WIN_32 + clearerr(hFile); +#endif + if (Written0) + Seek(Tell()-Written,SEEK_SET); + continue; + } + ErrHandler.WriteError(NULL,FileName); + } + break; + } + LastWrite=true; +} + + +int File::Read(void *Data,int Size) +{ + Int64 FilePos; + if (IgnoreReadErrors) + FilePos=Tell(); + int ReadSize; + while (true) + { + ReadSize=DirectRead(Data,Size); + if (ReadSize==-1) + { + ErrorType=FILE_READERROR; + if (AllowExceptions) + if (IgnoreReadErrors) + { + ReadSize=0; + for (int I=0;IMaxDeviceRead) + Size=MaxDeviceRead; + hFile=GetStdHandle(STD_INPUT_HANDLE); +#else + hFile=stdin; +#endif + } +#endif +#ifdef _WIN_32 + DWORD Read; + if (!ReadFile(hFile,Data,Size,&Read,NULL)) + { + if (IsDevice() && Size>MaxDeviceRead) + return(DirectRead(Data,MaxDeviceRead)); + if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE) + return(0); + return(-1); + } + return(Read); +#else + if (LastWrite) + { + fflush(hFile); + LastWrite=false; + } + clearerr(hFile); + int ReadSize=fread(Data,1,Size,hFile); + if (ferror(hFile)) + return(-1); + return(ReadSize); +#endif +} + + +void File::Seek(Int64 Offset,int Method) +{ + if (!RawSeek(Offset,Method) && AllowExceptions) + ErrHandler.SeekError(FileName); +} + + +bool File::RawSeek(Int64 Offset,int Method) +{ + if (hFile==BAD_HANDLE) + return(true); + if (!is64plus(Offset) && Method!=SEEK_SET) + { + Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset; + Method=SEEK_SET; + } +#ifdef _WIN_32 + LONG HighDist=int64to32(Offset>>32); + if (SetFilePointer(hFile,int64to32(Offset),&HighDist,Method)==0xffffffff && + GetLastError()!=NO_ERROR) + return(false); +#else + LastWrite=false; +#ifdef _LARGEFILE_SOURCE + if (fseeko(hFile,Offset,Method)!=0) +#else + if (fseek(hFile,int64to32(Offset),Method)!=0) +#endif + return(false); +#endif + return(true); +} + + +Int64 File::Tell() +{ +#ifdef _WIN_32 + LONG HighDist=0; + uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT); + if (LowDist==0xffffffff && GetLastError()!=NO_ERROR) + if (AllowExceptions) + ErrHandler.SeekError(FileName); + else + return(-1); + return(int32to64(HighDist,LowDist)); +#else +#ifdef _LARGEFILE_SOURCE + return(ftello(hFile)); +#else + return(ftell(hFile)); +#endif +#endif +} + + +void File::Prealloc(Int64 Size) +{ +#ifdef _WIN_32 + if (RawSeek(Size,SEEK_SET)) + { + Truncate(); + Seek(0,SEEK_SET); + } +#endif +} + + +byte File::GetByte() +{ + byte Byte=0; + Read(&Byte,1); + return(Byte); +} + + +void File::PutByte(byte Byte) +{ + Write(&Byte,1); +} + + +bool File::Truncate() +{ +#ifdef _WIN_32 + return(SetEndOfFile(hFile)); +#else + return(false); +#endif +} + + +void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta) +{ +#ifdef _WIN_32 + bool sm=ftm!=NULL && ftm->IsSet(); + bool sc=ftc!=NULL && ftc->IsSet(); + bool sa=fta!=NULL && fta->IsSet(); + FILETIME fm,fc,fa; + if (sm) + ftm->GetWin32(&fm); + if (sc) + ftc->GetWin32(&fc); + if (sa) + fta->GetWin32(&fa); + SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL); +#endif +} + + +void File::SetCloseFileTime(RarTime *ftm,RarTime *fta) +{ +#if defined(_UNIX) || defined(_EMX) + SetCloseFileTimeByName(FileName,ftm,fta); +#endif +} + + +void File::SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta) +{ +#if defined(_UNIX) || defined(_EMX) + bool setm=ftm!=NULL && ftm->IsSet(); + bool seta=fta!=NULL && fta->IsSet(); + if (setm || seta) + { + struct utimbuf ut; + if (setm) + ut.modtime=ftm->GetUnix(); + else + ut.modtime=fta->GetUnix(); + if (seta) + ut.actime=fta->GetUnix(); + else + ut.actime=ut.modtime; + utime(Name,&ut); + } +#endif +} + + +void File::GetOpenFileTime(RarTime *ft) +{ +#ifdef _WIN_32 + FILETIME FileTime; + GetFileTime(hFile,NULL,NULL,&FileTime); + *ft=FileTime; +#endif +#if defined(_UNIX) || defined(_EMX) + struct stat st; + fstat(fileno(hFile),&st); + *ft=st.st_mtime; +#endif +} + + +void File::SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta) +{ +#ifdef _WIN_32 + SetOpenFileTime(ftm,ftc,fta); +#endif +} + + +void File::SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr) +{ +#ifdef _WIN_32 + SetFileAttr(FileName,FileNameW,FileAttr); +#endif +#ifdef _EMX + SetCloseFileTime(ftm,fta); + SetFileAttr(FileName,FileNameW,FileAttr); +#endif +#ifdef _UNIX + SetCloseFileTime(ftm,fta); + chmod(FileName,(mode_t)FileAttr); +#endif +} + + +Int64 File::FileLength() +{ + SaveFilePos SavePos(*this); + Seek(0,SEEK_END); + return(Tell()); +} + + +void File::SetHandleType(FILE_HANDLETYPE Type) +{ + HandleType=Type; +} + + +bool File::IsDevice() +{ + if (hFile==BAD_HANDLE) + return(false); +#ifdef _WIN_32 + uint Type=GetFileType(hFile); + return(Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE); +#else + return(isatty(fileno(hFile))); +#endif +} + + +#ifndef SFX_MODULE +void File::fprintf(const char *fmt,...) +{ + va_list argptr; + va_start(argptr,fmt); + safebuf char Msg[2*NM+1024],OutMsg[2*NM+1024]; + vsprintf(Msg,fmt,argptr); +#ifdef _WIN_32 + for (int Src=0,Dest=0;;Src++) + { + char CurChar=Msg[Src]; + if (CurChar=='\n') + OutMsg[Dest++]='\r'; + OutMsg[Dest++]=CurChar; + if (CurChar==0) + break; + } +#else + strcpy(OutMsg,Msg); +#endif + Write(OutMsg,strlen(OutMsg)); + va_end(argptr); +} +#endif + + +bool File::RemoveCreated() +{ + RemoveCreatedActive++; + bool RetCode=true; + for (int I=0;ISetExceptions(false); + bool Success; + if (CreatedFiles[I]->NewFile) + Success=CreatedFiles[I]->Delete(); + else + Success=CreatedFiles[I]->Close(); + if (Success) + CreatedFiles[I]=NULL; + else + RetCode=false; + } + RemoveCreatedActive--; + return(RetCode); +} + + +#ifndef SFX_MODULE +long File::Copy(File &Dest,Int64 Length) +{ + Array Buffer(0x10000); + long CopySize=0; + bool CopyAll=(Length==INT64ERR); + + while (CopyAll || Length>0) + { + Wait(); + int SizeToRead=(!CopyAll && Length=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-PathIsSet(); + bool sc=ftc!=NULL && ftc->IsSet(); + bool sa=fta!=NULL && fta->IsSet(); + + if (!WinNT()) + return; + unsigned int DirAttr=GetFileAttr(Name); + bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0); + if (ResetAttr) + SetFileAttr(Name,NULL,0); + HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL); + if (hFile==INVALID_HANDLE_VALUE) + return; + FILETIME fm,fc,fa; + if (sm) + ftm->GetWin32(&fm); + if (sc) + ftc->GetWin32(&fc); + if (sa) + fta->GetWin32(&fa); + SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL); + CloseHandle(hFile); + if (ResetAttr) + SetFileAttr(Name,NULL,DirAttr); +#endif +#if defined(_UNIX) || defined(_EMX) + File::SetCloseFileTimeByName(Name,ftm,fta); +#endif +} + + +bool IsRemovable(const char *Name) +{ +#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); +#endif +} + + +#ifndef SFX_MODULE +Int64 GetFreeDisk(const char *Name) +{ +#ifdef _WIN_32 + char Root[NM]; + GetPathRoot(Name,Root); + + 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) + 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(®s,0,sizeof(regs)); + regs.h.ah=0x36; + regs.h.dl=Drive; + _int86 (0x21,®s,&outregs); + if (outregs.x.ax==0xffff) + return(1457664); + Int64 FreeSize=outregs.x.ax*outregs.x.cx; + FreeSize=FreeSize*outregs.x.bx; + return(FreeSize); + } +#else + #define DISABLEAUTODETECT + return(1457664); +#endif +} +#endif + + +bool FileExist(const char *Name,const wchar *NameW) +{ +#ifdef _WIN_32 + if (WinNT() && NameW!=NULL && *NameW!=0) + return(GetFileAttributesW(NameW)!=0xffffffff); + else + return(GetFileAttributes(Name)!=0xffffffff); +#elif defined(ENABLE_ACCESS) + return(access(Name,0)==0); +#else + struct FindData FD; + return(FindFile::FastFind(Name,NameW,&FD)); +#endif +} + + +bool WildFileExist(const char *Name,const wchar *NameW) +{ + if (IsWildcard(Name,NameW)) + { + FindFile Find; + Find.SetMask(Name); + Find.SetMaskW(NameW); + struct FindData fd; + return(Find.Next(&fd)); + } + return(FileExist(Name,NameW)); +} + + +bool IsDir(uint Attr) +{ +#if defined (_WIN_32) || defined(_EMX) + return(Attr!=0xffffffff && (Attr & 0x10)!=0); +#endif +#if defined(_UNIX) + return((Attr & 0xF000)==0x4000); +#endif +} + + +bool IsUnreadable(uint Attr) +{ +#if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR) + return(S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr)); +#endif + return(false); +} + + +bool IsLabel(uint Attr) +{ +#if defined (_WIN_32) || defined(_EMX) + return((Attr & 8)!=0); +#else + return(false); +#endif +} + + +bool IsLink(uint Attr) +{ +#ifdef _UNIX + return((Attr & 0xF000)==0xA000); +#endif + return(false); +} + + + + + + +bool IsDeleteAllowed(uint FileAttr) +{ +#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)); +#endif +} + + +void PrepareToDelete(const char *Name,const wchar *NameW) +{ +#if defined(_WIN_32) || defined(_EMX) + SetFileAttr(Name,NameW,0); +#endif +#ifdef _UNIX + chmod(Name,S_IRUSR|S_IWUSR|S_IXUSR); +#endif +} + + +uint GetFileAttr(const char *Name,const wchar *NameW) +{ +#ifdef _WIN_32 + if (WinNT() && NameW!=NULL && *NameW!=0) + return(GetFileAttributesW(NameW)); + else + return(GetFileAttributes(Name)); +#elif defined(_DJGPP) + return(_chmod(Name,0)); +#else + struct stat st; + if (stat(Name,&st)!=0) + return(0); +#ifdef _EMX + return(st.st_attr); +#else + return(st.st_mode); +#endif +#endif +} + + +bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr) +{ + bool Success; +#ifdef _WIN_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) + 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 + + +#ifndef SFX_MODULE +char *MkTemp(char *Name) +{ + int Length=strlen(Name); + if (Length<=6) + return(NULL); + int Random=clock(); + for (int Attempt=0;;Attempt++) + { + sprintf(Name+Length-6,"%06u",Random+Attempt); + Name[Length-4]='.'; + if (!FileExist(Name)) + break; + if (Attempt==1000) + return(NULL); + } + return(Name); +} +#endif + + + + +#ifndef SFX_MODULE +uint CalcFileCRC(File *SrcFile,Int64 Size) +{ + SaveFilePos SavePos(*SrcFile); + const int BufSize=0x10000; + Array Data(BufSize); + Int64 BlockCount=0; + uint DataCRC=0xffffffff; + int ReadSize; + + + SrcFile->Seek(0,SEEK_SET); + while ((ReadSize=SrcFile->Read(&Data[0],int64to32(Size==INT64ERR ? Int64(BufSize):Min(Int64(BufSize),Size))))!=0) + { + ++BlockCount; + if ((BlockCount & 15)==0) + { + Wait(); + } + DataCRC=CRC(DataCRC,&Data[0],ReadSize); + if (Size!=INT64ERR) + Size-=ReadSize; + } + return(DataCRC^0xffffffff); +} +#endif + + +bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW) +{ + return(rename(SrcName,DestName)==0); +} + + +bool DelFile(const char *Name) +{ + return(DelFile(Name,NULL)); +} + + +bool DelFile(const char *Name,const wchar *NameW) +{ + 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) + 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); +} +#endif diff --git a/unrar/filefn.hpp b/unrar/filefn.hpp new file mode 100644 index 0000000..3ad31b5 --- /dev/null +++ b/unrar/filefn.hpp @@ -0,0 +1,39 @@ +#ifndef _RAR_FILEFN_ +#define _RAR_FILEFN_ + +enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH}; + +MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr); +void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName); +void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta); +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 char *FileName); +void EraseDiskContents(const char *FileName); +bool IsDeleteAllowed(uint FileAttr); +void PrepareToDelete(const char *Name,const wchar *NameW=NULL); +uint GetFileAttr(const char *Name,const wchar *NameW=NULL); +bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr); +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 + +#endif diff --git a/unrar/filestr.cpp b/unrar/filestr.cpp new file mode 100644 index 0000000..d9f0dd5 --- /dev/null +++ b/unrar/filestr.cpp @@ -0,0 +1,139 @@ +#include "rar.hpp" + +static bool IsUnicode(byte *Data,int Size); + +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) + { + bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName):SrcFile.Open(FileName); + + if (!OpenCode) + { + if (AbortOnError) + ErrHandler.Exit(OPEN_ERROR); + return(false); + } + } + else + SrcFile.SetHandleType(FILE_HANDLESTD); + + unsigned int DataSize=0,ReadSize; + const int ReadBlock=1024; + Array Data(ReadBlock+5); + while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0) + { + DataSize+=ReadSize; + Data.Add(ReadSize); + } + + memset(&Data[DataSize],0,5); + + if (IsUnicode((byte *)&Data[0],DataSize)) + { + wchar *CurStr=(wchar *)&Data[2]; + Array AnsiName; + + while (*CurStr!=0) + { + wchar *NextStr=CurStr,*CmtPtr=NULL; + while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0) + { + if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/') + { + *NextStr=0; + CmtPtr=NextStr; + } + NextStr++; + } + *NextStr=0; + for (wchar *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--) + { + if (*SpacePtr!=' ' && *SpacePtr!='\t') + break; + *SpacePtr=0; + } + if (*CurStr) + { + int Length=strlenw(CurStr); + int AddSize=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]); + List->AddString(&AnsiName[0],CurStr); + } + CurStr=NextStr+1; + while (*CurStr=='\r' || *CurStr=='\n') + CurStr++; + } + } + 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); +} + + +bool IsUnicode(byte *Data,int Size) +{ + if (Size<4 || Data[0]!=0xff || Data[1]!=0xfe) + return(false); + for (int I=2;IError=false; + if (*FindMask==0) + return(false); +#ifdef _WIN_32 + if (FirstCall) + { + if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE) + return(false); + } + else + if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE) + return(false); +#else + if (FirstCall) + { + char DirName[NM]; + strcpy(DirName,FindMask); + RemoveNameFromPath(DirName); + if (*DirName==0) + 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); + } + } + while (1) + { + struct dirent *ent=readdir(dirp); + if (ent==NULL) + return(false); + if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0) + continue; + if (CmpName(FindMask,ent->d_name,MATCH_NAMES)) + { + char FullName[NM]; + strcpy(FullName,FindMask); + strcpy(PointToName(FullName),ent->d_name); + if (!FastFind(FullName,NULL,fd,GetSymLink)) + { + ErrHandler.OpenErrorMsg(FullName); + continue; + } + 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->IsDir=IsDir(fd->FileAttr); + FirstCall=FALSE; + char *Name=PointToName(fd->Name); + if (strcmp(Name,".")==0 || strcmp(Name,"..")==0) + return(Next(fd)); + return(true); +} + + +bool FindFile::FastFind(const char *FindMask,const wchar *FindMaskW,struct FindData *fd,bool GetSymLink) +{ + fd->Error=false; +#ifndef _UNIX + if (IsWildcard(FindMask,FindMaskW)) + return(false); +#endif +#ifdef _WIN_32 + HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd); + if (hFind==INVALID_HANDLE_VALUE) + return(false); + FindClose(hFind); +#else + struct stat st; + if (GetSymLink) + { +#ifdef SAVE_LINKS + if (lstat(FindMask,&st)!=0) +#else + if (stat(FindMask,&st)!=0) +#endif + { + fd->Error=(errno!=ENOENT); + return(false); + } + } + else + if (stat(FindMask,&st)!=0) + { + fd->Error=(errno!=ENOENT); + return(false); + } +#ifdef _DJGPP + fd->FileAttr=chmod(FindMask,0); +#elif defined(_EMX) + fd->FileAttr=st.st_attr; +#else + fd->FileAttr=st.st_mode; +#endif + fd->IsDir=IsDir(st.st_mode); + fd->Size=st.st_size; + fd->mtime=st.st_mtime; + fd->atime=st.st_atime; + fd->ctime=st.st_ctime; + fd->FileTime=fd->mtime.GetDos(); + strcpy(fd->Name,FindMask); + + *fd->NameW=0; +#ifdef _APPLE + if (!LowAscii(fd->Name)) + UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW)); +#elif defined(UNICODE_SUPPORTED) + if (!LowAscii(fd->Name) && UnicodeEnabled()) + CharToWide(fd->Name,fd->NameW); +#endif +#endif + fd->IsDir=IsDir(fd->FileAttr); + return(true); +} + + +#ifdef _WIN_32 +HANDLE FindFile::Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd) +{ +#ifndef _WIN_CE + if (WinNT()) +#endif + { + wchar WideMask[NM]; + if (MaskW!=NULL && *MaskW!=0) + strcpyw(WideMask,MaskW); + else + CharToWide(Mask,WideMask); + + WIN32_FIND_DATAW FindData; + if (hFind==INVALID_HANDLE_VALUE) + { + hFind=FindFirstFileW(WideMask,&FindData); + if (hFind==INVALID_HANDLE_VALUE) + { + int SysErr=GetLastError(); + fd->Error=(SysErr!=ERROR_FILE_NOT_FOUND && + SysErr!=ERROR_PATH_NOT_FOUND && + SysErr!=ERROR_NO_MORE_FILES); + } + } + else + if (!FindNextFileW(hFind,&FindData)) + { + hFind=INVALID_HANDLE_VALUE; + fd->Error=GetLastError()!=ERROR_NO_MORE_FILES; + } + + if (hFind!=INVALID_HANDLE_VALUE) + { + 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 + { + 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; + } + } +#endif + return(hFind); +} +#endif + diff --git a/unrar/find.hpp b/unrar/find.hpp new file mode 100644 index 0000000..8154819 --- /dev/null +++ b/unrar/find.hpp @@ -0,0 +1,48 @@ +#ifndef _RAR_FINDDATA_ +#define _RAR_FINDDATA_ + +struct FindData +{ + char Name[NM]; + wchar NameW[NM]; + Int64 Size; + uint FileAttr; + uint FileTime; + bool IsDir; + RarTime mtime; + RarTime ctime; + RarTime atime; +#ifdef _WIN_32 + char ShortName[NM]; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; +#endif + bool Error; +}; + +class FindFile +{ + private: +#ifdef _WIN_32 + static HANDLE Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,struct FindData *fd); +#endif + + char FindMask[NM]; + wchar FindMaskW[NM]; + int FirstCall; +#ifdef _WIN_32 + HANDLE hFind; +#else + DIR *dirp; +#endif + public: + FindFile(); + ~FindFile(); + 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 diff --git a/unrar/getbits.cpp b/unrar/getbits.cpp new file mode 100644 index 0000000..71ecfc8 --- /dev/null +++ b/unrar/getbits.cpp @@ -0,0 +1,24 @@ +#include "rar.hpp" + +BitInput::BitInput() +{ + InBuf=new byte[MAX_SIZE]; +} + + +BitInput::~BitInput() +{ + delete[] InBuf; +} + + +void BitInput::faddbits(int Bits) +{ + addbits(Bits); +} + + +unsigned int BitInput::fgetbits() +{ + return(getbits()); +} diff --git a/unrar/getbits.hpp b/unrar/getbits.hpp new file mode 100644 index 0000000..8819f53 --- /dev/null +++ b/unrar/getbits.hpp @@ -0,0 +1,37 @@ +#ifndef _RAR_GETBITS_ +#define _RAR_GETBITS_ + +class BitInput +{ + public: + enum BufferSize {MAX_SIZE=0x8000}; + protected: + int InAddr,InBit; + public: + BitInput(); + ~BitInput(); + + byte *InBuf; + + void InitBitInput() + { + InAddr=InBit=0; + } + void addbits(int Bits) + { + Bits+=InBit; + InAddr+=Bits>>3; + InBit=Bits&7; + } + unsigned int getbits() + { + unsigned int BitField=(uint)InBuf[InAddr] << 16; + BitField|=(uint)InBuf[InAddr+1] << 8; + BitField|=(uint)InBuf[InAddr+2]; + BitField >>= (8-InBit); + return(BitField & 0xffff); + } + void faddbits(int Bits); + unsigned int fgetbits(); +}; +#endif diff --git a/unrar/global.cpp b/unrar/global.cpp new file mode 100644 index 0000000..593a057 --- /dev/null +++ b/unrar/global.cpp @@ -0,0 +1,4 @@ +#define INCLUDEGLOBAL + + +#include "rar.hpp" diff --git a/unrar/global.hpp b/unrar/global.hpp new file mode 100644 index 0000000..35c6cf9 --- /dev/null +++ b/unrar/global.hpp @@ -0,0 +1,14 @@ +#ifndef _RAR_GLOBAL_ +#define _RAR_GLOBAL_ + +#ifdef INCLUDEGLOBAL + #define EXTVAR +#else + #define EXTVAR extern +#endif + +EXTVAR ErrorHandler ErrHandler; + + + +#endif diff --git a/unrar/headers.hpp b/unrar/headers.hpp new file mode 100644 index 0000000..f719a7e --- /dev/null +++ b/unrar/headers.hpp @@ -0,0 +1,304 @@ +#ifndef _RAR_HEADERS_ +#define _RAR_HEADERS_ + +#define SIZEOF_MARKHEAD 7 +#define SIZEOF_OLDMHD 7 +#define SIZEOF_NEWMHD 13 +#define SIZEOF_OLDLHD 21 +#define SIZEOF_NEWLHD 32 +#define SIZEOF_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 PACK_VER 29 +#define PACK_CRYPT_VER 29 +#define UNP_VER 29 +#define CRYPT_VER 29 +#define AV_VER 20 +#define PROTECT_VER 20 + +#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 LHD_SPLIT_BEFORE 0x0001 +#define LHD_SPLIT_AFTER 0x0002 +#define LHD_PASSWORD 0x0004 +#define LHD_COMMENT 0x0008 +#define LHD_SOLID 0x0010 + +#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_LARGE 0x0100 +#define LHD_UNICODE 0x0200 +#define LHD_SALT 0x0400 +#define LHD_VERSION 0x0800 +#define LHD_EXTTIME 0x1000 +#define LHD_EXTFLAGS 0x2000 + +#define SKIP_IF_UNKNOWN 0x4000 +#define LONG_BLOCK 0x8000 + +#define EARC_NEXT_VOLUME 0x0001 +#define EARC_DATACRC 0x0002 +#define EARC_REVSPACE 0x0004 +#define EARC_VOLNUMBER 0x0008 + +enum HEADER_TYPE { + MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76, + SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a, + ENDARC_HEAD=0x7b +}; + +enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103, + NTACL_HEAD=0x104,STREAM_HEAD=0x105 }; + +enum HOST_SYSTEM { + HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4, + HOST_BEOS=5,HOST_MAX +}; + +#define SUBHEAD_TYPE_CMT "CMT" +#define SUBHEAD_TYPE_ACL "ACL" +#define SUBHEAD_TYPE_STREAM "STM" +#define SUBHEAD_TYPE_UOWNER "UOW" +#define SUBHEAD_TYPE_AV "AV" +#define SUBHEAD_TYPE_RR "RR" +#define SUBHEAD_TYPE_OS2EA "EA2" +#define SUBHEAD_TYPE_BEOSEA "EABE" + +/* new file inherits a subblock when updating a host file */ +#define SUBHEAD_FLAGS_INHERITED 0x80000000 + +#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001 + +struct OldMainHeader +{ + byte Mark[4]; + ushort HeadSize; + byte Flags; +}; + + +struct OldFileHeader +{ + uint PackSize; + uint UnpSize; + ushort FileCRC; + ushort HeadSize; + uint FileTime; + byte FileAttr; + byte Flags; + byte UnpVer; + byte NameSize; + byte Method; +}; + + +struct MarkHeader +{ + byte Mark[7]; +}; + + +struct BaseBlock +{ + ushort HeadCRC; + HEADER_TYPE HeadType;//byte + ushort Flags; + ushort HeadSize; + + bool IsSubBlock() + { + if (HeadType==SUB_HEAD) + return(true); + if (HeadType==NEWSUB_HEAD && (Flags & LHD_SOLID)!=0) + return(true); + return(false); + } +}; + +struct BlockHeader:BaseBlock +{ + union { + uint DataSize; + uint PackSize; + }; +}; + + +struct MainHeader:BlockHeader +{ + ushort HighPosAV; + uint PosAV; +}; + + +#define SALT_SIZE 8 + +struct FileHeader:BlockHeader +{ + uint UnpSize; + byte HostOS; + uint FileCRC; + uint FileTime; + byte UnpVer; + byte Method; + ushort NameSize; + union { + uint FileAttr; + uint SubFlags; + }; +/* optional */ + uint HighPackSize; + uint HighUnpSize; +/* names */ + char FileName[NM]; + wchar FileNameW[NM]; +/* optional */ + Array SubData; + byte Salt[SALT_SIZE]; + + RarTime mtime; + RarTime ctime; + RarTime atime; + RarTime arctime; +/* dummy */ + Int64 FullPackSize; + Int64 FullUnpSize; + + void Clear(int SubDataSize) + { + SubData.Alloc(SubDataSize); + Flags=LONG_BLOCK; + SubFlags=0; + } + + bool CmpName(const char *Name) + { + return(strcmp(FileName,Name)==0); + } + + FileHeader& operator = (FileHeader &hd) + { + SubData.Reset(); + memcpy(this,&hd,sizeof(*this)); + SubData.CleanData(); + SubData=hd.SubData; + return(*this); + } +}; + + +struct EndArcHeader:BaseBlock +{ + uint ArcDataCRC; + ushort VolNumber; +}; + + +struct SubBlockHeader:BlockHeader +{ + ushort SubType; + byte Level; +}; + + +struct CommentHeader:BaseBlock +{ + ushort UnpSize; + byte UnpVer; + byte Method; + ushort CommCRC; +}; + + +struct ProtectHeader:BlockHeader +{ + byte Version; + ushort RecSectors; + uint TotalBlocks; + byte Mark[8]; +}; + + +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[NM]; + char GroupName[NM]; +}; + + +struct EAHeader:SubBlockHeader +{ + uint UnpSize; + byte UnpVer; + byte Method; + uint EACRC; +}; + + +struct StreamHeader:SubBlockHeader +{ + uint UnpSize; + byte UnpVer; + byte Method; + uint StreamCRC; + ushort StreamNameSize; +/* dummy */ + byte StreamName[NM]; +}; + + +struct MacFInfoHeader:SubBlockHeader +{ + uint fileType; + uint fileCreator; +}; + + +#endif diff --git a/unrar/int64.cpp b/unrar/int64.cpp new file mode 100644 index 0000000..996d0ea --- /dev/null +++ b/unrar/int64.cpp @@ -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 (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= (Int64 n1,Int64 n2) +{ + return(n1>n2 || n1==n2); +} + + +bool operator <= (Int64 n1,Int64 n2) +{ + return(n1='0' && *Str<='9') + { + n=n*10+*Str-'0'; + Str++; + } + return(n); +} diff --git a/unrar/int64.hpp b/unrar/int64.hpp new file mode 100644 index 0000000..a805752 --- /dev/null +++ b/unrar/int64.hpp @@ -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) +#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 (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 diff --git a/unrar/isnt.cpp b/unrar/isnt.cpp new file mode 100644 index 0000000..493a9eb --- /dev/null +++ b/unrar/isnt.cpp @@ -0,0 +1,17 @@ +#include "rar.hpp" + +#ifdef _WIN_32 +int WinNT() +{ + static int dwPlatformId=-1,dwMajorVersion; + if (dwPlatformId==-1) + { + OSVERSIONINFO WinVer; + WinVer.dwOSVersionInfoSize=sizeof(WinVer); + GetVersionEx(&WinVer); + dwPlatformId=WinVer.dwPlatformId; + dwMajorVersion=WinVer.dwMajorVersion; + } + return(dwPlatformId==VER_PLATFORM_WIN32_NT ? dwMajorVersion:0); +} +#endif diff --git a/unrar/isnt.hpp b/unrar/isnt.hpp new file mode 100644 index 0000000..0265236 --- /dev/null +++ b/unrar/isnt.hpp @@ -0,0 +1,6 @@ +#ifndef _RAR_ISNT_ +#define _RAR_ISNT_ + +int WinNT(); + +#endif diff --git a/unrar/license.txt b/unrar/license.txt new file mode 100644 index 0000000..5f78b72 --- /dev/null +++ b/unrar/license.txt @@ -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 - Alexander Roshal. + + 2. The unRAR sources may be used in any software to handle RAR + archives without limitations free of charge, but cannot be used + to re-create the RAR compression algorithm, which is proprietary. + Distribution of modified unRAR sources in separate form or as a + part of other software is permitted, provided that it is clearly + stated in the documentation and source comments that the code may + not be used to develop a RAR (WinRAR) compatible archiver. + + 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. + + + Alexander L. Roshal \ No newline at end of file diff --git a/unrar/list.cpp b/unrar/list.cpp new file mode 100644 index 0000000..e6de4a2 --- /dev/null +++ b/unrar/list.cpp @@ -0,0 +1,380 @@ +#include "rar.hpp" + +static void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare); +static void ListSymLink(Archive &Arc); +static void ListFileAttr(uint A,int HostOS); +static void ListOldSubHeader(Archive &Arc); +static void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical); + +void ListArchive(CommandData *Cmd) +{ + Int64 SumPackSize=0,SumUnpSize=0; + uint ArcCount=0,SumFileCount=0; + bool Technical=(Cmd->Command[1]=='T'); + bool Bare=(Cmd->Command[1]=='B'); + bool Verbose=(*Cmd->Command=='V'); + + char ArcName[NM]; + wchar ArcNameW[NM]; + + while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName))) + { + Archive Arc(Cmd); +#ifdef _WIN_32 + Arc.RemoveSequentialFlag(); +#endif + if (!Arc.WOpen(ArcName,ArcNameW)) + continue; + bool FileMatched=true; + while (1) + { + Int64 TotalPackSize=0,TotalUnpSize=0; + uint FileCount=0; + if (Arc.IsArchive(true)) + { + if (!Arc.IsOpened()) + break; + bool TitleShown=false; + if (!Bare) + { + Arc.ViewComment(); + mprintf("\n"); + if (Arc.Solid) + mprintf(St(MListSolid)); + if (Arc.SFXSize>0) + mprintf(St(MListSFX)); + if (Arc.Volume) + if (Arc.Solid) + mprintf(St(MListVol1)); + else + mprintf(St(MListVol2)); + else + if (Arc.Solid) + mprintf(St(MListArc1)); + else + mprintf(St(MListArc2)); + mprintf(" %s\n",Arc.FileName); + if (Technical) + { + if (Arc.Protected) + mprintf(St(MListRecRec)); + if (Arc.Locked) + mprintf(St(MListLock)); + } + } + while(Arc.ReadHeader()>0) + { + switch(Arc.GetHeaderType()) + { + case FILE_HEAD: + IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName); + if ((FileMatched=Cmd->IsProcessFile(Arc.NewLhd))==true) + { + ListFileHeader(Arc.NewLhd,Verbose,Technical,TitleShown,Bare); + if (!(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)) + { + TotalUnpSize+=Arc.NewLhd.FullUnpSize; + FileCount++; + } + TotalPackSize+=Arc.NewLhd.FullPackSize; + if (Technical) + ListSymLink(Arc); +#ifndef SFX_MODULE + if (Verbose) + Arc.ViewFileComment(); +#endif + } + break; +#ifndef SFX_MODULE + case SUB_HEAD: + if (Technical && FileMatched && !Bare) + ListOldSubHeader(Arc); + break; +#endif + case NEWSUB_HEAD: + if (FileMatched && !Bare) + { + if (Technical) + ListFileHeader(Arc.SubHead,Verbose,true,TitleShown,false); + ListNewSubHeader(Cmd,Arc,Technical); + } + break; + } + Arc.SeekToNext(); + } + if (!Bare) + if (TitleShown) + { + mprintf("\n"); + for (int I=0;I<79;I++) + mprintf("-"); + char UnpSizeText[20]; + itoa(TotalUnpSize,UnpSizeText); + + char PackSizeText[20]; + itoa(TotalPackSize,PackSizeText); + + mprintf("\n%5lu %16s %8s %3d%%",FileCount,UnpSizeText, + PackSizeText,ToPercent(TotalPackSize,TotalUnpSize)); + SumFileCount+=FileCount; + SumUnpSize+=TotalUnpSize; + SumPackSize+=TotalPackSize; +#ifndef SFX_MODULE + if (Arc.EndArcHead.Flags & EARC_VOLNUMBER) + { + mprintf(" "); + mprintf(St(MVolumeNumber),Arc.EndArcHead.VolNumber+1); + } +#endif + mprintf("\n"); + } + else + mprintf(St(MListNoFiles)); + + ArcCount++; + +#ifndef NOVOLUME + if (Cmd->VolSize!=0 && ((Arc.NewLhd.Flags & LHD_SPLIT_AFTER) || + Arc.GetHeaderType()==ENDARC_HEAD && + (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)!=0) && + MergeArchive(Arc,NULL,false,*Cmd->Command)) + { + Arc.Seek(0,SEEK_SET); + } + else +#endif + break; + } + else + { + if (Cmd->ArcNames->ItemsCount()<2 && !Bare) + mprintf(St(MNotRAR),Arc.FileName); + break; + } + } + } + if (ArcCount>1 && !Bare) + { + char UnpSizeText[20],PackSizeText[20]; + itoa(SumUnpSize,UnpSizeText); + itoa(SumPackSize,PackSizeText); + mprintf("\n%5lu %16s %8s %3d%%\n",SumFileCount,UnpSizeText, + PackSizeText,ToPercent(SumPackSize,SumUnpSize)); + } +} + + +void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,bool Bare) +{ + if (!Bare) + { + if (!TitleShown) + { + if (Verbose) + mprintf(St(MListPathComm)); + else + mprintf(St(MListName)); + mprintf(St(MListTitle)); + if (Technical) + mprintf(St(MListTechTitle)); + for (int I=0;I<79;I++) + mprintf("-"); + TitleShown=true; + } + + if (hd.HeadType==NEWSUB_HEAD) + mprintf(St(MSubHeadType),hd.FileName); + + mprintf("\n%c",(hd.Flags & LHD_PASSWORD) ? '*' : ' '); + } + + char *Name=hd.FileName; + +#ifdef UNICODE_SUPPORTED + char ConvertedName[NM]; + if ((hd.Flags & LHD_UNICODE)!=0 && *hd.FileNameW!=0 && UnicodeEnabled()) + { + if (WideToChar(hd.FileNameW,ConvertedName)) + Name=ConvertedName; + } +#endif + + if (Bare) + { + mprintf("%s\n",Verbose ? Name:PointToName(Name)); + return; + } + + 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 + if (hd.Flags & LHD_SPLIT_AFTER) + mprintf(" -->"); + else + mprintf("%3d%%",ToPercent(hd.FullPackSize,hd.FullUnpSize)); + + char DateStr[50]; + hd.mtime.GetText(DateStr,false); + mprintf(" %s ",DateStr); + + if (hd.HeadType==NEWSUB_HEAD) + mprintf(" %c....B ",(hd.SubFlags & SUBHEAD_FLAGS_INHERITED) ? 'I' : '.'); + else + ListFileAttr(hd.FileAttr,hd.HostOS); + + mprintf(" %8.8X",hd.FileCRC); + mprintf(" m%d",hd.Method-0x30); + if ((hd.Flags & LHD_WINDOWMASK)<=6*32) + mprintf("%c",((hd.Flags&LHD_WINDOWMASK)>>5)+'a'); + else + mprintf(" "); + mprintf(" %d.%d",hd.UnpVer/10,hd.UnpVer%10); + + static const char *RarOS[]={ + "DOS","OS/2","Win95/NT","Unix","MacOS","BeOS","WinCE","","","" + }; + + if (Technical) + mprintf("\n%22s %8s %4s", + (hd.HostOS",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 HOST_UNIX: + case HOST_BEOS: + switch (A & 0xF000) + { + case 0x4000: + mprintf("d"); + break; + case 0xA000: + mprintf("l"); + break; + default: + mprintf("-"); + break; + } + mprintf("%c%c%c%c%c%c%c%c%c", + (A & 0x0100) ? 'r' : '-', + (A & 0x0080) ? 'w' : '-', + (A & 0x0040) ? ((A & 0x0800) ? 's':'x'):((A & 0x0800) ? 'S':'-'), + (A & 0x0020) ? 'r' : '-', + (A & 0x0010) ? 'w' : '-', + (A & 0x0008) ? ((A & 0x0400) ? 's':'x'):((A & 0x0400) ? 'S':'-'), + (A & 0x0004) ? 'r' : '-', + (A & 0x0002) ? 'w' : '-', + (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 CmtData; + int ReadSize=Arc.ReadCommentData(CmtData); + 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 - - " +#define MUNRARTitle1 "\nUsage: unrar - - " +#define MRARTitle2 "\n <@listfiles...> " +#define MCHelpCmd "\n\n" +#define MCHelpCmdA "\n a Add files to archive" +#define MCHelpCmdC "\n c Add archive comment" +#define MCHelpCmdCF "\n cf Add files comment" +#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]= 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" +#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 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[+] Set file exclude and include attributes" +#define MCHelpSwED "\n ed Do not add empty directories" +#define MCHelpSwEE "\n ee Do not save and extract extended attributes" +#define MCHelpSwEN "\n en Do not put 'end of archive' block" +#define MCHelpSwEP "\n ep Exclude paths from names" +#define MCHelpSwEP1 "\n ep1 Exclude base directory from names" +#define MCHelpSwEP2 "\n ep2 Expand paths to full" +#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter" +#define MCHelpSwF "\n f Freshen files" +#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers" +#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages" +#define MCHelpSwIEML "\n ieml[addr] Send archive by email" +#define MCHelpSwIERR "\n ierr Send all messages to stderr" +#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)" +#define MCHelpSwINUL "\n inul Disable all messages" +#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation" +#define MCHelpSwISND "\n isnd Enable sound" +#define MCHelpSwK "\n k Lock archive" +#define MCHelpSwKB "\n kb Keep broken extracted files" +#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)" +#define MCHelpSwMC "\n mc Set advanced compression parameters" +#define MCHelpSwMD "\n md 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 MCHelpSwN "\n n Include only specified file" +#define MCHelpSwNa "\n n@ Read file names to include from stdin" +#define MCHelpSwNal "\n n@ 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 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

[:] 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[,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 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