summaryrefslogtreecommitdiff
path: root/unrar
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2008-06-08 11:04:43 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2008-06-08 11:04:43 +0200
commit16f738ecee689c6feb2acb7e4ef4d9bb4144ae7d (patch)
tree3d22f54f7298f81b18ed66d05a62fa8bfab359ab /unrar
downloadtuxcmd-modules-0.6.36.tar.xz
Diffstat (limited to 'unrar')
-rw-r--r--unrar/COPYING339
-rw-r--r--unrar/Makefile67
-rw-r--r--unrar/Makefile.unrar39
-rw-r--r--unrar/README43
-rw-r--r--unrar/rarlog.cpp69
-rw-r--r--unrar/rarlog.hpp13
l---------unrar/strutils.c1
l---------unrar/strutils.h1
l---------unrar/treepath_vfs.c1
l---------unrar/treepath_vfs.h1
l---------unrar/treepathutils.c1
l---------unrar/treepathutils.h1
-rw-r--r--unrar/unrar.c734
-rw-r--r--unrar/unrar/arccmt.cpp215
-rw-r--r--unrar/unrar/archive.cpp267
-rw-r--r--unrar/unrar/archive.hpp126
-rw-r--r--unrar/unrar/arcread.cpp653
-rw-r--r--unrar/unrar/array.hpp122
-rw-r--r--unrar/unrar/beosea.cpp113
-rw-r--r--unrar/unrar/cmddata.cpp1287
-rw-r--r--unrar/unrar/cmddata.hpp57
-rw-r--r--unrar/unrar/coder.cpp47
-rw-r--r--unrar/unrar/coder.hpp24
-rw-r--r--unrar/unrar/compress.hpp36
-rw-r--r--unrar/unrar/consio.cpp289
-rw-r--r--unrar/unrar/consio.hpp46
-rw-r--r--unrar/unrar/crc.cpp61
-rw-r--r--unrar/unrar/crc.hpp10
-rw-r--r--unrar/unrar/crypt.cpp381
-rw-r--r--unrar/unrar/crypt.hpp62
-rw-r--r--unrar/unrar/dll.cpp365
-rw-r--r--unrar/unrar/dll.def12
-rw-r--r--unrar/unrar/dll.hpp138
-rw-r--r--unrar/unrar/encname.cpp57
-rw-r--r--unrar/unrar/encname.hpp20
-rw-r--r--unrar/unrar/errhnd.cpp374
-rw-r--r--unrar/unrar/errhnd.hpp62
-rw-r--r--unrar/unrar/extinfo.cpp76
-rw-r--r--unrar/unrar/extinfo.hpp8
-rw-r--r--unrar/unrar/extract.cpp873
-rw-r--r--unrar/unrar/extract.hpp42
-rw-r--r--unrar/unrar/filcreat.cpp239
-rw-r--r--unrar/unrar/filcreat.hpp13
-rw-r--r--unrar/unrar/file.cpp689
-rw-r--r--unrar/unrar/file.hpp100
-rw-r--r--unrar/unrar/filefn.cpp570
-rw-r--r--unrar/unrar/filefn.hpp41
-rw-r--r--unrar/unrar/filestr.cpp145
-rw-r--r--unrar/unrar/filestr.hpp8
-rw-r--r--unrar/unrar/find.cpp296
-rw-r--r--unrar/unrar/find.hpp48
-rw-r--r--unrar/unrar/getbits.cpp24
-rw-r--r--unrar/unrar/getbits.hpp38
-rw-r--r--unrar/unrar/global.cpp4
-rw-r--r--unrar/unrar/global.hpp14
-rw-r--r--unrar/unrar/headers.hpp306
-rw-r--r--unrar/unrar/int64.cpp274
-rw-r--r--unrar/unrar/int64.hpp86
-rw-r--r--unrar/unrar/isnt.cpp17
-rw-r--r--unrar/unrar/isnt.hpp6
-rw-r--r--unrar/unrar/license.txt40
-rw-r--r--unrar/unrar/list.cpp388
-rw-r--r--unrar/unrar/list.hpp6
-rw-r--r--unrar/unrar/loclang.hpp349
-rw-r--r--unrar/unrar/log.cpp24
-rw-r--r--unrar/unrar/log.hpp18
-rw-r--r--unrar/unrar/makefile.bcc501
-rw-r--r--unrar/unrar/makefile.cygmin54
-rw-r--r--unrar/unrar/makefile.dj50
-rw-r--r--unrar/unrar/makefile.dmc54
-rw-r--r--unrar/unrar/makefile.msc564
-rw-r--r--unrar/unrar/makefile.unix119
-rw-r--r--unrar/unrar/match.cpp262
-rw-r--r--unrar/unrar/match.hpp12
-rw-r--r--unrar/unrar/model.cpp610
-rw-r--r--unrar/unrar/model.hpp132
-rw-r--r--unrar/unrar/msc.dep2532
-rw-r--r--unrar/unrar/options.cpp28
-rw-r--r--unrar/unrar/options.hpp142
-rw-r--r--unrar/unrar/os.hpp241
-rw-r--r--unrar/unrar/os2ea.cpp94
-rw-r--r--unrar/unrar/pathfn.cpp714
-rw-r--r--unrar/unrar/pathfn.hpp46
-rw-r--r--unrar/unrar/rar.cpp144
-rw-r--r--unrar/unrar/rar.hpp80
-rw-r--r--unrar/unrar/rardefs.hpp24
-rw-r--r--unrar/unrar/rarfn.hpp7
-rw-r--r--unrar/unrar/rarlang.hpp10
-rw-r--r--unrar/unrar/raros.hpp41
-rw-r--r--unrar/unrar/rartypes.hpp21
-rw-r--r--unrar/unrar/rarvm.cpp1109
-rw-r--r--unrar/unrar/rarvm.hpp109
-rw-r--r--unrar/unrar/rarvmtbl.cpp53
-rw-r--r--unrar/unrar/rawread.cpp126
-rw-r--r--unrar/unrar/rawread.hpp32
-rw-r--r--unrar/unrar/rdwrfn.cpp264
-rw-r--r--unrar/unrar/rdwrfn.hpp83
-rw-r--r--unrar/unrar/readme.txt63
-rw-r--r--unrar/unrar/recvol.cpp367
-rw-r--r--unrar/unrar/recvol.hpp16
-rw-r--r--unrar/unrar/resource.cpp12
-rw-r--r--unrar/unrar/resource.hpp14
-rw-r--r--unrar/unrar/rijndael.cpp298
-rw-r--r--unrar/unrar/rijndael.hpp37
-rw-r--r--unrar/unrar/rs.cpp143
-rw-r--r--unrar/unrar/rs.hpp32
-rw-r--r--unrar/unrar/savepos.cpp15
-rw-r--r--unrar/unrar/savepos.hpp15
-rw-r--r--unrar/unrar/scantree.cpp292
-rw-r--r--unrar/unrar/scantree.hpp52
-rw-r--r--unrar/unrar/sha1.cpp231
-rw-r--r--unrar/unrar/sha1.hpp17
-rw-r--r--unrar/unrar/smallfn.cpp23
-rw-r--r--unrar/unrar/smallfn.hpp8
-rw-r--r--unrar/unrar/strfn.cpp199
-rw-r--r--unrar/unrar/strfn.hpp34
-rw-r--r--unrar/unrar/strlist.cpp191
-rw-r--r--unrar/unrar/strlist.hpp39
-rw-r--r--unrar/unrar/suballoc.cpp258
-rw-r--r--unrar/unrar/suballoc.hpp87
-rw-r--r--unrar/unrar/system.cpp96
-rw-r--r--unrar/unrar/system.hpp26
-rw-r--r--unrar/unrar/timefn.cpp288
-rw-r--r--unrar/unrar/timefn.hpp57
-rw-r--r--unrar/unrar/ulinks.cpp32
-rw-r--r--unrar/unrar/ulinks.hpp9
-rw-r--r--unrar/unrar/unicode.cpp493
-rw-r--r--unrar/unrar/unicode.hpp82
-rw-r--r--unrar/unrar/unios2.cpp128
-rw-r--r--unrar/unrar/unpack.cpp1004
-rw-r--r--unrar/unrar/unpack.hpp217
-rw-r--r--unrar/unrar/unpack15.cpp511
-rw-r--r--unrar/unrar/unpack20.cpp370
-rw-r--r--unrar/unrar/uowners.cpp80
-rw-r--r--unrar/unrar/version.hpp6
-rw-r--r--unrar/unrar/volume.cpp221
-rw-r--r--unrar/unrar/volume.hpp11
-rw-r--r--unrar/unrar/win32acl.cpp127
-rw-r--r--unrar/unrar/win32stm.cpp154
l---------unrar/vfs_types.h1
l---------unrar/vfsutils.c1
l---------unrar/vfsutils.h1
142 files changed, 25492 insertions, 0 deletions
diff --git a/unrar/COPYING b/unrar/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/unrar/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/unrar/Makefile b/unrar/Makefile
new file mode 100644
index 0000000..32e1906
--- /dev/null
+++ b/unrar/Makefile
@@ -0,0 +1,67 @@
+# path definitions
+DESTDIR = /usr
+INSTALL=install -c
+INSTALL_DATA = ${INSTALL} -m 644
+DIR_UNRAR = unrar
+
+# compiler options
+CC = gcc
+CPP = g++
+CFLAGS =-I. -I/usr/include -I$(DIR_UNRAR) \
+ -Wall -fPIC -O2 -g \
+ -DG_DISABLE_DEPRECATED -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE \
+ -D__VERBOSE_DEBUGx
+
+LIB_SUFFIX=`if test \`uname -m\` = x86_64; then echo 64; fi`
+
+
+UNRAR_LIB_OBJ=$(DIR_UNRAR)/filestr.o $(DIR_UNRAR)/scantree.o $(DIR_UNRAR)/dll.o
+
+UNRAR_OBJECTS=$(DIR_UNRAR)/rar.o $(DIR_UNRAR)/strlist.o $(DIR_UNRAR)/strfn.o \
+ $(DIR_UNRAR)/pathfn.o $(DIR_UNRAR)/int64.o $(DIR_UNRAR)/savepos.o \
+ $(DIR_UNRAR)/global.o $(DIR_UNRAR)/file.o $(DIR_UNRAR)/filefn.o \
+ $(DIR_UNRAR)/filcreat.o $(DIR_UNRAR)/archive.o $(DIR_UNRAR)/arcread.o \
+ $(DIR_UNRAR)/unicode.o $(DIR_UNRAR)/system.o $(DIR_UNRAR)/isnt.o \
+ $(DIR_UNRAR)/crypt.o $(DIR_UNRAR)/crc.o $(DIR_UNRAR)/rawread.o \
+ $(DIR_UNRAR)/encname.o $(DIR_UNRAR)/resource.o $(DIR_UNRAR)/match.o \
+ $(DIR_UNRAR)/timefn.o $(DIR_UNRAR)/rdwrfn.o $(DIR_UNRAR)/consio.o \
+ $(DIR_UNRAR)/options.o $(DIR_UNRAR)/ulinks.o $(DIR_UNRAR)/errhnd.o \
+ $(DIR_UNRAR)/rarvm.o $(DIR_UNRAR)/rijndael.o $(DIR_UNRAR)/getbits.o \
+ $(DIR_UNRAR)/sha1.o $(DIR_UNRAR)/extinfo.o $(DIR_UNRAR)/extract.o \
+ $(DIR_UNRAR)/volume.o $(DIR_UNRAR)/list.o $(DIR_UNRAR)/find.o \
+ $(DIR_UNRAR)/unpack.o $(DIR_UNRAR)/cmddata.o
+
+
+VFS_COMMON_OBJECTS=strutils.o treepathutils.o treepath_vfs.o vfsutils.o
+
+VFS_OBJECTS=unrar.o rarlog.o
+
+
+.SUFFIXES: .c .cpp
+.c.o:
+ $(CC) $(CFLAGS) `pkg-config glib-2.0 --cflags` -c $<
+.cpp.o:
+ $(CPP) $(CFLAGS) `pkg-config glib-2.0 --cflags` -c $<
+
+
+all shared static: libunrar_plugin.so
+
+libunrar_plugin.so: libunrar $(VFS_COMMON_OBJECTS) $(VFS_OBJECTS)
+ $(CPP) -shared -o libunrar_plugin.so $(VFS_COMMON_OBJECTS) $(VFS_OBJECTS) $(UNRAR_OBJECTS) $(UNRAR_LIB_OBJ) $(CFLAGS) `pkg-config glib-2.0 --libs`
+
+libunrar:
+ ( cd $(DIR_UNRAR) && make -f ../Makefile.unrar ) || exit 1
+
+strutils.o: strutils.c strutils.h
+treepathutils.o: treepathutils.c treepathutils.h
+vfsutils.o: vfsutils.c vfsutils.h
+treepath_vfs.o: treepath_vfs.c treepath_vfs.h
+rarlog.o: rarlog.cpp rarlog.hpp
+
+install::
+ $(INSTALL) ./libunrar_plugin.so $(DESTDIR)/lib$(LIB_SUFFIX)/tuxcmd/
+
+clean:
+ ( cd $(DIR_UNRAR) && make -f ../Makefile.unrar clean ) || exit 1
+ rm -f *.o *.d *.gch libunrar_plugin.so
+
diff --git a/unrar/Makefile.unrar b/unrar/Makefile.unrar
new file mode 100644
index 0000000..c017bac
--- /dev/null
+++ b/unrar/Makefile.unrar
@@ -0,0 +1,39 @@
+#
+# Makefile for UNIX - unrar
+#
+# Note: you have to 'make clean' before you can build
+# the sfx module
+#
+#
+# Modified for needs of tuxcmd VFS plugin
+#
+
+# Linux using GCC
+CXX=g++
+CXXFLAGS=-O2 -fPIC -g
+DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRARDLL -DGUI
+
+##########################
+
+COMPILE=$(CXX) $(CXXFLAGS) $(DEFINES)
+LINK=$(CXX)
+
+UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o
+LIB_OBJ=filestr.o scantree.o dll.o
+
+OBJECTS=rar.o strlist.o strfn.o pathfn.o int64.o savepos.o global.o file.o filefn.o filcreat.o \
+ archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
+ resource.o match.o timefn.o rdwrfn.o consio.o options.o ulinks.o errhnd.o rarvm.o \
+ rijndael.o getbits.o sha1.o extinfo.o extract.o volume.o list.o find.o unpack.o cmddata.o
+
+.cpp.o:
+ $(COMPILE) -c $<
+
+all: lib
+
+clean:
+ rm -f *.o *.bak *~ *.so *.d
+
+lib: $(OBJECTS) $(LIB_OBJ)
+# @rm -f libunrar.so
+# $(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
diff --git a/unrar/README b/unrar/README
new file mode 100644
index 0000000..72e2f92
--- /dev/null
+++ b/unrar/README
@@ -0,0 +1,43 @@
+UNRAR plugin for Tux Commander
+ Version: 0.2.2
+ Release date: 2008-May-11
+
+Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net>
+http://tuxcmd.sourceforge.net
+
+This plugin uses UNRAR sources v3.7.1 beta1
+Copyright (C) Alexander L. Roshal
+http://www.rarlab.com/
+See unrar/license.txt for licensing conditions
+
+
+
+
+This is the RAR archiving VFS (Virtual File System) plugin for Tux Commander
+file manager. It incorporates unrar sources, which are statically linked
+thus no additional system libraries or utilities are required. This plugin
+is pretty stable for normal use at the current version.
+
+Feature highlights:
+ * read-only support for RAR archives
+ * full support for Unix file and directory permissions
+ * password protected archives are supported
+ * multidisk archives support
+ * large files (> 4GB) support
+ * can handle self-extracting .exe archives (when renamed to .rar)
+
+To be implemented:
+ * archive consistency testing (needs new VFS API)
+
+
+The current VFS implementation in Tux Commander lacks some extended features
+for both archiving and remote filesystems. This is one of the main goals for
+the 0.6.x series.
+
+
+For successful compilation you will need working gcc and g++ compiler and
+glib2 library installed with development files. The unrar sources are
+included in the plugin tree, no external files are required.
+
+Compilation has been tested with gcc compiler version 4.2.3 and 4.3.0
+
diff --git a/unrar/rarlog.cpp b/unrar/rarlog.cpp
new file mode 100644
index 0000000..1919975
--- /dev/null
+++ b/unrar/rarlog.cpp
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "errhnd.hpp"
+
+#define NM 1024
+#define safebuf static
+
+
+static char LogName[NM];
+
+void InitLogOptions(char *LogName)
+{
+ strcpy(::LogName,LogName);
+}
+
+void Log(const char *ArcName,const char *Format,...)
+{
+ printf("(WW) RARLog: ");
+ va_list ArgPtr;
+ va_start(ArgPtr,Format);
+ vprintf(Format,ArgPtr);
+ va_end(ArgPtr);
+ printf("\n");
+}
+
+
+void eprintf(const char *fmt,...)
+{
+ printf("(WW) RAReprintf: ");
+ va_list ArgPtr;
+ va_start(ArgPtr, fmt);
+ vprintf(fmt, ArgPtr);
+ va_end(ArgPtr);
+ printf("\n");
+}
+
+void mprintf(const char *fmt,...)
+{
+/*
+ printf("(WW) RARmprintf: ");
+ va_list ArgPtr;
+ va_start(ArgPtr, fmt);
+ vprintf(fmt, ArgPtr);
+ va_end(ArgPtr);
+ printf("\n");
+*/
+}
+
+int Ask(const char *AskStr)
+{
+ return 0;
+}
+
+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);
+// Alarm();
+ if (*Msg)
+ {
+ Log(ArcName,"\n%s",Msg);
+// mprintf("\n%s\n",St(MProgAborted));
+ }
+}
+
diff --git a/unrar/rarlog.hpp b/unrar/rarlog.hpp
new file mode 100644
index 0000000..68d9f29
--- /dev/null
+++ b/unrar/rarlog.hpp
@@ -0,0 +1,13 @@
+#ifndef _RAR_LOG_
+#define _RAR_LOG_
+
+void InitLogOptions(char *LogName);
+
+void Log(const char *ArcName,const char *Format,...);
+
+void mprintf(const char *fmt,...);
+void eprintf(const char *fmt,...);
+
+int Ask(const char *AskStr);
+
+#endif
diff --git a/unrar/strutils.c b/unrar/strutils.c
new file mode 120000
index 0000000..2b33d06
--- /dev/null
+++ b/unrar/strutils.c
@@ -0,0 +1 @@
+../common/strutils.c \ No newline at end of file
diff --git a/unrar/strutils.h b/unrar/strutils.h
new file mode 120000
index 0000000..1958ce7
--- /dev/null
+++ b/unrar/strutils.h
@@ -0,0 +1 @@
+../common/strutils.h \ No newline at end of file
diff --git a/unrar/treepath_vfs.c b/unrar/treepath_vfs.c
new file mode 120000
index 0000000..f4b41b3
--- /dev/null
+++ b/unrar/treepath_vfs.c
@@ -0,0 +1 @@
+../common/treepath_vfs.c \ No newline at end of file
diff --git a/unrar/treepath_vfs.h b/unrar/treepath_vfs.h
new file mode 120000
index 0000000..a1e19e7
--- /dev/null
+++ b/unrar/treepath_vfs.h
@@ -0,0 +1 @@
+../common/treepath_vfs.h \ No newline at end of file
diff --git a/unrar/treepathutils.c b/unrar/treepathutils.c
new file mode 120000
index 0000000..ae760bc
--- /dev/null
+++ b/unrar/treepathutils.c
@@ -0,0 +1 @@
+../common/treepathutils.c \ No newline at end of file
diff --git a/unrar/treepathutils.h b/unrar/treepathutils.h
new file mode 120000
index 0000000..4e3c904
--- /dev/null
+++ b/unrar/treepathutils.h
@@ -0,0 +1 @@
+../common/treepathutils.h \ No newline at end of file
diff --git a/unrar/unrar.c b/unrar/unrar.c
new file mode 100644
index 0000000..6435aeb
--- /dev/null
+++ b/unrar/unrar.c
@@ -0,0 +1,734 @@
+/* UNRAR plugin for Tux Commander
+ * version 0.2.2, designed for unrar v3.7.1 beta1
+ * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net>
+ * Check for updates on tuxcmd.sourceforge.net
+ *
+ * Uses UNRAR sources
+ * UnRAR - free utility for RAR archives
+ * Copyright (C) Alexander L. Roshal
+ * http://www.rarlab.com/
+ *
+
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fnmatch.h>
+#include <unistd.h>
+#include <glib.h>
+
+#include "vfs_types.h"
+#include "vfsutils.h"
+#include "strutils.h"
+#include "treepathutils.h"
+#include "treepath_vfs.h"
+
+#define _UNIX
+
+#include "unrar/version.hpp"
+#include "unrar/dll.hpp"
+
+
+// Compatibility types from headers.hpp
+enum HOST_SYSTEM {
+ HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
+ HOST_BEOS=5,HOST_MAX
+};
+
+
+#define VERSION "0.2.2"
+#define BUILD_DATE "2008-05-11"
+#define DEFAULT_BLOCK_SIZE 65536
+
+
+
+
+
+/******************************************************************************************************/
+/** Auxiliary classes */
+/************** ****************/
+
+
+
+// Declaration of the global plugin object
+struct TVFSGlobs {
+ TVFSLogFunc log_func;
+ char *curr_dir;
+ char *archive_path;
+
+ gboolean need_password;
+ gboolean passwd_callback;
+ char *password;
+
+ unsigned long block_size;
+
+ struct PathTree *files;
+ struct VfsFilelistData *vfs_filelist;
+
+ u_int64_t total_size;
+
+ void *extract_callback_data;
+ TVFSCopyCallBackFunc extract_callback_func;
+ u_int64_t extract_file_size;
+ u_int64_t extract_done;
+ gboolean extract_cancelled;
+};
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////
+// Basic initialization functions
+int VFSAllocNeeded()
+{
+ return sizeof(struct TVFSGlobs);
+}
+
+void VFSInit(struct TVFSGlobs *globs, TVFSLogFunc log_func)
+{
+ globs->block_size = DEFAULT_BLOCK_SIZE;
+ globs->extract_callback_data = NULL;
+ globs->extract_callback_func = NULL;
+ globs->need_password = FALSE;
+ globs->passwd_callback = FALSE;
+
+ globs->log_func = log_func;
+ if (globs->log_func != NULL) globs->log_func((char*)"unrar plugin: VFSInit");
+}
+
+void VFSDestroy(struct TVFSGlobs *globs)
+{
+ if (globs->log_func != NULL) globs->log_func((char*)"unrar plugin: VFSDestroy");
+}
+
+int VFSVersion()
+{
+ return 3;
+}
+
+struct TVFSInfo VFSGetInfo()
+{
+ struct TVFSInfo module_info;
+ module_info.Name = "UNRAR plugin";
+ module_info.Description = "RAR archiving plugin";
+ char *s = (char*)malloc(255);
+ snprintf(s, 255, "version %s, build date: %s\nusing unrar sources v%d.%d [%d-%.2d-%.2d]\n",
+ VERSION, BUILD_DATE, RARVER_MAJOR, RARVER_MINOR, RARVER_YEAR, RARVER_MONTH, RARVER_DAY);
+ module_info.About = strdup(s);
+ free(s);
+ s = (char*)malloc(255);
+ snprintf(s, 255, "Plugin Copyright (C) 2008 Tomáš Bžatek\nUNRAR sources Copyright (C) 2002-2007 Alexander Roshal");
+ module_info.Copyright = strdup(s);
+ return module_info;
+}
+
+char *VFSGetPrefix(struct TVFSGlobs *globs)
+{
+ return globs->archive_path;
+// return (char*)"unrar";
+}
+
+char *VFSGetExts()
+{
+ return (char*)"rar;r00;r01;r02;r03;r04;r05;r06;r07;r08;r09;r10;r11;r12;r13;r14;r15;r16;r17;r18;r19;r20;r21;r22;r23;r24;r25;r26;r27;r28;r29;r30;r31;r32;r33;r34;r35;r36;r37;r38;r39;r40;r41;r42;r43;r44;r45;r46;r47;r48;r49;r50;r51;r52;r53;r54;r55;r56;r57;r58;r59;r60;r61;r62;r63;r64;r65;r66;r67;r68;r69;r70;r71;r72;r73;r74;r75;r76;r77;r78;r79;r80;r81;r82;r83;r84;r85;r86;r87;r88;r89;r90;r91;r92;r93;r94;r95;r96;r97;r98;r99";
+}
+
+
+/**************************************************************************************************************************************/
+/**************************************************************************************************************************************/
+
+int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2)
+{
+// fprintf(stderr, "(II) unrar_callback called: msg = %d, UserData = %lx, sizeof(UserData) = %ld, P1 = %ld, P2 = %ld\n", msg, UserData, sizeof(UserData), P1, P2);
+
+ // >= 0 => Weiter, -1 => Stop
+ switch(msg)
+ {
+ case UCM_CHANGEVOLUME: {
+ if (P2 == RAR_VOL_ASK) {
+ fprintf(stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1);
+ if (P1)
+ if (access((char*)P1, R_OK) != 0) {
+ fprintf(stderr, "(EE) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK: access test failed - missing part? Error = %s \n", strerror(errno));
+ return -1;
+ }
+ } else
+ if (P2 == RAR_VOL_NOTIFY) {
+ fprintf(stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_NOTIFY, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1);
+ }
+ break;
+ }
+
+ case UCM_PROCESSDATA: {
+ fprintf(stderr, " (II) unrar_callback: UCM_PROCESSDATA message, P1 = %ld, P2 = %ld \n", P1, P2);
+ struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData;
+// printf(" (II) unrar_callback: globs = 0x%lX, UserData = 0x%lX \n", (unsigned long int)globs, UserData);
+ if ((globs) && (globs->extract_callback_func != NULL)) {
+// printf(" (II) unrar_callback: globs->extract_callback_func = 0x%lX, globs->extract_callback_data = 0x%lX \n", (unsigned long int)globs->extract_callback_func, (unsigned long int)globs->extract_callback_data);
+// long int res = globs->extract_callback_func((u_int64_t)P1, (u_int64_t)((u_int64_t)P1 + (u_int64_t)P2), globs->extract_callback_data);
+
+ globs->extract_done += P2;
+ int res = globs->extract_callback_func(globs->extract_done, globs->extract_file_size, globs->extract_callback_data);
+
+// fprintf(stderr, " (II) unrar_callback: res = %d \n", res);
+ if (! res ) {
+ globs->extract_cancelled = TRUE;
+ fprintf(stderr, "(WW) unrar_callback: received cancellation result\n");
+ return -1; // Cancel operation
+ }
+ }
+ break;
+ }
+
+ case UCM_NEEDPASSWORD: {
+ fprintf(stderr, " (II) unrar_callback: UCM_NEEDPASSWORD message, P1 = %ld, P2 = %ld, (char*)P1 = '%s', maxlen = %ld \n", P1, P2, (char*)P1, P2);
+ struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData;
+ if (globs) globs->passwd_callback = TRUE;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int PASCAL unrar_changevol_proc(char *ArcName, int Mode)
+{
+ fprintf(stderr, "(II) unrar_changevol_proc called: ArcName = '%s', Mode = %d\n", ArcName, Mode);
+
+ return 0;
+}
+
+int PASCAL unrar_process_data_proc(unsigned char *Addr, int Size)
+{
+ fprintf(stderr, "(II) unrar_process_data_proc called: Addr = '%s', Size = %d\n", Addr, Size);
+
+ return 0;
+}
+
+
+time_t rar_time_to_unix(unsigned int FileTime)
+{
+ struct tm t;
+ t.tm_sec = (FileTime & 0x1f) * 2;
+ t.tm_min = (FileTime >> 5) & 0x3f;
+ t.tm_hour = (FileTime >> 11) & 0x1f;
+ t.tm_mday = (FileTime >> 16) & 0x1f;
+ t.tm_mon = ((FileTime >> 21) & 0x0f)-1;
+ t.tm_year = (FileTime >> 25) + 80;
+ t.tm_isdst = -1;
+// printf("date: %d-%.2d-%.2d %d:%.2d:%.2d \n", t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
+ return(mktime(&t));
+}
+
+
+TVFSResult VFSOpen(struct TVFSGlobs *globs, char *sName)
+{
+ TVFSResult Result = cVFS_OK;
+
+ globs->files = filelist_tree_new();
+ globs->vfs_filelist = vfs_filelist_new(globs->files);
+ globs->curr_dir = NULL;
+ globs->archive_path = strdup(sName);
+ globs->total_size = 0;
+ globs->passwd_callback = FALSE;
+ fprintf(stderr, "(--) VFSOpen: trying to open archive '%s'...\n", globs->archive_path);
+
+ HANDLE PASCAL handle;
+ struct RAROpenArchiveDataEx *archive_data;
+
+ archive_data = (struct RAROpenArchiveDataEx*) malloc(sizeof(struct RAROpenArchiveDataEx));
+ memset(archive_data, 0, sizeof(struct RAROpenArchiveDataEx));
+ archive_data->ArcName = globs->archive_path;
+ archive_data->CmtBuf = NULL;
+ archive_data->CmtBufSize = 0;
+ archive_data->OpenMode = RAR_OM_LIST;
+
+ handle = RAROpenArchiveEx(archive_data);
+// printf(" handle = %lu \n", (unsigned long int)handle);
+// printf(" archive_data->OpenResult = %d \n", archive_data->OpenResult);
+// printf(" archive_data->CmtState = %d \n", archive_data->CmtState);
+// printf(" archive_data->CmtSize = %d \n", archive_data->CmtSize);
+
+ if ((handle) && (! archive_data->OpenResult))
+ {
+ // Set callbacks
+ RARSetCallback(handle, unrar_callback, (LONG)globs);
+// RARSetChangeVolProc(handle, unrar_changevol_proc);
+// RARSetProcessDataProc(handle, unrar_process_data_proc);
+
+ if (globs->password) {
+ fprintf(stderr, "(II) VFSOpen: Setting password... \n");
+ RARSetPassword(handle, globs->password);
+ }
+
+ struct RARHeaderDataEx *header;
+ header = (struct RARHeaderDataEx*) malloc(sizeof(struct RARHeaderDataEx));
+ memset(header, 0, sizeof(struct RARHeaderDataEx));
+ header->CmtBuf = NULL;
+ header->CmtBufSize = 0;
+
+ int PASCAL res = 0;
+ while ((res = RARReadHeaderEx(handle, header)) == 0)
+ {
+ printf(" header->FileName = '%s', Flags = 0x%x\n", header->FileName, header->Flags);
+
+ // Create a TVFSItem entry and fill all info
+ struct TVFSItem *item = (struct TVFSItem*)malloc(sizeof(struct TVFSItem));
+ memset(item, 0, sizeof(struct TVFSItem));
+
+ item->iSize = (u_int64_t)((u_int64_t)(header->UnpSizeHigh * 0x100000000) + (u_int64_t)header->UnpSize);
+ globs->total_size += item->iSize;
+ if ((header->Flags & 0x00e0 /* LHD_WINDOWMASK */ ) == 0x00e0 /* LHD_DIRECTORY */)
+ item->ItemType = vDirectory;
+ else item->ItemType = vRegular;
+ if ((header->Flags & 0x0004) == 0x0004) globs->need_password = TRUE;
+
+ switch (header->HostOS)
+ {
+ case HOST_MSDOS:
+ case HOST_OS2:
+ case HOST_WIN32:
+ if (header->FileAttr & 0x10) header->FileAttr = 0x41ff | header->FileAttr;
+ else
+ if (header->FileAttr & 1) header->FileAttr = 0x8124 | header->FileAttr;
+ else header->FileAttr = 0x81b6 | header->FileAttr;
+ break;
+ }
+
+ item->iMode = header->FileAttr;
+ item->iUID = geteuid();
+ item->iGID = getegid();
+ item->m_time = rar_time_to_unix(header->FileTime);
+ item->c_time = item->m_time;
+ item->a_time = item->m_time;
+
+ // Add item to the global list and continue with next file
+ filelist_tree_add_item(globs->files, header->FileName, item, 0);
+ int PASCAL res2 = RARProcessFile(handle, RAR_SKIP, NULL, NULL);
+ if (res2) printf("RARProcessFile result = %d\n", res2);
+ }
+// printf("\nRARReadHeader result = %d\n", res);
+ if (res != ERAR_END_ARCHIVE) {
+ fprintf(stderr, "(EE) VFSOpen: RARReadHeader result = %d\n", res);
+ Result = cVFS_Failed;
+ if ((res == ERAR_MISSING_PASSWORD) || ((res == ERAR_BAD_DATA) && (globs->passwd_callback)))
+ Result = cVFS_BadPassword;
+ }
+ free(header);
+
+ res = RARCloseArchive(handle);
+ if (res) {
+ fprintf(stderr, "(EE) VFSOpen: RARCloseArchive result = %d\n", res);
+ }
+ } else {
+ fprintf(stderr, "(EE) VFSOpen: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult);
+ Result = cVFS_Failed;
+ }
+
+ free(archive_data);
+ fprintf(stderr, "(II) VFSOpen: done. \n");
+ if (globs->need_password) printf("Password present.\n");
+ printf("\n\nList of items:\n");
+ filelist_tree_print(globs->files);
+
+ return Result;
+}
+
+
+TVFSResult VFSClose(struct TVFSGlobs *globs)
+{
+ if (globs) {
+ fprintf(stderr, "(II) VFSClose: Freeing objects...\n");
+ if (globs->vfs_filelist) vfs_filelist_free(globs->vfs_filelist);
+ if (globs->files) filelist_tree_free(globs->files);
+ if (globs->archive_path) free(globs->archive_path);
+ if (globs->curr_dir) free(globs->curr_dir);
+ if (globs->password) free(globs->password);
+ }
+ return cVFS_OK;
+}
+
+char *VFSGetPath(struct TVFSGlobs *globs)
+{
+ return include_trailing_path_sep(globs->curr_dir);
+}
+
+u_int64_t VFSGetFileSystemFree(struct TVFSGlobs *globs, char *APath)
+{
+ return 0;
+}
+
+u_int64_t VFSGetFileSystemSize(struct TVFSGlobs *globs, char *APath)
+{
+ return globs->total_size;
+}
+
+
+
+
+/******************************************************************************************************/
+
+TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath)
+{
+ if (NewPath == NULL) {
+ printf("(EE) VFSChangeDir: NewPath is NULL!\n");
+ return cVFS_Failed;
+ }
+
+ globs->curr_dir = vfs_filelist_change_dir(globs->vfs_filelist, NewPath);
+ if (globs->curr_dir) return cVFS_OK;
+ else return cVFS_Failed;
+}
+
+
+int VFSLogin(struct TVFSGlobs *globs, char *user, char *pass)
+{
+ return cVFS_Not_Supported;
+}
+
+int VFSSetPassword(struct TVFSGlobs *globs, char *pass)
+{
+ printf ("(II) VFSSetPassword: Going to set the password...\n");
+ if (globs->password) free(globs->password);
+ globs->password = strdup(pass);
+ return cVFS_OK;
+}
+
+int VFSGetPasswordRequired(struct TVFSGlobs *globs)
+{
+ if (globs) return globs->need_password;
+ return FALSE;
+}
+
+
+/******************************************************************************************************/
+
+TVFSResult VFSListFirst(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item)
+{
+ if (sDir == NULL) {
+ printf("(EE) VFSListFirst: sDir is NULL!\n");
+ return cVFS_Failed;
+ }
+ printf ("(--) VFSListFirst: Going to list all items in '%s'\n", sDir);
+
+ return vfs_filelist_list_first(globs->vfs_filelist, sDir, Item);
+}
+
+TVFSResult VFSListNext(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item)
+{
+ return vfs_filelist_list_next(globs->vfs_filelist, sDir, Item);
+}
+
+TVFSResult VFSListClose(struct TVFSGlobs *globs)
+{
+ return vfs_filelist_list_close(globs->vfs_filelist);
+}
+
+
+/******************************************************************************************************/
+long VFSFileExists(struct TVFSGlobs *globs, const char *FileName, const long Use_lstat)
+{
+ if (! globs) return FALSE;
+ return vfs_filelist_file_exists(globs->vfs_filelist, FileName, Use_lstat);
+}
+
+TVFSResult VFSFileInfo(struct TVFSGlobs *globs, char *AFileName, struct TVFSItem *Item)
+{
+ printf("(--) VFSFileInfo: requested info for object '%s'\n", AFileName);
+ if (!globs) return cVFS_Failed;
+ return vfs_filelist_file_info(globs->vfs_filelist, AFileName, Item);
+}
+
+
+/******************************************************************************************************/
+/** Recursive tree size counting */
+/************** ****************/
+
+u_int64_t VFSGetDirSize(struct TVFSGlobs *globs, char *APath)
+{
+ if (! globs) return 0;
+ return vfs_filelist_get_dir_size(globs->vfs_filelist, APath);
+}
+
+void VFSBreakGetDirSize(struct TVFSGlobs *globs)
+{
+ printf("(WW) VFSBreakGetDirSize: calling break\n");
+ if (globs) vfs_filelist_get_dir_size_break(globs->vfs_filelist);
+}
+
+
+/******************************************************************************************************/
+/** Methods modifying the archive */
+/************** ****************/
+
+TVFSResult VFSMkDir(struct TVFSGlobs *globs, const char *sDirName)
+{
+ printf("(WW) VFSMkDir: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+TVFSResult VFSRemove(struct TVFSGlobs *globs, const char *APath)
+{
+ printf("(WW) VFSRemove: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+TVFSResult VFSRename(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName)
+{
+ printf("(WW) VFSRename: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+TVFSResult VFSMakeSymLink(struct TVFSGlobs *globs, const char *NewFileName, const char *PointTo)
+{
+ printf("(WW) VFSMakeSymLink: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+TVFSResult VFSChmod(struct TVFSGlobs *globs, const char *FileName, const uint Mode)
+{
+ printf("(WW) VFSChmod: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+TVFSResult VFSChown(struct TVFSGlobs *globs, const char *FileName, const uint UID, const uint GID)
+{
+ printf("(WW) VFSChown: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+TVFSResult VFSChangeTimes(struct TVFSGlobs *globs, char *APath, long mtime, long atime)
+{
+ printf("(WW) VFSChangeTimes: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////
+
+TVFSFileDes VFSOpenFile(struct TVFSGlobs *globs, const char *APath, int Mode, int *Error)
+{
+ *Error = cVFS_Not_Supported;
+ return (TVFSFileDes)0;
+}
+
+TVFSResult VFSCloseFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor)
+{
+ return cVFS_Not_Supported;
+}
+
+u_int64_t VFSFileSeek(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, u_int64_t AbsoluteOffset, int *Error)
+{
+ *Error = cVFS_Not_Supported;
+ return 0;
+}
+
+int VFSReadFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int ABlockSize, int *Error)
+{
+ *Error = cVFS_Not_Supported;
+ return 0;
+}
+
+int VFSWriteFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int BytesCount, int *Error)
+{
+ *Error = cVFS_Not_Supported;
+ return 0;
+}
+
+void VFSSetBlockSize(struct TVFSGlobs *globs, int Value)
+{
+ globs->block_size = Value;
+}
+
+int VFSIsOnSameFS(struct TVFSGlobs *globs, const char *Path1, const char *Path2)
+{
+ printf("(WW) VFSIsOnSameFS: Not supported in UNRAR plugin.\n");
+ return TRUE;
+}
+
+int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path2)
+{
+ printf("(WW) VFSTwoSameFiles: Not supported in ZIP archives, comparing by paths.\n");
+ return compare_two_same_files(Path1, Path2);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////
+
+
+TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append)
+{
+ if ((sSrcName == NULL) || (sDstName == NULL) || (strlen(sSrcName) < 1) || (strlen(sDstName) < 1)) {
+ printf("(EE) VFSCopyOut: The value of 'sSrcName' or 'sDstName' is NULL or empty\n");
+ return cVFS_Failed;
+ }
+
+ printf("(II) VFSCopyOut: copying file '%s' out to '%s'\n", sSrcName, sDstName);
+
+ TVFSResult Result = cVFS_OK;
+
+ char *src;
+ if (! IS_DIR_SEP(*sSrcName)) src = g_build_path("/", globs->curr_dir, sSrcName, NULL);
+ else src = g_strdup(sSrcName);
+
+ printf("(II) VFSCopyOut: new src path: '%s'\n", src);
+
+// printf("(II) VFSCopyOut: pCallBackProgress = 0x%lX, data = 0x%lX\n", (unsigned long int)pCallBackProgress, (unsigned long int)data);
+ globs->extract_callback_data = data;
+ globs->extract_callback_func = pCallBackProgress;
+
+ HANDLE PASCAL handle;
+ struct RAROpenArchiveDataEx *archive_data;
+
+ archive_data = (struct RAROpenArchiveDataEx*) malloc(sizeof(struct RAROpenArchiveDataEx));
+ memset(archive_data, 0, sizeof(struct RAROpenArchiveDataEx));
+ archive_data->ArcName = globs->archive_path;
+ archive_data->CmtBuf = NULL;
+ archive_data->CmtBufSize = 0;
+ archive_data->OpenMode = RAR_OM_EXTRACT;
+
+ handle = RAROpenArchiveEx(archive_data);
+// printf(" handle = %lu \n", (unsigned long int)handle);
+// printf(" archive_data->OpenResult = %d \n", archive_data->OpenResult);
+// printf(" archive_data->CmtState = %d \n", archive_data->CmtState);
+// printf(" archive_data->CmtSize = %d \n", archive_data->CmtSize);
+// printf("sizeof(TVFSResult) = %ld \n", sizeof(TVFSResult));
+
+ if ((handle) && (! archive_data->OpenResult))
+ {
+ // Set callbacks
+// printf(" setting callback: globs = 0x%lX, (unsigned long int)globs = 0x%lX, (LONG)globs = 0x%lX\n", globs, (unsigned long int)globs, (LONG)globs);
+ RARSetCallback(handle, unrar_callback, (LONG)globs);
+// RARSetChangeVolProc(handle, unrar_changevol_proc);
+// RARSetProcessDataProc(handle, unrar_process_data_proc);
+
+ if (globs->password) {
+ printf("(II) VFSCopyOut: Setting password... \n");
+ RARSetPassword(handle, globs->password);
+ }
+
+ struct RARHeaderDataEx *header;
+ header = (struct RARHeaderDataEx*) malloc(sizeof(struct RARHeaderDataEx));
+ memset(header, 0, sizeof(struct RARHeaderDataEx));
+ header->CmtBuf = NULL;
+ header->CmtBufSize = 0;
+
+ int res = 0;
+ while ((res = RARReadHeaderEx(handle, header)) == 0)
+ {
+ char *ssrc = src;
+ char *asrc = header->FileName;
+ if (IS_DIR_SEP(*ssrc)) ssrc++;
+ if (IS_DIR_SEP(*asrc)) asrc++;
+ if (strcmp(ssrc, asrc) == 0) {
+// fprintf(stderr, "(II) VFSCopyOut: extract_file_path(sDstName) = '%s', extract_file_name(sDstName) = '%s' \n", extract_file_path(sDstName), extract_file_name(sDstName));
+ globs->extract_done = 0;
+ globs->extract_file_size = (u_int64_t)((u_int64_t)(header->UnpSizeHigh * 0x100000000) + (u_int64_t)header->UnpSize);
+ globs->extract_cancelled = FALSE;
+
+ int res2 = RARProcessFile(handle, RAR_EXTRACT, NULL, (char *)sDstName);
+
+ if (globs->extract_cancelled) Result = cVFS_Cancelled;
+ else
+ if (res2) {
+ fprintf(stderr, "(EE) VFSCopyOut: RARProcessFile result = %d\n", res2);
+ Result = cVFS_ReadErr;
+ }
+ break;
+ } else {
+ int res2 = RARProcessFile(handle, RAR_SKIP, NULL, NULL);
+ if (res2) {
+ fprintf(stderr, "(EE) VFSCopyOut: RARProcessFile result = %d\n", res2);
+ Result = cVFS_ReadErr;
+ }
+ }
+ }
+
+ if ((res != ERAR_END_ARCHIVE) && (res)) {
+ fprintf(stderr, "(EE) VFSCopyOut: RARReadHeader result = %d\n", res);
+ switch (res) {
+ case ERAR_NO_MEMORY:
+ case ERAR_SMALL_BUF:
+ Result = cVFS_mallocFailed;
+ break;
+ case ERAR_BAD_DATA:
+ case ERAR_BAD_ARCHIVE:
+ case ERAR_UNKNOWN_FORMAT:
+ case ERAR_EOPEN:
+ case ERAR_ECLOSE:
+ case ERAR_EREAD:
+ Result = cVFS_ReadErr;
+ break;
+ case ERAR_ECREATE:
+ case ERAR_EWRITE:
+ Result = cVFS_WriteErr;
+ break;
+ case ERAR_MISSING_PASSWORD:
+ Result = cVFS_BadPassword;
+ break;
+ case ERAR_UNKNOWN:
+ default:
+ Result = cVFS_WriteErr;
+ break;
+ }
+ }
+
+ free(header);
+
+ res = RARCloseArchive(handle);
+ if (res) {
+ fprintf(stderr, "(EE) VFSCopyOut: RARCloseArchive result = %d\n", res);
+ Result = cVFS_ReadErr;
+ }
+ } else {
+ fprintf(stderr, "(EE) VFSCopyOut: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult);
+ Result = cVFS_ReadErr;
+ }
+
+ free(archive_data);
+ g_free(src);
+
+ fprintf(stderr, "(II) VFSCopyOut: finished. \n");
+ return Result;
+}
+
+TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append)
+{
+ printf("(WW) VFSCopyIn: Not supported in UNRAR plugin.\n");
+ return cVFS_Not_Supported;
+}
+
+
+
+
+/**********
+ * TODO:
+ * - no error reporting when archive is corrupted
+ * - archive testing (needs new VFS API)
+ *
+ ***/
diff --git a/unrar/unrar/arccmt.cpp b/unrar/unrar/arccmt.cpp
new file mode 100644
index 0000000..6ada2f0
--- /dev/null
+++ b/unrar/unrar/arccmt.cpp
@@ -0,0 +1,215 @@
+bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
+{
+ 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,CmtDataW)!=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)
+ {
+#ifdef NOCRYPT
+ return(false);
+#else
+ UnpCmtLength=GetByte()+(GetByte()<<8);
+ CmtLength-=2;
+ DataIO.SetCmt13Encryption();
+#endif
+ }
+ 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)
+ {
+ int CmtSize=CmtData->Size();
+ OemToCharBuff((char *)CmtData->Addr(),(char *)CmtData->Addr(),CmtSize);
+
+ if (CmtDataW!=NULL)
+ {
+ CmtDataW->Alloc(CmtSize+1);
+ CmtData->Push(0);
+ CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
+ CmtData->Alloc(CmtSize);
+ CmtDataW->Alloc(strlenw(CmtDataW->Addr()));
+ }
+ }
+#endif
+ return(CmtData->Size()>0);
+}
+
+
+int Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
+{
+ bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
+ if (!ReadSubData(CmtData,NULL))
+ return(0);
+ int CmtSize=CmtData->Size();
+ if (Unicode)
+ {
+ CmtSize/=2;
+ Array<wchar> DataW(CmtSize+1);
+ RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
+ DataW[CmtSize]=0;
+ int DestSize=CmtSize*4;
+ CmtData->Alloc(DestSize+1);
+ WideToChar(DataW.Addr(),(char *)CmtData->Addr(),DestSize);
+ (*CmtData)[DestSize]=0;
+ CmtSize=strlen((char *)CmtData->Addr());
+ CmtData->Alloc(CmtSize);
+ if (CmtDataW!=NULL)
+ {
+ *CmtDataW=DataW;
+ CmtDataW->Alloc(CmtSize);
+ }
+ }
+ else
+ if (CmtDataW!=NULL)
+ {
+ CmtData->Push(0);
+ CmtDataW->Alloc(CmtSize+1);
+ CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
+ CmtData->Alloc(CmtSize);
+ CmtDataW->Alloc(strlenw(CmtDataW->Addr()));
+ }
+ return(CmtSize);
+}
+
+
+void Archive::ViewComment()
+{
+#ifndef GUI
+ if (Cmd->DisableComment)
+ return;
+ Array<byte> CmtBuf;
+ if (GetComment(&CmtBuf,NULL))
+ {
+ 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<char> CmtBuf(MaxSize);
+ SaveFilePos SavePos(*this);
+ Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
+ Int64 SaveCurBlockPos=CurBlockPos;
+ Int64 SaveNextBlockPos=NextBlockPos;
+
+ int Size=ReadHeader();
+
+ CurBlockPos=SaveCurBlockPos;
+ NextBlockPos=SaveNextBlockPos;
+
+ if (Size<7 || CommHead.HeadType!=COMM_HEAD)
+ return;
+ if (CommHead.HeadCRC!=HeaderCRC)
+ {
+#ifndef GUI
+ Log(FileName,St(MLogCommHead));
+#endif
+ return;
+ }
+ if (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER ||
+ CommHead.Method > 0x30 || CommHead.UnpSize > MaxSize)
+ return;
+ Read(&CmtBuf[0],CommHead.UnpSize);
+ if (CommHead.CommCRC!=((~CRC(0xffffffff,&CmtBuf[0],CommHead.UnpSize)&0xffff)))
+ {
+ Log(FileName,St(MLogBrokFCmt));
+ }
+ else
+ {
+ OutComment(&CmtBuf[0],CommHead.UnpSize);
+#ifndef GUI
+ mprintf("\n");
+#endif
+ }
+}
+#endif
diff --git a/unrar/unrar/archive.cpp b/unrar/unrar/archive.cpp
new file mode 100644
index 0000000..3460f99
--- /dev/null
+++ b/unrar/unrar/archive.cpp
@@ -0,0 +1,267 @@
+#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<char> Buffer(MAXSFXSIZE);
+ long CurPos=int64to32(Tell());
+ int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
+ for (int I=0;I<ReadSize;I++)
+ if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I]))
+ {
+ if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
+ {
+ char *D=&Buffer[28-CurPos];
+ if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
+ 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;
+
+ if (NewMhd.EncryptVer>UNP_VER)
+ {
+#ifdef RARDLL
+ Cmd->DllError=ERAR_UNKNOWN_FORMAT;
+#else
+ ErrHandler.SetErrorCode(WARNING);
+ #if !defined(SILENT) && !defined(SFX_MODULE)
+ Log(FileName,St(MUnknownMeth),FileName);
+ Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
+ #endif
+#endif
+ return(false);
+ }
+#ifdef RARDLL
+ SilentOpen=true;
+#endif
+
+ //if not encrypted, we'll check it below
+ NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0;
+
+ 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;
+ }
+ if (!Volume || !NotFirstVolume)
+ {
+ strcpy(FirstVolumeName,FileName);
+ strcpyw(FirstVolumeNameW,FileNameW);
+ }
+
+ 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/unrar/archive.hpp b/unrar/unrar/archive.hpp
new file mode 100644
index 0000000..1e0675e
--- /dev/null
+++ b/unrar/unrar/archive.hpp
@@ -0,0 +1,126 @@
+#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 ConvertNameCase(char *Name);
+ void ConvertNameCase(wchar *Name);
+ void ConvertUnknownHeader();
+ int ReadOldHeader();
+ void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array<byte> &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<byte> *CmtData,Array<wchar> *CmtDataW);
+ void ViewComment();
+ void ViewFileComment();
+ void SetLatestTime(RarTime *NewTime);
+ void SeekToNext();
+ bool CheckAccess();
+ bool IsArcDir();
+ bool IsArcLabel();
+ void ConvertAttributes();
+ int GetRecoverySize(bool Required);
+ void VolSubtractHeaderSize(int SubSize);
+ void AddSubData(byte *SrcData,int DataSize,File *SrcFile,char *Name,bool AllowSplit);
+ bool ReadSubData(Array<byte> *UnpData,File *DestFile);
+ int GetHeaderType() {return(CurHeaderType);};
+ int ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW);
+ void WriteCommentData(byte *Data,int DataSize,bool FileComment);
+ RAROptions* GetRAROptions() {return(Cmd);}
+ void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
+
+ 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/unrar/arcread.cpp b/unrar/unrar/arcread.cpp
new file mode 100644
index 0000000..43a23db
--- /dev/null
+++ b/unrar/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,false,NewMhd.EncryptVer>=36);
+ 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.HeadSize<SIZEOF_SHORTBLOCKHEAD)
+ {
+#ifndef SHELL_EXT
+ Log(FileName,St(MLogFileHead),"???");
+#endif
+ BrokenFileHeader=true;
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return(0);
+ }
+
+ if (ShortBlock.HeadType==COMM_HEAD)
+ Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
+ else
+ if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0)
+ Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
+ else
+ Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);
+
+ NextBlockPos=CurBlockPos+ShortBlock.HeadSize;
+
+ switch(ShortBlock.HeadType)
+ {
+ case MAIN_HEAD:
+ *(BaseBlock *)&NewMhd=ShortBlock;
+ Raw.Get(NewMhd.HighPosAV);
+ Raw.Get(NewMhd.PosAV);
+ if (NewMhd.Flags & MHD_ENCRYPTVER)
+ Raw.Get(NewMhd.EncryptVer);
+ break;
+ case ENDARC_HEAD:
+ *(BaseBlock *)&EndArcHead=ShortBlock;
+ if (EndArcHead.Flags & EARC_DATACRC)
+ Raw.Get(EndArcHead.ArcDataCRC);
+ if (EndArcHead.Flags & EARC_VOLNUMBER)
+ Raw.Get(EndArcHead.VolNumber);
+ break;
+ case FILE_HEAD:
+ case NEWSUB_HEAD:
+ {
+ FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
+ *(BaseBlock *)hd=ShortBlock;
+ Raw.Get(hd->PackSize);
+ 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;
+
+ strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));
+
+ 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);
+ if (Length==hd->NameSize)
+ {
+ UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
+ WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1);
+ ExtToInt(hd->FileName,hd->FileName);
+ }
+ else
+ {
+ Length++;
+ 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;J<count;J++)
+ {
+ byte CurByte;
+ Raw.Get(CurByte);
+ rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
+ }
+ CurTime->SetLocal(&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;
+}
+
+
+#ifndef SHELL_EXT
+bool Archive::ReadSubData(Array<byte> *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*/36)
+ {
+#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,
+ SubHead.UnpVer>=36);
+ 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/unrar/array.hpp b/unrar/unrar/array.hpp
new file mode 100644
index 0000000..1130bfb
--- /dev/null
+++ b/unrar/unrar/array.hpp
@@ -0,0 +1,122 @@
+#ifndef _RAR_ARRAY_
+#define _RAR_ARRAY_
+
+extern ErrorHandler ErrHandler;
+
+template <class T> 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<T> &Src);
+ void Push(T Item);
+ T* Addr() {return(Buffer);}
+};
+
+template <class T> void Array<T>::CleanData()
+{
+ Buffer=NULL;
+ BufSize=0;
+ AllocSize=0;
+}
+
+
+template <class T> Array<T>::Array()
+{
+ CleanData();
+}
+
+
+template <class T> Array<T>::Array(int Size)
+{
+ Buffer=(T *)rarmalloc(sizeof(T)*Size);
+ if (Buffer==NULL && Size!=0)
+ ErrHandler.MemoryError();
+
+ AllocSize=BufSize=Size;
+}
+
+
+template <class T> Array<T>::~Array()
+{
+ if (Buffer!=NULL)
+ rarfree(Buffer);
+}
+
+
+template <class T> inline T& Array<T>::operator [](int Item)
+{
+ return(Buffer[Item]);
+}
+
+
+template <class T> inline int Array<T>::Size()
+{
+ return(BufSize);
+}
+
+
+template <class T> void Array<T>::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 <class T> void Array<T>::Alloc(int Items)
+{
+ if (Items>AllocSize)
+ Add(Items-BufSize);
+ else
+ BufSize=Items;
+}
+
+
+template <class T> void Array<T>::Reset()
+{
+ if (Buffer!=NULL)
+ {
+ rarfree(Buffer);
+ Buffer=NULL;
+ }
+ BufSize=0;
+ AllocSize=0;
+}
+
+
+template <class T> void Array<T>::operator =(Array<T> &Src)
+{
+ Reset();
+ Alloc(Src.BufSize);
+ if (Src.BufSize!=0)
+ memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
+}
+
+
+template <class T> void Array<T>::Push(T Item)
+{
+ Add(1);
+ (*this)[Size()-1]=Item;
+}
+
+#endif
diff --git a/unrar/unrar/beosea.cpp b/unrar/unrar/beosea.cpp
new file mode 100644
index 0000000..86eb7d4
--- /dev/null
+++ b/unrar/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<byte> UnpData(Arc.EAHead.UnpSize);
+ DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
+ DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
+ DataIO.EnableShowProgress(false);
+ DataIO.SetFiles(&Arc,NULL);
+ Unpack.SetDestSize(Arc.EAHead.UnpSize);
+ Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
+
+ if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
+ {
+ Log(Arc.FileName,St(MEABroken),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+ int fd = open(FileName,O_WRONLY);
+ if (fd==-1)
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ return;
+ }
+
+ int AttrPos=0;
+ while (AttrPos<Arc.EAHead.UnpSize)
+ {
+ unsigned char *CurItem=&UnpData[AttrPos];
+ int NameSize=CurItem[0]+((int)CurItem[1]<<8);
+ int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
+ int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
+ char Name[1024];
+ if (NameSize>=sizeof(Name))
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ break;
+ }
+ memcpy(Name,CurItem+10,NameSize);
+ Name[NameSize]=0;
+ if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ break;
+ }
+ AttrPos+=10+NameSize+Size;
+ }
+ close(fd);
+ mprintf(St(MShowEA));
+}
+
+
+void ExtractBeEANew(Archive &Arc,char *FileName)
+{
+ Array<byte> SubData;
+ if (!Arc.ReadSubData(&SubData,NULL))
+ return;
+
+ int fd = open(FileName,O_WRONLY);
+ if (fd==-1)
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ return;
+ }
+
+ int AttrPos=0;
+ while (AttrPos<Arc.EAHead.UnpSize)
+ {
+ unsigned char *CurItem=&SubData[AttrPos];
+ int NameSize=CurItem[0]+((int)CurItem[1]<<8);
+ int Type=CurItem[2]+((int)CurItem[3]<<8)+((int)CurItem[4]<<16)+((int)CurItem[5]<<24);
+ int Size=CurItem[6]+((int)CurItem[7]<<8)+((int)CurItem[8]<<16)+((int)CurItem[9]<<24);
+ char Name[1024];
+ if (NameSize>=sizeof(Name))
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ break;
+ }
+ memcpy(Name,CurItem+10,NameSize);
+ Name[NameSize]=0;
+ if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ break;
+ }
+ AttrPos+=10+NameSize+Size;
+ }
+ close(fd);
+ mprintf(St(MShowEA));
+}
+
diff --git a/unrar/unrar/cmddata.cpp b/unrar/unrar/cmddata.cpp
new file mode 100644
index 0000000..41f3dd7
--- /dev/null
+++ b/unrar/unrar/cmddata.cpp
@@ -0,0 +1,1287 @@
+#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)
+void CommandData::ParseArg(char *Arg,wchar *ArgW)
+{
+ if (IsSwitch(*Arg) && !NoMoreSwitches)
+ if (Arg[1]=='-')
+ NoMoreSwitches=true;
+ else
+ ProcessSwitch(&Arg[1]);
+ else
+ if (*Command==0)
+ {
+ strncpyz(Command,Arg,ASIZE(Command));
+ if (ArgW!=NULL)
+ strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0]));
+ if (etoupper(*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=etoupper(*Command);
+ if (*Command!='I' && *Command!='S')
+ strupper(Command);
+#endif
+ }
+ else
+ if (*ArcName==0)
+ {
+ strncpyz(ArcName,Arg,ASIZE(ArcName));
+ if (ArgW!=NULL)
+ strncpyzw(ArcNameW,ArgW,ASIZE(ArcNameW));
+ }
+ else
+ {
+ int Length=strlen(Arg);
+ char EndChar=Arg[Length-1];
+ char CmdChar=etoupper(*Command);
+ bool Add=strchr("AFUM",CmdChar)!=NULL;
+ bool Extract=CmdChar=='X' || CmdChar=='E';
+ if ((IsDriveDiv(EndChar) || IsPathDiv(EndChar)) && !Add)
+ {
+ strncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
+ if (ArgW!=NULL)
+ strncpyzw(ExtrPathW,ArgW,ASIZE(ExtrPathW));
+ }
+ 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))
+ {
+ FileLists=true;
+
+ RAR_CHARSET Charset=FilelistCharset;
+
+#if defined(_WIN_32) && !defined(GUI)
+ // for compatibility reasons we use OEM encoding
+ // in Win32 console version by default
+
+ if (Charset==RCH_DEFAULT)
+ Charset=RCH_OEM;
+#endif
+
+ ReadTextFile(Arg+1,FileArgs,false,true,Charset,true,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=etoupper(*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
+
+
+
+// return 'false' if -cfg- is present and preprocess switches
+// which must be processed before the rest of command line
+
+#ifndef SFX_MODULE
+bool CommandData::IsConfigEnabled(int argc,char *argv[])
+{
+ bool ConfigEnabled=true;
+ for (int I=1;I<argc;I++)
+ if (IsSwitch(*argv[I]))
+ {
+ if (stricomp(&argv[I][1],"cfg-")==0)
+ ConfigEnabled=false;
+#ifndef GUI
+ if (strnicomp(&argv[I][1],"ilog",4)==0)
+ {
+ // ensure that correct log file name is already set
+ // if we need to report an error when processing the command line
+ ProcessSwitch(&argv[I][1]);
+ InitLogOptions(LogName);
+ }
+#endif
+ if (strnicomp(&argv[I][1],"sc",2)==0)
+ {
+ // process -cs before reading any file lists
+ ProcessSwitch(&argv[I][1]);
+ }
+ }
+ return(ConfigEnabled);
+}
+#endif
+
+
+#if !defined(GUI) && !defined(SFX_MODULE)
+void CommandData::ReadConfig(int argc,char *argv[])
+{
+ StringList List;
+ if (ReadTextFile(DefConfigName,&List,true))
+ {
+ char *Str;
+ while ((Str=List.GetString())!=NULL)
+ {
+ while (isspace(*Str))
+ Str++;
+ if (strnicomp(Str,"switches=",9)==0)
+ ProcessSwitchesString(Str+9);
+ }
+ }
+}
+#endif
+
+
+#if !defined(SFX_MODULE) && !defined(_WIN_CE)
+void CommandData::ProcessSwitchesString(char *Str)
+{
+ while (*Str)
+ {
+ while (!IsSwitch(*Str) && *Str!=0)
+ Str++;
+ if (*Str==0)
+ break;
+ char *Next=Str;
+ while (!(Next[0]==' ' && IsSwitch(Next[1])) && *Next!=0)
+ Next++;
+ char NextChar=*Next;
+ *Next=0;
+ ProcessSwitch(Str+1);
+ *Next=NextChar;
+ Str=Next;
+ }
+}
+#endif
+
+
+#if !defined(SFX_MODULE)
+void CommandData::ProcessSwitch(char *Switch)
+{
+
+ switch(etoupper(Switch[0]))
+ {
+ case 'I':
+ if (strnicomp(&Switch[1],"LOG",3)==0)
+ {
+ strncpyz(LogName,Switch[4] ? Switch+4:DefLogName,ASIZE(LogName));
+ break;
+ }
+ if (stricomp(&Switch[1],"SND")==0)
+ {
+ Sound=true;
+ break;
+ }
+ if (stricomp(&Switch[1],"ERR")==0)
+ {
+ MsgStream=MSG_STDERR;
+ break;
+ }
+ if (strnicomp(&Switch[1],"EML",3)==0)
+ {
+ strncpyz(EmailTo,Switch[4] ? Switch+4:"@",ASIZE(EmailTo));
+ EmailTo[sizeof(EmailTo)-1]=0;
+ break;
+ }
+ if (stricomp(&Switch[1],"NUL")==0)
+ {
+ MsgStream=MSG_NULL;
+ break;
+ }
+ if (etoupper(Switch[1])=='D')
+ {
+ for (int I=2;Switch[I]!=0;I++)
+ switch(etoupper(Switch[I]))
+ {
+ case 'Q':
+ MsgStream=MSG_ERRONLY;
+ break;
+ case 'C':
+ DisableCopyright=true;
+ break;
+ case 'D':
+ DisableDone=true;
+ break;
+ case 'P':
+ DisablePercentage=true;
+ break;
+ }
+ break;
+ }
+ if (stricomp(&Switch[1],"OFF")==0)
+ {
+ Shutdown=true;
+ break;
+ }
+ break;
+ case 'T':
+ switch(etoupper(Switch[1]))
+ {
+ case 'K':
+ ArcTime=ARCTIME_KEEP;
+ break;
+ case 'L':
+ ArcTime=ARCTIME_LATEST;
+ break;
+ case 'O':
+ FileTimeBefore.SetAgeText(Switch+2);
+ break;
+ case 'N':
+ FileTimeAfter.SetAgeText(Switch+2);
+ break;
+ case 'B':
+ FileTimeBefore.SetIsoText(Switch+2);
+ break;
+ case 'A':
+ FileTimeAfter.SetIsoText(Switch+2);
+ break;
+ case 'S':
+ {
+ EXTTIME_MODE Mode=EXTTIME_HIGH3;
+ bool CommonMode=Switch[2]>='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(etoupper(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(etoupper(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;
+ strncpyz(GenerateMask,Switch+2,ASIZE(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;
+ default:
+ BadSwitch(Switch);
+ break;
+ }
+ break;
+ case 'D':
+ if (Switch[2]==0)
+ switch(etoupper(Switch[1]))
+ {
+ case 'S':
+ DisableSortSolid=true;
+ break;
+ case 'H':
+ OpenShared=true;
+ break;
+ case 'F':
+ DeleteFiles=true;
+ break;
+ }
+ break;
+ case 'O':
+ switch(etoupper(Switch[1]))
+ {
+ case '+':
+ Overwrite=OVERWRITE_ALL;
+ break;
+ case '-':
+ Overwrite=OVERWRITE_NONE;
+ break;
+ case 'R':
+ Overwrite=OVERWRITE_AUTORENAME;
+ 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(etoupper(Switch[1]))
+ {
+ case 0:
+ Recurse=RECURSE_ALWAYS;
+ break;
+ case '-':
+ Recurse=0;
+ break;
+ case '0':
+ Recurse=RECURSE_WILDCARDS;
+ break;
+#ifndef _WIN_CE
+ case 'I':
+ {
+ Priority=atoi(Switch+2);
+ char *ChPtr=strchr(Switch+2,':');
+ if (ChPtr!=NULL)
+ {
+ SleepTime=atoi(ChPtr+1);
+ InitSystemOptions(SleepTime);
+ }
+ SetPriority(Priority);
+ }
+ break;
+#endif
+ }
+ break;
+ case 'Y':
+ AllYes=true;
+ break;
+ case 'N':
+ case 'X':
+ if (Switch[1]!=0)
+ {
+ StringList *Args=etoupper(Switch[0])=='N' ? InclArgs:ExclArgs;
+ if (Switch[1]=='@' && !IsWildcard(Switch))
+ {
+ RAR_CHARSET Charset=FilelistCharset;
+
+#if defined(_WIN_32) && !defined(GUI)
+ // for compatibility reasons we use OEM encoding
+ // in Win32 console version by default
+
+ if (Charset==RCH_DEFAULT)
+ Charset=RCH_OEM;
+#endif
+
+ ReadTextFile(Switch+2,Args,false,true,Charset,true,true);
+ }
+ else
+ Args->AddString(Switch+1);
+ }
+ break;
+ case 'E':
+ switch(etoupper(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
+ strncpyz(Password,Switch+1,ASIZE(Password));
+ break;
+ case 'H':
+ if (etoupper(Switch[1])=='P')
+ {
+ EncryptHeaders=true;
+ if (Switch[2]!=0)
+ strncpyz(Password,Switch+2,ASIZE(Password));
+ else
+ if (*Password==0)
+ {
+ GetPassword(PASSWORD_GLOBAL,NULL,Password,sizeof(Password));
+ eprintf("\n");
+ }
+ }
+ break;
+ case 'Z':
+ strncpyz(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",ASIZE(CommentFile));
+ break;
+ case 'M':
+ switch(etoupper(Switch[1]))
+ {
+ case 'C':
+ {
+ char *Str=Switch+2;
+ if (*Str=='-')
+ for (int I=0;I<sizeof(FilterModes)/sizeof(FilterModes[0]);I++)
+ FilterModes[I].State=FILTER_DISABLE;
+ else
+ while (*Str)
+ {
+ int Param1=0,Param2=0;
+ FilterState State=FILTER_AUTO;
+ FilterType Type=FILTER_NONE;
+ if (isdigit(*Str))
+ {
+ Param1=atoi(Str);
+ while (isdigit(*Str))
+ Str++;
+ }
+ if (*Str==':' && isdigit(Str[1]))
+ {
+ Param2=atoi(++Str);
+ while (isdigit(*Str))
+ Str++;
+ }
+ switch(etoupper(*(Str++)))
+ {
+ case 'T': Type=FILTER_PPM; break;
+ case 'E': Type=FILTER_E8; break;
+ case 'D': Type=FILTER_DELTA; break;
+ case 'A': Type=FILTER_AUDIO; break;
+ case 'C': Type=FILTER_RGB; break;
+ case 'I': Type=FILTER_ITANIUM; break;
+ case 'L': Type=FILTER_UPCASETOLOW; break;
+ }
+ if (*Str=='+' || *Str=='-')
+ State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE;
+ FilterModes[Type].State=State;
+ FilterModes[Type].Param1=Param1;
+ FilterModes[Type].Param2=Param2;
+ }
+ }
+ break;
+ case 'M':
+ break;
+ case 'D':
+ {
+ if ((WinSize=atoi(&Switch[2]))==0)
+ WinSize=0x10000<<(etoupper(Switch[2])-'A');
+ else
+ WinSize*=1024;
+ if (!CheckWinSize())
+ BadSwitch(Switch);
+ }
+ break;
+ case 'S':
+ {
+ char *Names=Switch+2,DefNames[512];
+ if (*Names==0)
+ {
+ strcpy(DefNames,DefaultStoreList);
+ Names=DefNames;
+ }
+ while (*Names!=0)
+ {
+ char *End=strchr(Names,';');
+ if (End!=NULL)
+ *End=0;
+ if (*Names=='.')
+ Names++;
+ char Mask[NM];
+ if (strpbrk(Names,"*?.")==NULL)
+ sprintf(Mask,"*.%s",Names);
+ else
+ strcpy(Mask,Names);
+ StoreArgs->AddString(Mask);
+ if (End==NULL)
+ break;
+ Names=End+1;
+ }
+ }
+ break;
+#ifdef PACK_SMP
+ case 'T':
+ Threads=atoi(Switch+2);
+ if (Threads>MaxSearchThreads)
+ BadSwitch(Switch);
+ else
+ {
+ }
+ break;
+#endif
+ default:
+ Method=Switch[1]-'0';
+ if (Method>5 || Method<0)
+ BadSwitch(Switch);
+ break;
+ }
+ break;
+ case 'V':
+ switch(etoupper(Switch[1]))
+ {
+#ifdef _WIN_32
+ case 'D':
+ EraseDisk=true;
+ break;
+#endif
+ case 'N':
+ OldNumbering=true;
+ break;
+ case 'P':
+ VolumePause=true;
+ break;
+ case 'E':
+ if (etoupper(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;
+ else
+ BadSwitch(Switch);
+ break;
+ case 'U':
+ if (Switch[1]==0)
+ UpdateFiles=true;
+ else
+ BadSwitch(Switch);
+ break;
+ case 'W':
+ strncpyz(TempPath,&Switch[1],ASIZE(TempPath));
+ 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(etoupper(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;
+ case 'L':
+ if (isdigit(Switch[2]))
+ FileSizeLess=atoil(Switch+2);
+ break;
+ case 'M':
+ if (isdigit(Switch[2]))
+ FileSizeMore=atoil(Switch+2);
+ break;
+ case 'C':
+ {
+ RAR_CHARSET rch;
+ switch(etoupper(Switch[2]))
+ {
+ case 'A':
+ rch=RCH_ANSI;
+ break;
+ case 'O':
+ rch=RCH_OEM;
+ break;
+ case 'U':
+ rch=RCH_UNICODE;
+ break;
+ default :
+ BadSwitch(Switch);
+ break;
+ };
+ if (Switch[3]==0)
+ CommentCharset=FilelistCharset=rch;
+ else
+ for (int I=3;Switch[I]!=0;I++)
+ switch(etoupper(Switch[I]))
+ {
+ case 'C':
+ CommentCharset=rch;
+ break;
+ case 'L':
+ FilelistCharset=rch;
+ break;
+ default:
+ BadSwitch(Switch);
+ break;
+ }
+ }
+ break;
+
+ }
+ break;
+ case 'C':
+ if (Switch[2]==0)
+ switch(etoupper(Switch[1]))
+ {
+ case '-':
+ DisableComment=true;
+ break;
+ case 'U':
+ ConvertNames=NAMES_UPPERCASE;
+ break;
+ case 'L':
+ ConvertNames=NAMES_LOWERCASE;
+ break;
+ }
+ break;
+ case 'K':
+ switch(etoupper(Switch[1]))
+ {
+ case 'B':
+ KeepBroken=true;
+ break;
+ case 0:
+ Lock=true;
+ break;
+ }
+ break;
+#ifndef GUI
+ case '?' :
+ OutHelp();
+ break;
+#endif
+ default :
+ BadSwitch(Switch);
+ break;
+ }
+}
+#endif
+
+
+#ifndef SFX_MODULE
+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,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
+ MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSL,MCHelpSwSM,MCHelpSwTA,
+ MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwVUnr,
+ MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY
+#else
+ MRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdA,MCHelpCmdC,MCHelpCmdCF,
+ MCHelpCmdCH,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,MCHelpSwMT,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,MCHelpSwOp,
+ MCHelpSwOm,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOS,MCHelpSwOW,
+ MCHelpSwP,MCHelpSwPm,MCHelpSwR,MCHelpSwR0,MCHelpSwRI,MCHelpSwRR,
+ MCHelpSwRV,MCHelpSwS,MCHelpSwSm,MCHelpSwSC,MCHelpSwSFX,MCHelpSwSI,
+ MCHelpSwSL,MCHelpSwSM,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;I<sizeof(Help)/sizeof(Help[0]);I++)
+ {
+#ifndef SFX_MODULE
+#ifdef DISABLEAUTODETECT
+ if (Help[I]==MCHelpSwV)
+ continue;
+#endif
+#ifndef _WIN_32
+ static MSGID Win32Only[]={
+ MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
+ MCHelpSwEP2,MCHelpSwOC
+ };
+ bool Found=false;
+ for (int J=0;J<sizeof(Win32Only)/sizeof(Win32Only[0]);J++)
+ if (Help[I]==Win32Only[J])
+ {
+ Found=true;
+ break;
+ }
+ if (Found)
+ continue;
+#endif
+#if !defined(_UNIX) && !defined(_WIN_32)
+ if (Help[I]==MCHelpSwOW)
+ continue;
+#endif
+#if !defined(_WIN_32) && !defined(_EMX)
+ if (Help[I]==MCHelpSwAC)
+ continue;
+#endif
+#ifndef SAVE_LINKS
+ if (Help[I]==MCHelpSwOL)
+ continue;
+#endif
+#ifndef _WIN_32
+ if (Help[I]==MCHelpSwRI)
+ continue;
+#endif
+#ifndef PACK_SMP
+ if (Help[I]==MCHelpSwMT)
+ continue;
+#endif
+#ifndef _BEOS
+ if (Help[I]==MCHelpSwEE)
+ {
+#if defined(_EMX) && !defined(_DJGPP)
+ if (_osmode != OS2_MODE)
+ continue;
+#else
+ continue;
+#endif
+ }
+#endif
+#endif
+ mprintf(St(Help[I]));
+ }
+ mprintf("\n");
+ ErrHandler.Exit(USER_ERROR);
+#endif
+}
+
+
+bool CommandData::ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode)
+{
+ char *Name=ConvertPath(CheckName,NULL);
+ char FullName[NM],*CurName;
+ *FullName=0;
+ Args->Rewind();
+ while ((CurName=Args->GetString())!=NULL)
+#ifndef SFX_MODULE
+ if (CheckFullPath && IsFullPath(CurName))
+ {
+ if (*FullName==0)
+ ConvertNameToFull(CheckName,FullName);
+ if (CmpName(CurName,FullName,MatchMode))
+ return(true);
+ }
+ else
+#endif
+ if (CmpName(ConvertPath(CurName,NULL),Name,MatchMode))
+ return(true);
+ return(false);
+}
+
+
+bool CommandData::ExclCheck(char *CheckName,bool CheckFullPath)
+{
+ if (ExclCheckArgs(ExclArgs,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
+ return(true);
+ if (InclArgs->ItemsCount()==0)
+ return(false);
+ if (ExclCheckArgs(InclArgs,CheckName,false,MATCH_WILDSUBPATH))
+ 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
+
+
+#ifndef SFX_MODULE
+bool CommandData::SizeCheck(Int64 Size)
+{
+ if (FileSizeLess!=INT64ERR && Size>=FileSizeLess)
+ return(true);
+ if (FileSizeMore!=INT64ERR && Size<=FileSizeMore)
+ 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);
+ if ((NewLhd.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (NewLhd.FileAttr & InclFileAttr)==0)
+ return(0);
+ if ((NewLhd.Flags & LHD_WINDOWMASK)!=LHD_DIRECTORY && SizeCheck(NewLhd.FullUnpSize))
+ 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;
+ bool CorrectUnicode=true;
+ if (ArgNameW==NULL)
+ {
+ if (!CharToWide(ArgName,ArgW) || *ArgW==0)
+ CorrectUnicode=false;
+ ArgNameW=ArgW;
+ }
+ if ((NewLhd.Flags & LHD_UNICODE)==0)
+ {
+ if (!CharToWide(NewLhd.FileName,NameW) || *NameW==0)
+ CorrectUnicode=false;
+ NamePtr=NameW;
+ }
+ if (CmpName(ArgNameW,NamePtr,MatchType))
+ {
+ if (ExactMatch!=NULL)
+ *ExactMatch=stricompcw(ArgNameW,NamePtr)==0;
+ return(StringCount);
+ }
+ if (CorrectUnicode)
+ continue;
+ }
+#endif
+ if (CmpName(ArgName,NewLhd.FileName,MatchType))
+ {
+ if (ExactMatch!=NULL)
+ *ExactMatch=stricompc(ArgName,NewLhd.FileName)==0;
+ return(StringCount);
+ }
+ }
+ return(0);
+}
+
+
+#ifndef GUI
+void CommandData::ProcessCommand()
+{
+#ifndef SFX_MODULE
+
+ const char *SingleCharCommands="FUADPXETK";
+ if (Command[1] && strchr(SingleCharCommands,*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;
+#ifndef SILENT
+ case 'V':
+ case 'L':
+ ListArchive(this);
+ break;
+ default:
+ OutHelp();
+#endif
+ }
+ if (!BareOutput)
+ mprintf("\n");
+}
+#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(etoupper(*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;I<sizeof(ValidSize)/sizeof(ValidSize[0]);I++)
+ if (WinSize==ValidSize[I])
+ return(true);
+ WinSize=0x400000;
+ return(false);
+}
+#endif
diff --git a/unrar/unrar/cmddata.hpp b/unrar/unrar/cmddata.hpp
new file mode 100644
index 0000000..5dfe2dc
--- /dev/null
+++ b/unrar/unrar/cmddata.hpp
@@ -0,0 +1,57 @@
+#ifndef _RAR_CMDDATA_
+#define _RAR_CMDDATA_
+
+#define DefaultStoreList "7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;taz;tgz;z;zip"
+
+class CommandData:public RAROptions
+{
+ private:
+ void ProcessSwitchesString(char *Str);
+ void ProcessSwitch(char *Switch);
+ void BadSwitch(char *Switch);
+ bool ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode);
+ uint GetExclAttr(char *Str);
+
+ bool FileLists;
+ bool NoMoreSwitches;
+ bool TimeConverted;
+ bool BareOutput;
+ public:
+ CommandData();
+ ~CommandData();
+ void Init();
+ void Close();
+ void ParseArg(char *Arg,wchar *ArgW);
+ void ParseDone();
+ void ParseEnvVar();
+ void ReadConfig(int argc,char *argv[]);
+ bool IsConfigEnabled(int argc,char *argv[]);
+ void OutTitle();
+ void OutHelp();
+ bool IsSwitch(int Ch);
+ bool ExclCheck(char *CheckName,bool CheckFullPath);
+ bool StoreCheck(char *CheckName);
+ bool TimeCheck(RarTime &ft);
+ bool SizeCheck(Int64 Size);
+ int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH);
+ void ProcessCommand();
+ void AddArcName(char *Name,wchar *NameW);
+ bool GetArcName(char *Name,wchar *NameW,int MaxSize);
+ bool CheckWinSize();
+
+ int GetRecoverySize(char *Str,int DefSize);
+
+ char Command[NM+16];
+ wchar CommandW[NM+16];
+
+ char ArcName[NM];
+ wchar ArcNameW[NM];
+
+ StringList *FileArgs;
+ StringList *ExclArgs;
+ StringList *InclArgs;
+ StringList *ArcNames;
+ StringList *StoreArgs;
+};
+
+#endif
diff --git a/unrar/unrar/coder.cpp b/unrar/unrar/coder.cpp
new file mode 100644
index 0000000..cb6a883
--- /dev/null
+++ b/unrar/unrar/coder.cpp
@@ -0,0 +1,47 @@
+
+
+inline unsigned int RangeCoder::GetChar()
+{
+ return(UnpackRead->GetChar());
+}
+
+
+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))<TOP || range<BOT && ((range=-low&(BOT-1)),1)) \
+ { \
+ code=(code << 8) | read->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/unrar/coder.hpp b/unrar/unrar/coder.hpp
new file mode 100644
index 0000000..f09f911
--- /dev/null
+++ b/unrar/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/unrar/compress.hpp b/unrar/unrar/compress.hpp
new file mode 100644
index 0000000..3181e45
--- /dev/null
+++ b/unrar/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/unrar/consio.cpp b/unrar/unrar/consio.cpp
new file mode 100644
index 0000000..f1f4ba0
--- /dev/null
+++ b/unrar/unrar/consio.cpp
@@ -0,0 +1,289 @@
+#include "rar.hpp"
+
+#ifndef GUI
+#include "log.cpp"
+#endif
+
+#if !defined(GUI) && !defined(SILENT)
+static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
+#endif
+
+static MESSAGE_TYPE MsgStream=MSG_STDOUT;
+static 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) || defined(__sparc) || defined(sparc) || defined (__VMS)
+ fgets(Str,MaxLength-1,stdin);
+#else
+ strncpyz(Str,getpass(""),MaxLength);
+#endif
+ Str[MaxLength-1]=0;
+ RemoveLF(Str);
+}
+#endif
+#endif
+
+
+#if !defined(GUI) && !defined(SILENT)
+unsigned int GetKey()
+{
+#ifdef SILENT
+ return(0);
+#else
+ char Str[80];
+#ifdef __GNUC__
+ fgets(Str,sizeof(Str),stdin);
+ return(Str[0]);
+#else
+ File SrcFile;
+ SrcFile.SetHandleType(FILE_HANDLESTD);
+ SrcFile.Read(Str,sizeof(Str));
+ return(Str[0]);
+#endif
+#endif
+}
+#endif
+
+
+#ifndef SILENT
+bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength)
+{
+ Alarm();
+ while (true)
+ {
+ char PromptStr[NM+256];
+#if defined(_EMX) || defined(_BEOS)
+ strcpy(PromptStr,St(MAskPswEcho));
+#else
+ strcpy(PromptStr,St(MAskPsw));
+#endif
+ if (Type!=PASSWORD_GLOBAL)
+ {
+ strcat(PromptStr,St(MFor));
+ char *NameOnly=PointToName(FileName);
+ if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
+ strcat(PromptStr,NameOnly);
+ }
+ eprintf("\n%s: ",PromptStr);
+ GetPasswordText(Password,MaxLength);
+ if (*Password==0 && Type==PASSWORD_GLOBAL)
+ return(false);
+ if (Type==PASSWORD_GLOBAL)
+ {
+ eprintf(St(MReAskPsw));
+ char CmpStr[MAXPASSWORD];
+ GetPasswordText(CmpStr,ASIZE(CmpStr));
+ if (*CmpStr==0 || strcmp(Password,CmpStr)!=0)
+ {
+ eprintf(St(MNotMatchPsw));
+ 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];
+ strncpyz(CurItem,NextItem+1,ASIZE(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;I<NumItems && !Found;I++)
+ if (loctoupper(Item[I][ItemKeyPos[I]])==loctoupper(CurKey))
+ Found=true;
+ if (!Found && CurKey!=' ')
+ break;
+ KeyPos++;
+ }
+ ItemKeyPos[NumItems]=KeyPos;
+ NumItems++;
+ }
+
+ for (int I=0;I<NumItems;I++)
+ {
+ eprintf(I==0 ? (NumItems>4 ? "\n":" "):", ");
+ int KeyPos=ItemKeyPos[I];
+ for (int J=0;J<KeyPos;J++)
+ eprintf("%c",Item[I][J]);
+ eprintf("[%c]%s",Item[I][KeyPos],&Item[I][KeyPos+1]);
+ }
+ eprintf(" ");
+ int Ch=GetKey();
+#if defined(_WIN_32)
+ OemToCharBuff((LPCSTR)&Ch,(LPTSTR)&Ch,1);
+#endif
+ Ch=loctoupper(Ch);
+ for (int I=0;I<NumItems;I++)
+ if (Ch==Item[I][ItemKeyPos[I]])
+ return(I+1);
+ return(0);
+}
+#endif
+
+
+int KbdAnsi(char *Addr,int Size)
+{
+ int RetCode=0;
+#ifndef GUI
+ for (int I=0;I<Size;I++)
+ if (Addr[I]==27 && Addr[I+1]=='[')
+ {
+ for (int J=I+2;J<Size;J++)
+ {
+ if (Addr[J]=='\"')
+ return(2);
+ if (!isdigit(Addr[J]) && Addr[J]!=';')
+ break;
+ }
+ RetCode=1;
+ }
+#endif
+ return(RetCode);
+}
+
+
+void OutComment(char *Comment,int Size)
+{
+#ifndef GUI
+ if (KbdAnsi(Comment,Size)==2)
+ return;
+ const int MaxOutSize=0x400;
+ for (int I=0;I<Size;I+=MaxOutSize)
+ {
+ char Msg[MaxOutSize+1];
+ int CopySize=Min(MaxOutSize,Size-I);
+ strncpy(Msg,Comment+I,CopySize);
+ Msg[CopySize]=0;
+ mprintf("%s",Msg);
+ }
+ mprintf("\n");
+#endif
+}
diff --git a/unrar/unrar/consio.hpp b/unrar/unrar/consio.hpp
new file mode 100644
index 0000000..003a011
--- /dev/null
+++ b/unrar/unrar/consio.hpp
@@ -0,0 +1,46 @@
+#ifndef _RAR_CONSIO_
+#define _RAR_CONSIO_
+
+enum {ALARM_SOUND,ERROR_SOUND,QUESTION_SOUND};
+
+enum PASSWORD_TYPE {PASSWORD_GLOBAL,PASSWORD_FILE,PASSWORD_ARCHIVE};
+
+void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound);
+
+#ifndef SILENT
+void mprintf(const char *fmt,...);
+void eprintf(const char *fmt,...);
+void Alarm();
+void GetPasswordText(char *Str,int MaxLength);
+unsigned int GetKey();
+bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength);
+int Ask(const char *AskStr);
+#endif
+
+int KbdAnsi(char *Addr,int Size);
+void OutComment(char *Comment,int Size);
+
+#ifdef SILENT
+#ifdef __GNUC__
+ #define mprintf(args...)
+ #define eprintf(args...)
+#else
+ #ifdef _MSC_VER
+ inline void mprintf(const char *fmt,...) {}
+ #else
+ inline void mprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
+ #endif
+ inline void eprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
+ inline void mprintf(const char *fmt,int b) {}
+ inline void eprintf(const char *fmt,int b) {}
+ inline void mprintf(const char *fmt,const char *a,int b) {}
+ inline void eprintf(const char *fmt,const char *a,int b) {}
+#endif
+inline void Alarm() {}
+inline void GetPasswordText(char *Str,int MaxLength) {}
+inline unsigned int GetKey() {return(0);}
+inline bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength) {return(false);}
+inline int Ask(const char *AskStr) {return(0);}
+#endif
+
+#endif
diff --git a/unrar/unrar/crc.cpp b/unrar/unrar/crc.cpp
new file mode 100644
index 0000000..1d91e45
--- /dev/null
+++ b/unrar/unrar/crc.cpp
@@ -0,0 +1,61 @@
+#include "rar.hpp"
+
+uint CRCTab[256];
+
+void InitCRC()
+{
+ for (int I=0;I<256;I++)
+ {
+ uint C=I;
+ for (int J=0;J<8;J++)
+ C=(C & 1) ? (C>>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) && defined(ALLOW_NOT_ALIGNED_INT)
+ while (Size>0 && ((long)Data & 7))
+ {
+ StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8);
+ Size--;
+ Data++;
+ }
+ while (Size>=8)
+ {
+ StartCRC^=*(uint32 *)Data;
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ StartCRC^=*(uint32 *)(Data+4);
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
+ Data+=8;
+ Size-=8;
+ }
+#endif
+ for (int I=0;I<Size;I++)
+ StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
+ return(StartCRC);
+}
+
+#ifndef SFX_MODULE
+ushort OldCRC(ushort StartCRC,const void *Addr,uint Size)
+{
+ byte *Data=(byte *)Addr;
+ for (int I=0;I<Size;I++)
+ {
+ StartCRC=(StartCRC+Data[I])&0xffff;
+ StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;
+ }
+ return(StartCRC);
+}
+#endif
diff --git a/unrar/unrar/crc.hpp b/unrar/unrar/crc.hpp
new file mode 100644
index 0000000..47ee7e2
--- /dev/null
+++ b/unrar/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/unrar/crypt.cpp b/unrar/unrar/crypt.cpp
new file mode 100644
index 0000000..04a1d70
--- /dev/null
+++ b/unrar/unrar/crypt.cpp
@@ -0,0 +1,381 @@
+#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<NROUNDS;I++)
+ {
+ T=((C+rol(D,11,32))^Key[I&3]);
+ TA=A^substLong(T);
+ T=((D^rol(C,17,32))+Key[I&3]);
+ TB=B^substLong(T);
+ A=C;
+ B=D;
+ C=TA;
+ D=TB;
+ }
+#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
+ C^=Key[0];
+ Buf[0]=(byte)C;
+ Buf[1]=(byte)(C>>8);
+ Buf[2]=(byte)(C>>16);
+ Buf[3]=(byte)(C>>24);
+ D^=Key[1];
+ Buf[4]=(byte)D;
+ Buf[5]=(byte)(D>>8);
+ Buf[6]=(byte)(D>>16);
+ Buf[7]=(byte)(D>>24);
+ A^=Key[2];
+ Buf[8]=(byte)A;
+ Buf[9]=(byte)(A>>8);
+ Buf[10]=(byte)(A>>16);
+ Buf[11]=(byte)(A>>24);
+ B^=Key[3];
+ Buf[12]=(byte)B;
+ Buf[13]=(byte)(B>>8);
+ Buf[14]=(byte)(B>>16);
+ Buf[15]=(byte)(B>>24);
+#else
+ BufPtr[0]=C^Key[0];
+ BufPtr[1]=D^Key[1];
+ BufPtr[2]=A^Key[2];
+ BufPtr[3]=B^Key[3];
+#endif
+ UpdKeys(Buf);
+}
+
+
+void CryptData::DecryptBlock20(byte *Buf)
+{
+ byte InBuf[16];
+ uint A,B,C,D,T,TA,TB;
+#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
+ A=((uint)Buf[0]|((uint)Buf[1]<<8)|((uint)Buf[2]<<16)|((uint)Buf[3]<<24))^Key[0];
+ B=((uint)Buf[4]|((uint)Buf[5]<<8)|((uint)Buf[6]<<16)|((uint)Buf[7]<<24))^Key[1];
+ C=((uint)Buf[8]|((uint)Buf[9]<<8)|((uint)Buf[10]<<16)|((uint)Buf[11]<<24))^Key[2];
+ D=((uint)Buf[12]|((uint)Buf[13]<<8)|((uint)Buf[14]<<16)|((uint)Buf[15]<<24))^Key[3];
+#else
+ uint32 *BufPtr=(uint32 *)Buf;
+ A=BufPtr[0]^Key[0];
+ B=BufPtr[1]^Key[1];
+ C=BufPtr[2]^Key[2];
+ D=BufPtr[3]^Key[3];
+#endif
+ memcpy(InBuf,Buf,sizeof(InBuf));
+ for(int I=NROUNDS-1;I>=0;I--)
+ {
+ T=((C+rol(D,11,32))^Key[I&3]);
+ TA=A^substLong(T);
+ T=((D^rol(C,17,32))+Key[I&3]);
+ TB=B^substLong(T);
+ A=C;
+ B=D;
+ C=TA;
+ D=TB;
+ }
+#if defined(BIG_ENDIAN) || !defined(PRESENT_INT32) || !defined(ALLOW_NOT_ALIGNED_INT)
+ C^=Key[0];
+ Buf[0]=(byte)C;
+ Buf[1]=(byte)(C>>8);
+ Buf[2]=(byte)(C>>16);
+ Buf[3]=(byte)(C>>24);
+ D^=Key[1];
+ Buf[4]=(byte)D;
+ Buf[5]=(byte)(D>>8);
+ Buf[6]=(byte)(D>>16);
+ Buf[7]=(byte)(D>>24);
+ A^=Key[2];
+ Buf[8]=(byte)A;
+ Buf[9]=(byte)(A>>8);
+ Buf[10]=(byte)(A>>16);
+ Buf[11]=(byte)(A>>24);
+ B^=Key[3];
+ Buf[12]=(byte)B;
+ Buf[13]=(byte)(B>>8);
+ Buf[14]=(byte)(B>>16);
+ Buf[15]=(byte)(B>>24);
+#else
+ BufPtr[0]=C^Key[0];
+ BufPtr[1]=D^Key[1];
+ BufPtr[2]=A^Key[2];
+ BufPtr[3]=B^Key[3];
+#endif
+ UpdKeys(InBuf);
+}
+
+
+void CryptData::UpdKeys(byte *Buf)
+{
+ for (int I=0;I<16;I+=4)
+ {
+ Key[0]^=CRCTab[Buf[I]];
+ Key[1]^=CRCTab[Buf[I+1]];
+ Key[2]^=CRCTab[Buf[I+2]];
+ Key[3]^=CRCTab[Buf[I+3]];
+ }
+}
+
+
+void CryptData::Swap(byte *Ch1,byte *Ch2)
+{
+ byte Ch=*Ch1;
+ *Ch1=*Ch2;
+ *Ch2=Ch;
+}
+#endif
+
+
+void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
+{
+ 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
+ strncpyz((char *)Psw,Password,ASIZE(Psw));
+#endif
+ int PswLength=strlen(Password);
+ memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
+ for (int J=0;J<256;J++)
+ for (int I=0;I<PswLength;I+=2)
+ {
+ uint N1=(byte)CRCTab[(Psw[I]-J)&0xff];
+ uint N2=(byte)CRCTab[(Psw[I+1]+J)&0xff];
+ for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
+ Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]);
+ }
+ for (int I=0;I<PswLength;I+=16)
+ EncryptBlock20(&Psw[I]);
+#endif
+ return;
+ }
+
+ bool Cached=false;
+ for (int I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++)
+ if (strcmp(Cache[I].Password,Password)==0 &&
+ (Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
+ Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&
+ Cache[I].HandsOffHash==HandsOffHash)
+ {
+ memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey));
+ memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit));
+ Cached=true;
+ break;
+ }
+
+ if (!Cached)
+ {
+ wchar PswW[MAXPASSWORD];
+ CharToWide(Password,PswW,MAXPASSWORD-1);
+ PswW[MAXPASSWORD-1]=0;
+ byte RawPsw[2*MAXPASSWORD+SALT_SIZE];
+ WideToRaw(PswW,RawPsw);
+ int RawLength=2*strlenw(PswW);
+ if (Salt!=NULL)
+ {
+ memcpy(RawPsw+RawLength,Salt,SALT_SIZE);
+ RawLength+=SALT_SIZE;
+ }
+ hash_context c;
+ hash_initial(&c);
+
+ const int HashRounds=0x40000;
+ for (int I=0;I<HashRounds;I++)
+ {
+ hash_process( &c, RawPsw, RawLength, HandsOffHash);
+ byte PswNum[3];
+ PswNum[0]=(byte)I;
+ PswNum[1]=(byte)(I>>8);
+ PswNum[2]=(byte)(I>>16);
+ hash_process( &c, PswNum, 3, HandsOffHash);
+ if (I%(HashRounds/16)==0)
+ {
+ hash_context tempc=c;
+ uint32 digest[5];
+ hash_final( &tempc, digest, HandsOffHash);
+ AESInit[I/(HashRounds/16)]=(byte)digest[4];
+ }
+ }
+ uint32 digest[5];
+ hash_final( &c, digest, HandsOffHash);
+ for (int I=0;I<4;I++)
+ for (int J=0;J<4;J++)
+ AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
+
+ strcpy(Cache[CachePos].Password,Password);
+ if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true)
+ memcpy(Cache[CachePos].Salt,Salt,SALT_SIZE);
+ Cache[CachePos].HandsOffHash=HandsOffHash;
+ memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey));
+ memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit));
+ CachePos=(CachePos+1)%(sizeof(Cache)/sizeof(Cache[0]));
+ }
+ rin.init(Encrypt ? Rijndael::Encrypt : Rijndael::Decrypt,AESKey,AESInit);
+}
+
+
+#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/unrar/crypt.hpp b/unrar/unrar/crypt.hpp
new file mode 100644
index 0000000..e70aaa3
--- /dev/null
+++ b/unrar/unrar/crypt.hpp
@@ -0,0 +1,62 @@
+#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];
+ bool HandsOffHash;
+};
+
+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,bool HandsOffHash);
+ 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/unrar/dll.cpp b/unrar/unrar/dll.cpp
new file mode 100644
index 0000000..f1a2cc9
--- /dev/null
+++ b/unrar/unrar/dll.cpp
@@ -0,0 +1,365 @@
+#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->Cmd.DllError=0;
+ 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))
+ {
+ r->OpenResult=ERAR_EOPEN;
+ delete Data;
+ return(NULL);
+ }
+ if (!Data->Arc.IsArchive(false))
+ {
+ r->OpenResult=Data->Cmd.DllError!=0 ? Data->Cmd.DllError:ERAR_BAD_ARCHIVE;
+ delete Data;
+ return(NULL);
+ }
+ r->Flags=Data->Arc.NewMhd.Flags;
+ Array<byte> CmtData;
+ if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
+ {
+ 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->Extract.SignatureFound=false;
+ Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
+ return(RARReadHeader(hArcData,D));
+ }
+ else
+ return(ERAR_EOPEN);
+ return(Data->Arc.BrokenFileHeader ? ERAR_BAD_DATA:ERAR_END_ARCHIVE);
+ }
+ if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
+ {
+ int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
+ if (Code==0)
+ return(RARReadHeader(hArcData,D));
+ else
+ return(Code);
+ }
+ strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
+ strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
+ D->Flags=Data->Arc.NewLhd.Flags;
+ D->PackSize=Data->Arc.NewLhd.PackSize;
+ D->UnpSize=Data->Arc.NewLhd.UnpSize;
+ D->HostOS=Data->Arc.NewLhd.HostOS;
+ D->FileCRC=Data->Arc.NewLhd.FileCRC;
+ D->FileTime=Data->Arc.NewLhd.FileTime;
+ D->UnpVer=Data->Arc.NewLhd.UnpVer;
+ D->Method=Data->Arc.NewLhd.Method;
+ D->FileAttr=Data->Arc.NewLhd.FileAttr;
+ D->CmtSize=0;
+ D->CmtState=0;
+ }
+ catch (int ErrCode)
+ {
+ return(RarErrorToDll(ErrCode));
+ }
+ return(0);
+}
+
+
+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->Extract.SignatureFound=false;
+ 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))
+ {
+ int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
+ if (Code==0)
+ return(RARReadHeaderEx(hArcData,D));
+ else
+ return(Code);
+ }
+ strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
+ if (*Data->Arc.FileNameW)
+ strncpyw(D->ArcNameW,Data->Arc.FileNameW,sizeof(D->ArcNameW));
+ else
+ CharToWide(Data->Arc.FileName,D->ArcNameW);
+ strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(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->Extract.SignatureFound=false;
+ 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;
+}
+
+#ifndef NOCRYPT
+void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
+{
+ DataSet *Data=(DataSet *)hArcData;
+ strncpyz(Data->Cmd.Password,Password,ASIZE(Data->Cmd.Password));
+}
+#endif
+
+
+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/unrar/dll.def b/unrar/unrar/dll.def
new file mode 100644
index 0000000..660f69b
--- /dev/null
+++ b/unrar/unrar/dll.def
@@ -0,0 +1,12 @@
+EXPORTS
+ RAROpenArchive
+ RAROpenArchiveEx
+ RARCloseArchive
+ RARReadHeader
+ RARReadHeaderEx
+ RARProcessFile
+ RARSetCallback
+ RARSetChangeVolProc
+ RARSetProcessDataProc
+ RARSetPassword
+ RARGetDllVersion
diff --git a/unrar/unrar/dll.hpp b/unrar/unrar/dll.hpp
new file mode 100644
index 0000000..4b67744
--- /dev/null
+++ b/unrar/unrar/dll.hpp
@@ -0,0 +1,138 @@
+#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 ERAR_MISSING_PASSWORD 22
+
+#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/unrar/encname.cpp b/unrar/unrar/encname.cpp
new file mode 100644
index 0000000..6f57cd9
--- /dev/null
+++ b/unrar/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<EncSize && DecPos<MaxDecSize)
+ {
+ if (FlagBits==0)
+ {
+ Flags=EncName[EncPos++];
+ FlagBits=8;
+ }
+ switch(Flags>>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 && DecPos<MaxDecSize;Length--,DecPos++)
+ NameW[DecPos]=((Name[DecPos]+Correction)&0xff)+(HighByte<<8);
+ }
+ else
+ for (Length+=2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++)
+ NameW[DecPos]=Name[DecPos];
+ }
+ break;
+ }
+ Flags<<=2;
+ FlagBits-=2;
+ }
+ NameW[DecPos<MaxDecSize ? DecPos:MaxDecSize-1]=0;
+}
diff --git a/unrar/unrar/encname.hpp b/unrar/unrar/encname.hpp
new file mode 100644
index 0000000..586f421
--- /dev/null
+++ b/unrar/unrar/encname.hpp
@@ -0,0 +1,20 @@
+#ifndef _RAR_ENCNAME_
+#define _RAR_ENCNAME_
+
+class EncodeFileName
+{
+ private:
+ void AddFlags(int Value);
+
+ byte *EncName;
+ byte Flags;
+ int FlagBits;
+ int FlagsPos;
+ int DestSize;
+ public:
+ EncodeFileName();
+ int Encode(char *Name,wchar *NameW,byte *EncName);
+ void Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,int MaxDecSize);
+};
+
+#endif
diff --git a/unrar/unrar/errhnd.cpp b/unrar/unrar/errhnd.cpp
new file mode 100644
index 0000000..035eae9
--- /dev/null
+++ b/unrar/unrar/errhnd.cpp
@@ -0,0 +1,374 @@
+#include "rar.hpp"
+
+
+static bool UserBreak;
+
+ErrorHandler::ErrorHandler()
+{
+ Clean();
+}
+
+
+void ErrorHandler::Clean()
+{
+ ExitCode=SUCCESS;
+ ErrCount=0;
+ EnableBreak=true;
+ Silent=false;
+ DoShutdown=false;
+}
+
+
+void ErrorHandler::MemoryError()
+{
+ MemoryErrorMsg();
+ Throw(MEMORY_ERROR);
+}
+
+
+void ErrorHandler::OpenError(const char *FileName)
+{
+#ifndef SILENT
+ OpenErrorMsg(FileName);
+ Throw(OPEN_ERROR);
+#endif
+}
+
+
+void ErrorHandler::CloseError(const char *FileName)
+{
+#ifndef SILENT
+ if (!UserBreak)
+ {
+ ErrMsg(NULL,St(MErrFClose),FileName);
+ SysErrMsg();
+ }
+#endif
+#if !defined(SILENT) || defined(RARDLL)
+ Throw(FATAL_ERROR);
+#endif
+}
+
+
+void ErrorHandler::ReadError(const char *FileName)
+{
+#ifndef SILENT
+ ReadErrorMsg(NULL,FileName);
+#endif
+#if !defined(SILENT) || defined(RARDLL)
+ Throw(FATAL_ERROR);
+#endif
+}
+
+
+bool ErrorHandler::AskRepeatRead(const char *FileName)
+{
+#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE)
+ if (!Silent)
+ {
+ mprintf("\n");
+ Log(NULL,St(MErrRead),FileName);
+ return(Ask(St(MRetryAbort))==1);
+ }
+#endif
+ return(false);
+}
+
+
+void ErrorHandler::WriteError(const char *ArcName,const char *FileName)
+{
+#ifndef SILENT
+ WriteErrorMsg(ArcName,FileName);
+#endif
+#if !defined(SILENT) || defined(RARDLL)
+ Throw(WRITE_ERROR);
+#endif
+}
+
+
+#ifdef _WIN_32
+void ErrorHandler::WriteErrorFAT(const char *FileName)
+{
+#if !defined(SILENT) && !defined(SFX_MODULE)
+ SysErrMsg();
+ ErrMsg(NULL,St(MNTFSRequired),FileName);
+#endif
+#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
+ Throw(WRITE_ERROR);
+#endif
+}
+#endif
+
+
+bool ErrorHandler::AskRepeatWrite(const char *FileName)
+{
+#if !defined(SILENT) && !defined(_WIN_CE)
+ if (!Silent)
+ {
+ mprintf("\n");
+ Log(NULL,St(MErrWrite),FileName);
+ return(Ask(St(MRetryAbort))==1);
+ }
+#endif
+ return(false);
+}
+
+
+void ErrorHandler::SeekError(const char *FileName)
+{
+#ifndef SILENT
+ if (!UserBreak)
+ {
+ ErrMsg(NULL,St(MErrSeek),FileName);
+ SysErrMsg();
+ }
+#endif
+#if !defined(SILENT) || defined(RARDLL)
+ Throw(FATAL_ERROR);
+#endif
+}
+
+
+void ErrorHandler::GeneralErrMsg(const char *Msg)
+{
+#ifndef SILENT
+ Log(NULL,"%s",Msg);
+ SysErrMsg();
+#endif
+}
+
+
+void ErrorHandler::MemoryErrorMsg()
+{
+#ifndef SILENT
+ ErrMsg(NULL,St(MErrOutMem));
+#endif
+}
+
+
+void ErrorHandler::OpenErrorMsg(const char *FileName)
+{
+ OpenErrorMsg(NULL,FileName);
+}
+
+
+void ErrorHandler::OpenErrorMsg(const char *ArcName,const char *FileName)
+{
+#ifndef SILENT
+ Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotOpen),FileName);
+ Alarm();
+ SysErrMsg();
+#endif
+}
+
+
+void ErrorHandler::CreateErrorMsg(const char *FileName)
+{
+ CreateErrorMsg(NULL,FileName);
+}
+
+
+void ErrorHandler::CreateErrorMsg(const char *ArcName,const char *FileName)
+{
+#ifndef SILENT
+ Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotCreate),FileName);
+ Alarm();
+#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAXPATH)
+ if (GetLastError()==ERROR_PATH_NOT_FOUND)
+ {
+ int NameLength=strlen(FileName);
+ if (!IsFullPath(FileName))
+ {
+ char CurDir[NM];
+ GetCurrentDirectory(sizeof(CurDir),CurDir);
+ NameLength+=strlen(CurDir)+1;
+ }
+ if (NameLength>MAXPATH)
+ {
+ Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAXPATH);
+ }
+ }
+#endif
+ SysErrMsg();
+#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(SFX_MODULE) && !defined(SILENT)
+#ifdef _WIN_32
+ #define STRCHR strchr
+ #define ERRCHAR char
+ ERRCHAR *lpMsgBuf=NULL;
+ int ErrType=GetLastError();
+ if (ErrType!=0 && FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,ErrType,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&lpMsgBuf,0,NULL))
+ {
+ 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
+
+#if defined(_UNIX) || defined(_EMX)
+ char *err=strerror(errno);
+ if (err!=NULL)
+ Log(NULL,"\n%s",err);
+#endif
+
+#endif
+}
+
+
+
+
diff --git a/unrar/unrar/errhnd.hpp b/unrar/unrar/errhnd.hpp
new file mode 100644
index 0000000..732243c
--- /dev/null
+++ b/unrar/unrar/errhnd.hpp
@@ -0,0 +1,62 @@
+#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 GeneralErrMsg(const char *Msg);
+ 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/unrar/extinfo.cpp b/unrar/unrar/extinfo.cpp
new file mode 100644
index 0000000..13239fe
--- /dev/null
+++ b/unrar/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/unrar/extinfo.hpp b/unrar/unrar/extinfo.hpp
new file mode 100644
index 0000000..db7cea5
--- /dev/null
+++ b/unrar/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/unrar/extract.cpp b/unrar/unrar/extract.cpp
new file mode 100644
index 0000000..e9d7517
--- /dev/null
+++ b/unrar/unrar/extract.cpp
@@ -0,0 +1,873 @@
+#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 (true)
+ {
+ char PrevCmdPassword[MAXPASSWORD];
+ strcpy(PrevCmdPassword,Cmd->Password);
+
+ EXTRACT_ARC_CODE Code=ExtractArchive(Cmd);
+
+/*
+ restore Cmd->Password which could be changed in IsArchive() call
+ for next header encrypted archive
+*/
+ strcpy(Cmd->Password,PrevCmdPassword);
+
+ if (Code!=EXTRACT_ARC_REPEAT)
+ break;
+ }
+ 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();
+
+ // RAR can close a corrupt encrypted archive
+ if (!Arc.IsOpened())
+ return(EXTRACT_ARC_NEXT);
+
+
+ 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
+ ErrHandler.SetErrorCode(WARNING);
+ }
+ ExactMatch=false;
+ }
+
+ FirstFile=false;
+#endif
+
+ if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
+ {
+ if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
+#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.FirstVolumeName));
+ 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);
+
+ char DiskLetter=etoupper(DestFileName[0]);
+
+ if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2]) &&
+ DiskLetter>='A' && DiskLetter<='Z')
+ 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.FirstVolumeNameW!=0)
+ strcpyw(FileNameW,Arc.FirstVolumeNameW);
+ else
+ CharToWide(Arc.FirstVolumeName,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 && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0;
+
+ 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;
+ }
+
+ // skip encrypted file if no password is specified
+ if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && *Password==0)
+ {
+ ErrHandler.SetErrorCode(WARNING);
+#ifdef RARDLL
+ Cmd->DllError=ERAR_MISSING_PASSWORD;
+#endif
+ ExtrFile=false;
+ }
+
+#ifdef RARDLL
+ if (*Cmd->DllDestName)
+ {
+ strncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
+ *DestFileNameW=0;
+ if (Cmd->DllOpMode!=RAR_EXTRACT)
+ ExtrFile=false;
+ }
+ if (*Cmd->DllDestNameW)
+ {
+ strncpyzw(DestFileNameW,Cmd->DllDestNameW,ASIZE(DestFileNameW));
+ DestNameW=DestFileNameW;
+ if (Cmd->DllOpMode!=RAR_EXTRACT)
+ ExtrFile=false;
+ }
+#endif
+
+#ifdef SFX_MODULE
+ if ((Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.UnpVer!=29) &&
+ 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));
+ char OrigName[sizeof(DestFileName)];
+ strncpyz(OrigName,DestFileName,ASIZE(OrigName));
+
+ MakeNameUsable(DestFileName,true);
+ CreatePath(DestFileName,NULL,true);
+ if (FileCreate(Cmd,&CurFile,DestFileName,NULL,Cmd->Overwrite,&UserReject,Arc.NewLhd.FullUnpSize,Arc.NewLhd.FileTime))
+ {
+#ifndef SFX_MODULE
+ Log(Arc.FileName,St(MRenaming),OrigName,DestFileName);
+#endif
+ 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,
+ Arc.NewLhd.UnpVer>=36);
+ 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);
+
+ bool LinkCreateMode=!Cmd->Test && !SkipSolid;
+ if (ExtractLink(DataIO,Arc,DestFileName,DataIO.UnpFileCRC,LinkCreateMode))
+ PrevExtracted=LinkCreateMode;
+ else
+ if ((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;
+/*
+ else
+ Arc.NewLhd.FileAttr|=FA_ARCH; //set archive bit for unpacked files (file is not backed up)
+*/
+#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<byte> Buffer(0x10000);
+ while (1)
+ {
+ unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
+ if (Code==0 || (int)Code==-1)
+ break;
+ Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
+ DataIO.UnpWrite(&Buffer[0],Code);
+ if (DestUnpSize>=0)
+ DestUnpSize-=Code;
+ }
+}
+
diff --git a/unrar/unrar/extract.hpp b/unrar/unrar/extract.hpp
new file mode 100644
index 0000000..09dfc94
--- /dev/null
+++ b/unrar/unrar/extract.hpp
@@ -0,0 +1,42 @@
+#ifndef _RAR_EXTRACT_
+#define _RAR_EXTRACT_
+
+enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
+
+class CmdExtract
+{
+ private:
+ EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
+
+ 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;
+ char DestFileName[NM];
+ wchar DestFileNameW[NM];
+ bool PasswordCancelled;
+ public:
+ CmdExtract();
+ ~CmdExtract();
+ void DoExtract(CommandData *Cmd);
+ void ExtractArchiveInit(CommandData *Cmd,Archive &Arc);
+ bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,
+ bool &Repeat);
+ static void UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize);
+
+ bool SignatureFound;
+};
+
+#endif
diff --git a/unrar/unrar/filcreat.cpp b/unrar/unrar/filcreat.cpp
new file mode 100644
index 0000000..175736a
--- /dev/null
+++ b/unrar/unrar/filcreat.cpp
@@ -0,0 +1,239 @@
+#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,sizeof(NewName)-1);
+ NewName[Size]=0;
+ OemToChar(NewName,NewName);
+#else
+ fgets(NewName,sizeof(NewName),stdin);
+#endif
+ RemoveLF(NewName);
+ if (PointToName(NewName)==NewName)
+ strcpy(PointToName(Name),NewName);
+ else
+ strcpy(Name,NewName);
+ if (NameW!=NULL)
+ *NameW=0;
+ continue;
+ }
+ if (Choice==6)
+ ErrHandler.Exit(USER_BREAK);
+ }
+ if (Mode==OVERWRITE_AUTORENAME)
+ {
+ if (GetAutoRenamedName(Name))
+ {
+ if (NameW!=NULL)
+ *NameW=0;
+ }
+ else
+ Mode=OVERWRITE_ASK;
+ continue;
+ }
+ }
+ if (NewFile!=NULL && NewFile->Create(Name,NameW))
+ return(true);
+ PrepareToDelete(Name,NameW);
+ CreatePath(Name,NameW,true);
+ return(NewFile!=NULL ? NewFile->Create(Name,NameW):DelFile(Name,NameW));
+}
+
+
+bool GetAutoRenamedName(char *Name)
+{
+ char NewName[NM];
+
+ if (strlen(Name)>sizeof(NewName)-10)
+ return(false);
+ char *Ext=GetExt(Name);
+ if (Ext==NULL)
+ Ext=Name+strlen(Name);
+ for (int FileVer=1;;FileVer++)
+ {
+ sprintf(NewName,"%.*s(%d)%s",Ext-Name,Name,FileVer,Ext);
+ if (!FileExist(NewName))
+ {
+ strcpy(Name,NewName);
+ break;
+ }
+ if (FileVer>=1000000)
+ return(false);
+ }
+ return(true);
+}
+
+
+#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)
+ {
+ strncpyz(NewName,Name,ASIZE(NewName));
+ sprintf(PointToName(NewName),"rtmp%d",I);
+ if (!FileExist(NewName))
+ break;
+ }
+ if (FileExist(NewName))
+ return(false);
+ char FullName[NM];
+ strncpyz(FullName,Name,ASIZE(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/unrar/filcreat.hpp b/unrar/unrar/filcreat.hpp
new file mode 100644
index 0000000..d803582
--- /dev/null
+++ b/unrar/unrar/filcreat.hpp
@@ -0,0 +1,13 @@
+#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);
+bool GetAutoRenamedName(char *Name);
+
+#if defined(_WIN_32) && !defined(_WIN_CE)
+bool UpdateExistingShortName(char *Name,wchar *NameW);
+#endif
+
+#endif
diff --git a/unrar/unrar/file.cpp b/unrar/unrar/file.cpp
new file mode 100644
index 0000000..a2c43b8
--- /dev/null
+++ b/unrar/unrar/file.cpp
@@ -0,0 +1,689 @@
+#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
+
+#ifdef _OSF_SOURCE
+ extern "C" int flock(int, int);
+#endif
+
+ 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;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
+ if (CreatedFiles[I]==NULL)
+ {
+ CreatedFiles[I]=this;
+ break;
+ }
+}
+
+
+#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
+void File::TCreate(const char *Name,const wchar *NameW)
+{
+ if (!WCreate(Name,NameW))
+ ErrHandler.Exit(FATAL_ERROR);
+}
+#endif
+
+
+bool File::WCreate(const char *Name,const wchar *NameW)
+{
+ if (Create(Name,NameW))
+ return(true);
+ ErrHandler.SetErrorCode(CREATE_ERROR);
+ ErrHandler.CreateErrorMsg(Name);
+ return(false);
+}
+
+
+bool File::Close()
+{
+ bool Success=true;
+ if (HandleType!=FILE_HANDLENORMAL)
+ HandleType=FILE_HANDLENORMAL;
+ else
+ if (hFile!=BAD_HANDLE)
+ {
+ if (!SkipClose)
+ {
+#ifdef _WIN_32
+ Success=CloseHandle(hFile);
+#else
+ Success=fclose(hFile)!=EOF;
+#endif
+ if (Success || !RemoveCreatedActive)
+ for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
+ if (CreatedFiles[I]==this)
+ {
+ CreatedFiles[I]=NULL;
+ break;
+ }
+ }
+ hFile=BAD_HANDLE;
+ if (!Success && AllowExceptions)
+ ErrHandler.CloseError(FileName);
+ }
+ CloseCount++;
+ return(Success);
+}
+
+
+void File::Flush()
+{
+#ifdef _WIN_32
+ FlushFileBuffers(hFile);
+#else
+ fflush(hFile);
+#endif
+}
+
+
+bool File::Delete()
+{
+ if (HandleType!=FILE_HANDLENORMAL)
+ return(false);
+ if (hFile!=BAD_HANDLE)
+ Close();
+ if (!AllowDelete)
+ return(false);
+ return(DelFile(FileName,FileNameW));
+}
+
+
+bool File::Rename(const char *NewName)
+{
+ bool Success=strcmp(FileName,NewName)==0;
+ if (!Success)
+ Success=rename(FileName,NewName)==0;
+ if (Success)
+ {
+ strcpy(FileName,NewName);
+ *FileNameW=0;
+ }
+ return(Success);
+}
+
+
+void File::Write(const void *Data,int Size)
+{
+ if (Size==0)
+ return;
+#ifndef _WIN_CE
+ if (HandleType!=FILE_HANDLENORMAL)
+ switch(HandleType)
+ {
+ case FILE_HANDLESTD:
+#ifdef _WIN_32
+ hFile=GetStdHandle(STD_OUTPUT_HANDLE);
+#else
+ hFile=stdout;
+#endif
+ break;
+ case FILE_HANDLEERR:
+#ifdef _WIN_32
+ hFile=GetStdHandle(STD_ERROR_HANDLE);
+#else
+ hFile=stderr;
+#endif
+ break;
+ }
+#endif
+ while (1)
+ {
+ bool Success;
+#ifdef _WIN_32
+ DWORD Written;
+ if (HandleType!=FILE_HANDLENORMAL)
+ {
+ const int MaxSize=0x4000;
+ for (int I=0;I<Size;I+=MaxSize)
+ if (!(Success=WriteFile(hFile,(byte *)Data+I,Min(Size-I,MaxSize),&Written,NULL)))
+ break;
+ }
+ else
+ Success=WriteFile(hFile,Data,Size,&Written,NULL);
+#else
+ int Written=fwrite(Data,1,Size,hFile);
+ Success=Written==Size && !ferror(hFile);
+#endif
+ if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
+ {
+#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(RARDLL)
+ int ErrCode=GetLastError();
+ Int64 FilePos=Tell();
+ Int64 FreeSize=GetFreeDisk(FileName);
+ SetLastError(ErrCode);
+ if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
+ ErrHandler.WriteErrorFAT(FileName);
+#endif
+ if (ErrHandler.AskRepeatWrite(FileName))
+ {
+#ifndef _WIN_32
+ clearerr(hFile);
+#endif
+ if (Written<Size && Written>0)
+ 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;I<Size;I+=512)
+ {
+ Seek(FilePos+I,SEEK_SET);
+ int SizeToRead=Min(Size-I,512);
+ int ReadCode=DirectRead(Data,SizeToRead);
+ ReadSize+=(ReadCode==-1) ? 512:ReadCode;
+ }
+ }
+ else
+ {
+ if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName))
+ continue;
+ ErrHandler.ReadError(FileName);
+ }
+ }
+ break;
+ }
+ return(ReadSize);
+}
+
+
+int File::DirectRead(void *Data,int Size)
+{
+#ifdef _WIN_32
+ const int MaxDeviceRead=20000;
+#endif
+#ifndef _WIN_CE
+ if (HandleType==FILE_HANDLESTD)
+ {
+#ifdef _WIN_32
+ if (Size>MaxDeviceRead)
+ 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;
+#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
+ if (fseeko(hFile,Offset,Method)!=0)
+#else
+ if (fseek(hFile,(long)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
+#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_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;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
+ if (CreatedFiles[I]!=NULL)
+ {
+ CreatedFiles[I]->SetExceptions(false);
+ bool Success;
+ if (CreatedFiles[I]->NewFile)
+ Success=CreatedFiles[I]->Delete();
+ else
+ Success=CreatedFiles[I]->Close();
+ if (Success)
+ CreatedFiles[I]=NULL;
+ else
+ RetCode=false;
+ }
+ RemoveCreatedActive--;
+ return(RetCode);
+}
+
+
+#ifndef SFX_MODULE
+long File::Copy(File &Dest,Int64 Length)
+{
+ Array<char> Buffer(0x10000);
+ long CopySize=0;
+ bool CopyAll=(Length==INT64ERR);
+
+ while (CopyAll || Length>0)
+ {
+ Wait();
+ int SizeToRead=(!CopyAll && Length<Buffer.Size()) ? int64to32(Length):Buffer.Size();
+ int ReadSize=Read(&Buffer[0],SizeToRead);
+ if (ReadSize==0)
+ break;
+ Dest.Write(&Buffer[0],ReadSize);
+ CopySize+=ReadSize;
+ if (!CopyAll)
+ Length-=ReadSize;
+ }
+ return(CopySize);
+}
+#endif
diff --git a/unrar/unrar/file.hpp b/unrar/unrar/file.hpp
new file mode 100644
index 0000000..afa9529
--- /dev/null
+++ b/unrar/unrar/file.hpp
@@ -0,0 +1,100 @@
+#ifndef _RAR_FILE_
+#define _RAR_FILE_
+
+#ifdef _WIN_32
+typedef HANDLE FileHandle;
+#define BAD_HANDLE INVALID_HANDLE_VALUE
+#else
+typedef FILE* FileHandle;
+#define BAD_HANDLE NULL
+#endif
+
+class RAROptions;
+
+enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD,FILE_HANDLEERR};
+
+enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR};
+
+struct FileStat
+{
+ uint FileAttr;
+ uint FileTime;
+ Int64 FileSize;
+ bool IsDir;
+};
+
+
+class File
+{
+ private:
+ void AddFileToList(FileHandle hFile);
+
+ FileHandle hFile;
+ bool LastWrite;
+ FILE_HANDLETYPE HandleType;
+ bool SkipClose;
+ bool IgnoreReadErrors;
+ bool NewFile;
+ bool AllowDelete;
+ bool AllowExceptions;
+#ifdef _WIN_32
+ bool NoSequentialRead;
+#endif
+ protected:
+ bool OpenShared;
+ public:
+ char FileName[NM];
+ wchar FileNameW[NM];
+
+ FILE_ERRORTYPE ErrorType;
+
+ uint CloseCount;
+ public:
+ File();
+ virtual ~File();
+ void operator = (File &SrcFile);
+ bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false);
+ void TOpen(const char *Name,const wchar *NameW=NULL);
+ bool WOpen(const char *Name,const wchar *NameW=NULL);
+ bool Create(const char *Name,const wchar *NameW=NULL);
+ void TCreate(const char *Name,const wchar *NameW=NULL);
+ bool WCreate(const char *Name,const wchar *NameW=NULL);
+ bool Close();
+ void Flush();
+ bool Delete();
+ bool Rename(const char *NewName);
+ void Write(const void *Data,int Size);
+ int Read(void *Data,int Size);
+ int DirectRead(void *Data,int Size);
+ void Seek(Int64 Offset,int Method);
+ bool RawSeek(Int64 Offset,int Method);
+ Int64 Tell();
+ void Prealloc(Int64 Size);
+ byte GetByte();
+ void PutByte(byte Byte);
+ bool Truncate();
+ void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
+ void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
+ static void SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta);
+ void SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta);
+ void SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr);
+ void GetOpenFileTime(RarTime *ft);
+ bool IsOpened() {return(hFile!=BAD_HANDLE);};
+ Int64 FileLength();
+ void SetHandleType(FILE_HANDLETYPE Type);
+ FILE_HANDLETYPE GetHandleType() {return(HandleType);};
+ bool IsDevice();
+ void fprintf(const char *fmt,...);
+ static bool RemoveCreated();
+ FileHandle GetHandle() {return(hFile);};
+ void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;};
+ char *GetName() {return(FileName);}
+ long Copy(File &Dest,Int64 Length=INT64ERR);
+ void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
+ void SetExceptions(bool Allow) {AllowExceptions=Allow;}
+#ifdef _WIN_32
+ void RemoveSequentialFlag() {NoSequentialRead=true;}
+#endif
+};
+
+#endif
diff --git a/unrar/unrar/filefn.cpp b/unrar/unrar/filefn.cpp
new file mode 100644
index 0000000..1c43eae
--- /dev/null
+++ b/unrar/unrar/filefn.cpp
@@ -0,0 +1,570 @@
+#include "rar.hpp"
+
+MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
+{
+#ifdef _WIN_32
+ int Success;
+ if (WinNT() && NameW!=NULL && *NameW!=0)
+ Success=CreateDirectoryW(NameW,NULL);
+ else
+ Success=CreateDirectory(Name,NULL);
+ if (Success)
+ {
+ SetFileAttr(Name,NameW,Attr);
+ return(MKDIR_SUCCESS);
+ }
+ int ErrCode=GetLastError();
+ if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
+ return(MKDIR_BADPATH);
+ return(MKDIR_ERROR);
+#endif
+#ifdef _EMX
+#ifdef _DJGPP
+ if (mkdir(Name,(Attr & FA_RDONLY) ? 0:S_IWUSR)==0)
+#else
+ if (__mkdir(Name)==0)
+#endif
+ {
+ SetFileAttr(Name,NameW,Attr);
+ return(MKDIR_SUCCESS);
+ }
+ return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
+#endif
+#ifdef _UNIX
+ int prevmask=umask(0);
+ int ErrCode=Name==NULL ? -1:mkdir(Name,(mode_t)Attr);
+ umask(prevmask);
+ if (ErrCode==-1)
+ return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
+ return(MKDIR_SUCCESS);
+#endif
+}
+
+
+bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
+{
+#if defined(_WIN_32) || defined(_EMX)
+ uint DirAttr=0;
+#else
+ uint DirAttr=0777;
+#endif
+#ifdef UNICODE_SUPPORTED
+ bool Wide=PathW!=NULL && *PathW!=0 && UnicodeEnabled();
+#else
+ bool Wide=false;
+#endif
+ bool IgnoreAscii=false;
+ bool Success=true;
+
+ const char *s=Path;
+ for (int PosW=0;;PosW++)
+ {
+ if (s==NULL || s-Path>=NM || *s==0)
+ IgnoreAscii=true;
+ if (Wide && (PosW>=NM || PathW[PosW]==0) || !Wide && IgnoreAscii)
+ break;
+ if (Wide && PathW[PosW]==CPATHDIVIDER || !Wide && *s==CPATHDIVIDER)
+ {
+ wchar *DirPtrW=NULL,DirNameW[NM];
+ if (Wide)
+ {
+ strncpyw(DirNameW,PathW,PosW);
+ DirNameW[PosW]=0;
+ DirPtrW=DirNameW;
+ }
+ char DirName[NM];
+ if (IgnoreAscii)
+ WideToChar(DirPtrW,DirName);
+ else
+ {
+#ifndef DBCS_SUPPORTED
+ if (*s!=CPATHDIVIDER)
+ for (const char *n=s;*n!=0 && n-Path<NM;n++)
+ if (*n==CPATHDIVIDER)
+ {
+ s=n;
+ break;
+ }
+#endif
+ strncpy(DirName,Path,s-Path);
+ DirName[s-Path]=0;
+ }
+ if (MakeDir(DirName,DirPtrW,DirAttr)==MKDIR_SUCCESS)
+ {
+#ifndef GUI
+ mprintf(St(MCreatDir),DirName);
+ mprintf(" %s",St(MOk));
+#endif
+ }
+ else
+ Success=false;
+ }
+ if (!IgnoreAscii)
+ s=charnext(s);
+ }
+ if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
+ if (MakeDir(Path,PathW,DirAttr)!=MKDIR_SUCCESS)
+ Success=false;
+ return(Success);
+}
+
+
+void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
+{
+#ifdef _WIN_32
+ if (!WinNT())
+ return;
+
+ bool sm=ftm!=NULL && ftm->IsSet();
+ bool sc=ftc!=NULL && ftc->IsSet();
+ bool sa=fta!=NULL && fta->IsSet();
+
+ 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=etoupper(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,ASIZE(Root));
+ ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
+ uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
+ if (pGetDiskFreeSpaceEx(*Root ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
+ uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
+ return(int32to64(uiUserFree.u.HighPart,uiUserFree.u.LowPart));
+ }
+
+ 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,ASIZE(Root));
+ dev_t Dev=dev_for_path(*Root ? Root:".");
+ if (Dev<0)
+ return(1457664);
+ fs_info Info;
+ if (fs_stat_dev(Dev,&Info)!=0)
+ return(1457664);
+ Int64 FreeSize=Info.block_size;
+ FreeSize=FreeSize*Info.free_blocks;
+ return(FreeSize);
+#elif defined(_UNIX)
+ return(1457664);
+#elif defined(_EMX)
+ int Drive=(!isalpha(Name[0]) || Name[1]!=':') ? 0:etoupper(Name[0])-'A'+1;
+#ifndef _DJGPP
+ if (_osmode == OS2_MODE)
+ {
+ FSALLOCATE fsa;
+ if (DosQueryFSInfo(Drive,1,&fsa,sizeof(fsa))!=0)
+ return(1457664);
+ Int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
+ FreeSize=FreeSize*fsa.cUnitAvail;
+ return(FreeSize);
+ }
+ else
+#endif
+ {
+ union REGS regs,outregs;
+ memset(&regs,0,sizeof(regs));
+ regs.h.ah=0x36;
+ regs.h.dl=Drive;
+#ifdef _DJGPP
+ int86 (0x21,&regs,&outregs);
+#else
+ _int86 (0x21,&regs,&outregs);
+#endif
+ if (outregs.x.ax==0xffff)
+ return(1457664);
+ Int64 FreeSize=outregs.x.ax*outregs.x.cx;
+ FreeSize=FreeSize*outregs.x.bx;
+ return(FreeSize);
+ }
+#else
+ #define DISABLEAUTODETECT
+ return(1457664);
+#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);
+#else
+ return(false);
+#endif
+}
+
+
+
+
+
+
+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,CALCCRC_SHOWMODE ShowMode)
+{
+ SaveFilePos SavePos(*SrcFile);
+ const int BufSize=0x10000;
+ Array<byte> Data(BufSize);
+ Int64 BlockCount=0;
+ uint DataCRC=0xffffffff;
+ int ReadSize;
+
+#if !defined(SILENT) && !defined(_WIN_CE)
+ Int64 FileLength=SrcFile->FileLength();
+ if (ShowMode!=CALCCRC_SHOWNONE)
+ {
+ mprintf(St(MCalcCRC));
+ mprintf(" ");
+ }
+
+#endif
+
+ 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)
+ {
+#if !defined(SILENT) && !defined(_WIN_CE)
+ if (ShowMode==CALCCRC_SHOWALL)
+ mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*Int64(BufSize),FileLength));
+#endif
+ Wait();
+ }
+ DataCRC=CRC(DataCRC,&Data[0],ReadSize);
+ if (Size!=INT64ERR)
+ Size-=ReadSize;
+ }
+#if !defined(SILENT) && !defined(_WIN_CE)
+ if (ShowMode==CALCCRC_SHOWALL)
+ mprintf("\b\b\b\b ");
+#endif
+ 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/unrar/filefn.hpp b/unrar/unrar/filefn.hpp
new file mode 100644
index 0000000..ec6cba5
--- /dev/null
+++ b/unrar/unrar/filefn.hpp
@@ -0,0 +1,41 @@
+#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);
+bool 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);
+
+
+enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL};
+uint CalcFileCRC(File *SrcFile,Int64 Size=INT64ERR,CALCCRC_SHOWMODE ShowMode=CALCCRC_SHOWNONE);
+
+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/unrar/filestr.cpp b/unrar/unrar/filestr.cpp
new file mode 100644
index 0000000..55e79a1
--- /dev/null
+++ b/unrar/unrar/filestr.cpp
@@ -0,0 +1,145 @@
+#include "rar.hpp"
+
+static bool IsUnicode(byte *Data,int Size);
+
+bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
+ RAR_CHARSET SrcCharset,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<char> Data(ReadBlock+5);
+ while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0)
+ {
+ DataSize+=ReadSize;
+ Data.Add(ReadSize);
+ }
+
+ memset(&Data[DataSize],0,5);
+
+ if (SrcCharset==RCH_UNICODE ||
+ SrcCharset==RCH_DEFAULT && IsUnicode((byte *)&Data[0],DataSize))
+ {
+ // Unicode in native system format, can be more than 2 bytes per character
+ Array<wchar> DataW(Data.Size()/2+1);
+ for (int I=2;I<Data.Size()-1;I+=2)
+ DataW[(I-2)/2]=(wchar)Data[I]+(wchar)Data[I+1]*256;
+
+ wchar *CurStr=&DataW[0];
+ Array<char> AnsiName;
+
+ while (*CurStr!=0)
+ {
+ wchar *NextStr=CurStr,*CmtPtr=NULL;
+ while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
+ {
+ if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
+ {
+ *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=4*(Length-AnsiName.Size()+1);
+ if (AddSize>0)
+ AnsiName.Add(AddSize);
+ if (Unquote && *CurStr=='\"' && CurStr[Length-1]=='\"')
+ {
+ CurStr[Length-1]=0;
+ CurStr++;
+ }
+ WideToChar(CurStr,&AnsiName[0],AnsiName.Size());
+ List->AddString(&AnsiName[0],CurStr);
+ }
+ CurStr=NextStr+1;
+ while (*CurStr=='\r' || *CurStr=='\n')
+ CurStr++;
+ }
+ }
+ 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 (SrcCharset==RCH_OEM)
+ 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;I<Size;I++)
+ if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
+ return(true);
+ return(false);
+}
diff --git a/unrar/unrar/filestr.hpp b/unrar/unrar/filestr.hpp
new file mode 100644
index 0000000..43ce417
--- /dev/null
+++ b/unrar/unrar/filestr.hpp
@@ -0,0 +1,8 @@
+#ifndef _RAR_FILESTR_
+#define _RAR_FILESTR_
+
+bool ReadTextFile(char *Name,StringList *List,bool Config,
+ bool AbortOnError=false,RAR_CHARSET SrcCharset=RCH_DEFAULT,
+ bool Unquote=false,bool SkipComments=false);
+
+#endif
diff --git a/unrar/unrar/find.cpp b/unrar/unrar/find.cpp
new file mode 100644
index 0000000..9885ee6
--- /dev/null
+++ b/unrar/unrar/find.cpp
@@ -0,0 +1,296 @@
+#include "rar.hpp"
+
+FindFile::FindFile()
+{
+ *FindMask=0;
+ *FindMaskW=0;
+ FirstCall=TRUE;
+#ifdef _WIN_32
+ hFind=INVALID_HANDLE_VALUE;
+#else
+ dirp=NULL;
+#endif
+}
+
+
+FindFile::~FindFile()
+{
+#ifdef _WIN_32
+ if (hFind!=INVALID_HANDLE_VALUE)
+ FindClose(hFind);
+#else
+ if (dirp!=NULL)
+ closedir(dirp);
+#endif
+}
+
+
+void FindFile::SetMask(const char *FindMask)
+{
+ strcpy(FindFile::FindMask,FindMask);
+ if (*FindMaskW==0)
+ CharToWide(FindMask,FindMaskW);
+ FirstCall=TRUE;
+}
+
+
+void FindFile::SetMaskW(const wchar *FindMaskW)
+{
+ if (FindMaskW==NULL)
+ return;
+ strcpyw(FindFile::FindMaskW,FindMaskW);
+ if (*FindMask==0)
+ WideToChar(FindMaskW,FindMask);
+ FirstCall=TRUE;
+}
+
+
+bool FindFile::Next(struct FindData *fd,bool GetSymLink)
+{
+ fd->Error=false;
+ if (*FindMask==0)
+ return(false);
+#ifdef _WIN_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);
+ *PointToName(FullName)=0;
+ if (strlen(FullName)+strlen(ent->d_name)>=ASIZE(FullName)-1)
+ {
+#ifndef SILENT
+ Log(NULL,"\n%s%s",FullName,ent->d_name);
+ Log(NULL,St(MPathTooLong));
+#endif
+ return(false);
+ }
+ strcat(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/unrar/find.hpp b/unrar/unrar/find.hpp
new file mode 100644
index 0000000..8154819
--- /dev/null
+++ b/unrar/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/unrar/getbits.cpp b/unrar/unrar/getbits.cpp
new file mode 100644
index 0000000..71ecfc8
--- /dev/null
+++ b/unrar/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/unrar/getbits.hpp b/unrar/unrar/getbits.hpp
new file mode 100644
index 0000000..eff4daf
--- /dev/null
+++ b/unrar/unrar/getbits.hpp
@@ -0,0 +1,38 @@
+#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();
+ bool Overflow(int IncPtr) {return(InAddr+IncPtr>=MAX_SIZE);}
+};
+#endif
diff --git a/unrar/unrar/global.cpp b/unrar/unrar/global.cpp
new file mode 100644
index 0000000..593a057
--- /dev/null
+++ b/unrar/unrar/global.cpp
@@ -0,0 +1,4 @@
+#define INCLUDEGLOBAL
+
+
+#include "rar.hpp"
diff --git a/unrar/unrar/global.hpp b/unrar/unrar/global.hpp
new file mode 100644
index 0000000..35c6cf9
--- /dev/null
+++ b/unrar/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/unrar/headers.hpp b/unrar/unrar/headers.hpp
new file mode 100644
index 0000000..acf597d
--- /dev/null
+++ b/unrar/unrar/headers.hpp
@@ -0,0 +1,306 @@
+#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 36
+#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 MHD_ENCRYPTVER 0x0200
+
+#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 // not last volume
+#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:BaseBlock
+{
+ ushort HighPosAV;
+ uint PosAV;
+ byte EncryptVer;
+};
+
+
+#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<byte> 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/unrar/int64.cpp b/unrar/unrar/int64.cpp
new file mode 100644
index 0000000..996d0ea
--- /dev/null
+++ b/unrar/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<n2.LowPart)
+ n1.HighPart++;
+ n1.HighPart+=n2.HighPart;
+ return(n1);
+}
+
+
+Int64 operator - (Int64 n1,Int64 n2)
+{
+ if (n1.LowPart<n2.LowPart)
+ n1.HighPart--;
+ n1.LowPart-=n2.LowPart;
+ n1.HighPart-=n2.HighPart;
+ return(n1);
+}
+
+
+Int64 operator += (Int64 &n1,Int64 n2)
+{
+ n1=n1+n2;
+ return(n1);
+}
+
+
+Int64 operator -= (Int64 &n1,Int64 n2)
+{
+ n1=n1-n2;
+ return(n1);
+}
+
+
+Int64 operator *= (Int64 &n1,Int64 n2)
+{
+ n1=n1*n2;
+ return(n1);
+}
+
+
+Int64 operator /= (Int64 &n1,Int64 n2)
+{
+ n1=n1/n2;
+ return(n1);
+}
+
+
+Int64 operator | (Int64 n1,Int64 n2)
+{
+ n1.LowPart|=n2.LowPart;
+ n1.HighPart|=n2.HighPart;
+ return(n1);
+}
+
+
+Int64 operator & (Int64 n1,Int64 n2)
+{
+ n1.LowPart&=n2.LowPart;
+ n1.HighPart&=n2.HighPart;
+ return(n1);
+}
+
+
+/*
+inline void operator -= (Int64 &n1,unsigned int n2)
+{
+ if (n1.LowPart<n2)
+ n1.HighPart--;
+ n1.LowPart-=n2;
+}
+
+
+inline void operator ++ (Int64 &n)
+{
+ if (++n.LowPart == 0)
+ ++n.HighPart;
+}
+
+
+inline void operator -- (Int64 &n)
+{
+ if (n.LowPart-- == 0)
+ n.HighPart--;
+}
+*/
+
+bool operator == (Int64 n1,Int64 n2)
+{
+ return(n1.LowPart==n2.LowPart && n1.HighPart==n2.HighPart);
+}
+
+
+bool operator > (Int64 n1,Int64 n2)
+{
+ return((int)n1.HighPart>(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart>n2.LowPart);
+}
+
+
+bool operator < (Int64 n1,Int64 n2)
+{
+ return((int)n1.HighPart<(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart<n2.LowPart);
+}
+
+
+bool operator != (Int64 n1,Int64 n2)
+{
+ return(n1.LowPart!=n2.LowPart || n1.HighPart!=n2.HighPart);
+}
+
+
+bool operator >= (Int64 n1,Int64 n2)
+{
+ return(n1>n2 || n1==n2);
+}
+
+
+bool operator <= (Int64 n1,Int64 n2)
+{
+ return(n1<n2 || n1==n2);
+}
+
+
+void Int64::Set(uint HighPart,uint LowPart)
+{
+ Int64::HighPart=HighPart;
+ Int64::LowPart=LowPart;
+}
+#endif
+
+void itoa(Int64 n,char *Str)
+{
+ if (n<=0xffffffff)
+ {
+ sprintf(Str,"%u",int64to32(n));
+ return;
+ }
+
+ char NumStr[50];
+ int Pos=0;
+
+ do
+ {
+ NumStr[Pos++]=int64to32(n%10)+'0';
+ n=n/10;
+ } while (n!=0);
+
+ for (int I=0;I<Pos;I++)
+ Str[I]=NumStr[Pos-I-1];
+ Str[Pos]=0;
+}
+
+
+Int64 atoil(char *Str)
+{
+ Int64 n=0;
+ while (*Str>='0' && *Str<='9')
+ {
+ n=n*10+*Str-'0';
+ Str++;
+ }
+ return(n);
+}
diff --git a/unrar/unrar/int64.hpp b/unrar/unrar/int64.hpp
new file mode 100644
index 0000000..d2f34bb
--- /dev/null
+++ b/unrar/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) || defined(__SUNPRO_CC)
+#define NATIVE_INT64
+typedef long long Int64;
+#endif
+
+#ifdef NATIVE_INT64
+
+#define int64to32(x) ((uint)(x))
+#define int32to64(high,low) ((((Int64)(high))<<32)+(low))
+#define is64plus(x) (x>=0)
+
+#else
+
+class Int64
+{
+ public:
+ Int64();
+ Int64(uint n);
+ Int64(uint HighPart,uint LowPart);
+
+// Int64 operator = (Int64 n);
+ Int64 operator << (int n);
+ Int64 operator >> (int n);
+
+ friend Int64 operator / (Int64 n1,Int64 n2);
+ friend Int64 operator * (Int64 n1,Int64 n2);
+ friend Int64 operator % (Int64 n1,Int64 n2);
+ friend Int64 operator + (Int64 n1,Int64 n2);
+ friend Int64 operator - (Int64 n1,Int64 n2);
+ friend Int64 operator += (Int64 &n1,Int64 n2);
+ friend Int64 operator -= (Int64 &n1,Int64 n2);
+ friend Int64 operator *= (Int64 &n1,Int64 n2);
+ friend Int64 operator /= (Int64 &n1,Int64 n2);
+ friend Int64 operator | (Int64 n1,Int64 n2);
+ friend Int64 operator & (Int64 n1,Int64 n2);
+ inline friend void operator -= (Int64 &n1,unsigned int n2)
+ {
+ if (n1.LowPart<n2)
+ n1.HighPart--;
+ n1.LowPart-=n2;
+ }
+ inline friend void operator ++ (Int64 &n)
+ {
+ if (++n.LowPart == 0)
+ ++n.HighPart;
+ }
+ inline friend void operator -- (Int64 &n)
+ {
+ if (n.LowPart-- == 0)
+ n.HighPart--;
+ }
+ friend bool operator == (Int64 n1,Int64 n2);
+ friend bool operator > (Int64 n1,Int64 n2);
+ friend bool operator < (Int64 n1,Int64 n2);
+ friend bool operator != (Int64 n1,Int64 n2);
+ friend bool operator >= (Int64 n1,Int64 n2);
+ friend bool operator <= (Int64 n1,Int64 n2);
+
+ void Set(uint HighPart,uint LowPart);
+ uint GetLowPart() {return(LowPart);}
+
+ uint LowPart;
+ uint HighPart;
+};
+
+inline uint int64to32(Int64 n) {return(n.GetLowPart());}
+#define int32to64(high,low) (Int64((high),(low)))
+#define is64plus(x) ((int)(x).HighPart>=0)
+
+#endif
+
+#define INT64ERR int32to64(0x80000000,0)
+#define INT64MAX int32to64(0x7fffffff,0)
+
+void itoa(Int64 n,char *Str);
+Int64 atoil(char *Str);
+
+#endif
diff --git a/unrar/unrar/isnt.cpp b/unrar/unrar/isnt.cpp
new file mode 100644
index 0000000..493a9eb
--- /dev/null
+++ b/unrar/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/unrar/isnt.hpp b/unrar/unrar/isnt.hpp
new file mode 100644
index 0000000..0265236
--- /dev/null
+++ b/unrar/unrar/isnt.hpp
@@ -0,0 +1,6 @@
+#ifndef _RAR_ISNT_
+#define _RAR_ISNT_
+
+int WinNT();
+
+#endif
diff --git a/unrar/unrar/license.txt b/unrar/unrar/license.txt
new file mode 100644
index 0000000..ec35e09
--- /dev/null
+++ b/unrar/unrar/license.txt
@@ -0,0 +1,40 @@
+ ****** ***** ****** 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. It is allowed
+ to distribute UnRAR inside of other software packages.
+
+ 4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
+ NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
+ YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
+ DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
+ OR MISUSING THIS SOFTWARE.
+
+ 5. Installing and using the UnRAR utility signifies acceptance of
+ these terms and conditions of the license.
+
+ 6. If you don't agree with terms of the license you must remove
+ UnRAR files from your storage devices and cease to use the
+ utility.
+
+ Thank you for your interest in RAR and UnRAR.
+
+
+ Alexander L. Roshal \ No newline at end of file
diff --git a/unrar/unrar/list.cpp b/unrar/unrar/list.cpp
new file mode 100644
index 0000000..d569006
--- /dev/null
+++ b/unrar/unrar/list.cpp
@@ -0,0 +1,388 @@
+#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();
+
+ // RAR can close a corrupt encrypted archive
+ if (!Arc.IsOpened())
+ break;
+
+ 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)
+ {
+ int HeaderType=Arc.GetHeaderType();
+ if (HeaderType==ENDARC_HEAD)
+ break;
+ switch(HeaderType)
+ {
+ 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,ToPercentUnlim(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,ToPercentUnlim(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) && *ConvertedName!=0)
+ 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%%",ToPercentUnlim(hd.FullPackSize,hd.FullUnpSize));
+
+ char DateStr[50];
+ hd.mtime.GetText(DateStr,false);
+ mprintf(" %s ",DateStr);
+
+ if (hd.HeadType==NEWSUB_HEAD)
+ mprintf(" %c....B ",(hd.SubFlags & SUBHEAD_FLAGS_INHERITED) ? 'I' : '.');
+ else
+ ListFileAttr(hd.FileAttr,hd.HostOS);
+
+ mprintf(" %8.8X",hd.FileCRC);
+ mprintf(" m%d",hd.Method-0x30);
+ if ((hd.Flags & LHD_WINDOWMASK)<=6*32)
+ mprintf("%c",((hd.Flags&LHD_WINDOWMASK)>>5)+'a');
+ else
+ mprintf(" ");
+ mprintf(" %d.%d",hd.UnpVer/10,hd.UnpVer%10);
+
+ static const char *RarOS[]={
+ "DOS","OS/2","Win95/NT","Unix","MacOS","BeOS","WinCE","","",""
+ };
+
+ if (Technical)
+ mprintf("\n%22s %8s %4s",
+ (hd.HostOS<sizeof(RarOS)/sizeof(RarOS[0]) ? RarOS[hd.HostOS]:""),
+ (hd.Flags & LHD_SOLID) ? St(MYes):St(MNo),
+ (hd.Flags & LHD_VERSION) ? St(MYes):St(MNo));
+}
+
+
+void ListSymLink(Archive &Arc)
+{
+ if (Arc.NewLhd.HostOS==HOST_UNIX && (Arc.NewLhd.FileAttr & 0xF000)==0xA000)
+ {
+ char FileName[NM];
+ int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1);
+ Arc.Read(FileName,DataSize);
+ FileName[DataSize]=0;
+ mprintf("\n%22s %s","-->",FileName);
+ }
+}
+
+
+void ListFileAttr(uint A,int HostOS)
+{
+ switch(HostOS)
+ {
+ case HOST_MSDOS:
+ case HOST_OS2:
+ case HOST_WIN32:
+ case HOST_MACOS:
+ mprintf(" %c%c%c%c%c%c%c ",
+ (A & 0x08) ? 'V' : '.',
+ (A & 0x10) ? 'D' : '.',
+ (A & 0x01) ? 'R' : '.',
+ (A & 0x02) ? 'H' : '.',
+ (A & 0x04) ? 'S' : '.',
+ (A & 0x20) ? 'A' : '.',
+ (A & 0x800) ? 'C' : '.');
+ break;
+ case 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 (Arc.SubHead.CmpName(SUBHEAD_TYPE_CMT) &&
+ (Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0 && !Cmd->DisableComment)
+ {
+ Array<byte> CmtData;
+ int ReadSize=Arc.ReadCommentData(&CmtData,NULL);
+ if (ReadSize!=0)
+ {
+ mprintf(St(MFileComment));
+ OutComment((char *)&CmtData[0],ReadSize);
+ }
+ }
+ if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM) &&
+ (Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0)
+ {
+ int DestSize=Arc.SubHead.SubData.Size()/2;
+ wchar DestNameW[NM];
+ char DestName[NM];
+ if (DestSize<sizeof(DestName))
+ {
+ RawToWide(&Arc.SubHead.SubData[0],DestNameW,DestSize);
+ DestNameW[DestSize]=0;
+ WideToChar(DestNameW,DestName);
+ mprintf("\n %s",DestName);
+ }
+ }
+}
diff --git a/unrar/unrar/list.hpp b/unrar/unrar/list.hpp
new file mode 100644
index 0000000..7721ae5
--- /dev/null
+++ b/unrar/unrar/list.hpp
@@ -0,0 +1,6 @@
+#ifndef _RAR_LIST_
+#define _RAR_LIST_
+
+void ListArchive(CommandData *Cmd);
+
+#endif
diff --git a/unrar/unrar/loclang.hpp b/unrar/unrar/loclang.hpp
new file mode 100644
index 0000000..c425bb3
--- /dev/null
+++ b/unrar/unrar/loclang.hpp
@@ -0,0 +1,349 @@
+#define MYesNo "_Yes_No"
+#define MYesNoAll "_Yes_No_All"
+#define MYesNoAllRenQ "_Yes_No_All_nEver_Rename_Quit"
+#define MContinueQuit "_Continue_Quit"
+#define MRetryAbort "_Retry_Abort"
+#define MCopyright "\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d"
+#define MRegTo "\nRegistered to %s\n"
+#define MShare "\nShareware version Type RAR -? for help\n"
+#define MUCopyright "\nUNRAR %s freeware Copyright (c) 1993-%d Alexander Roshal\n"
+#define MBeta "beta"
+#define MMonthJan "Jan"
+#define MMonthFeb "Feb"
+#define MMonthMar "Mar"
+#define MMonthApr "Apr"
+#define MMonthMay "May"
+#define MMonthJun "Jun"
+#define MMonthJul "Jul"
+#define MMonthAug "Aug"
+#define MMonthSep "Sep"
+#define MMonthOct "Oct"
+#define MMonthNov "Nov"
+#define MMonthDec "Dec"
+#define MRARTitle1 "\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
+#define MUNRARTitle1 "\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
+#define MRARTitle2 "\n <@listfiles...> <path_to_extract\\>"
+#define MCHelpCmd "\n\n<Commands>"
+#define MCHelpCmdA "\n a Add files to archive"
+#define MCHelpCmdC "\n c Add archive comment"
+#define MCHelpCmdCF "\n cf Add files comment"
+#define MCHelpCmdCH "\n ch Change archive parameters"
+#define MCHelpCmdCW "\n cw Write archive comment to file"
+#define MCHelpCmdD "\n d Delete files from archive"
+#define MCHelpCmdE "\n e Extract files to current directory"
+#define MCHelpCmdF "\n f Freshen files in archive"
+#define MCHelpCmdI "\n i[par]=<str> Find string in archives"
+#define MCHelpCmdK "\n k Lock archive"
+#define MCHelpCmdL "\n l[t,b] List archive [technical, bare]"
+#define MCHelpCmdM "\n m[f] Move to archive [files only]"
+#define MCHelpCmdP "\n p Print file to stdout"
+#define MCHelpCmdR "\n r Repair archive"
+#define MCHelpCmdRC "\n rc Reconstruct missing volumes"
+#define MCHelpCmdRN "\n rn Rename archived files"
+#define MCHelpCmdRR "\n rr[N] Add data recovery record"
+#define MCHelpCmdRV "\n rv[N] Create recovery volumes"
+#define MCHelpCmdS "\n s[name|-] Convert archive to or from SFX"
+#define MCHelpCmdT "\n t Test archive files"
+#define MCHelpCmdU "\n u Update files in archive"
+#define MCHelpCmdV "\n v[t,b] Verbosely list archive [technical,bare]"
+#define MCHelpCmdX "\n x Extract files with full path"
+#define MCHelpSw "\n\n<Switches>"
+#define MCHelpSwm "\n - Stop switches scanning"
+#define MCHelpSwAC "\n ac Clear Archive attribute after compression or extraction"
+#define MCHelpSwAD "\n ad Append archive name to destination path"
+#define MCHelpSwAG "\n ag[format] Generate archive name using the current date"
+#define MCHelpSwAO "\n ao Add files with Archive attribute set"
+#define MCHelpSwAP "\n ap<path> Set path inside archive"
+#define MCHelpSwAS "\n as Synchronize archive contents"
+#define MCHelpSwAV "\n av Put authenticity verification (registered versions only)"
+#define MCHelpSwAVm "\n av- Disable authenticity verification check"
+#define MCHelpSwCm "\n c- Disable comments show"
+#define MCHelpSwCFGm "\n cfg- Disable read configuration"
+#define MCHelpSwCL "\n cl Convert names to lower case"
+#define MCHelpSwCU "\n cu Convert names to upper case"
+#define MCHelpSwDF "\n df Delete files after archiving"
+#define MCHelpSwDH "\n dh Open shared files"
+#define MCHelpSwDS "\n ds Disable name sort for solid archive"
+#define MCHelpSwEa "\n e[+]<attr> Set file exclude and include attributes"
+#define MCHelpSwED "\n ed Do not add empty directories"
+#define MCHelpSwEE "\n ee Do not save and extract extended attributes"
+#define MCHelpSwEN "\n en Do not put 'end of archive' block"
+#define MCHelpSwEP "\n ep Exclude paths from names"
+#define MCHelpSwEP1 "\n ep1 Exclude base directory from names"
+#define MCHelpSwEP2 "\n ep2 Expand paths to full"
+#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter"
+#define MCHelpSwF "\n f Freshen files"
+#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers"
+#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages"
+#define MCHelpSwIEML "\n ieml[addr] Send archive by email"
+#define MCHelpSwIERR "\n ierr Send all messages to stderr"
+#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)"
+#define MCHelpSwINUL "\n inul Disable all messages"
+#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation"
+#define MCHelpSwISND "\n isnd Enable sound"
+#define MCHelpSwK "\n k Lock archive"
+#define MCHelpSwKB "\n kb Keep broken extracted files"
+#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)"
+#define MCHelpSwMC "\n mc<par> Set advanced compression parameters"
+#define MCHelpSwMD "\n md<size> Dictionary size in KB (64,128,256,512,1024,2048,4096 or A-G)"
+#define MCHelpSwMS "\n ms[ext;ext] Specify file types to store"
+#define MCHelpSwMT "\n mt<threads> Set the number of threads"
+#define MCHelpSwN "\n n<file> Include only specified file"
+#define MCHelpSwNa "\n n@ Read file names to include from stdin"
+#define MCHelpSwNal "\n n@<list> Include files in specified list file"
+#define MCHelpSwOp "\n o+ Overwrite existing files"
+#define MCHelpSwOm "\n o- Do not overwrite existing files"
+#define MCHelpSwOC "\n oc Set NTFS Compressed attribute"
+#define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file"
+#define MCHelpSwOR "\n or Rename files automatically"
+#define MCHelpSwOS "\n os Save NTFS streams"
+#define MCHelpSwOW "\n ow Save or restore file owner and group"
+#define MCHelpSwP "\n p[password] Set password"
+#define MCHelpSwPm "\n p- Do not query password"
+#define MCHelpSwR "\n r Recurse subdirectories"
+#define MCHelpSwR0 "\n r0 Recurse subdirectories for wildcard names only"
+#define MCHelpSwRI "\n ri<P>[:<S>] Set priority (0-default,1-min..15-max) and sleep time in ms"
+#define MCHelpSwRR "\n rr[N] Add data recovery record"
+#define MCHelpSwRV "\n rv[N] Create recovery volumes"
+#define MCHelpSwS "\n s[<N>,v[-],e] Create solid archive"
+#define MCHelpSwSm "\n s- Disable solid archiving"
+#define MCHelpSwSC "\n sc<chr>[obj] Specify the character set"
+#define MCHelpSwSFX "\n sfx[name] Create SFX archive"
+#define MCHelpSwSI "\n si[name] Read data from standard input (stdin)"
+#define MCHelpSwSL "\n sl<size> Process files with size less than specified"
+#define MCHelpSwSM "\n sm<size> Process files with size more than specified"
+#define MCHelpSwT "\n t Test files after archiving"
+#define MCHelpSwTK "\n tk Keep original archive time"
+#define MCHelpSwTL "\n tl Set archive time to latest file"
+#define MCHelpSwTN "\n tn<time> Process files newer than <time>"
+#define MCHelpSwTO "\n to<time> Process files older than <time>"
+#define MCHelpSwTA "\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
+#define MCHelpSwTB "\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
+#define MCHelpSwTS "\n ts<m,c,a>[N] Save or restore file time (modification, creation, access)"
+#define MCHelpSwU "\n u Update files"
+#define MCHelpSwV "\n v Create volumes with size autodetection or list all volumes"
+#define MCHelpSwVUnr "\n v List all volumes"
+#define MCHelpSwVn "\n v<size>[k,b] Create volumes with size=<size>*1000 [*1024, *1]"
+#define MCHelpSwVD "\n vd Erase disk contents before creating volume"
+#define MCHelpSwVER "\n ver[n] File version control"
+#define MCHelpSwVN "\n vn Use the old style volume naming scheme"
+#define MCHelpSwVP "\n vp Pause before each volume"
+#define MCHelpSwW "\n w<path> Assign work directory"
+#define MCHelpSwX "\n x<file> Exclude specified file"
+#define MCHelpSwXa "\n x@ Read file names to exclude from stdin"
+#define MCHelpSwXal "\n x@<list> Exclude files in specified list file"
+#define MCHelpSwY "\n y Assume Yes on all queries"
+#define MCHelpSwZ "\n z[file] Read archive comment from file"
+#define MBadArc "\nERROR: Bad archive %s\n"
+#define MAskPsw "Enter password (will not be echoed)"
+#define MAskPswEcho "Enter password"
+#define MReAskPsw "\nReenter password: "
+#define MFor " for "
+#define MNotMatchPsw "\nERROR: Passwords do not match\n"
+#define MErrWrite "Write error in the file %s"
+#define MErrRead "Read error in the file %s"
+#define MErrSeek "Seek error in the file %s"
+#define MErrFClose "Cannot close the file %s"
+#define MErrOutMem "Not enough memory"
+#define MErrBrokenArc "Corrupt archive - use 'Repair' command"
+#define MProgAborted "Program aborted"
+#define MErrRename "\nCannot rename %s to %s"
+#define MAbsNextVol "\nCannot find volume %s"
+#define MBreak "\nUser break\n"
+#define MAskCreatVol "\nCreate next volume ?"
+#define MAskNextDisk "\nDisk full. Insert next"
+#define MCreatVol "\n\nCreating %sarchive %s\n"
+#define MAskNextVol "\nInsert disk with %s"
+#define MTestVol "\n\nTesting archive %s\n"
+#define MExtrVol "\n\nExtracting from %s\n"
+#define MConverting "\nConverting %s"
+#define MCvtToSFX "\nConvert archives to SFX"
+#define MCvtFromSFX "\nRemoving SFX module"
+#define MNotSFX "\n%s is not SFX archive"
+#define MNotRAR "\n%s is not RAR archive"
+#define MNotFirstVol "\n%s is not the first volume"
+#define MCvtOldFormat "\n%s - cannot convert to SFX archive with old format"
+#define MCannotCreate "\nCannot create %s"
+#define MCannotOpen "\nCannot open %s"
+#define MUnknownMeth "\nUnknown method in %s"
+#define MVerRequired "\nYou need RAR %d.%d to unpack it"
+#define MOk " OK"
+#define MDone "\nDone"
+#define MLockingArc "\nLocking archive"
+#define MNotMdfOld "\n\nERROR: Cannot modify old format archive"
+#define MNotMdfLock "\n\nERROR: Locked archive"
+#define MNotMdfVol "\n\nERROR: Cannot modify volume"
+#define MVerifyAV "\nVerifying authenticity information ... "
+#define MFailedAV " Failed\n"
+#define MStrAV1 "\n\nArchive %s"
+#define MStrAV2 "\ncreated at %s"
+#define MStrAV3 "\nby %s\n"
+#define MLogFailedAV "Invalid authenticity information"
+#define MAddingAV "\nAdding authenticity verification "
+#define MAVOldStyle "\n\nOld style authenticity information"
+#define MPackAskReg "\nEvaluation copy. Please register.\n"
+#define MCreateArchive "\nCreating %sarchive %s\n"
+#define MUpdateArchive "\nUpdating %sarchive %s\n"
+#define MAddSolid "solid "
+#define MAddFile "\nAdding %-58s "
+#define MUpdFile "\nUpdating %-58s "
+#define MAddPoints "\n... %-58s "
+#define MCannotUpdPswSolid "\nERROR: Cannot update solid archives with password\n"
+#define MMoveDelFiles "\n\nDeleting files %s..."
+#define MMoveDelDirs "and directories"
+#define MMoveDelFile "\nDeleting %-30s"
+#define MMoveDeleted " deleted"
+#define MMoveNotDeleted " NOT DELETED"
+#define MClearAttrib "\n\nClearing attributes..."
+#define MMoveDelDir "\nDeleting directory %-30s"
+#define MWarErrFOpen "\nWARNING: Cannot open %d %s"
+#define MErrOpenFiles "files"
+#define MErrOpenFile "file"
+#define MAddNoFiles "\nWARNING: No files"
+#define MMdfEncrSol "\n%s: encrypted"
+#define MCannotMdfEncrSol "\nCannot modify solid archive containing encrypted files"
+#define MAddAnalyze "\nAnalyzing archived files: "
+#define MRepacking "\nRepacking archived files: "
+#define MCRCFailed "\n%-20s - CRC failed"
+#define MExtrTest "\n\nTesting archive %s\n"
+#define MExtracting "\n\nExtracting from %s\n"
+#define MUseCurPsw "\n%s - use current password ?"
+#define MCreatDir "\nCreating %-56s"
+#define MExtrSkipFile "\nSkipping %-56s"
+#define MExtrTestFile "\nTesting %-56s"
+#define MExtrFile "\nExtracting %-56s"
+#define MExtrPoints "\n... %-56s"
+#define MExtrErrMkDir "\nCannot create directory %s"
+#define MExtrPrinting "\n------ Printing %s\n\n"
+#define MEncrBadCRC "\nEncrypted file: CRC failed in %s (password incorrect ?)"
+#define MExtrNoFiles "\nNo files to extract"
+#define MExtrAllOk "\nAll OK"
+#define MExtrTotalErr "\nTotal errors: %ld"
+#define MFileExists "\n\n%s already exists. Overwrite it ?"
+#define MAskOverwrite "\nOverwrite %s ?"
+#define MAskNewName "\nEnter new name: "
+#define MLogMainHead "\nThe archive header is corrupt"
+#define MLogFileHead "\n%s - the file header is corrupt"
+#define MLogCommHead "\nThe comment header is corrupt\n"
+#define MLogProtectHead "The data recovery header is corrupt"
+#define MReadStdinCmt "\nReading comment from stdin\n"
+#define MReadCommFrom "\nReading comment from %s"
+#define MDelComment "\nDeleting comment from %s"
+#define MAddComment "\nAdding comment to %s"
+#define MFCommAdd "\nAdding file comments"
+#define MAskFComm "\n\nReading comment for %s : %s from stdin\n"
+#define MLogCommBrk "\nThe archive comment is corrupt"
+#define MCommAskCont "\nPress 'Enter' to continue or 'Q' to quit:"
+#define MLogBrokFCmt "\nThe file comment is corrupt"
+#define MAbsDestName "\nDestination file name required"
+#define MWriteCommTo "\nWrite comment to %s"
+#define MCommNotPres "\nComment is not present"
+#define MDelFrom "\nDeleting from %s"
+#define MDeleting "\nDeleting %s"
+#define MEraseArc "\nErasing empty archive %s"
+#define MNoDelFiles "\nNo files to delete"
+#define MLogTitle "\n\n-------- %2d %s %d, archive %s\n"
+#define MPathTooLong "\nERROR: Path too long\n"
+#define MListSolid "Solid "
+#define MListSFX "SFX "
+#define MListVol1 "volume"
+#define MListVol2 "Volume"
+#define MListArc1 "archive"
+#define MListArc2 "Archive"
+#define MListRecRec "\nRecovery record is present\n"
+#define MListLock "\nLock is present\n"
+#define MListPathComm "\nPathname/Comment\n "
+#define MListName "\n Name "
+#define MListTitle " Size Packed Ratio Date Time Attr CRC Meth Ver\n"
+#define MListTechTitle " Host OS Solid Old\n"
+#define MListEAHead "\n OS/2 extended attributes"
+#define MListUOHead "\n Unix Owner/Group data: %-14s %-14s"
+#define MListBeEAHead "\n BeOS extended attributes"
+#define MListNTACLHead "\n NTFS security data"
+#define MListStrmHead "\n NTFS stream: %s"
+#define MListUnkHead "\n Unknown subheader type: 0x%04x"
+#define MFileComment "\nComment: "
+#define MYes "Yes"
+#define MNo "No"
+#define MListNoFiles " 0 files\n"
+#define MRprReconstr "\nReconstructing %s"
+#define MRprBuild "\nBuilding %s"
+#define MRprOldFormat "\nCannot repair archive with old format"
+#define MRprFind "\nFound %s"
+#define MRprAskIsSol "\nThe archive header is corrupt. Mark archive as solid ?"
+#define MRprNoFiles "\nNo files found"
+#define MRprSuspEntry "\n\nSuspicious entry %s"
+#define MRprDir "\nDirectory"
+#define MRprSuspSize "\nSize %ld Packed %ld"
+#define MRprSuspAdd "\nAdd it to archive ?"
+#define MLogUnexpEOF "\nUnexpected end of archive"
+#define MRepAskReconst "\nReconstruct archive structure ?"
+#define MRecScanning "\nScanning..."
+#define MRecRNotFound "\nData recovery record not found"
+#define MRecRFound "\nData recovery record found"
+#define MRecSecDamage "\nSector %ld (offsets %lX...%lX) damaged"
+#define MRecCorrected " - data recovered"
+#define MRecFailed " - cannot recover data"
+#define MAddRecRec "\nAdding data recovery record"
+#define MEraseForVolume "\n\nErasing contents of drive %c:\n"
+#define MGetOwnersError "\nWARNING: Cannot get %s owner and group\n"
+#define MErrGetOwnerID "\nWARNING: Cannot get owner %s ID\n"
+#define MErrGetGroupID "\nWARNING: Cannot get group %s ID\n"
+#define MOwnersBroken "\nERROR: %s group and owner data are corrupt\n"
+#define MSetOwnersError "\nWARNING: Cannot set %s owner and group\n"
+#define MErrLnkRead "\nWARNING: Cannot read symbolic link %s"
+#define MErrCreateLnk "\nWARNING: Cannot create link %s"
+#define MSymLinkExists "\nWARNING: Symbolic link %s already exists"
+#define MAskRetryCreate "\nCannot create %s. Retry ?"
+#define MListMACHead1 "\n MacOS file type: %c%c%c%c ; "
+#define MListMACHead2 "file creator: %c%c%c%c\n"
+#define MDataBadCRC "\n%-20s : packed data CRC failed in volume %s"
+#define MFileRO "\n%s is read-only"
+#define MACLGetError "\nWARNING: Cannot get %s security data\n"
+#define MACLSetError "\nWARNING: Cannot set %s security data\n"
+#define MACLBroken "\nERROR: %s security data are corrupt\n"
+#define MACLUnknown "\nWARNING: Unknown format of %s security data\n"
+#define MStreamBroken "\nERROR: %s stream data are corrupt\n"
+#define MStreamUnknown "\nWARNING: Unknown format of %s stream data\n"
+#define MInvalidName "\nERROR: Invalid file name %s"
+#define MEABroken "\nERROR: %s extended attributes are corrupt\n"
+#define MEAUnknHeader "\nWARNING: %s - unknown format of extended attributes\n"
+#define MCannotSetEA "\nWARNING: cannot set extended attributes to %s\n"
+#define MCannotGetEA "\nERROR: Cannot get extended attributes of %s\n"
+#define MShowEA " (+EA)"
+#define MSkipEA "\n...skipping extended attributes"
+#define MProcessArc "\n\nProcessing archive %s"
+#define MSyncScanError "\nFile search errors, cannot synchronize archive"
+#define MCorrectingName "\nWARNING: Attempting to correct the invalid file name"
+#define MUnpCannotMerge "\nWARNING: You need to start extraction from a previous volume to unpack %s"
+#define MUnknownOption "\nERROR: Unknown option: %s"
+#define MSubHeadCorrupt "\nERROR: Corrupt data header found, ignored"
+#define MSubHeadUnknown "\nWARNING: Unknown data header format, ignored"
+#define MSubHeadDataCRC "\nERROR: Corrupt %s data block"
+#define MSubHeadType "\nData header type: %s"
+#define MScanError "\nCannot read contents of %s"
+#define MNotVolume "\n%s is not volume"
+#define MRecVolDiffSets "\nERROR: %s and %s belong to different sets"
+#define MRecVolMissing "\n%d volumes missing"
+#define MRecVolFound "\n%d recovery volumes found"
+#define MRecVolAllExist "\nNothing to reconstruct"
+#define MRecVolCannotFix "\nReconstruction impossible"
+#define MReconstructing "\nReconstructing..."
+#define MCreating "\nCreating %s"
+#define MRenaming "\nRenaming %s to %s"
+#define MNTFSRequired "\nWrite error: only NTFS file system supports files larger than 4 GB"
+#define MErrChangeAttr "\nWARNING: Cannot change attributes of %s"
+#define MWrongSFXVer "\nERROR: default SFX module does not support RAR %d.%d archives"
+#define MCannotEncName "\nCannot encrypt archive already contained encrypted files"
+#define MCannotEmail "\nCannot email the file %s"
+#define MCopyrightS "\nRAR SFX archive"
+#define MSHelpCmd "\n\n<Commands>"
+#define MSHelpCmdE "\n -x Extract from archive (default)"
+#define MSHelpCmdT "\n -t Test archive files"
+#define MSHelpCmdV "\n -v Verbosely list contents of archive"
+#define MMaxPathLimit "\nTotal path and file name length must not exceed %d characters"
+#define MRecVolLimit "\nTotal number of usual and recovery volumes must not exceed 255"
+#define MVolumeNumber "volume %d"
+#define MCannotDelete "\nCannot delete %s"
+#define MCalcCRC "\nCalculating the control sum"
+#define MTooLargeSFXArc "\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB."
diff --git a/unrar/unrar/log.cpp b/unrar/unrar/log.cpp
new file mode 100644
index 0000000..966e9de
--- /dev/null
+++ b/unrar/unrar/log.cpp
@@ -0,0 +1,24 @@
+#include "rar.hpp"
+
+
+static char LogName[NM];
+
+void InitLogOptions(char *LogName)
+{
+ strcpy(::LogName,LogName);
+}
+
+
+#ifndef SILENT
+void Log(const char *ArcName,const char *Format,...)
+{
+ safebuf char Msg[2*NM+1024];
+ va_list ArgPtr;
+ va_start(ArgPtr,Format);
+ vsprintf(Msg,Format,ArgPtr);
+ va_end(ArgPtr);
+ eprintf("%s",Msg);
+}
+#endif
+
+
diff --git a/unrar/unrar/log.hpp b/unrar/unrar/log.hpp
new file mode 100644
index 0000000..52d6b8d
--- /dev/null
+++ b/unrar/unrar/log.hpp
@@ -0,0 +1,18 @@
+#ifndef _RAR_LOG_
+#define _RAR_LOG_
+
+void InitLogOptions(char *LogName);
+
+#ifndef SILENT
+void Log(const char *ArcName,const char *Format,...);
+#endif
+
+#ifdef SILENT
+#ifdef __GNUC__
+#define Log(args...)
+#else
+inline void Log(const char *a,const char *b,const char *c=NULL,const char *d=NULL) {}
+#endif
+#endif
+
+#endif
diff --git a/unrar/unrar/makefile.bcc b/unrar/unrar/makefile.bcc
new file mode 100644
index 0000000..7b833c6
--- /dev/null
+++ b/unrar/unrar/makefile.bcc
@@ -0,0 +1,501 @@
+.AUTODEPEND
+
+basepath = $(BASEPATHCC)
+binpath = $(basepath)\bin
+libpath = $(basepath)\lib
+rarpath = .
+incpath = $(basepath)\include;$(rarpath)
+
+cc = $(binpath)\bcc32
+link = $(binpath)\ilink32
+
+objpath = .
+guiopt = -WC -H=$(objpath)\rar.csm
+
+!ifndef RARDLL
+!ifndef GUI
+guiopt=$(guiopt) -x-
+!endif
+!ifdef SFX_MODULE
+guiopt=$(guiopt) -x-
+!endif
+!endif
+
+!ifdef DEBUG
+optdeb=-Od -k -vi- -DDEBUG
+!else
+# -O is not safe to use with -pr and int64 return values, so let's turn it off
+optdeb=-O1 -O- -k-
+#optdeb=-Ob -Oe -Og -Oi -Ol -Om -Op -OS -Ov -Z -Oc
+!endif
+
+
+optunrar=-DUNRAR
+linkdest=unrar.exe
+
+!ifdef SFX_MODULE
+optunrar=-DUNRAR -DSFX_MODULE
+linkdest=sfx.exe
+!endif
+
+linkopt = -L$(libpath) -ap -c -v -s -V4.0 -Gn
+compopt = -P -c -I$(incpath) -R -v -vi -w-pch -w-par -K -f-\
+ -ff- -a4 -pr -RT- $(optdeb) $(guiopt) $(optunrar) -d -w-8072
+
+!ifdef RARDLL
+SILENT=true
+linkdest=unrar.dll
+linkopt=$(linkopt) -Tpd
+compopt=$(compopt) -DRARDLL
+!else
+linkopt=$(linkopt) -Tpe -B:0x400000
+!endif
+
+!ifdef SILENT
+compopt=$(compopt) -DSILENT
+!endif
+
+
+rar: $(linkdest)
+
+Dep_SFX= \
+ $(objpath)\strlist.obj\
+ $(objpath)\strfn.obj\
+ $(objpath)\pathfn.obj\
+ $(objpath)\cmddata.obj\
+ $(objpath)\consio.obj\
+ $(objpath)\int64.obj\
+ $(objpath)\savepos.obj\
+ $(objpath)\file.obj\
+ $(objpath)\filefn.obj\
+ $(objpath)\filcreat.obj\
+ $(objpath)\sha1.obj\
+ $(objpath)\archive.obj\
+ $(objpath)\arcread.obj\
+ $(objpath)\unicode.obj\
+ $(objpath)\system.obj\
+ $(objpath)\isnt.obj\
+ $(objpath)\crc.obj\
+ $(objpath)\crypt.obj\
+ $(objpath)\rijndael.obj\
+ $(objpath)\rawread.obj\
+ $(objpath)\encname.obj\
+ $(objpath)\resource.obj\
+ $(objpath)\match.obj\
+ $(objpath)\find.obj\
+ $(objpath)\timefn.obj\
+ $(objpath)\getbits.obj\
+ $(objpath)\rarvm.obj\
+ $(objpath)\rdwrfn.obj\
+ $(objpath)\options.obj\
+ $(objpath)\ulinks.obj\
+ $(objpath)\errhnd.obj\
+ $(objpath)\volume.obj\
+ $(objpath)\rs.obj\
+ $(objpath)\recvol.obj\
+ $(objpath)\extinfo.obj\
+ $(objpath)\extract.obj\
+ $(objpath)\unpack.obj\
+ $(objpath)\rar.obj\
+ $(objpath)\global.obj
+
+Dep_Unrar = \
+ $(objpath)\filestr.obj\
+ $(objpath)\scantree.obj
+
+Dep_Dll = \
+ $(objpath)\dll.obj
+
+#Dep_SFXOnly = $(objpath)\rtl.obj
+
+!ifndef GUI
+!ifndef SILENT
+Dep_Console = \
+ $(objpath)\list.obj
+!endif
+!endif
+
+!ifdef SFX_MODULE
+Dep = $(Dep_SFX) $(Dep_SFXOnly)
+!else
+Dep = $(Dep_SFX) $(Dep_Unrar)
+!endif
+
+!ifndef GUI
+Dep = $(Dep) $(Dep_Console)
+!endif
+
+!ifdef RARDLL
+Dep = $(Dep) $(Dep_Dll)
+!endif
+
+!ifdef GUI
+$(linkdest) : $(Dep)
+ echo Done
+!else
+$(linkdest) : $(Dep)
+ $(link) @&&|
+ $(linkopt) +
+#!ifdef SFX_MODULE
+#$(objpath)\dummy.obj+
+#$(objpath)\ll.obj+
+#$(objpath)\rtl.obj+
+#!else
+!ifdef RARDLL
+$(libpath)\c0d32.obj+
+!else
+$(libpath)\c0x32.obj+
+!endif
+#!endif
+$(objpath)\strlist.obj+
+$(objpath)\strfn.obj+
+$(objpath)\pathfn.obj+
+$(objpath)\int64.obj+
+$(objpath)\savepos.obj+
+$(objpath)\global.obj+
+$(objpath)\file.obj+
+$(objpath)\filefn.obj+
+$(objpath)\filcreat.obj+
+$(objpath)\sha1.obj+
+$(objpath)\archive.obj+
+$(objpath)\arcread.obj+
+$(objpath)\unicode.obj+
+$(objpath)\system.obj+
+$(objpath)\isnt.obj+
+$(objpath)\crc.obj+
+$(objpath)\crypt.obj+
+$(objpath)\rijndael.obj+
+$(objpath)\rawread.obj+
+$(objpath)\encname.obj+
+$(objpath)\resource.obj+
+$(objpath)\match.obj+
+$(objpath)\find.obj+
+!ifndef SFX_MODULE
+$(objpath)\filestr.obj+
+$(objpath)\scantree.obj+
+!endif
+$(objpath)\timefn.obj+
+$(objpath)\getbits.obj+
+$(objpath)\rarvm.obj+
+$(objpath)\rdwrfn.obj+
+$(objpath)\consio.obj+
+$(objpath)\cmddata.obj+
+$(objpath)\options.obj+
+$(objpath)\ulinks.obj+
+$(objpath)\volume.obj+
+$(objpath)\extinfo.obj+
+$(objpath)\extract.obj+
+$(objpath)\rs.obj+
+$(objpath)\recvol.obj+
+!ifndef SILENT
+!ifndef GUI
+$(objpath)\list.obj+
+!endif
+!endif
+!ifdef RARDLL
+$(objpath)\dll.obj+
+!endif
+$(objpath)\errhnd.obj+
+$(objpath)\unpack.obj+
+$(objpath)\rar.obj
+$<,$*
+$(libpath)\cw32.lib+
+$(libpath)\import32.lib
+!ifdef RARDLL
+$(rarpath)\dll.def
+!else
+
+!endif
+|
+!endif
+
+$(objpath)\rar.obj : $(rarpath)\rar.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rar.cpp
+|
+
+$(objpath)\strlist.obj : $(rarpath)\strlist.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\strlist.cpp
+|
+
+$(objpath)\strfn.obj : $(rarpath)\strfn.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\strfn.cpp
+|
+
+$(objpath)\pathfn.obj : $(rarpath)\pathfn.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\pathfn.cpp
+|
+
+$(objpath)\int64.obj : $(rarpath)\int64.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\int64.cpp
+|
+
+$(objpath)\savepos.obj : $(rarpath)\savepos.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\savepos.cpp
+|
+
+$(objpath)\global.obj : $(rarpath)\global.cpp
+ $(cc) -q @&&|
+ $(compopt) -H- -o$@ $(rarpath)\global.cpp
+|
+
+$(objpath)\file.obj : $(rarpath)\file.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\file.cpp
+|
+
+$(objpath)\filefn.obj : $(rarpath)\filefn.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\filefn.cpp
+|
+
+$(objpath)\filestr.obj : $(rarpath)\filestr.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\filestr.cpp
+|
+
+$(objpath)\filcreat.obj : $(rarpath)\filcreat.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\filcreat.cpp
+|
+
+$(objpath)\sha1.obj : $(rarpath)\sha1.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\sha1.cpp
+|
+
+$(objpath)\ec.obj : $(rarpath)\ec.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\ec.cpp
+|
+
+$(objpath)\av.obj : $(rarpath)\av.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\av.cpp
+|
+
+$(objpath)\archive.obj : $(rarpath)\archive.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\archive.cpp
+|
+
+$(objpath)\arcread.obj : $(rarpath)\arcread.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\arcread.cpp
+|
+
+$(objpath)\unicode.obj : $(rarpath)\unicode.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\unicode.cpp
+|
+
+$(objpath)\system.obj : $(rarpath)\system.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\system.cpp
+|
+
+$(objpath)\isnt.obj : $(rarpath)\isnt.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\isnt.cpp
+|
+
+$(objpath)\crc.obj : $(rarpath)\crc.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\crc.cpp
+|
+
+$(objpath)\crypt.obj : $(rarpath)\crypt.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\crypt.cpp
+|
+
+$(objpath)\rijndael.obj : $(rarpath)\rijndael.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rijndael.cpp
+|
+
+$(objpath)\rawread.obj : $(rarpath)\rawread.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rawread.cpp
+|
+
+$(objpath)\rawwrite.obj : $(rarpath)\rawwrite.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rawwrite.cpp
+|
+
+$(objpath)\encname.obj : $(rarpath)\encname.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\encname.cpp
+|
+
+$(objpath)\resource.obj : $(rarpath)\resource.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\resource.cpp
+|
+
+$(objpath)\match.obj : $(rarpath)\match.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\match.cpp
+|
+
+$(objpath)\find.obj : $(rarpath)\find.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\find.cpp
+|
+
+$(objpath)\scantree.obj : $(rarpath)\scantree.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\scantree.cpp
+|
+
+$(objpath)\timefn.obj : $(rarpath)\timefn.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\timefn.cpp
+|
+
+$(objpath)\getbits.obj : $(rarpath)\getbits.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\getbits.cpp
+|
+
+$(objpath)\rarvm.obj : $(rarpath)\rarvm.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rarvm.cpp
+|
+
+$(objpath)\putbits.obj : $(rarpath)\putbits.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\putbits.cpp
+|
+
+$(objpath)\pack.obj : $(rarpath)\pack.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\pack.cpp
+|
+
+$(objpath)\packbord.obj : $(rarpath)\packbord.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\packbord.cpp
+|
+
+$(objpath)\packanlz.obj : $(rarpath)\packanlz.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\packanlz.cpp
+|
+
+$(objpath)\cblock.obj : $(rarpath)\cblock.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\cblock.cpp
+|
+
+$(objpath)\add.obj : $(rarpath)\add.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\add.cpp
+|
+
+$(objpath)\addlist.obj : $(rarpath)\addlist.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\addlist.cpp
+|
+
+$(objpath)\procarc.obj : $(rarpath)\procarc.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\procarc.cpp
+|
+
+$(objpath)\sfx.obj : $(rarpath)\sfx.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\sfx.cpp
+|
+
+$(objpath)\comment.obj : $(rarpath)\comment.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\comment.cpp
+|
+
+$(objpath)\rs.obj : $(rarpath)\rs.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rs.cpp
+|
+
+$(objpath)\recvol.obj : $(rarpath)\recvol.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\recvol.cpp
+|
+
+$(objpath)\repair.obj : $(rarpath)\repair.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\repair.cpp
+|
+
+$(objpath)\rdwrfn.obj : $(rarpath)\rdwrfn.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rdwrfn.cpp
+|
+
+$(objpath)\consio.obj : $(rarpath)\consio.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\consio.cpp
+|
+
+$(objpath)\cmddata.obj : $(rarpath)\cmddata.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\cmddata.cpp
+|
+
+$(objpath)\options.obj : $(rarpath)\options.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\options.cpp
+|
+
+$(objpath)\ulinks.obj : $(rarpath)\ulinks.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\ulinks.cpp
+|
+
+$(objpath)\errhnd.obj : $(rarpath)\errhnd.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\errhnd.cpp
+|
+
+$(objpath)\volume.obj : $(rarpath)\volume.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\volume.cpp
+|
+
+$(objpath)\extinfo.obj : $(rarpath)\extinfo.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\extinfo.cpp
+|
+
+
+$(objpath)\extract.obj : $(rarpath)\extract.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\extract.cpp
+|
+
+$(objpath)\list.obj : $(rarpath)\list.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\list.cpp
+|
+
+$(objpath)\rtl.obj : $(rarpath)\rtl.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\rtl.cpp
+|
+
+$(objpath)\unpack.obj : $(rarpath)\unpack.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\unpack.cpp
+|
+
+$(objpath)\dll.obj : $(rarpath)\dll.cpp
+ $(cc) -q @&&|
+ $(compopt) -o$@ $(rarpath)\dll.cpp
+| \ No newline at end of file
diff --git a/unrar/unrar/makefile.cygmin b/unrar/unrar/makefile.cygmin
new file mode 100644
index 0000000..9e0cfa8
--- /dev/null
+++ b/unrar/unrar/makefile.cygmin
@@ -0,0 +1,54 @@
+#
+# Makefile for cygmin/mingw - unrar
+#
+# Note: you have to 'make clean' before you can build
+# the sfx module
+#
+
+# POSIX using Cygmin GCC 3.3.1
+#CXX = g++
+#CXXFLAGS = -O2 -Wno-deprecated
+#DEFINES = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DLITTLE_ENDIAN
+
+# Win32 using Cygmin GCC 3.3.1
+CXX = g++ -mno-cygwin
+CXXFLAGS = -O2 -Wno-deprecated
+DEFINES = -D_MSC_VER -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+
+# Win32 using Mingw32 GCC 3.3.2
+#CXX = g++
+#CXXFLAGS = -O2 -Wno-deprecated
+#DEFINES = -D_MSC_VER -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+
+##########################
+
+COMPILE=$(CXX) $(CXXFLAGS) $(DEFINES)
+LINK=$(CXX)
+
+UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o
+
+OBJECTS=rar.o strlist.o strfn.o pathfn.o int64.o savepos.o global.o \
+ file.o filefn.o filcreat.o archive.o arcread.o unicode.o \
+ system.o isnt.o crypt.o crc.o rawread.o encname.o \
+ resource.o match.o timefn.o rdwrfn.o consio.o options.o \
+ ulinks.o errhnd.o rarvm.o rijndael.o getbits.o sha1.o \
+ extinfo.o extract.o volume.o list.o find.o unpack.o cmddata.o
+
+.cpp.o:
+ $(COMPILE) -D$(WHAT) -c $<
+
+all: unrar
+
+clean:
+ @rm -f *.o *.bak *~
+
+unrar: WHAT=UNRAR
+unrar: $(OBJECTS) $(UNRAR_OBJ)
+ @rm -f makeunrar
+ $(LINK) -Wl,-s -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
+
+sfx: WHAT=SFX_MODULE
+sfx: $(OBJECTS)
+ @rm -f default.sfx
+ $(LINK) -Wl,-s -o default.sfx $(LDFLAGS) $(OBJECTS) -DSFX_MODULE
+
diff --git a/unrar/unrar/makefile.dj b/unrar/unrar/makefile.dj
new file mode 100644
index 0000000..4d9dae5
--- /dev/null
+++ b/unrar/unrar/makefile.dj
@@ -0,0 +1,50 @@
+#
+# Makefile for DJGPP - unrar
+#
+# Note: you have to 'make clean' before you can build
+# the sfx module
+#
+
+# DOS32 using DJGPP 2.03 Patchlevel 2 and GCC 2.95.3
+CXX = gpp
+CXXFLAGS = -O2 -Wno-deprecated
+#DEFINES = -D_MSC_VER -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+
+##########################
+
+.PHONY: all clean veryclean
+
+COMPILE=$(CXX) $(CXXFLAGS) $(DEFINES)
+LINK=$(CXX)
+
+UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o
+
+OBJECTS=rar.o strlist.o strfn.o pathfn.o int64.o savepos.o global.o \
+ file.o filefn.o filcreat.o archive.o arcread.o unicode.o \
+ system.o isnt.o crypt.o crc.o rawread.o encname.o \
+ resource.o match.o timefn.o rdwrfn.o consio.o options.o \
+ ulinks.o errhnd.o rarvm.o rijndael.o getbits.o sha1.o \
+ extinfo.o extract.o volume.o list.o find.o unpack.o cmddata.o
+
+.cpp.o:
+ $(COMPILE) -D$(WHAT) -c $<
+
+all: unrar
+
+unrar: WHAT=UNRAR
+unrar: $(OBJECTS) $(UNRAR_OBJ)
+ $(LINK) -Wl,-s -o unrar.exe $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
+ exe2coff unrar.exe
+ cp -u $(DJDIR)/bin/cwsdstub.exe .
+ copy /b cwsdstub.exe+unrar unrar.exe
+ -upx --ultra-brute unrar.exe
+
+sfx: WHAT=SFX_MODULE
+sfx: $(OBJECTS)
+ $(LINK) -Wl,-s -o default.sfx $(LDFLAGS) $(OBJECTS) -DSFX_MODULE
+
+clean:
+ $(RM) $(OBJECTS) $(UNRAR_OBJ)
+
+veryclean: clean
+ $(RM) unrar.exe default.sfx cwsdstub.exe unrar
diff --git a/unrar/unrar/makefile.dmc b/unrar/unrar/makefile.dmc
new file mode 100644
index 0000000..f0e1198
--- /dev/null
+++ b/unrar/unrar/makefile.dmc
@@ -0,0 +1,54 @@
+# Makefile for Digital Mars C++ Compiler
+# http://www.rarlab.com
+# http://www.digitalmars.com
+#
+# DEFINES: UNRAR RARDLL GUI SFX_MODULE SILENT
+
+NAME = unrar
+EXT = exe
+
+CPP = dmc
+
+LINK = link
+
+# --------------
+# Release Build
+# --------------
+DEFINES = -DNDEBUG -D_MSC_VER -DUNRAR
+CPPFLAGS = -o+all -ff -Nc -g- -Ae
+LNKFLAGS = /EXETYPE:NT /MACHINE:i386 /SUBSYSTEM:CONSOLE /NOLOGO /NODEBUG /NOCODEVIEW /PACKFUNCTIONS
+
+# --------------
+# Debug Build
+# --------------
+#DEFINES = -D_DEBUG -D_MSC_VER -DUNRAR
+#CPPFLAGS = -o+none -Nc -S -gf -Ae
+#LNKFLAGS = /EXETYPE:NT /MACHINE:i386 /SUBSYSTEM:CONSOLE /NOLOGO /DEBUG
+
+OBJ = rar.obj strlist.obj strfn.obj pathfn.obj int64.obj savepos.obj global.obj \
+ file.obj filefn.obj filcreat.obj archive.obj arcread.obj unicode.obj \
+ system.obj isnt.obj crypt.obj crc.obj rawread.obj encname.obj \
+ resource.obj match.obj timefn.obj rdwrfn.obj consio.obj options.obj \
+ ulinks.obj errhnd.obj rarvm.obj rijndael.obj getbits.obj sha1.obj \
+ extinfo.obj extract.obj volume.obj find.obj unpack.obj cmddata.obj \
+ filestr.obj recvol.obj rs.obj scantree.obj \
+ list.obj \
+# dll.obj \
+
+LIB = kernel32.lib+user32.lib+advapi32.lib
+
+#DEF = dll.def
+
+link: $(OBJ)
+ $(LINK) $(LNKFLAGS) $(OBJ), $(NAME).$(EXT), $(NAME).map, $(LIB), $(DEF)
+
+.c.obj:
+ $(CPP) $(CPPFLAGS) $(DEFINES) -c $< -o $@
+
+.cpp.obj:
+ $(CPP) $(CPPFLAGS) $(DEFINES) -c $< -o $@
+
+clean:
+ del $(OBJ)
+ del $(NAME).$(EXT)
+ del $(NAME).map
diff --git a/unrar/unrar/makefile.msc b/unrar/unrar/makefile.msc
new file mode 100644
index 0000000..77d82ef
--- /dev/null
+++ b/unrar/unrar/makefile.msc
@@ -0,0 +1,564 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on unrar.dsp
+!IF "$(CFG)" == ""
+CFG=unrar - Win32 Release
+!MESSAGE No configuration specified. Defaulting to unrar - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "unrar - Win32 Release" && "$(CFG)" != "unrar - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "unrar.mak" CFG="unrar - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "unrar - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "unrar - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "unrar - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\unrar.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\archive.obj"
+ -@erase "$(INTDIR)\arcread.obj"
+ -@erase "$(INTDIR)\cmddata.obj"
+ -@erase "$(INTDIR)\consio.obj"
+ -@erase "$(INTDIR)\crc.obj"
+ -@erase "$(INTDIR)\crypt.obj"
+ -@erase "$(INTDIR)\encname.obj"
+ -@erase "$(INTDIR)\errhnd.obj"
+ -@erase "$(INTDIR)\extinfo.obj"
+ -@erase "$(INTDIR)\extract.obj"
+ -@erase "$(INTDIR)\filcreat.obj"
+ -@erase "$(INTDIR)\file.obj"
+ -@erase "$(INTDIR)\filefn.obj"
+ -@erase "$(INTDIR)\filestr.obj"
+ -@erase "$(INTDIR)\find.obj"
+ -@erase "$(INTDIR)\getbits.obj"
+ -@erase "$(INTDIR)\global.obj"
+ -@erase "$(INTDIR)\int64.obj"
+ -@erase "$(INTDIR)\isnt.obj"
+ -@erase "$(INTDIR)\list.obj"
+ -@erase "$(INTDIR)\match.obj"
+ -@erase "$(INTDIR)\options.obj"
+ -@erase "$(INTDIR)\pathfn.obj"
+ -@erase "$(INTDIR)\rar.obj"
+ -@erase "$(INTDIR)\rarvm.obj"
+ -@erase "$(INTDIR)\rawread.obj"
+ -@erase "$(INTDIR)\rdwrfn.obj"
+ -@erase "$(INTDIR)\recvol.obj"
+ -@erase "$(INTDIR)\resource.obj"
+ -@erase "$(INTDIR)\rijndael.obj"
+ -@erase "$(INTDIR)\rs.obj"
+ -@erase "$(INTDIR)\savepos.obj"
+ -@erase "$(INTDIR)\scantree.obj"
+ -@erase "$(INTDIR)\sha1.obj"
+ -@erase "$(INTDIR)\strfn.obj"
+ -@erase "$(INTDIR)\strlist.obj"
+ -@erase "$(INTDIR)\system.obj"
+ -@erase "$(INTDIR)\timefn.obj"
+ -@erase "$(INTDIR)\ulinks.obj"
+ -@erase "$(INTDIR)\unicode.obj"
+ -@erase "$(INTDIR)\unpack.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\volume.obj"
+ -@erase "$(OUTDIR)\unrar.exe"
+ -@erase "$(OUTDIR)\unrar.map"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "UNRAR" /Fp"$(INTDIR)\unrar.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\unrar.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\unrar.pdb" /map:"$(INTDIR)\unrar.map" /machine:I386 /out:"$(OUTDIR)\unrar.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\rar.obj" \
+ "$(INTDIR)\strlist.obj" \
+ "$(INTDIR)\strfn.obj" \
+ "$(INTDIR)\pathfn.obj" \
+ "$(INTDIR)\int64.obj" \
+ "$(INTDIR)\savepos.obj" \
+ "$(INTDIR)\global.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\filefn.obj" \
+ "$(INTDIR)\filcreat.obj" \
+ "$(INTDIR)\archive.obj" \
+ "$(INTDIR)\arcread.obj" \
+ "$(INTDIR)\unicode.obj" \
+ "$(INTDIR)\system.obj" \
+ "$(INTDIR)\isnt.obj" \
+ "$(INTDIR)\crypt.obj" \
+ "$(INTDIR)\crc.obj" \
+ "$(INTDIR)\rawread.obj" \
+ "$(INTDIR)\encname.obj" \
+ "$(INTDIR)\resource.obj" \
+ "$(INTDIR)\match.obj" \
+ "$(INTDIR)\timefn.obj" \
+ "$(INTDIR)\rdwrfn.obj" \
+ "$(INTDIR)\consio.obj" \
+ "$(INTDIR)\options.obj" \
+ "$(INTDIR)\ulinks.obj" \
+ "$(INTDIR)\errhnd.obj" \
+ "$(INTDIR)\rarvm.obj" \
+ "$(INTDIR)\rijndael.obj" \
+ "$(INTDIR)\getbits.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\extinfo.obj" \
+ "$(INTDIR)\extract.obj" \
+ "$(INTDIR)\volume.obj" \
+ "$(INTDIR)\list.obj" \
+ "$(INTDIR)\find.obj" \
+ "$(INTDIR)\unpack.obj" \
+ "$(INTDIR)\cmddata.obj" \
+ "$(INTDIR)\filestr.obj" \
+ "$(INTDIR)\recvol.obj" \
+ "$(INTDIR)\rs.obj" \
+ "$(INTDIR)\scantree.obj"
+
+"$(OUTDIR)\unrar.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "unrar - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\unrar.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\archive.obj"
+ -@erase "$(INTDIR)\arcread.obj"
+ -@erase "$(INTDIR)\cmddata.obj"
+ -@erase "$(INTDIR)\consio.obj"
+ -@erase "$(INTDIR)\crc.obj"
+ -@erase "$(INTDIR)\crypt.obj"
+ -@erase "$(INTDIR)\encname.obj"
+ -@erase "$(INTDIR)\errhnd.obj"
+ -@erase "$(INTDIR)\extinfo.obj"
+ -@erase "$(INTDIR)\extract.obj"
+ -@erase "$(INTDIR)\filcreat.obj"
+ -@erase "$(INTDIR)\file.obj"
+ -@erase "$(INTDIR)\filefn.obj"
+ -@erase "$(INTDIR)\filestr.obj"
+ -@erase "$(INTDIR)\find.obj"
+ -@erase "$(INTDIR)\getbits.obj"
+ -@erase "$(INTDIR)\global.obj"
+ -@erase "$(INTDIR)\int64.obj"
+ -@erase "$(INTDIR)\isnt.obj"
+ -@erase "$(INTDIR)\list.obj"
+ -@erase "$(INTDIR)\match.obj"
+ -@erase "$(INTDIR)\options.obj"
+ -@erase "$(INTDIR)\pathfn.obj"
+ -@erase "$(INTDIR)\rar.obj"
+ -@erase "$(INTDIR)\rarvm.obj"
+ -@erase "$(INTDIR)\rawread.obj"
+ -@erase "$(INTDIR)\rdwrfn.obj"
+ -@erase "$(INTDIR)\recvol.obj"
+ -@erase "$(INTDIR)\resource.obj"
+ -@erase "$(INTDIR)\rijndael.obj"
+ -@erase "$(INTDIR)\rs.obj"
+ -@erase "$(INTDIR)\savepos.obj"
+ -@erase "$(INTDIR)\scantree.obj"
+ -@erase "$(INTDIR)\sha1.obj"
+ -@erase "$(INTDIR)\strfn.obj"
+ -@erase "$(INTDIR)\strlist.obj"
+ -@erase "$(INTDIR)\system.obj"
+ -@erase "$(INTDIR)\timefn.obj"
+ -@erase "$(INTDIR)\ulinks.obj"
+ -@erase "$(INTDIR)\unicode.obj"
+ -@erase "$(INTDIR)\unpack.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\volume.obj"
+ -@erase "$(OUTDIR)\unrar.exe"
+ -@erase "$(OUTDIR)\unrar.ilk"
+ -@erase "$(OUTDIR)\unrar.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "UNRAR" /Fp"$(INTDIR)\unrar.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\unrar.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\unrar.pdb" /debug /machine:I386 /out:"$(OUTDIR)\unrar.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\rar.obj" \
+ "$(INTDIR)\strlist.obj" \
+ "$(INTDIR)\strfn.obj" \
+ "$(INTDIR)\pathfn.obj" \
+ "$(INTDIR)\int64.obj" \
+ "$(INTDIR)\savepos.obj" \
+ "$(INTDIR)\global.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\filefn.obj" \
+ "$(INTDIR)\filcreat.obj" \
+ "$(INTDIR)\archive.obj" \
+ "$(INTDIR)\arcread.obj" \
+ "$(INTDIR)\unicode.obj" \
+ "$(INTDIR)\system.obj" \
+ "$(INTDIR)\isnt.obj" \
+ "$(INTDIR)\crypt.obj" \
+ "$(INTDIR)\crc.obj" \
+ "$(INTDIR)\rawread.obj" \
+ "$(INTDIR)\encname.obj" \
+ "$(INTDIR)\resource.obj" \
+ "$(INTDIR)\match.obj" \
+ "$(INTDIR)\timefn.obj" \
+ "$(INTDIR)\rdwrfn.obj" \
+ "$(INTDIR)\consio.obj" \
+ "$(INTDIR)\options.obj" \
+ "$(INTDIR)\ulinks.obj" \
+ "$(INTDIR)\errhnd.obj" \
+ "$(INTDIR)\rarvm.obj" \
+ "$(INTDIR)\rijndael.obj" \
+ "$(INTDIR)\getbits.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\extinfo.obj" \
+ "$(INTDIR)\extract.obj" \
+ "$(INTDIR)\volume.obj" \
+ "$(INTDIR)\list.obj" \
+ "$(INTDIR)\find.obj" \
+ "$(INTDIR)\unpack.obj" \
+ "$(INTDIR)\cmddata.obj" \
+ "$(INTDIR)\filestr.obj" \
+ "$(INTDIR)\recvol.obj" \
+ "$(INTDIR)\rs.obj" \
+ "$(INTDIR)\scantree.obj"
+
+"$(OUTDIR)\unrar.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("msc.dep")
+!INCLUDE "msc.dep"
+!ELSE
+!MESSAGE Warning: cannot find "msc.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "unrar - Win32 Release" || "$(CFG)" == "unrar - Win32 Debug"
+SOURCE=.\archive.cpp
+
+"$(INTDIR)\archive.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\arcread.cpp
+
+"$(INTDIR)\arcread.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\cmddata.cpp
+
+"$(INTDIR)\cmddata.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\consio.cpp
+
+"$(INTDIR)\consio.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\crc.cpp
+
+"$(INTDIR)\crc.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\crypt.cpp
+
+"$(INTDIR)\crypt.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\encname.cpp
+
+"$(INTDIR)\encname.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\errhnd.cpp
+
+"$(INTDIR)\errhnd.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\extinfo.cpp
+
+"$(INTDIR)\extinfo.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\extract.cpp
+
+"$(INTDIR)\extract.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\filcreat.cpp
+
+"$(INTDIR)\filcreat.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\file.cpp
+
+"$(INTDIR)\file.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\filefn.cpp
+
+"$(INTDIR)\filefn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\filestr.cpp
+
+"$(INTDIR)\filestr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\find.cpp
+
+"$(INTDIR)\find.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\getbits.cpp
+
+"$(INTDIR)\getbits.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\global.cpp
+
+"$(INTDIR)\global.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\int64.cpp
+
+"$(INTDIR)\int64.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\isnt.cpp
+
+"$(INTDIR)\isnt.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\list.cpp
+
+"$(INTDIR)\list.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\match.cpp
+
+"$(INTDIR)\match.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\options.cpp
+
+"$(INTDIR)\options.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\pathfn.cpp
+
+"$(INTDIR)\pathfn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\rar.cpp
+
+"$(INTDIR)\rar.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\rarvm.cpp
+
+"$(INTDIR)\rarvm.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\rawread.cpp
+
+"$(INTDIR)\rawread.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\rdwrfn.cpp
+
+"$(INTDIR)\rdwrfn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\recvol.cpp
+
+"$(INTDIR)\recvol.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\resource.cpp
+
+"$(INTDIR)\resource.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\rijndael.cpp
+
+"$(INTDIR)\rijndael.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\rs.cpp
+
+"$(INTDIR)\rs.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\savepos.cpp
+
+"$(INTDIR)\savepos.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\scantree.cpp
+
+"$(INTDIR)\scantree.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\sha1.cpp
+
+"$(INTDIR)\sha1.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\strfn.cpp
+
+"$(INTDIR)\strfn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\strlist.cpp
+
+"$(INTDIR)\strlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\system.cpp
+
+"$(INTDIR)\system.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\timefn.cpp
+
+"$(INTDIR)\timefn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\ulinks.cpp
+
+"$(INTDIR)\ulinks.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\unicode.cpp
+
+"$(INTDIR)\unicode.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\unpack.cpp
+
+"$(INTDIR)\unpack.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=.\volume.cpp
+
+"$(INTDIR)\volume.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/unrar/unrar/makefile.unix b/unrar/unrar/makefile.unix
new file mode 100644
index 0000000..f2a7dcf
--- /dev/null
+++ b/unrar/unrar/makefile.unix
@@ -0,0 +1,119 @@
+#
+# Makefile for UNIX - unrar
+#
+# Note: you have to 'make clean' before you can build
+# the sfx module
+#
+
+# Linux using GCC
+CXX=g++
+CXXFLAGS=-O2
+DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+STRIP=strip
+
+# Linux using LCC
+#CXX=lcc
+#CXXFLAGS=-O2
+#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+#STRIP=strip
+
+# HP UX using aCC
+#CXX=aCC
+#CXXFLAGS=-AA +O2 +Onolimit
+#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+#STRIP=strip
+
+# IRIX using GCC
+#CXX=g++
+#CXXFLAGS=-O2
+#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1
+#STRIP=strip
+
+# IRIX using MIPSPro (experimental)
+#CXX=CC
+#CXXFLAGS=-O2 -mips3 -woff 1234,1156,3284 -LANG:std
+#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -DNATIVE_INT64 -DInt64=int64_t
+#STRIP=strip
+
+# AIX using xlC (IBM VisualAge C++ 5.0)
+#CXX=xlC
+#CXXFLAGS=-O -qinline -qro -qroconst -qmaxmem=16384 -qcpluscmt
+#DEFINES=-D_LARGE_FILES -D_LARGE_FILE_API
+#LIBS=-lbsd
+#STRIP=strip
+
+# Solaris using CC (SUN Forte Developer 7 C++)
+#CXX=CC
+#CXXFLAGS=-xO2 -xbuiltin=%all -xinline=%auto
+#DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+#STRIP=strip
+
+# Solaris using GCC (optimized for UltraSPARC 1 CPU)
+#CXX=g++
+#CXXFLAGS=-O3 -mcpu=v9 -mtune=ultrasparc -m32
+#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+#STRIP=/usr/ccs/bin/strip
+
+# Tru64 5.1B using GCC3
+#CXX=g++
+#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_XOPEN_SOURCE=500
+#STRIP=strip
+#LDFLAGS=-rpath /usr/local/gcc/lib
+
+# Tru64 5.1B using DEC C++
+#CXX=cxx
+#CXXFLAGS=-O4 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DNATIVE_INT64 -DInt64=long
+#STRIP=strip
+#LDFLAGS=
+
+# QNX 6.x using GCC
+#CXX=g++
+#CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fexceptions
+#STRIP=strip
+#LDFLAGS=-fexceptions
+
+# Cross-compile
+# Linux using arm-linux-g++
+#CXX=arm-linux-g++
+#CXXFLAGS=-O2
+#DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+#STRIP=arm-linux-strip
+#LDFLAGS=-static
+
+##########################
+
+COMPILE=$(CXX) $(CXXFLAGS) $(DEFINES)
+LINK=$(CXX)
+
+UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o
+LIB_OBJ=filestr.o scantree.o dll.o
+
+OBJECTS=rar.o strlist.o strfn.o pathfn.o int64.o savepos.o global.o file.o filefn.o filcreat.o \
+ archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
+ resource.o match.o timefn.o rdwrfn.o consio.o options.o ulinks.o errhnd.o rarvm.o \
+ rijndael.o getbits.o sha1.o extinfo.o extract.o volume.o list.o find.o unpack.o cmddata.o
+
+.cpp.o:
+ $(COMPILE) -D$(WHAT) -c $<
+
+all: unrar
+
+clean:
+ @rm -f *.o *.bak *~
+
+unrar: WHAT=UNRAR
+unrar: $(OBJECTS) $(UNRAR_OBJ)
+ @rm -f unrar
+ $(LINK) -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
+ $(STRIP) unrar
+
+sfx: WHAT=SFX_MODULE
+sfx: $(OBJECTS)
+ @rm -f default.sfx
+ $(LINK) -o default.sfx $(LDFLAGS) $(OBJECTS)
+ $(STRIP) default.sfx
+
+lib: WHAT=RARDLL
+lib: $(OBJECTS) $(LIB_OBJ)
+ @rm -f libunrar.so
+ $(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
diff --git a/unrar/unrar/match.cpp b/unrar/unrar/match.cpp
new file mode 100644
index 0000000..de03fb4
--- /dev/null
+++ b/unrar/unrar/match.cpp
@@ -0,0 +1,262 @@
+#include "rar.hpp"
+
+static bool match(char *pattern,char *string,bool ForceCase);
+static bool match(wchar *pattern,wchar *string,bool ForceCase);
+
+static int mstricompc(const char *Str1,const char *Str2,bool ForceCase);
+static int mstricompcw(const wchar *Str1,const wchar *Str2,bool ForceCase);
+static int mstrnicompc(const char *Str1,const char *Str2,int N,bool ForceCase);
+static int mstrnicompcw(const wchar *Str1,const wchar *Str2,int N,bool ForceCase);
+
+inline uint toupperc(byte ch,bool ForceCase)
+{
+ if (ForceCase)
+ return(ch);
+#ifdef _WIN_32
+ return((uint)CharUpper((LPTSTR)(ch)));
+#elif defined(_UNIX)
+ return(ch);
+#else
+ return(toupper(ch));
+#endif
+}
+
+
+inline uint touppercw(uint ch,bool ForceCase)
+{
+ if (ForceCase)
+ return(ch);
+#if defined(_UNIX)
+ return(ch);
+#else
+ return(toupperw(ch));
+#endif
+}
+
+
+bool CmpName(char *Wildcard,char *Name,int CmpPath)
+{
+ bool ForceCase=(CmpPath&MATCH_FORCECASESENSITIVE)!=0;
+
+ CmpPath&=MATCH_MODEMASK;
+
+ if (CmpPath!=MATCH_NAMES)
+ {
+ int WildLength=strlen(Wildcard);
+ if (CmpPath!=MATCH_EXACTPATH && mstrnicompc(Wildcard,Name,WildLength,ForceCase)==0)
+ {
+ char NextCh=Name[WildLength];
+ if (NextCh=='\\' || NextCh=='/' || NextCh==0)
+ return(true);
+ }
+ char Path1[NM],Path2[NM];
+ GetFilePath(Wildcard,Path1,ASIZE(Path1));
+ GetFilePath(Name,Path2,ASIZE(Path1));
+ if (mstricompc(Wildcard,Path2,ForceCase)==0)
+ return(true);
+ if ((CmpPath==MATCH_PATH || CmpPath==MATCH_EXACTPATH) && mstricompc(Path1,Path2,ForceCase)!=0)
+ return(false);
+ if (CmpPath==MATCH_SUBPATH || CmpPath==MATCH_WILDSUBPATH)
+ if (IsWildcard(Path1))
+ return(match(Wildcard,Name,ForceCase));
+ else
+ if (CmpPath==MATCH_SUBPATH || IsWildcard(Wildcard))
+ {
+ if (*Path1 && mstrnicompc(Path1,Path2,strlen(Path1),ForceCase)!=0)
+ return(false);
+ }
+ else
+ if (mstricompc(Path1,Path2,ForceCase)!=0)
+ return(false);
+ }
+ char *Name1=PointToName(Wildcard);
+ char *Name2=PointToName(Name);
+ if (mstrnicompc("__rar_",Name2,6,false)==0)
+ return(false);
+ return(match(Name1,Name2,ForceCase));
+}
+
+
+#ifndef SFX_MODULE
+bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath)
+{
+ bool ForceCase=(CmpPath&MATCH_FORCECASESENSITIVE)!=0;
+
+ CmpPath&=MATCH_MODEMASK;
+
+ if (CmpPath!=MATCH_NAMES)
+ {
+ int WildLength=strlenw(Wildcard);
+ if (CmpPath!=MATCH_EXACTPATH && mstrnicompcw(Wildcard,Name,WildLength,ForceCase)==0)
+ {
+ wchar NextCh=Name[WildLength];
+ if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
+ return(true);
+ }
+ wchar Path1[NM],Path2[NM];
+ GetFilePath(Wildcard,Path1,ASIZE(Path1));
+ GetFilePath(Name,Path2,ASIZE(Path2));
+ if ((CmpPath==MATCH_PATH || CmpPath==MATCH_EXACTPATH) && mstricompcw(Path1,Path2,ForceCase)!=0)
+ return(false);
+ if (CmpPath==MATCH_SUBPATH || CmpPath==MATCH_WILDSUBPATH)
+ if (IsWildcard(NULL,Path1))
+ return(match(Wildcard,Name,ForceCase));
+ else
+ if (CmpPath==MATCH_SUBPATH || IsWildcard(NULL,Wildcard))
+ {
+ if (*Path1 && mstrnicompcw(Path1,Path2,strlenw(Path1),ForceCase)!=0)
+ return(false);
+ }
+ else
+ if (mstricompcw(Path1,Path2,ForceCase)!=0)
+ return(false);
+ }
+ wchar *Name1=PointToName(Wildcard);
+ wchar *Name2=PointToName(Name);
+ if (mstrnicompcw(L"__rar_",Name2,6,false)==0)
+ return(false);
+ return(match(Name1,Name2,ForceCase));
+}
+#endif
+
+
+bool match(char *pattern,char *string,bool ForceCase)
+{
+ for (;; ++string)
+ {
+ char stringc=toupperc(*string,ForceCase);
+ char patternc=toupperc(*pattern++,ForceCase);
+ switch (patternc)
+ {
+ case 0:
+ return(stringc==0);
+ case '?':
+ if (stringc == 0)
+ return(false);
+ break;
+ case '*':
+ if (*pattern==0)
+ return(true);
+ if (*pattern=='.')
+ {
+ if (pattern[1]=='*' && pattern[2]==0)
+ return(true);
+ char *dot=strchr(string,'.');
+ if (pattern[1]==0)
+ return (dot==NULL || dot[1]==0);
+ if (dot!=NULL)
+ {
+ string=dot;
+ if (strpbrk(pattern,"*?")==NULL && strchr(string+1,'.')==NULL)
+ return(mstricompc(pattern+1,string+1,ForceCase)==0);
+ }
+ }
+
+ while (*string)
+ if (match(pattern,string++,ForceCase))
+ return(true);
+ return(false);
+ default:
+ if (patternc != stringc)
+ if (patternc=='.' && stringc==0)
+ return(match(pattern,string,ForceCase));
+ else
+ return(false);
+ break;
+ }
+ }
+}
+
+
+#ifndef SFX_MODULE
+bool match(wchar *pattern,wchar *string,bool ForceCase)
+{
+ for (;; ++string)
+ {
+ wchar stringc=touppercw(*string,ForceCase);
+ wchar patternc=touppercw(*pattern++,ForceCase);
+ switch (patternc)
+ {
+ case 0:
+ return(stringc==0);
+ case '?':
+ if (stringc == 0)
+ return(false);
+ break;
+ case '*':
+ if (*pattern==0)
+ return(true);
+ if (*pattern=='.')
+ {
+ if (pattern[1]=='*' && pattern[2]==0)
+ return(true);
+ wchar *dot=strchrw(string,'.');
+ if (pattern[1]==0)
+ return (dot==NULL || dot[1]==0);
+ if (dot!=NULL)
+ {
+ string=dot;
+ if (strpbrkw(pattern,L"*?")==NULL && strchrw(string+1,'.')==NULL)
+ return(mstricompcw(pattern+1,string+1,ForceCase)==0);
+ }
+ }
+
+ while (*string)
+ if (match(pattern,string++,ForceCase))
+ return(true);
+ return(false);
+ default:
+ if (patternc != stringc)
+ if (patternc=='.' && stringc==0)
+ return(match(pattern,string,ForceCase));
+ else
+ return(false);
+ break;
+ }
+ }
+}
+#endif
+
+
+int mstricompc(const char *Str1,const char *Str2,bool ForceCase)
+{
+ if (ForceCase)
+ return(strcmp(Str1,Str2));
+ return(stricompc(Str1,Str2));
+}
+
+
+#ifndef SFX_MODULE
+int mstricompcw(const wchar *Str1,const wchar *Str2,bool ForceCase)
+{
+ if (ForceCase)
+ return(strcmpw(Str1,Str2));
+ return(stricompcw(Str1,Str2));
+}
+#endif
+
+
+int mstrnicompc(const char *Str1,const char *Str2,int N,bool ForceCase)
+{
+ if (ForceCase)
+ return(strncmp(Str1,Str2,N));
+#if defined(_UNIX)
+ return(strncmp(Str1,Str2,N));
+#else
+ return(strnicomp(Str1,Str2,N));
+#endif
+}
+
+
+#ifndef SFX_MODULE
+int mstrnicompcw(const wchar *Str1,const wchar *Str2,int N,bool ForceCase)
+{
+ if (ForceCase)
+ return(strncmpw(Str1,Str2,N));
+#if defined(_UNIX)
+ return(strncmpw(Str1,Str2,N));
+#else
+ return(strnicmpw(Str1,Str2,N));
+#endif
+}
+#endif
diff --git a/unrar/unrar/match.hpp b/unrar/unrar/match.hpp
new file mode 100644
index 0000000..5ea6115
--- /dev/null
+++ b/unrar/unrar/match.hpp
@@ -0,0 +1,12 @@
+#ifndef _RAR_MATCH_
+#define _RAR_MATCH_
+
+enum {MATCH_NAMES,MATCH_PATH,MATCH_EXACTPATH,MATCH_SUBPATH,MATCH_WILDSUBPATH};
+
+#define MATCH_MODEMASK 0x0000ffff
+#define MATCH_FORCECASESENSITIVE 0x80000000
+
+bool CmpName(char *Wildcard,char *Name,int CmpPath);
+bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath);
+
+#endif
diff --git a/unrar/unrar/model.cpp b/unrar/unrar/model.cpp
new file mode 100644
index 0000000..abc73d2
--- /dev/null
+++ b/unrar/unrar/model.cpp
@@ -0,0 +1,610 @@
+/****************************************************************************
+ * This file is part of PPMd project *
+ * Written and distributed to public domain by Dmitry Shkarin 1997, *
+ * 1999-2000 *
+ * Contents: model description and encoding/decoding routines *
+ ****************************************************************************/
+
+inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats,
+ STATE& FirstState)
+{
+ PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext();
+ if ( pc )
+ {
+ pc->NumStats=1;
+ pc->OneState=FirstState;
+ pc->Suffix=this;
+ pStats->Successor=pc;
+ }
+ return pc;
+}
+
+
+ModelPPM::ModelPPM()
+{
+ MinContext=NULL;
+ MaxContext=NULL;
+ MedContext=NULL;
+}
+
+
+void ModelPPM::RestartModelRare()
+{
+ int i, k, m;
+ memset(CharMask,0,sizeof(CharMask));
+ SubAlloc.InitSubAllocator();
+ InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
+ MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext();
+ MinContext->Suffix=NULL;
+ OrderFall=MaxOrder;
+ MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
+ FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2);
+ for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
+ {
+ MinContext->U.Stats[i].Symbol=i;
+ MinContext->U.Stats[i].Freq=1;
+ MinContext->U.Stats[i].Successor=NULL;
+ }
+
+ static const ushort InitBinEsc[]={
+ 0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051
+ };
+
+ for (i=0;i < 128;i++)
+ for (k=0;k < 8;k++)
+ for (m=0;m < 64;m += 8)
+ BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2);
+ for (i=0;i < 25;i++)
+ for (k=0;k < 16;k++)
+ SEE2Cont[i][k].init(5*i+10);
+}
+
+
+void ModelPPM::StartModelRare(int MaxOrder)
+{
+ int i, k, m ,Step;
+ EscCount=1;
+/*
+ if (MaxOrder < 2)
+ {
+ memset(CharMask,0,sizeof(CharMask));
+ OrderFall=ModelPPM::MaxOrder;
+ MinContext=MaxContext;
+ while (MinContext->Suffix != NULL)
+ {
+ MinContext=MinContext->Suffix;
+ OrderFall--;
+ }
+ FoundState=MinContext->U.Stats;
+ MinContext=MaxContext;
+ }
+ else
+*/
+ {
+ ModelPPM::MaxOrder=MaxOrder;
+ RestartModelRare();
+ NS2BSIndx[0]=2*0;
+ NS2BSIndx[1]=2*1;
+ memset(NS2BSIndx+2,2*2,9);
+ memset(NS2BSIndx+11,2*3,256-11);
+ for (i=0;i < 3;i++)
+ NS2Indx[i]=i;
+ for (m=i, k=Step=1;i < 256;i++)
+ {
+ NS2Indx[i]=m;
+ if ( !--k )
+ {
+ k = ++Step;
+ m++;
+ }
+ }
+ memset(HB2Flag,0,0x40);
+ memset(HB2Flag+0x40,0x08,0x100-0x40);
+ DummySEE2Cont.Shift=PERIOD_BITS;
+ }
+}
+
+
+void PPM_CONTEXT::rescale(ModelPPM *Model)
+{
+ int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
+ STATE* p1, * p;
+ for (p=Model->FoundState;p != U.Stats;p--)
+ _PPMD_SWAP(p[0],p[-1]);
+ U.Stats->Freq += 4;
+ U.SummFreq += 4;
+ EscFreq=U.SummFreq-p->Freq;
+ Adder=(Model->OrderFall != 0);
+ U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
+ do
+ {
+ EscFreq -= (++p)->Freq;
+ U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
+ if (p[0].Freq > p[-1].Freq)
+ {
+ STATE tmp=*(p1=p);
+ do
+ {
+ p1[0]=p1[-1];
+ } while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq);
+ *p1=tmp;
+ }
+ } while ( --i );
+ if (p->Freq == 0)
+ {
+ do
+ {
+ i++;
+ } while ((--p)->Freq == 0);
+ EscFreq += i;
+ if ((NumStats -= i) == 1)
+ {
+ STATE tmp=*U.Stats;
+ do
+ {
+ tmp.Freq-=(tmp.Freq >> 1);
+ EscFreq>>=1;
+ } while (EscFreq > 1);
+ Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1);
+ *(Model->FoundState=&OneState)=tmp; return;
+ }
+ }
+ U.SummFreq += (EscFreq -= (EscFreq >> 1));
+ int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
+ if (n0 != n1)
+ U.Stats = (STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
+ Model->FoundState=U.Stats;
+}
+
+
+inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1)
+{
+#ifdef __ICL
+ static
+#endif
+ STATE UpState;
+ PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
+ STATE * p, * ps[MAX_O], ** pps=ps;
+ if ( !Skip )
+ {
+ *pps++ = FoundState;
+ if ( !pc->Suffix )
+ goto NO_LOOP;
+ }
+ if ( p1 )
+ {
+ p=p1;
+ pc=pc->Suffix;
+ goto LOOP_ENTRY;
+ }
+ do
+ {
+ pc=pc->Suffix;
+ if (pc->NumStats != 1)
+ {
+ if ((p=pc->U.Stats)->Symbol != FoundState->Symbol)
+ do
+ {
+ p++;
+ } while (p->Symbol != FoundState->Symbol);
+ }
+ else
+ p=&(pc->OneState);
+LOOP_ENTRY:
+ if (p->Successor != UpBranch)
+ {
+ pc=p->Successor;
+ break;
+ }
+ *pps++ = p;
+ } while ( pc->Suffix );
+NO_LOOP:
+ if (pps == ps)
+ return pc;
+ UpState.Symbol=*(byte*) UpBranch;
+ UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
+ if (pc->NumStats != 1)
+ {
+ if ((byte*) pc <= SubAlloc.pText)
+ return(NULL);
+ if ((p=pc->U.Stats)->Symbol != UpState.Symbol)
+ do
+ {
+ p++;
+ } while (p->Symbol != UpState.Symbol);
+ uint cf=p->Freq-1;
+ uint s0=pc->U.SummFreq-pc->NumStats-cf;
+ UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
+ }
+ else
+ UpState.Freq=pc->OneState.Freq;
+ do
+ {
+ pc = pc->createChild(this,*--pps,UpState);
+ if ( !pc )
+ return NULL;
+ } while (pps != ps);
+ return pc;
+}
+
+
+inline void ModelPPM::UpdateModel()
+{
+ STATE fs = *FoundState, *p = NULL;
+ PPM_CONTEXT *pc, *Successor;
+ uint ns1, ns, cf, sf, s0;
+ if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
+ {
+ if (pc->NumStats != 1)
+ {
+ if ((p=pc->U.Stats)->Symbol != fs.Symbol)
+ {
+ do
+ {
+ p++;
+ } while (p->Symbol != fs.Symbol);
+ if (p[0].Freq >= p[-1].Freq)
+ {
+ _PPMD_SWAP(p[0],p[-1]);
+ p--;
+ }
+ }
+ if (p->Freq < MAX_FREQ-9)
+ {
+ p->Freq += 2;
+ pc->U.SummFreq += 2;
+ }
+ }
+ else
+ {
+ p=&(pc->OneState);
+ p->Freq += (p->Freq < 32);
+ }
+ }
+ if ( !OrderFall )
+ {
+ MinContext=MaxContext=FoundState->Successor=CreateSuccessors(TRUE,p);
+ if ( !MinContext )
+ goto RESTART_MODEL;
+ return;
+ }
+ *SubAlloc.pText++ = fs.Symbol;
+ Successor = (PPM_CONTEXT*) SubAlloc.pText;
+ if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
+ goto RESTART_MODEL;
+ if ( fs.Successor )
+ {
+ if ((byte*) fs.Successor <= SubAlloc.pText &&
+ (fs.Successor=CreateSuccessors(FALSE,p)) == NULL)
+ goto RESTART_MODEL;
+ if ( !--OrderFall )
+ {
+ Successor=fs.Successor;
+ SubAlloc.pText -= (MaxContext != MinContext);
+ }
+ }
+ else
+ {
+ FoundState->Successor=Successor;
+ fs.Successor=MinContext;
+ }
+ s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1);
+ for (pc=MaxContext;pc != MinContext;pc=pc->Suffix)
+ {
+ if ((ns1=pc->NumStats) != 1)
+ {
+ if ((ns1 & 1) == 0)
+ {
+ pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
+ if ( !pc->U.Stats )
+ goto RESTART_MODEL;
+ }
+ pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1));
+ }
+ else
+ {
+ p=(STATE*) SubAlloc.AllocUnits(1);
+ if ( !p )
+ goto RESTART_MODEL;
+ *p=pc->OneState;
+ pc->U.Stats=p;
+ if (p->Freq < MAX_FREQ/4-1)
+ p->Freq += p->Freq;
+ else
+ p->Freq = MAX_FREQ-4;
+ pc->U.SummFreq=p->Freq+InitEsc+(ns > 3);
+ }
+ cf=2*fs.Freq*(pc->U.SummFreq+6);
+ sf=s0+pc->U.SummFreq;
+ if (cf < 6*sf)
+ {
+ cf=1+(cf > sf)+(cf >= 4*sf);
+ pc->U.SummFreq += 3;
+ }
+ else
+ {
+ cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf);
+ pc->U.SummFreq += cf;
+ }
+ p=pc->U.Stats+ns1;
+ p->Successor=Successor;
+ p->Symbol = fs.Symbol;
+ p->Freq = cf;
+ pc->NumStats=++ns1;
+ }
+ MaxContext=MinContext=fs.Successor;
+ return;
+RESTART_MODEL:
+ RestartModelRare();
+ EscCount=0;
+}
+
+
+// Tabulated escapes for exponential symbol distribution
+static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
+#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
+
+
+
+inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
+{
+ STATE& rs=OneState;
+ Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
+ ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
+ Model->NS2BSIndx[Suffix->NumStats-1]+
+ Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+
+ ((Model->RunLength >> 26) & 0x20)];
+ if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs)
+ {
+ Model->FoundState=&rs;
+ rs.Freq += (rs.Freq < 128);
+ Model->Coder.SubRange.LowCount=0;
+ Model->Coder.SubRange.HighCount=bs;
+ bs = SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
+ Model->PrevSuccess=1;
+ Model->RunLength++;
+ }
+ else
+ {
+ Model->Coder.SubRange.LowCount=bs;
+ bs = SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
+ Model->Coder.SubRange.HighCount=BIN_SCALE;
+ Model->InitEsc=ExpEscape[bs >> 10];
+ Model->NumMasked=1;
+ Model->CharMask[rs.Symbol]=Model->EscCount;
+ Model->PrevSuccess=0;
+ Model->FoundState=NULL;
+ }
+}
+
+
+inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
+{
+ (Model->FoundState=p)->Freq += 4;
+ U.SummFreq += 4;
+ if (p[0].Freq > p[-1].Freq)
+ {
+ _PPMD_SWAP(p[0],p[-1]);
+ Model->FoundState=--p;
+ if (p->Freq > MAX_FREQ)
+ rescale(Model);
+ }
+}
+
+
+
+
+inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
+{
+ Model->Coder.SubRange.scale=U.SummFreq;
+ STATE* p=U.Stats;
+ int i, HiCnt;
+ int count=Model->Coder.GetCurrentCount();
+ if (count>=Model->Coder.SubRange.scale)
+ return(false);
+ if (count < (HiCnt=p->Freq))
+ {
+ Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale);
+ Model->RunLength += Model->PrevSuccess;
+ (Model->FoundState=p)->Freq=(HiCnt += 4);
+ U.SummFreq += 4;
+ if (HiCnt > MAX_FREQ)
+ rescale(Model);
+ Model->Coder.SubRange.LowCount=0;
+ return(true);
+ }
+ else
+ if (Model->FoundState==NULL)
+ return(false);
+ Model->PrevSuccess=0;
+ i=NumStats-1;
+ while ((HiCnt += (++p)->Freq) <= count)
+ if (--i == 0)
+ {
+ Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
+ Model->Coder.SubRange.LowCount=HiCnt;
+ Model->CharMask[p->Symbol]=Model->EscCount;
+ i=(Model->NumMasked=NumStats)-1;
+ Model->FoundState=NULL;
+ do
+ {
+ Model->CharMask[(--p)->Symbol]=Model->EscCount;
+ } while ( --i );
+ Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
+ return(true);
+ }
+ Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
+ update1(Model,p);
+ return(true);
+}
+
+
+inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
+{
+ (Model->FoundState=p)->Freq += 4;
+ U.SummFreq += 4;
+ if (p->Freq > MAX_FREQ)
+ rescale(Model);
+ Model->EscCount++;
+ Model->RunLength=Model->InitRL;
+}
+
+
+inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
+{
+ SEE2_CONTEXT* psee2c;
+ if (NumStats != 256)
+ {
+ psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
+ (Diff < Suffix->NumStats-NumStats)+
+ 2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+
+ Model->HiBitsFlag;
+ Model->Coder.SubRange.scale=psee2c->getMean();
+ }
+ else
+ {
+ psee2c=&Model->DummySEE2Cont;
+ Model->Coder.SubRange.scale=1;
+ }
+ return psee2c;
+}
+
+
+
+
+inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
+{
+ int count, HiCnt, i=NumStats-Model->NumMasked;
+ SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
+ STATE* ps[256], ** pps=ps, * p=U.Stats-1;
+ HiCnt=0;
+ do
+ {
+ do
+ {
+ p++;
+ } while (Model->CharMask[p->Symbol] == Model->EscCount);
+ HiCnt += p->Freq;
+ *pps++ = p;
+ } while ( --i );
+ Model->Coder.SubRange.scale += HiCnt;
+ count=Model->Coder.GetCurrentCount();
+ if (count>=Model->Coder.SubRange.scale)
+ return(false);
+ p=*(pps=ps);
+ if (count < HiCnt)
+ {
+ HiCnt=0;
+ while ((HiCnt += p->Freq) <= count)
+ p=*++pps;
+ Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
+ psee2c->update();
+ update2(Model,p);
+ }
+ else
+ {
+ Model->Coder.SubRange.LowCount=HiCnt;
+ Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
+ i=NumStats-Model->NumMasked;
+ pps--;
+ do
+ {
+ Model->CharMask[(*++pps)->Symbol]=Model->EscCount;
+ } while ( --i );
+ psee2c->Summ += Model->Coder.SubRange.scale;
+ Model->NumMasked = NumStats;
+ }
+ return(true);
+}
+
+
+inline void ModelPPM::ClearMask()
+{
+ EscCount=1;
+ memset(CharMask,0,sizeof(CharMask));
+}
+
+
+
+
+// reset PPM variables after data error allowing safe resuming
+// of further data processing
+void ModelPPM::CleanUp()
+{
+ SubAlloc.StopSubAllocator();
+ SubAlloc.StartSubAllocator(1);
+ StartModelRare(2);
+}
+
+
+bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
+{
+ int MaxOrder=UnpackRead->GetChar();
+ bool Reset=MaxOrder & 0x20;
+
+ int MaxMB;
+ if (Reset)
+ MaxMB=UnpackRead->GetChar();
+ else
+ if (SubAlloc.GetAllocatedMemory()==0)
+ return(false);
+ if (MaxOrder & 0x40)
+ EscChar=UnpackRead->GetChar();
+ Coder.InitDecoder(UnpackRead);
+ if (Reset)
+ {
+ MaxOrder=(MaxOrder & 0x1f)+1;
+ if (MaxOrder>16)
+ MaxOrder=16+(MaxOrder-16)*3;
+ if (MaxOrder==1)
+ {
+ SubAlloc.StopSubAllocator();
+ return(false);
+ }
+ SubAlloc.StartSubAllocator(MaxMB+1);
+ StartModelRare(MaxOrder);
+ }
+ return(MinContext!=NULL);
+}
+
+
+int ModelPPM::DecodeChar()
+{
+ if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
+ return(-1);
+ if (MinContext->NumStats != 1)
+ {
+ if ((byte*)MinContext->U.Stats <= SubAlloc.pText || (byte*)MinContext->U.Stats>SubAlloc.HeapEnd)
+ return(-1);
+ if (!MinContext->decodeSymbol1(this))
+ return(-1);
+ }
+ else
+ MinContext->decodeBinSymbol(this);
+ Coder.Decode();
+ while ( !FoundState )
+ {
+ ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
+ do
+ {
+ OrderFall++;
+ MinContext=MinContext->Suffix;
+ if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
+ return(-1);
+ } while (MinContext->NumStats == NumMasked);
+ if (!MinContext->decodeSymbol2(this))
+ return(-1);
+ Coder.Decode();
+ }
+ int Symbol=FoundState->Symbol;
+ if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText)
+ MinContext=MaxContext=FoundState->Successor;
+ else
+ {
+ UpdateModel();
+ if (EscCount == 0)
+ ClearMask();
+ }
+ ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
+ return(Symbol);
+}
diff --git a/unrar/unrar/model.hpp b/unrar/unrar/model.hpp
new file mode 100644
index 0000000..f39323b
--- /dev/null
+++ b/unrar/unrar/model.hpp
@@ -0,0 +1,132 @@
+#ifndef _RAR_PPMMODEL_
+#define _RAR_PPMMODEL_
+
+#include "coder.hpp"
+#include "suballoc.hpp"
+
+const int MAX_O=64; /* maximum allowed model order */
+
+const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
+ INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
+
+#ifndef STRICT_ALIGNMENT_REQUIRED
+#pragma pack(1)
+#endif
+
+struct SEE2_CONTEXT
+{ // SEE-contexts for PPM-contexts with masked symbols
+ ushort Summ;
+ byte Shift, Count;
+ void init(int InitVal)
+ {
+ Summ=InitVal << (Shift=PERIOD_BITS-4);
+ Count=4;
+ }
+ uint getMean()
+ {
+ uint RetVal=SHORT16(Summ) >> Shift;
+ Summ -= RetVal;
+ return RetVal+(RetVal == 0);
+ }
+ void update()
+ {
+ if (Shift < PERIOD_BITS && --Count == 0)
+ {
+ Summ += Summ;
+ Count=3 << Shift++;
+ }
+ }
+};
+
+
+class ModelPPM;
+struct PPM_CONTEXT;
+
+struct STATE
+{
+ byte Symbol;
+ byte Freq;
+ PPM_CONTEXT* Successor;
+};
+
+struct FreqData
+{
+ ushort SummFreq;
+ STATE _PACK_ATTR * Stats;
+};
+
+struct PPM_CONTEXT
+{
+ ushort NumStats;
+ union
+ {
+ FreqData U;
+ STATE OneState;
+ };
+
+ PPM_CONTEXT* Suffix;
+ inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
+ inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
+ inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
+ inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
+ inline bool decodeSymbol1(ModelPPM *Model); // other orders:
+ inline bool decodeSymbol2(ModelPPM *Model); // BCD context
+ inline void update1(ModelPPM *Model,STATE* p); // CD suffix
+ inline void update2(ModelPPM *Model,STATE* p); // BCDE successor
+ void rescale(ModelPPM *Model);
+ inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
+ inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
+};
+
+#ifndef STRICT_ALIGNMENT_REQUIRED
+#ifdef _AIX
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+#endif
+
+const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK));
+const uint FIXED_UNIT_SIZE=12;
+
+/*
+inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext):
+ NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; }
+inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {}
+*/
+
+template <class T>
+inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
+
+
+class ModelPPM
+{
+ private:
+ friend struct PPM_CONTEXT;
+
+ _PACK_ATTR SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
+
+ struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
+ STATE* FoundState; // found next state transition
+ int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
+ byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
+ byte EscCount, PrevSuccess, HiBitsFlag;
+ ushort BinSumm[128][64]; // binary SEE-contexts
+
+ RangeCoder Coder;
+ SubAllocator SubAlloc;
+
+ void RestartModelRare();
+ void StartModelRare(int MaxOrder);
+ inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);
+
+ inline void UpdateModel();
+ inline void ClearMask();
+ public:
+ ModelPPM();
+ void CleanUp(); // reset PPM variables after data error
+ bool DecodeInit(Unpack *UnpackRead,int &EscChar);
+ int DecodeChar();
+};
+
+#endif
diff --git a/unrar/unrar/msc.dep b/unrar/unrar/msc.dep
new file mode 100644
index 0000000..1205afa
--- /dev/null
+++ b/unrar/unrar/msc.dep
@@ -0,0 +1,2532 @@
+# Microsoft Developer Studio Generated Dependency File, included by unrar.mak
+
+.\archive.cpp : \
+ ".\arccmt.cpp"\
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\arcread.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\cmddata.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\consio.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.cpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\crc.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\crypt.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\encname.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\errhnd.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\extinfo.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+ ".\win32acl.cpp"\
+ ".\win32stm.cpp"\
+
+
+.\extract.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\filcreat.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\file.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\filefn.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\filestr.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\find.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\getbits.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\global.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\int64.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\isnt.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\list.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\match.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\options.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\pathfn.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\rar.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.cpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\rarvm.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rarvmtbl.cpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\rawread.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\rdwrfn.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\recvol.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\resource.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\rijndael.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\rs.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\savepos.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\scantree.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\sha1.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\strfn.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\strlist.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\system.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\timefn.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\ulinks.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\unicode.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\unpack.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.cpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.cpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.cpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\unpack15.cpp"\
+ ".\unpack20.cpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
+
+.\volume.cpp : \
+ ".\archive.hpp"\
+ ".\array.hpp"\
+ ".\cmddata.hpp"\
+ ".\coder.hpp"\
+ ".\compress.hpp"\
+ ".\consio.hpp"\
+ ".\crc.hpp"\
+ ".\crypt.hpp"\
+ ".\encname.hpp"\
+ ".\errhnd.hpp"\
+ ".\extinfo.hpp"\
+ ".\extract.hpp"\
+ ".\filcreat.hpp"\
+ ".\file.hpp"\
+ ".\filefn.hpp"\
+ ".\filestr.hpp"\
+ ".\find.hpp"\
+ ".\getbits.hpp"\
+ ".\global.hpp"\
+ ".\headers.hpp"\
+ ".\int64.hpp"\
+ ".\isnt.hpp"\
+ ".\list.hpp"\
+ ".\loclang.hpp"\
+ ".\log.hpp"\
+ ".\match.hpp"\
+ ".\model.hpp"\
+ ".\options.hpp"\
+ ".\os.hpp"\
+ ".\pathfn.hpp"\
+ ".\rar.hpp"\
+ ".\rardefs.hpp"\
+ ".\rarfn.hpp"\
+ ".\rarlang.hpp"\
+ ".\raros.hpp"\
+ ".\rartypes.hpp"\
+ ".\rarvm.hpp"\
+ ".\rawread.hpp"\
+ ".\rdwrfn.hpp"\
+ ".\recvol.hpp"\
+ ".\resource.hpp"\
+ ".\rijndael.hpp"\
+ ".\rs.hpp"\
+ ".\savepos.hpp"\
+ ".\scantree.hpp"\
+ ".\sha1.hpp"\
+ ".\smallfn.hpp"\
+ ".\strfn.hpp"\
+ ".\strlist.hpp"\
+ ".\suballoc.hpp"\
+ ".\system.hpp"\
+ ".\timefn.hpp"\
+ ".\ulinks.hpp"\
+ ".\unicode.hpp"\
+ ".\unpack.hpp"\
+ ".\version.hpp"\
+ ".\volume.hpp"\
+
diff --git a/unrar/unrar/options.cpp b/unrar/unrar/options.cpp
new file mode 100644
index 0000000..e6efb42
--- /dev/null
+++ b/unrar/unrar/options.cpp
@@ -0,0 +1,28 @@
+#include "rar.hpp"
+
+RAROptions::RAROptions()
+{
+ Init();
+}
+
+
+RAROptions::~RAROptions()
+{
+ memset(this,0,sizeof(RAROptions));
+}
+
+
+void RAROptions::Init()
+{
+ memset(this,0,sizeof(RAROptions));
+ WinSize=0x400000;
+ Overwrite=OVERWRITE_ASK;
+ Method=3;
+ MsgStream=MSG_STDOUT;
+ ConvertNames=NAMES_ORIGINALCASE;
+ ProcessEA=true;
+ xmtime=EXTTIME_HIGH3;
+ CurVolNum=0;
+ FileSizeLess=INT64ERR;
+ FileSizeMore=INT64ERR;
+}
diff --git a/unrar/unrar/options.hpp b/unrar/unrar/options.hpp
new file mode 100644
index 0000000..cc2db48
--- /dev/null
+++ b/unrar/unrar/options.hpp
@@ -0,0 +1,142 @@
+#ifndef _RAR_OPTIONS_
+#define _RAR_OPTIONS_
+
+#define DEFAULT_RECOVERY -1
+
+#define DEFAULT_RECVOLUMES -10
+
+enum PathExclMode {
+ EXCL_NONE,EXCL_BASEPATH,EXCL_SKIPWHOLEPATH,EXCL_SAVEFULLPATH,
+ EXCL_SKIPABSPATH,EXCL_ABSPATH
+};
+enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
+ SOLID_VOLUME_DEPENDENT=8,SOLID_VOLUME_INDEPENDENT=16};
+enum {ARCTIME_NONE,ARCTIME_KEEP,ARCTIME_LATEST};
+enum EXTTIME_MODE {
+ EXTTIME_NONE,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
+};
+enum {NAMES_ORIGINALCASE,NAMES_UPPERCASE,NAMES_LOWERCASE};
+enum MESSAGE_TYPE {MSG_STDOUT,MSG_STDERR,MSG_ERRONLY,MSG_NULL};
+enum OVERWRITE_MODE {
+ OVERWRITE_ASK,OVERWRITE_ALL,OVERWRITE_NONE,OVERWRITE_AUTORENAME
+};
+
+enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE };
+
+#define MAX_FILTERS 16
+enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE};
+
+
+struct FilterMode
+{
+ FilterState State;
+ int Param1;
+ int Param2;
+};
+
+
+class RAROptions
+{
+ public:
+ RAROptions();
+ ~RAROptions();
+ void Init();
+
+ uint ExclFileAttr;
+ uint InclFileAttr;
+ bool InclAttrSet;
+ uint WinSize;
+ char TempPath[NM];
+ char SFXModule[NM];
+ char ExtrPath[NM];
+ wchar ExtrPathW[NM];
+ char CommentFile[NM];
+ RAR_CHARSET CommentCharset;
+ RAR_CHARSET FilelistCharset;
+ char ArcPath[NM];
+ char Password[MAXPASSWORD];
+ bool EncryptHeaders;
+ char LogName[NM];
+ MESSAGE_TYPE MsgStream;
+ bool Sound;
+ OVERWRITE_MODE Overwrite;
+ int Method;
+ int Recovery;
+ int RecVolNumber;
+ bool DisablePercentage;
+ bool DisableCopyright;
+ bool DisableDone;
+ int Solid;
+ int SolidCount;
+ bool ClearArc;
+ bool AddArcOnly;
+ bool AV;
+ bool DisableComment;
+ bool FreshFiles;
+ bool UpdateFiles;
+ PathExclMode ExclPath;
+ int Recurse;
+ Int64 VolSize;
+ Array<Int64> NextVolSizes;
+ int CurVolNum;
+ bool AllYes;
+ bool DisableViewAV;
+ bool DisableSortSolid;
+ int ArcTime;
+ int ConvertNames;
+ bool ProcessOwners;
+ bool SaveLinks;
+ int Priority;
+ int SleepTime;
+ bool KeepBroken;
+ bool EraseDisk;
+ bool OpenShared;
+ bool ExclEmptyDir;
+ bool DeleteFiles;
+ bool SyncFiles;
+ bool GenerateArcName;
+ char GenerateMask[80];
+ bool ProcessEA;
+ bool SaveStreams;
+ bool SetCompressedAttr;
+ uint FileTimeOlder;
+ uint FileTimeNewer;
+ RarTime FileTimeBefore;
+ RarTime FileTimeAfter;
+ Int64 FileSizeLess;
+ Int64 FileSizeMore;
+ bool OldNumbering;
+ bool Lock;
+ bool Test;
+ bool VolumePause;
+ FilterMode FilterModes[MAX_FILTERS];
+ char EmailTo[NM];
+ int VersionControl;
+ bool NoEndBlock;
+ bool AppendArcNameToPath;
+ bool Shutdown;
+ EXTTIME_MODE xmtime;
+ EXTTIME_MODE xctime;
+ EXTTIME_MODE xatime;
+ EXTTIME_MODE xarctime;
+ char CompressStdin[NM];
+
+#ifdef PACK_SMP
+ uint Threads;
+#endif
+
+
+
+
+#ifdef RARDLL
+ char DllDestName[NM];
+ wchar DllDestNameW[NM];
+ int DllOpMode;
+ int DllError;
+ LONG UserData;
+ UNRARCALLBACK Callback;
+ CHANGEVOLPROC ChangeVolProc;
+ PROCESSDATAPROC ProcessDataProc;
+#endif
+};
+#endif
diff --git a/unrar/unrar/os.hpp b/unrar/unrar/os.hpp
new file mode 100644
index 0000000..453b9b0
--- /dev/null
+++ b/unrar/unrar/os.hpp
@@ -0,0 +1,241 @@
+#ifndef _RAR_OS_
+#define _RAR_OS_
+
+#define FALSE 0
+#define TRUE 1
+
+#ifdef __EMX__
+ #define INCL_BASE
+#endif
+
+#if defined(_WIN_32) || defined(_EMX)
+#define ENABLE_BAD_ALLOC
+#endif
+
+
+#if defined(_WIN_32) || defined(_EMX)
+
+#define LITTLE_ENDIAN
+#define NM 1024
+
+#ifdef _WIN_32
+
+ #define STRICT
+ #undef WINVER
+ #undef _WIN32_WINNT
+ #define WINVER 0x0400
+ #define _WIN32_WINNT 0x0300
+
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <prsht.h>
+
+#ifndef _WIN_CE
+ #include <shlobj.h>
+ #include <winioctl.h>
+#endif
+
+#endif
+
+#ifndef _WIN_CE
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <dos.h>
+#endif
+
+#if !defined(_EMX) && !defined(_MSC_VER) && !defined(_WIN_CE)
+ #include <dir.h>
+#endif
+#ifdef _MSC_VER
+ #define for if (0) ; else for
+#ifndef _WIN_CE
+ #include <direct.h>
+#endif
+#else
+ #include <dirent.h>
+#endif
+
+#ifndef _WIN_CE
+ #include <share.h>
+#endif
+
+#if defined(ENABLE_BAD_ALLOC) && !defined(_WIN_CE)
+ #include <new.h>
+#endif
+
+#ifdef _EMX
+ #include <unistd.h>
+ #include <pwd.h>
+ #include <grp.h>
+ #include <errno.h>
+ #ifdef _DJGPP
+ #include <utime.h>
+ #else
+ #include <os2.h>
+ #include <sys/utime.h>
+ #include <emx/syscalls.h>
+ #endif
+#else
+ #if defined(_MSC_VER) || defined(__MINGW32__)
+ #include <exception>
+ #else
+ #include <except.h>
+ #endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#ifndef _WIN_CE
+ #include <fcntl.h>
+ #include <dos.h>
+ #include <io.h>
+ #include <time.h>
+ #include <signal.h>
+#endif
+
+/*
+#ifdef _WIN_32
+#pragma hdrstop
+#endif
+*/
+
+#define ENABLE_ACCESS
+
+#define DefConfigName "rar.ini"
+#define DefLogName "rar.log"
+
+
+#define PATHDIVIDER "\\"
+#define PATHDIVIDERW L"\\"
+#define CPATHDIVIDER '\\'
+#define MASKALL "*"
+#define MASKALLW L"*"
+
+#define READBINARY "rb"
+#define READTEXT "rt"
+#define UPDATEBINARY "r+b"
+#define CREATEBINARY "w+b"
+#define APPENDTEXT "at"
+
+#if defined(_WIN_32)
+ #ifdef _MSC_VER
+ #define _stdfunction __cdecl
+ #else
+ #define _stdfunction _USERENTRY
+ #endif
+#else
+ #define _stdfunction
+#endif
+
+#endif
+
+#ifdef _UNIX
+
+#define NM 1024
+
+#ifdef _BEOS
+#include <be/kernel/fs_info.h>
+#include <be/kernel/fs_attr.h>
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#if defined(__QNXNTO__)
+ #include <sys/param.h>
+#endif
+#if defined(__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__)
+ #include <sys/param.h>
+ #include <sys/mount.h>
+#else
+#endif
+#include <pwd.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <time.h>
+#include <signal.h>
+#include <utime.h>
+#include <locale.h>
+
+#ifdef S_IFLNK
+#define SAVE_LINKS
+#endif
+
+#define ENABLE_ACCESS
+
+#define DefConfigName ".rarrc"
+#define DefLogName ".rarlog"
+
+
+#define PATHDIVIDER "/"
+#define PATHDIVIDERW L"/"
+#define CPATHDIVIDER '/'
+#define MASKALL "*"
+#define MASKALLW L"*"
+
+#define READBINARY "r"
+#define READTEXT "r"
+#define UPDATEBINARY "r+"
+#define CREATEBINARY "w+"
+#define APPENDTEXT "a"
+
+#define _stdfunction
+
+#ifdef _APPLE
+ #if defined(__BIG_ENDIAN__) && !defined(BIG_ENDIAN)
+ #define BIG_ENDIAN
+ #undef LITTLE_ENDIAN
+ #endif
+ #if defined(__i386__) && !defined(LITTLE_ENDIAN)
+ #define LITTLE_ENDIAN
+ #undef BIG_ENDIAN
+ #endif
+#endif
+
+#if defined(__sparc) || defined(sparc) || defined(__hpux)
+ #ifndef BIG_ENDIAN
+ #define BIG_ENDIAN
+ #endif
+#endif
+
+#endif
+
+typedef const char* MSGID;
+
+#define safebuf static
+
+#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
+ #if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
+ #undef LITTLE_ENDIAN
+ #elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
+ #undef BIG_ENDIAN
+ #else
+ #error "Both LITTLE_ENDIAN and BIG_ENDIAN are defined. Undef something one"
+ #endif
+#endif
+
+#if !defined(BIG_ENDIAN) && !defined(_WIN_CE) && defined(_WIN_32)
+/* allow not aligned integer access, increases speed in some operations */
+#define ALLOW_NOT_ALIGNED_INT
+#endif
+
+#if defined(__sparc) || defined(sparc) || defined(__sparcv9)
+/* prohibit not aligned access to data structures in text comression
+ algorithm, increases memory requirements */
+#define STRICT_ALIGNMENT_REQUIRED
+#endif
+
+#endif // _RAR_OS_
diff --git a/unrar/unrar/os2ea.cpp b/unrar/unrar/os2ea.cpp
new file mode 100644
index 0000000..f418615
--- /dev/null
+++ b/unrar/unrar/os2ea.cpp
@@ -0,0 +1,94 @@
+#include <os2.h>
+
+
+
+void ExtractOS2EA(Archive &Arc,char *FileName)
+{
+ if (_osmode != OS2_MODE)
+ {
+ mprintf(St(MSkipEA));
+ return;
+ }
+
+ if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
+ {
+ Log(Arc.FileName,St(MEABroken),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
+ {
+ Log(Arc.FileName,St(MEAUnknHeader),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ return;
+ }
+
+ struct StructEAOP2
+ {
+ char *GEAPtr;
+ char *FEAPtr;
+ unsigned long Error;
+ } EAOP2;
+
+ ComprDataIO DataIO;
+ Unpack Unpack(&DataIO);
+ Unpack.Init();
+
+ Array<unsigned char> UnpData(Arc.EAHead.UnpSize);
+ DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
+ DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
+ DataIO.EnableShowProgress(false);
+ DataIO.SetFiles(&Arc,NULL);
+ Unpack.SetDestSize(Arc.EAHead.UnpSize);
+ Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
+
+ if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
+ {
+ Log(Arc.FileName,St(MEABroken),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ EAOP2.FEAPtr=(char *)&UnpData[0];
+ EAOP2.GEAPtr=NULL;
+ if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ }
+ File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
+ mprintf(St(MShowEA));
+}
+
+
+void ExtractOS2EANew(Archive &Arc,char *FileName)
+{
+ if (_osmode != OS2_MODE)
+ {
+ mprintf(St(MSkipEA));
+ return;
+ }
+
+ Array<byte> SubData;
+ if (!Arc.ReadSubData(&SubData,NULL))
+ return;
+
+ struct StructEAOP2
+ {
+ char *GEAPtr;
+ char *FEAPtr;
+ unsigned long Error;
+ } EAOP2;
+
+ EAOP2.FEAPtr=(char *)&SubData[0];
+ EAOP2.GEAPtr=NULL;
+ if (DosSetPathInfo((unsigned char *)FileName,2,&EAOP2,sizeof(EAOP2),0x10)!=0)
+ {
+ Log(Arc.FileName,St(MCannotSetEA),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ }
+ File::SetCloseFileTimeByName(FileName,&Arc.NewLhd.mtime,&Arc.NewLhd.atime);
+ mprintf(St(MShowEA));
+}
+
diff --git a/unrar/unrar/pathfn.cpp b/unrar/unrar/pathfn.cpp
new file mode 100644
index 0000000..e635d16
--- /dev/null
+++ b/unrar/unrar/pathfn.cpp
@@ -0,0 +1,714 @@
+#include "rar.hpp"
+
+char* PointToName(const char *Path)
+{
+ const char *Found=NULL;
+ for (const char *s=Path;*s!=0;s=charnext(s))
+ if (IsPathDiv(*s))
+ Found=(char*)(s+1);
+ if (Found!=NULL)
+ return((char*)Found);
+ return (char*)((*Path && IsDriveDiv(Path[1]) && charnext(Path)==Path+1) ? Path+2:Path);
+}
+
+
+wchar* PointToName(const wchar *Path)
+{
+ for (int I=strlenw(Path)-1;I>=0;I--)
+ if (IsPathDiv(Path[I]))
+ return (wchar*)&Path[I+1];
+ return (wchar*)((*Path && IsDriveDiv(Path[1])) ? Path+2:Path);
+}
+
+
+char* PointToLastChar(const char *Path)
+{
+ for (const char *s=Path,*p=Path;;p=s,s=charnext(s))
+ if (*s==0)
+ return((char *)p);
+}
+
+
+char* ConvertPath(const char *SrcPath,char *DestPath)
+{
+ const char *DestPtr=SrcPath;
+
+ /* prevents \..\ in any part of path string */
+ for (const char *s=DestPtr;*s!=0;s++)
+ if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
+ DestPtr=s+4;
+
+ /* removes any sequence of . and \ in the beginning of path string */
+ while (*DestPtr)
+ {
+ const char *s=DestPtr;
+ if (s[0] && IsDriveDiv(s[1]))
+ s+=2;
+ else
+ if (s[0]=='\\' && s[1]=='\\')
+ {
+ const char *Slash=strchr(s+2,'\\');
+ if (Slash!=NULL && (Slash=strchr(Slash+1,'\\'))!=NULL)
+ s=Slash+1;
+ }
+ for (const char *t=s;*t!=0;t++)
+ if (IsPathDiv(*t))
+ s=t+1;
+ else
+ if (*t!='.')
+ break;
+ if (s==DestPtr)
+ break;
+ DestPtr=s;
+ }
+
+ /* code above does not remove last "..", doing here */
+ if (DestPtr[0]=='.' && DestPtr[1]=='.' && DestPtr[2]==0)
+ DestPtr+=2;
+
+ if (DestPath!=NULL)
+ {
+ char TmpStr[NM];
+ strncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
+ strcpy(DestPath,TmpStr);
+ }
+ return((char *)DestPtr);
+}
+
+
+wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
+{
+ const wchar *DestPtr=SrcPath;
+ for (const wchar *s=DestPtr;*s!=0;s++)
+ if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
+ DestPtr=s+4;
+ while (*DestPtr)
+ {
+ const wchar *s=DestPtr;
+ if (s[0] && IsDriveDiv(s[1]))
+ s+=2;
+ if (s[0]=='\\' && s[1]=='\\')
+ {
+ const wchar *Slash=strchrw(s+2,'\\');
+ if (Slash!=NULL && (Slash=strchrw(Slash+1,'\\'))!=NULL)
+ s=Slash+1;
+ }
+ for (const wchar *t=s;*t!=0;t++)
+ if (IsPathDiv(*t))
+ s=t+1;
+ else
+ if (*t!='.')
+ break;
+ if (s==DestPtr)
+ break;
+ DestPtr=s;
+ }
+ if (DestPath!=NULL)
+ {
+ wchar TmpStr[NM];
+ strncpyw(TmpStr,DestPtr,sizeof(TmpStr)/sizeof(TmpStr[0])-1);
+ strcpyw(DestPath,TmpStr);
+ }
+ return((wchar *)DestPtr);
+}
+
+
+void SetExt(char *Name,const char *NewExt)
+{
+ char *Dot=GetExt(Name);
+ if (NewExt==NULL)
+ {
+ if (Dot!=NULL)
+ *Dot=0;
+ }
+ else
+ if (Dot==NULL)
+ {
+ strcat(Name,".");
+ strcat(Name,NewExt);
+ }
+ else
+ strcpy(Dot+1,NewExt);
+}
+
+
+#ifndef SFX_MODULE
+void SetExt(wchar *Name,const wchar *NewExt)
+{
+ if (Name==NULL || *Name==0)
+ return;
+ wchar *Dot=GetExt(Name);
+ if (NewExt==NULL)
+ {
+ if (Dot!=NULL)
+ *Dot=0;
+ }
+ else
+ if (Dot==NULL)
+ {
+ strcatw(Name,L".");
+ strcatw(Name,NewExt);
+ }
+ else
+ strcpyw(Dot+1,NewExt);
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void SetSFXExt(char *SFXName)
+{
+#ifdef _UNIX
+ SetExt(SFXName,"sfx");
+#endif
+
+#if defined(_WIN_32) || defined(_EMX)
+ SetExt(SFXName,"exe");
+#endif
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void SetSFXExt(wchar *SFXName)
+{
+ if (SFXName==NULL || *SFXName==0)
+ return;
+
+#ifdef _UNIX
+ SetExt(SFXName,L"sfx");
+#endif
+
+#if defined(_WIN_32) || defined(_EMX)
+ SetExt(SFXName,L"exe");
+#endif
+}
+#endif
+
+
+char *GetExt(const char *Name)
+{
+ return(strrchrd(PointToName(Name),'.'));
+}
+
+
+wchar *GetExt(const wchar *Name)
+{
+ return(Name==NULL ? (wchar *)L"":strrchrw(PointToName(Name),'.'));
+}
+
+
+bool CmpExt(const char *Name,const char *Ext)
+{
+ char *NameExt=GetExt(Name);
+ return(NameExt!=NULL && stricomp(NameExt+1,Ext)==0);
+}
+
+
+bool IsWildcard(const char *Str,const wchar *StrW)
+{
+ if (StrW!=NULL && *StrW!=0)
+ return(strpbrkw(StrW,L"*?")!=NULL);
+ return(Str==NULL ? false:strpbrk(Str,"*?")!=NULL);
+}
+
+
+bool IsPathDiv(int Ch)
+{
+#if defined(_WIN_32) || defined(_EMX)
+ return(Ch=='\\' || Ch=='/');
+#else
+ return(Ch==CPATHDIVIDER);
+#endif
+}
+
+
+bool IsDriveDiv(int Ch)
+{
+#ifdef _UNIX
+ return(false);
+#else
+ return(Ch==':');
+#endif
+}
+
+
+int GetPathDisk(const char *Path)
+{
+ if (IsDiskLetter(Path))
+ return(etoupper(*Path)-'A');
+ else
+ return(-1);
+}
+
+
+void AddEndSlash(char *Path)
+{
+ char *LastChar=PointToLastChar(Path);
+ if (*LastChar!=0 && *LastChar!=CPATHDIVIDER)
+ strcat(LastChar,PATHDIVIDER);
+}
+
+
+void AddEndSlash(wchar *Path)
+{
+ int Length=strlenw(Path);
+ if (Length>0 && Path[Length-1]!=CPATHDIVIDER)
+ strcatw(Path,PATHDIVIDERW);
+}
+
+
+// returns file path including the trailing path separator symbol
+void GetFilePath(const char *FullName,char *Path,int MaxLength)
+{
+ int PathLength=Min(MaxLength-1,PointToName(FullName)-FullName);
+ strncpy(Path,FullName,PathLength);
+ Path[PathLength]=0;
+}
+
+
+// returns file path including the trailing path separator symbol
+void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength)
+{
+ int PathLength=Min(MaxLength-1,PointToName(FullName)-FullName);
+ strncpyw(Path,FullName,PathLength);
+ Path[PathLength]=0;
+}
+
+
+// removes name and returns file path without the trailing
+// path separator symbol
+void RemoveNameFromPath(char *Path)
+{
+ char *Name=PointToName(Path);
+ if (Name>=Path+2 && (!IsDriveDiv(Path[1]) || Name>=Path+4))
+ Name--;
+ *Name=0;
+}
+
+
+#ifndef SFX_MODULE
+// removes name and returns file path without the trailing
+// path separator symbol
+void RemoveNameFromPath(wchar *Path)
+{
+ wchar *Name=PointToName(Path);
+ if (Name>=Path+2 && (!IsDriveDiv(Path[1]) || Name>=Path+4))
+ Name--;
+ *Name=0;
+}
+#endif
+
+
+#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
+void GetAppDataPath(char *Path)
+{
+ LPMALLOC g_pMalloc;
+ SHGetMalloc(&g_pMalloc);
+ LPITEMIDLIST ppidl;
+ *Path=0;
+ bool Success=false;
+ if (SHGetSpecialFolderLocation(NULL,CSIDL_APPDATA,&ppidl)==NOERROR &&
+ SHGetPathFromIDList(ppidl,Path) && *Path!=0)
+ {
+ AddEndSlash(Path);
+ strcat(Path,"WinRAR");
+ Success=FileExist(Path) || MakeDir(Path,NULL,0)==MKDIR_SUCCESS;
+ }
+ if (!Success)
+ {
+ GetModuleFileName(NULL,Path,NM);
+ RemoveNameFromPath(Path);
+ }
+ g_pMalloc->Free(ppidl);
+}
+#endif
+
+
+#ifndef SFX_MODULE
+bool EnumConfigPaths(char *Path,int Number)
+{
+#ifdef _EMX
+ static char RARFileName[NM];
+ if (Number==-1)
+ strcpy(RARFileName,Path);
+ if (Number!=0)
+ return(false);
+#ifndef _DJGPP
+ if (_osmode==OS2_MODE)
+ {
+ PTIB ptib;
+ PPIB ppib;
+ DosGetInfoBlocks(&ptib, &ppib);
+ DosQueryModuleName(ppib->pib_hmte,NM,Path);
+ }
+ else
+#endif
+ strcpy(Path,RARFileName);
+ RemoveNameFromPath(Path);
+ return(true);
+#elif defined(_UNIX)
+ if (Number==0)
+ {
+ char *EnvStr=getenv("HOME");
+ if (EnvStr==NULL)
+ return(false);
+ strncpy(Path,EnvStr,NM-1);
+ Path[NM-1]=0;
+ return(true);
+ }
+ static const char *AltPath[]={
+ "/etc","/etc/rar","/usr/lib","/usr/local/lib","/usr/local/etc"
+ };
+ Number--;
+ if (Number<0 || Number>=sizeof(AltPath)/sizeof(AltPath[0]))
+ return(false);
+ strcpy(Path,AltPath[Number]);
+ return(true);
+#elif defined(_WIN_32)
+
+ if (Number<0 || Number>1)
+ return(false);
+ if (Number==0)
+ GetAppDataPath(Path);
+ else
+ {
+ GetModuleFileName(NULL,Path,NM);
+ RemoveNameFromPath(Path);
+ }
+ return(true);
+
+#else
+ return(false);
+#endif
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void GetConfigName(const char *Name,char *FullName,bool CheckExist)
+{
+ for (int I=0;EnumConfigPaths(FullName,I);I++)
+ {
+ AddEndSlash(FullName);
+ strcat(FullName,Name);
+ if (!CheckExist || WildFileExist(FullName))
+ break;
+ }
+}
+#endif
+
+
+// returns a pointer to rightmost digit of volume number
+char* GetVolNumPart(char *ArcName)
+{
+ char *ChPtr=ArcName+strlen(ArcName)-1;
+ while (!isdigit(*ChPtr) && ChPtr>ArcName)
+ ChPtr--;
+ char *NumPtr=ChPtr;
+ while (isdigit(*NumPtr) && NumPtr>ArcName)
+ NumPtr--;
+ while (NumPtr>ArcName && *NumPtr!='.')
+ {
+ if (isdigit(*NumPtr))
+ {
+ char *Dot=strchrd(PointToName(ArcName),'.');
+ if (Dot!=NULL && Dot<NumPtr)
+ ChPtr=NumPtr;
+ break;
+ }
+ NumPtr--;
+ }
+ return(ChPtr);
+}
+
+
+void NextVolumeName(char *ArcName,bool OldNumbering)
+{
+ char *ChPtr;
+ if ((ChPtr=GetExt(ArcName))==NULL)
+ {
+ strcat(ArcName,".rar");
+ ChPtr=GetExt(ArcName);
+ }
+ else
+ if (ChPtr[1]==0 || stricomp(ChPtr+1,"exe")==0 || stricomp(ChPtr+1,"sfx")==0)
+ strcpy(ChPtr+1,"rar");
+ if (!OldNumbering)
+ {
+ ChPtr=GetVolNumPart(ArcName);
+
+ while ((++(*ChPtr))=='9'+1)
+ {
+ *ChPtr='0';
+ ChPtr--;
+ if (ChPtr<ArcName || !isdigit(*ChPtr))
+ {
+ for (char *EndPtr=ArcName+strlen(ArcName);EndPtr!=ChPtr;EndPtr--)
+ *(EndPtr+1)=*EndPtr;
+ *(ChPtr+1)='1';
+ break;
+ }
+ }
+ }
+ else
+ if (!isdigit(*(ChPtr+2)) || !isdigit(*(ChPtr+3)))
+ strcpy(ChPtr+2,"00");
+ else
+ {
+ ChPtr+=3;
+ while ((++(*ChPtr))=='9'+1)
+ if (*(ChPtr-1)=='.')
+ {
+ *ChPtr='A';
+ break;
+ }
+ else
+ {
+ *ChPtr='0';
+ ChPtr--;
+ }
+ }
+}
+
+
+bool IsNameUsable(const char *Name)
+{
+#ifndef _UNIX
+ if (Name[0] && Name[1] && strchr(Name+2,':')!=NULL)
+ return(false);
+ for (const char *s=Name;*s!=0;s=charnext(s))
+ {
+ if (*s<32)
+ return(false);
+ if (*s==' ' && IsPathDiv(s[1]))
+ return(false);
+ }
+#endif
+ return(*Name!=0 && strpbrk(Name,"?*<>|\"")==NULL);
+}
+
+
+void MakeNameUsable(char *Name,bool Extended)
+{
+ for (char *s=Name;*s!=0;s=charnext(s))
+ {
+ if (strchr(Extended ? "?*<>|\"":"?*",*s)!=NULL || Extended && *s<32)
+ *s='_';
+#ifdef _EMX
+ if (*s=='=')
+ *s='_';
+#endif
+#ifndef _UNIX
+ if (s-Name>1 && *s==':')
+ *s='_';
+ if (*s==' ' && IsPathDiv(s[1]))
+ *s='_';
+#endif
+ }
+}
+
+
+char* UnixSlashToDos(char *SrcName,char *DestName,uint MaxLength)
+{
+ if (DestName!=NULL && DestName!=SrcName)
+ if (strlen(SrcName)>=MaxLength)
+ {
+ *DestName=0;
+ return(DestName);
+ }
+ else
+ strcpy(DestName,SrcName);
+ for (char *s=SrcName;*s!=0;s=charnext(s))
+ {
+ if (*s=='/')
+ if (DestName==NULL)
+ *s='\\';
+ else
+ DestName[s-SrcName]='\\';
+ }
+ return(DestName==NULL ? SrcName:DestName);
+}
+
+
+char* DosSlashToUnix(char *SrcName,char *DestName,uint MaxLength)
+{
+ if (DestName!=NULL && DestName!=SrcName)
+ if (strlen(SrcName)>=MaxLength)
+ {
+ *DestName=0;
+ return(DestName);
+ }
+ else
+ strcpy(DestName,SrcName);
+ for (char *s=SrcName;*s!=0;s=charnext(s))
+ {
+ if (*s=='\\')
+ if (DestName==NULL)
+ *s='/';
+ else
+ DestName[s-SrcName]='/';
+ }
+ return(DestName==NULL ? SrcName:DestName);
+}
+
+
+wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName,uint MaxLength)
+{
+ if (DestName!=NULL && DestName!=SrcName)
+ if (strlenw(SrcName)>=MaxLength)
+ {
+ *DestName=0;
+ return(DestName);
+ }
+ else
+ strcpyw(DestName,SrcName);
+ for (wchar *s=SrcName;*s!=0;s++)
+ {
+ if (*s=='/')
+ if (DestName==NULL)
+ *s='\\';
+ else
+ DestName[s-SrcName]='\\';
+ }
+ return(DestName==NULL ? SrcName:DestName);
+}
+
+
+bool IsFullPath(const char *Path)
+{
+ char PathOnly[NM];
+ GetFilePath(Path,PathOnly,ASIZE(PathOnly));
+ if (IsWildcard(PathOnly))
+ return(true);
+#if defined(_WIN_32) || defined(_EMX)
+ return(Path[0]=='\\' && Path[1]=='\\' ||
+ IsDiskLetter(Path) && IsPathDiv(Path[2]));
+#else
+ return(IsPathDiv(Path[0]));
+#endif
+}
+
+
+bool IsDiskLetter(const char *Path)
+{
+ char Letter=etoupper(Path[0]);
+ return(Letter>='A' && Letter<='Z' && IsDriveDiv(Path[1]));
+}
+
+
+void GetPathRoot(const char *Path,char *Root)
+{
+ *Root=0;
+ if (IsDiskLetter(Path))
+ sprintf(Root,"%c:\\",*Path);
+ else
+ if (Path[0]=='\\' && Path[1]=='\\')
+ {
+ const char *Slash=strchr(Path+2,'\\');
+ if (Slash!=NULL)
+ {
+ int Length;
+ if ((Slash=strchr(Slash+1,'\\'))!=NULL)
+ Length=Slash-Path+1;
+ else
+ Length=strlen(Path);
+ strncpy(Root,Path,Length);
+ Root[Length]=0;
+ }
+ }
+}
+
+
+int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate)
+{
+ int Version=0;
+ char *VerText=strrchrd(Name,';');
+ if (VerText!=NULL)
+ {
+ Version=atoi(VerText+1);
+ if (Truncate)
+ *VerText=0;
+ }
+ if (NameW!=NULL)
+ {
+ wchar *VerTextW=strrchrw(NameW,';');
+ if (VerTextW!=NULL)
+ {
+ if (Version==0)
+ Version=atoiw(VerTextW+1);
+ if (Truncate)
+ *VerTextW=0;
+ }
+ }
+ return(Version);
+}
+
+
+#ifndef SFX_MODULE
+char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering)
+{
+ if (FirstName!=VolName)
+ strcpy(FirstName,VolName);
+ char *VolNumStart=FirstName;
+ if (NewNumbering)
+ {
+ int N='1';
+ for (char *ChPtr=GetVolNumPart(FirstName);ChPtr>FirstName;ChPtr--)
+ if (isdigit(*ChPtr))
+ {
+ *ChPtr=N;
+ N='0';
+ }
+ else
+ if (N=='0')
+ {
+ VolNumStart=ChPtr+1;
+ break;
+ }
+ }
+ else
+ {
+ SetExt(FirstName,"rar");
+ VolNumStart=GetExt(FirstName);
+ }
+ if (!FileExist(FirstName))
+ {
+ char Mask[NM];
+ strcpy(Mask,FirstName);
+ SetExt(Mask,"*");
+ FindFile Find;
+ Find.SetMask(Mask);
+ struct FindData FD;
+ while (Find.Next(&FD))
+ {
+ Archive Arc;
+ if (Arc.Open(FD.Name,FD.NameW) && Arc.IsArchive(true) && !Arc.NotFirstVolume)
+ {
+ strcpy(FirstName,FD.Name);
+ break;
+ }
+ }
+ }
+ return(VolNumStart);
+}
+#endif
+
+
+
+
+wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW)
+{
+ if (NameW!=NULL && *NameW!=0)
+ {
+ if (DestW!=NameW)
+ strcpyw(DestW,NameW);
+ }
+ else
+ CharToWide(Name,DestW);
+ return(DestW);
+}
+
+
+
+
diff --git a/unrar/unrar/pathfn.hpp b/unrar/unrar/pathfn.hpp
new file mode 100644
index 0000000..6975993
--- /dev/null
+++ b/unrar/unrar/pathfn.hpp
@@ -0,0 +1,46 @@
+#ifndef _RAR_PATHFN_
+#define _RAR_PATHFN_
+
+char* PointToName(const char *Path);
+wchar* PointToName(const wchar *Path);
+char* PointToLastChar(const char *Path);
+char* ConvertPath(const char *SrcPath,char *DestPath);
+wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath);
+void SetExt(char *Name,const char *NewExt);
+void SetExt(wchar *Name,const wchar *NewExt);
+void SetSFXExt(char *SFXName);
+void SetSFXExt(wchar *SFXName);
+char *GetExt(const char *Name);
+wchar *GetExt(const wchar *Name);
+bool CmpExt(const char *Name,const char *Ext);
+bool IsWildcard(const char *Str,const wchar *StrW=NULL);
+bool IsPathDiv(int Ch);
+bool IsDriveDiv(int Ch);
+int GetPathDisk(const char *Path);
+void AddEndSlash(char *Path);
+void AddEndSlash(wchar *Path);
+void GetFilePath(const char *FullName,char *Path,int MaxLength);
+void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength);
+void RemoveNameFromPath(char *Path);
+void RemoveNameFromPath(wchar *Path);
+void GetAppDataPath(char *Path);
+bool EnumConfigPaths(char *Path,int Number);
+void GetConfigName(const char *Name,char *FullName,bool CheckExist);
+char* GetVolNumPart(char *ArcName);
+void NextVolumeName(char *ArcName,bool OldNumbering);
+bool IsNameUsable(const char *Name);
+void MakeNameUsable(char *Name,bool Extended);
+char* UnixSlashToDos(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
+char* DosSlashToUnix(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
+wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName=NULL,uint MaxLength=NM);
+bool IsFullPath(const char *Path);
+bool IsDiskLetter(const char *Path);
+void GetPathRoot(const char *Path,char *Root);
+int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate);
+char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering);
+wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW);
+
+
+inline char* GetOutputName(const char *Name) {return((char *)Name);};
+
+#endif
diff --git a/unrar/unrar/rar.cpp b/unrar/unrar/rar.cpp
new file mode 100644
index 0000000..a55fd55
--- /dev/null
+++ b/unrar/unrar/rar.cpp
@@ -0,0 +1,144 @@
+#include "rar.hpp"
+
+
+#include "smallfn.cpp"
+
+#ifdef _DJGPP
+extern "C" char **__crt0_glob_function (char *arg) { return 0; }
+extern "C" void __crt0_load_environment_file (char *progname) { }
+#endif
+
+#if !defined(GUI) && !defined(RARDLL)
+int main(int argc, char *argv[])
+{
+#ifdef _UNIX
+ setlocale(LC_ALL,"");
+#endif
+
+#if defined(_EMX) && !defined(_DJGPP)
+ uni_init(0);
+#endif
+
+#if !defined(_SFX_RTL_) && !defined(_WIN_32)
+ setbuf(stdout,NULL);
+#endif
+
+#if !defined(SFX_MODULE) && defined(_EMX)
+ EnumConfigPaths(argv[0],-1);
+#endif
+
+ ErrHandler.SetSignalHandlers(true);
+
+ RARInitData();
+
+#ifdef SFX_MODULE
+ char ModuleName[NM];
+#ifdef _WIN_32
+ GetModuleFileName(NULL,ModuleName,sizeof(ModuleName));
+#else
+ strcpy(ModuleName,argv[0]);
+#endif
+#endif
+
+#ifdef _WIN_32
+ SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+
+
+#endif
+
+#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
+ bool ShutdownOnClose;
+#endif
+
+#ifdef ALLOW_EXCEPTIONS
+ try
+#endif
+ {
+
+ CommandData Cmd;
+#ifdef SFX_MODULE
+ strcpy(Cmd.Command,"X");
+ char *Switch=NULL;
+#ifdef _SFX_RTL_
+ char *CmdLine=GetCommandLine();
+ if (CmdLine!=NULL && *CmdLine=='\"')
+ CmdLine=strchr(CmdLine+1,'\"');
+ if (CmdLine!=NULL && (CmdLine=strpbrk(CmdLine," /"))!=NULL)
+ {
+ while (isspace(*CmdLine))
+ CmdLine++;
+ Switch=CmdLine;
+ }
+#else
+ Switch=argc>1 ? argv[1]:NULL;
+#endif
+ if (Switch!=NULL && Cmd.IsSwitch(Switch[0]))
+ {
+ int UpperCmd=etoupper(Switch[1]);
+ switch(UpperCmd)
+ {
+ case 'T':
+ case 'V':
+ Cmd.Command[0]=UpperCmd;
+ break;
+ case '?':
+ Cmd.OutHelp();
+ break;
+ }
+ }
+ Cmd.AddArcName(ModuleName,NULL);
+#else
+ if (Cmd.IsConfigEnabled(argc,argv))
+ {
+ Cmd.ReadConfig(argc,argv);
+ Cmd.ParseEnvVar();
+ }
+ for (int I=1;I<argc;I++)
+ Cmd.ParseArg(argv[I],NULL);
+#endif
+ Cmd.ParseDone();
+
+#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
+ ShutdownOnClose=Cmd.Shutdown;
+#endif
+
+ InitConsoleOptions(Cmd.MsgStream,Cmd.Sound);
+ InitLogOptions(Cmd.LogName);
+ ErrHandler.SetSilent(Cmd.AllYes || Cmd.MsgStream==MSG_NULL);
+ ErrHandler.SetShutdown(Cmd.Shutdown);
+
+ Cmd.OutTitle();
+ Cmd.ProcessCommand();
+ }
+#ifdef ALLOW_EXCEPTIONS
+ catch (int ErrCode)
+ {
+ ErrHandler.SetErrorCode(ErrCode);
+ }
+#ifdef ENABLE_BAD_ALLOC
+ catch (bad_alloc)
+ {
+ ErrHandler.SetErrorCode(MEMORY_ERROR);
+ }
+#endif
+ catch (...)
+ {
+ ErrHandler.SetErrorCode(FATAL_ERROR);
+ }
+#endif
+ File::RemoveCreated();
+#if defined(SFX_MODULE) && defined(_DJGPP)
+ _chmod(ModuleName,1,0x20);
+#endif
+#if defined(_EMX) && !defined(_DJGPP)
+ uni_done();
+#endif
+#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
+ if (ShutdownOnClose)
+ Shutdown();
+#endif
+ return(ErrHandler.GetErrorCode());
+}
+#endif
+
+
diff --git a/unrar/unrar/rar.hpp b/unrar/unrar/rar.hpp
new file mode 100644
index 0000000..229ee09
--- /dev/null
+++ b/unrar/unrar/rar.hpp
@@ -0,0 +1,80 @@
+#ifndef _RAR_RARCOMMON_
+#define _RAR_RARCOMMON_
+
+#include "raros.hpp"
+#include "os.hpp"
+
+
+#ifdef RARDLL
+#include "dll.hpp"
+#endif
+
+#ifndef _WIN_CE
+#include "version.hpp"
+#endif
+#include "rartypes.hpp"
+#include "rardefs.hpp"
+#include "rarlang.hpp"
+#include "int64.hpp"
+#include "unicode.hpp"
+#include "errhnd.hpp"
+#include "array.hpp"
+#include "timefn.hpp"
+#include "options.hpp"
+#include "headers.hpp"
+#include "rarfn.hpp"
+#include "pathfn.hpp"
+#include "strfn.hpp"
+#include "strlist.hpp"
+#include "file.hpp"
+#include "sha1.hpp"
+#include "crc.hpp"
+#include "rijndael.hpp"
+#include "crypt.hpp"
+#include "filefn.hpp"
+#include "filestr.hpp"
+#include "find.hpp"
+#include "scantree.hpp"
+#include "savepos.hpp"
+#include "getbits.hpp"
+#include "rdwrfn.hpp"
+#include "archive.hpp"
+#include "match.hpp"
+#include "cmddata.hpp"
+#include "filcreat.hpp"
+#include "consio.hpp"
+#include "system.hpp"
+#include "isnt.hpp"
+#include "log.hpp"
+#include "rawread.hpp"
+#include "encname.hpp"
+#include "resource.hpp"
+#include "compress.hpp"
+
+
+#include "rarvm.hpp"
+#include "model.hpp"
+
+
+#include "unpack.hpp"
+
+
+#include "extinfo.hpp"
+#include "extract.hpp"
+
+
+
+#include "list.hpp"
+
+
+
+#include "rs.hpp"
+#include "recvol.hpp"
+#include "volume.hpp"
+#include "smallfn.hpp"
+#include "ulinks.hpp"
+
+#include "global.hpp"
+
+
+#endif
diff --git a/unrar/unrar/rardefs.hpp b/unrar/unrar/rardefs.hpp
new file mode 100644
index 0000000..24f97b5
--- /dev/null
+++ b/unrar/unrar/rardefs.hpp
@@ -0,0 +1,24 @@
+#ifndef _RAR_DEFS_
+#define _RAR_DEFS_
+
+#define Min(x,y) (((x)<(y)) ? (x):(y))
+#define Max(x,y) (((x)>(y)) ? (x):(y))
+
+#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
+
+#define MAXPASSWORD 128
+#define MAXSFXSIZE 0x80000
+
+#define DefSFXName "default.sfx"
+#define DefSortListName "rarfiles.lst"
+
+#ifndef FA_RDONLY
+ #define FA_RDONLY 0x01
+ #define FA_HIDDEN 0x02
+ #define FA_SYSTEM 0x04
+ #define FA_LABEL 0x08
+ #define FA_DIREC 0x10
+ #define FA_ARCH 0x20
+#endif
+
+#endif
diff --git a/unrar/unrar/rarfn.hpp b/unrar/unrar/rarfn.hpp
new file mode 100644
index 0000000..05ffdbc
--- /dev/null
+++ b/unrar/unrar/rarfn.hpp
@@ -0,0 +1,7 @@
+#ifndef _RAR_FN_
+#define _RAR_FN_
+
+void RARInitData();
+
+
+#endif
diff --git a/unrar/unrar/rarlang.hpp b/unrar/unrar/rarlang.hpp
new file mode 100644
index 0000000..6151d15
--- /dev/null
+++ b/unrar/unrar/rarlang.hpp
@@ -0,0 +1,10 @@
+#ifndef _RAR_LANG_
+#define _RAR_LANG_
+
+ #ifdef USE_RC
+ #include "rarres.hpp"
+ #else
+ #include "loclang.hpp"
+ #endif
+
+#endif
diff --git a/unrar/unrar/raros.hpp b/unrar/unrar/raros.hpp
new file mode 100644
index 0000000..e686798
--- /dev/null
+++ b/unrar/unrar/raros.hpp
@@ -0,0 +1,41 @@
+#ifndef _RAR_RAROS_
+#define _RAR_RAROS_
+
+#ifdef __EMX__
+ #define _EMX
+#endif
+
+#ifdef __DJGPP__
+ #define _DJGPP
+ #define _EMX
+#endif
+
+#if defined(__WIN32__) || defined(_WIN32)
+ #define _WIN_32
+#endif
+
+#ifdef _WIN32_WCE
+ #define _WIN_32
+ #define _WIN_CE
+ #ifdef WM_FILECHANGEINFO
+ #define PC2002
+ #else
+ #undef PC2002
+ #endif
+#endif
+
+#ifdef __BEOS__
+ #define _UNIX
+ #define _BEOS
+#endif
+
+#ifdef __APPLE__
+ #define _UNIX
+ #define _APPLE
+#endif
+
+#if !defined(_EMX) && !defined(_WIN_32) && !defined(_BEOS) && !defined(_APPLE)
+ #define _UNIX
+#endif
+
+#endif
diff --git a/unrar/unrar/rartypes.hpp b/unrar/unrar/rartypes.hpp
new file mode 100644
index 0000000..56fccf6
--- /dev/null
+++ b/unrar/unrar/rartypes.hpp
@@ -0,0 +1,21 @@
+#ifndef _RAR_TYPES_
+#define _RAR_TYPES_
+
+typedef unsigned char byte; //8 bits
+typedef unsigned short ushort; //preferably 16 bits, but can be more
+typedef unsigned int uint; //32 bits or more
+
+typedef unsigned int uint32; //32 bits exactly
+typedef int sint32; //signed 32 bits exactly
+#define PRESENT_INT32
+
+#if defined(_WIN_32) || defined(__GNUC__) || defined(__sgi) || defined(_AIX) || defined(__sun) || defined(__hpux) || defined(_OSF_SOURCE)
+typedef wchar_t wchar;
+#else
+typedef ushort wchar;
+#endif
+
+#define SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
+#define UINT32(x) (sizeof(uint32)==4 ? (uint32)(x):((x)&0xffffffff))
+
+#endif
diff --git a/unrar/unrar/rarvm.cpp b/unrar/unrar/rarvm.cpp
new file mode 100644
index 0000000..987e3ae
--- /dev/null
+++ b/unrar/unrar/rarvm.cpp
@@ -0,0 +1,1109 @@
+#include "rar.hpp"
+
+#include "rarvmtbl.cpp"
+
+RarVM::RarVM()
+{
+ Mem=NULL;
+}
+
+
+RarVM::~RarVM()
+{
+ delete[] Mem;
+}
+
+
+void RarVM::Init()
+{
+ if (Mem==NULL)
+ Mem=new byte[VM_MEMSIZE+4];
+}
+
+/*********************************************************************
+ IS_VM_MEM macro checks if address belongs to VM memory pool (Mem).
+ Only Mem data are always low endian regardless of machine architecture,
+ so we need to convert them to native format when reading or writing.
+ VM registers have endianness of host machine.
+**********************************************************************/
+#define IS_VM_MEM(a) (((byte*)a)>=Mem && ((byte*)a)<Mem+VM_MEMSIZE)
+
+inline uint RarVM::GetValue(bool ByteMode,uint *Addr)
+{
+ if (ByteMode)
+ {
+#ifdef BIG_ENDIAN
+ if (IS_VM_MEM(Addr))
+ return(*(byte *)Addr);
+ else
+ return(*Addr & 0xff);
+#else
+ return(*(byte *)Addr);
+#endif
+ }
+ else
+ {
+#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
+ if (IS_VM_MEM(Addr))
+ {
+ byte *B=(byte *)Addr;
+ return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
+ }
+ else
+ return UINT32(*Addr);
+#else
+ return UINT32(*Addr);
+#endif
+ }
+}
+
+#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
+ #define GET_VALUE(ByteMode,Addr) GetValue(ByteMode,(uint *)Addr)
+#else
+ #define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):UINT32(*(uint *)(Addr)))
+#endif
+
+
+inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value)
+{
+ if (ByteMode)
+ {
+#ifdef BIG_ENDIAN
+ if (IS_VM_MEM(Addr))
+ *(byte *)Addr=Value;
+ else
+ *Addr=(*Addr & ~0xff)|(Value & 0xff);
+#else
+ *(byte *)Addr=Value;
+#endif
+ }
+ else
+ {
+#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
+ if (IS_VM_MEM(Addr))
+ {
+ ((byte *)Addr)[0]=(byte)Value;
+ ((byte *)Addr)[1]=(byte)(Value>>8);
+ ((byte *)Addr)[2]=(byte)(Value>>16);
+ ((byte *)Addr)[3]=(byte)(Value>>24);
+ }
+ else
+ *(uint *)Addr=Value;
+#else
+ *(uint32 *)Addr=Value;
+#endif
+ }
+}
+
+#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
+ #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint *)Addr,Value)
+#else
+ #define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=(Value)):(*(uint32 *)(Addr)=((uint32)(Value))))
+#endif
+
+
+void RarVM::SetLowEndianValue(uint *Addr,uint Value)
+{
+#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
+ ((byte *)Addr)[0]=(byte)Value;
+ ((byte *)Addr)[1]=(byte)(Value>>8);
+ ((byte *)Addr)[2]=(byte)(Value>>16);
+ ((byte *)Addr)[3]=(byte)(Value>>24);
+#else
+ *(uint32 *)Addr=Value;
+#endif
+}
+
+
+inline uint* RarVM::GetOperand(VM_PreparedOperand *CmdOp)
+{
+ if (CmdOp->Type==VM_OPREGMEM)
+ return((uint *)&Mem[(*CmdOp->Addr+CmdOp->Base)&VM_MEMMASK]);
+ else
+ return(CmdOp->Addr);
+}
+
+
+void RarVM::Execute(VM_PreparedProgram *Prg)
+{
+ memcpy(R,Prg->InitR,sizeof(Prg->InitR));
+ unsigned int GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE);
+ if (GlobalSize)
+ memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize);
+ unsigned int StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize);
+ if (StaticSize)
+ memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize);
+
+ R[7]=VM_MEMSIZE;
+ Flags=0;
+
+ VM_PreparedCommand *PreparedCode=Prg->AltCmd ? Prg->AltCmd:&Prg->Cmd[0];
+ if (!ExecuteCode(PreparedCode,Prg->CmdCount))
+ PreparedCode[0].OpCode=VM_RET;
+ uint NewBlockPos=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20])&VM_MEMMASK;
+ uint NewBlockSize=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c])&VM_MEMMASK;
+ if (NewBlockPos+NewBlockSize>=VM_MEMSIZE)
+ NewBlockPos=NewBlockSize=0;
+ Prg->FilteredData=Mem+NewBlockPos;
+ Prg->FilteredDataSize=NewBlockSize;
+
+ Prg->GlobalData.Reset();
+
+ uint DataSize=Min(GET_VALUE(false,(uint*)&Mem[VM_GLOBALMEMADDR+0x30]),VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE);
+ if (DataSize!=0)
+ {
+ Prg->GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE);
+ memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE);
+ }
+}
+
+
+/*
+Note:
+ Due to performance considerations RAR VM may set VM_FS, VM_FC, VM_FZ
+ incorrectly for byte operands. These flags are always valid only
+ for 32-bit operands. Check implementation of concrete VM command
+ to see if it sets flags right.
+*/
+
+#define SET_IP(IP) \
+ if ((IP)>=CodeSize) \
+ return(true); \
+ if (--MaxOpCount<=0) \
+ return(false); \
+ Cmd=PreparedCode+(IP);
+
+bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
+{
+ int MaxOpCount=25000000;
+ VM_PreparedCommand *Cmd=PreparedCode;
+ while (1)
+ {
+#ifndef NORARVM
+ uint *Op1=GetOperand(&Cmd->Op1);
+ uint *Op2=GetOperand(&Cmd->Op2);
+#endif
+ switch(Cmd->OpCode)
+ {
+#ifndef NORARVM
+ case VM_MOV:
+ SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2));
+ break;
+#ifdef VM_OPTIMIZE
+ case VM_MOVB:
+ SET_VALUE(true,Op1,GET_VALUE(true,Op2));
+ break;
+ case VM_MOVD:
+ SET_VALUE(false,Op1,GET_VALUE(false,Op2));
+ break;
+#endif
+ case VM_CMP:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
+ Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
+ }
+ break;
+#ifdef VM_OPTIMIZE
+ case VM_CMPB:
+ {
+ uint Value1=GET_VALUE(true,Op1);
+ uint Result=UINT32(Value1-GET_VALUE(true,Op2));
+ Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
+ }
+ break;
+ case VM_CMPD:
+ {
+ uint Value1=GET_VALUE(false,Op1);
+ uint Result=UINT32(Value1-GET_VALUE(false,Op2));
+ Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
+ }
+ break;
+#endif
+ case VM_ADD:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
+ if (Cmd->ByteMode)
+ {
+ Result&=0xff;
+ Flags=(Result<Value1)|(Result==0 ? VM_FZ:((Result&0x80) ? VM_FS:0));
+ }
+ else
+ Flags=(Result<Value1)|(Result==0 ? VM_FZ:(Result&VM_FS));
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+#ifdef VM_OPTIMIZE
+ case VM_ADDB:
+ SET_VALUE(true,Op1,GET_VALUE(true,Op1)+GET_VALUE(true,Op2));
+ break;
+ case VM_ADDD:
+ SET_VALUE(false,Op1,GET_VALUE(false,Op1)+GET_VALUE(false,Op2));
+ break;
+#endif
+ case VM_SUB:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
+ Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+#ifdef VM_OPTIMIZE
+ case VM_SUBB:
+ SET_VALUE(true,Op1,GET_VALUE(true,Op1)-GET_VALUE(true,Op2));
+ break;
+ case VM_SUBD:
+ SET_VALUE(false,Op1,GET_VALUE(false,Op1)-GET_VALUE(false,Op2));
+ break;
+#endif
+ case VM_JZ:
+ if ((Flags & VM_FZ)!=0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_JNZ:
+ if ((Flags & VM_FZ)==0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_INC:
+ {
+ uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
+ if (Cmd->ByteMode)
+ Result&=0xff;
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ Flags=Result==0 ? VM_FZ:Result&VM_FS;
+ }
+ break;
+#ifdef VM_OPTIMIZE
+ case VM_INCB:
+ SET_VALUE(true,Op1,GET_VALUE(true,Op1)+1);
+ break;
+ case VM_INCD:
+ SET_VALUE(false,Op1,GET_VALUE(false,Op1)+1);
+ break;
+#endif
+ case VM_DEC:
+ {
+ uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1);
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ Flags=Result==0 ? VM_FZ:Result&VM_FS;
+ }
+ break;
+#ifdef VM_OPTIMIZE
+ case VM_DECB:
+ SET_VALUE(true,Op1,GET_VALUE(true,Op1)-1);
+ break;
+ case VM_DECD:
+ SET_VALUE(false,Op1,GET_VALUE(false,Op1)-1);
+ break;
+#endif
+ case VM_JMP:
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ case VM_XOR:
+ {
+ uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2));
+ Flags=Result==0 ? VM_FZ:Result&VM_FS;
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_AND:
+ {
+ uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
+ Flags=Result==0 ? VM_FZ:Result&VM_FS;
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_OR:
+ {
+ uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2));
+ Flags=Result==0 ? VM_FZ:Result&VM_FS;
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_TEST:
+ {
+ uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
+ Flags=Result==0 ? VM_FZ:Result&VM_FS;
+ }
+ break;
+ case VM_JS:
+ if ((Flags & VM_FS)!=0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_JNS:
+ if ((Flags & VM_FS)==0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_JB:
+ if ((Flags & VM_FC)!=0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_JBE:
+ if ((Flags & (VM_FC|VM_FZ))!=0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_JA:
+ if ((Flags & (VM_FC|VM_FZ))==0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_JAE:
+ if ((Flags & VM_FC)==0)
+ {
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ }
+ break;
+ case VM_PUSH:
+ R[7]-=4;
+ SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],GET_VALUE(false,Op1));
+ break;
+ case VM_POP:
+ SET_VALUE(false,Op1,GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK]));
+ R[7]+=4;
+ break;
+ case VM_CALL:
+ R[7]-=4;
+ SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Cmd-PreparedCode+1);
+ SET_IP(GET_VALUE(false,Op1));
+ continue;
+ case VM_NOT:
+ SET_VALUE(Cmd->ByteMode,Op1,~GET_VALUE(Cmd->ByteMode,Op1));
+ break;
+ case VM_SHL:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
+ uint Result=UINT32(Value1<<Value2);
+ Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1<<(Value2-1))&0x80000000 ? VM_FC:0);
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_SHR:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
+ uint Result=UINT32(Value1>>Value2);
+ Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_SAR:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
+ uint Result=UINT32(((int)Value1)>>Value2);
+ Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_NEG:
+ {
+ uint Result=UINT32(-GET_VALUE(Cmd->ByteMode,Op1));
+ Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS);
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+#ifdef VM_OPTIMIZE
+ case VM_NEGB:
+ SET_VALUE(true,Op1,-GET_VALUE(true,Op1));
+ break;
+ case VM_NEGD:
+ SET_VALUE(false,Op1,-GET_VALUE(false,Op1));
+ break;
+#endif
+ case VM_PUSHA:
+ {
+ const int RegCount=sizeof(R)/sizeof(R[0]);
+ for (int I=0,SP=R[7]-4;I<RegCount;I++,SP-=4)
+ SET_VALUE(false,(uint *)&Mem[SP & VM_MEMMASK],R[I]);
+ R[7]-=RegCount*4;
+ }
+ break;
+ case VM_POPA:
+ {
+ const int RegCount=sizeof(R)/sizeof(R[0]);
+ for (uint I=0,SP=R[7];I<RegCount;I++,SP+=4)
+ R[7-I]=GET_VALUE(false,(uint *)&Mem[SP & VM_MEMMASK]);
+ }
+ break;
+ case VM_PUSHF:
+ R[7]-=4;
+ SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Flags);
+ break;
+ case VM_POPF:
+ Flags=GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK]);
+ R[7]+=4;
+ break;
+ case VM_MOVZX:
+ SET_VALUE(false,Op1,GET_VALUE(true,Op2));
+ break;
+ case VM_MOVSX:
+ SET_VALUE(false,Op1,(signed char)GET_VALUE(true,Op2));
+ break;
+ case VM_XCHG:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2));
+ SET_VALUE(Cmd->ByteMode,Op2,Value1);
+ }
+ break;
+ case VM_MUL:
+ {
+ uint Result=GET_VALUE(Cmd->ByteMode,Op1)*GET_VALUE(Cmd->ByteMode,Op2);
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_DIV:
+ {
+ uint Divider=GET_VALUE(Cmd->ByteMode,Op2);
+ if (Divider!=0)
+ {
+ uint Result=GET_VALUE(Cmd->ByteMode,Op1)/Divider;
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ }
+ break;
+ case VM_ADC:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint FC=(Flags&VM_FC);
+ uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
+ if (Cmd->ByteMode)
+ Result&=0xff;
+ Flags=(Result<Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+ case VM_SBB:
+ {
+ uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
+ uint FC=(Flags&VM_FC);
+ uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
+ if (Cmd->ByteMode)
+ Result&=0xff;
+ Flags=(Result>Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
+ SET_VALUE(Cmd->ByteMode,Op1,Result);
+ }
+ break;
+#endif // for #ifndef NORARVM
+ case VM_RET:
+ if (R[7]>=VM_MEMSIZE)
+ return(true);
+ SET_IP(GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK]));
+ R[7]+=4;
+ continue;
+#ifdef VM_STANDARDFILTERS
+ case VM_STANDARD:
+ ExecuteStandardFilter((VM_StandardFilters)Cmd->Op1.Data);
+ break;
+#endif
+ case VM_PRINT:
+ break;
+ }
+ Cmd++;
+ --MaxOpCount;
+ }
+}
+
+
+
+
+void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
+{
+ InitBitInput();
+ memcpy(InBuf,Code,Min(CodeSize,BitInput::MAX_SIZE));
+
+ byte XorSum=0;
+ for (int I=1;I<CodeSize;I++)
+ XorSum^=Code[I];
+
+ faddbits(8);
+
+ Prg->CmdCount=0;
+ if (XorSum==Code[0])
+ {
+#ifdef VM_STANDARDFILTERS
+ VM_StandardFilters FilterType=IsStandardFilter(Code,CodeSize);
+ if (FilterType!=VMSF_NONE)
+ {
+ Prg->Cmd.Add(1);
+ VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++];
+ CurCmd->OpCode=VM_STANDARD;
+ CurCmd->Op1.Data=FilterType;
+ CurCmd->Op1.Addr=&CurCmd->Op1.Data;
+ CurCmd->Op2.Addr=&CurCmd->Op2.Data;
+ CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE;
+ CodeSize=0;
+ }
+#endif
+ uint DataFlag=fgetbits();
+ faddbits(1);
+
+/* Read static data contained in DB operators. This data cannot be changed,
+ it is a part of VM code, not a filter parameter.
+*/
+ if (DataFlag&0x8000)
+ {
+ int DataSize=ReadData(*this)+1;
+ for (int I=0;InAddr<CodeSize && I<DataSize;I++)
+ {
+ Prg->StaticData.Add(1);
+ Prg->StaticData[I]=fgetbits()>>8;
+ faddbits(8);
+ }
+ }
+
+ while (InAddr<CodeSize)
+ {
+ Prg->Cmd.Add(1);
+ VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount];
+ uint Data=fgetbits();
+ if ((Data&0x8000)==0)
+ {
+ CurCmd->OpCode=(VM_Commands)(Data>>12);
+ faddbits(4);
+ }
+ else
+ {
+ CurCmd->OpCode=(VM_Commands)((Data>>10)-24);
+ faddbits(6);
+ }
+ if (VM_CmdFlags[CurCmd->OpCode] & VMCF_BYTEMODE)
+ {
+ CurCmd->ByteMode=fgetbits()>>15;
+ faddbits(1);
+ }
+ else
+ CurCmd->ByteMode=0;
+ CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE;
+ int OpNum=(VM_CmdFlags[CurCmd->OpCode] & VMCF_OPMASK);
+ CurCmd->Op1.Addr=CurCmd->Op2.Addr=NULL;
+ if (OpNum>0)
+ {
+ DecodeArg(CurCmd->Op1,CurCmd->ByteMode);
+ if (OpNum==2)
+ DecodeArg(CurCmd->Op2,CurCmd->ByteMode);
+ else
+ {
+ if (CurCmd->Op1.Type==VM_OPINT && (VM_CmdFlags[CurCmd->OpCode]&(VMCF_JUMP|VMCF_PROC)))
+ {
+ int Distance=CurCmd->Op1.Data;
+ if (Distance>=256)
+ Distance-=256;
+ else
+ {
+ if (Distance>=136)
+ Distance-=264;
+ else
+ if (Distance>=16)
+ Distance-=8;
+ else
+ if (Distance>=8)
+ Distance-=16;
+ Distance+=Prg->CmdCount;
+ }
+ CurCmd->Op1.Data=Distance;
+ }
+ }
+ }
+ Prg->CmdCount++;
+ }
+ }
+ Prg->Cmd.Add(1);
+ VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++];
+ CurCmd->OpCode=VM_RET;
+ CurCmd->Op1.Addr=&CurCmd->Op1.Data;
+ CurCmd->Op2.Addr=&CurCmd->Op2.Data;
+ CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE;
+
+ for (int I=0;I<Prg->CmdCount;I++)
+ {
+ VM_PreparedCommand *Cmd=&Prg->Cmd[I];
+ if (Cmd->Op1.Addr==NULL)
+ Cmd->Op1.Addr=&Cmd->Op1.Data;
+ if (Cmd->Op2.Addr==NULL)
+ Cmd->Op2.Addr=&Cmd->Op2.Data;
+ }
+
+#ifdef VM_OPTIMIZE
+ if (CodeSize!=0)
+ Optimize(Prg);
+#endif
+}
+
+
+void RarVM::DecodeArg(VM_PreparedOperand &Op,bool ByteMode)
+{
+ uint Data=fgetbits();
+ if (Data & 0x8000)
+ {
+ Op.Type=VM_OPREG;
+ Op.Data=(Data>>12)&7;
+ Op.Addr=&R[Op.Data];
+ faddbits(4);
+ }
+ else
+ if ((Data & 0xc000)==0)
+ {
+ Op.Type=VM_OPINT;
+ if (ByteMode)
+ {
+ Op.Data=(Data>>6) & 0xff;
+ faddbits(10);
+ }
+ else
+ {
+ faddbits(2);
+ Op.Data=ReadData(*this);
+ }
+ }
+ else
+ {
+ Op.Type=VM_OPREGMEM;
+ if ((Data & 0x2000)==0)
+ {
+ Op.Data=(Data>>10)&7;
+ Op.Addr=&R[Op.Data];
+ Op.Base=0;
+ faddbits(6);
+ }
+ else
+ {
+ if ((Data & 0x1000)==0)
+ {
+ Op.Data=(Data>>9)&7;
+ Op.Addr=&R[Op.Data];
+ faddbits(7);
+ }
+ else
+ {
+ Op.Data=0;
+ faddbits(4);
+ }
+ Op.Base=ReadData(*this);
+ }
+ }
+}
+
+
+uint RarVM::ReadData(BitInput &Inp)
+{
+ uint Data=Inp.fgetbits();
+ switch(Data&0xc000)
+ {
+ case 0:
+ Inp.faddbits(6);
+ return((Data>>10)&0xf);
+ case 0x4000:
+ if ((Data&0x3c00)==0)
+ {
+ Data=0xffffff00|((Data>>2)&0xff);
+ Inp.faddbits(14);
+ }
+ else
+ {
+ Data=(Data>>6)&0xff;
+ Inp.faddbits(10);
+ }
+ return(Data);
+ case 0x8000:
+ Inp.faddbits(2);
+ Data=Inp.fgetbits();
+ Inp.faddbits(16);
+ return(Data);
+ default:
+ Inp.faddbits(2);
+ Data=(Inp.fgetbits()<<16);
+ Inp.faddbits(16);
+ Data|=Inp.fgetbits();
+ Inp.faddbits(16);
+ return(Data);
+ }
+}
+
+
+void RarVM::SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize)
+{
+ if (Pos<VM_MEMSIZE && Data!=Mem+Pos)
+ memmove(Mem+Pos,Data,Min(DataSize,VM_MEMSIZE-Pos));
+}
+
+
+#ifdef VM_OPTIMIZE
+void RarVM::Optimize(VM_PreparedProgram *Prg)
+{
+ VM_PreparedCommand *Code=&Prg->Cmd[0];
+ int CodeSize=Prg->CmdCount;
+
+ for (int I=0;I<CodeSize;I++)
+ {
+ VM_PreparedCommand *Cmd=Code+I;
+ switch(Cmd->OpCode)
+ {
+ case VM_MOV:
+ Cmd->OpCode=Cmd->ByteMode ? VM_MOVB:VM_MOVD;
+ continue;
+ case VM_CMP:
+ Cmd->OpCode=Cmd->ByteMode ? VM_CMPB:VM_CMPD;
+ continue;
+ }
+ if ((VM_CmdFlags[Cmd->OpCode] & VMCF_CHFLAGS)==0)
+ continue;
+ bool FlagsRequired=false;
+ for (int J=I+1;J<CodeSize;J++)
+ {
+ int Flags=VM_CmdFlags[Code[J].OpCode];
+ if (Flags & (VMCF_JUMP|VMCF_PROC|VMCF_USEFLAGS))
+ {
+ FlagsRequired=true;
+ break;
+ }
+ if (Flags & VMCF_CHFLAGS)
+ break;
+ }
+ if (FlagsRequired)
+ continue;
+ switch(Cmd->OpCode)
+ {
+ case VM_ADD:
+ Cmd->OpCode=Cmd->ByteMode ? VM_ADDB:VM_ADDD;
+ continue;
+ case VM_SUB:
+ Cmd->OpCode=Cmd->ByteMode ? VM_SUBB:VM_SUBD;
+ continue;
+ case VM_INC:
+ Cmd->OpCode=Cmd->ByteMode ? VM_INCB:VM_INCD;
+ continue;
+ case VM_DEC:
+ Cmd->OpCode=Cmd->ByteMode ? VM_DECB:VM_DECD;
+ continue;
+ case VM_NEG:
+ Cmd->OpCode=Cmd->ByteMode ? VM_NEGB:VM_NEGD;
+ continue;
+ }
+ }
+}
+#endif
+
+
+#ifdef VM_STANDARDFILTERS
+VM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize)
+{
+ struct StandardFilterSignature
+ {
+ int Length;
+ uint CRC;
+ VM_StandardFilters Type;
+ } StdList[]={
+ 53, 0xad576887, VMSF_E8,
+ 57, 0x3cd7e57e, VMSF_E8E9,
+ 120, 0x3769893f, VMSF_ITANIUM,
+ 29, 0x0e06077d, VMSF_DELTA,
+ 149, 0x1c2c5dc8, VMSF_RGB,
+ 216, 0xbc85e701, VMSF_AUDIO,
+ 40, 0x46b9c560, VMSF_UPCASE
+ };
+ uint CodeCRC=CRC(0xffffffff,Code,CodeSize)^0xffffffff;
+ for (int I=0;I<sizeof(StdList)/sizeof(StdList[0]);I++)
+ if (StdList[I].CRC==CodeCRC && StdList[I].Length==CodeSize)
+ return(StdList[I].Type);
+ return(VMSF_NONE);
+}
+
+
+void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
+{
+ switch(FilterType)
+ {
+ case VMSF_E8:
+ case VMSF_E8E9:
+ {
+ byte *Data=Mem;
+ int DataSize=R[4];
+ uint FileOffset=R[6];
+
+ if (DataSize>=VM_GLOBALMEMADDR || DataSize<4)
+ break;
+
+ const int FileSize=0x1000000;
+ byte CmpByte2=FilterType==VMSF_E8E9 ? 0xe9:0xe8;
+ for (int CurPos=0;CurPos<DataSize-4;)
+ {
+ byte CurByte=*(Data++);
+ CurPos++;
+ if (CurByte==0xe8 || CurByte==CmpByte2)
+ {
+#ifdef PRESENT_INT32
+ sint32 Offset=CurPos+FileOffset;
+ sint32 Addr=GET_VALUE(false,Data);
+ if (Addr<0)
+ {
+ if (Addr+Offset>=0)
+ SET_VALUE(false,Data,Addr+FileSize);
+ }
+ else
+ if (Addr<FileSize)
+ SET_VALUE(false,Data,Addr-Offset);
+#else
+ long Offset=CurPos+FileOffset;
+ long Addr=GET_VALUE(false,Data);
+ if ((Addr & 0x80000000)!=0)
+ {
+ if (((Addr+Offset) & 0x80000000)==0)
+ SET_VALUE(false,Data,Addr+FileSize);
+ }
+ else
+ if (((Addr-FileSize) & 0x80000000)!=0)
+ SET_VALUE(false,Data,Addr-Offset);
+#endif
+ Data+=4;
+ CurPos+=4;
+ }
+ }
+ }
+ break;
+ case VMSF_ITANIUM:
+ {
+ byte *Data=Mem;
+ int DataSize=R[4];
+ uint FileOffset=R[6];
+
+ if (DataSize>=VM_GLOBALMEMADDR || DataSize<21)
+ break;
+
+ int CurPos=0;
+
+ FileOffset>>=4;
+
+ while (CurPos<DataSize-21)
+ {
+ int Byte=(Data[0]&0x1f)-0x10;
+ if (Byte>=0)
+ {
+ static byte Masks[16]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
+ byte CmdMask=Masks[Byte];
+ if (CmdMask!=0)
+ for (int I=0;I<=2;I++)
+ if (CmdMask & (1<<I))
+ {
+ int StartPos=I*41+5;
+ int OpType=FilterItanium_GetBits(Data,StartPos+37,4);
+ if (OpType==5)
+ {
+ int Offset=FilterItanium_GetBits(Data,StartPos+13,20);
+ FilterItanium_SetBits(Data,(Offset-FileOffset)&0xfffff,StartPos+13,20);
+ }
+ }
+ }
+ Data+=16;
+ CurPos+=16;
+ FileOffset++;
+ }
+ }
+ break;
+ case VMSF_DELTA:
+ {
+ int DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
+ SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
+ if (DataSize>=VM_GLOBALMEMADDR/2)
+ break;
+
+// bytes from same channels are grouped to continual data blocks,
+// so we need to place them back to their interleaving positions
+
+ for (int CurChannel=0;CurChannel<Channels;CurChannel++)
+ {
+ byte PrevByte=0;
+ for (int DestPos=DataSize+CurChannel;DestPos<Border;DestPos+=Channels)
+ Mem[DestPos]=(PrevByte-=Mem[SrcPos++]);
+ }
+ }
+ break;
+ case VMSF_RGB:
+ {
+ int DataSize=R[4],Width=R[0]-3,PosR=R[1];
+ byte *SrcData=Mem,*DestData=SrcData+DataSize;
+ const int Channels=3;
+ SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
+ if (DataSize>=VM_GLOBALMEMADDR/2 || PosR<0)
+ break;
+ for (int CurChannel=0;CurChannel<Channels;CurChannel++)
+ {
+ unsigned int PrevByte=0;
+
+ for (int I=CurChannel;I<DataSize;I+=Channels)
+ {
+ unsigned int Predicted;
+ int UpperPos=I-Width;
+ if (UpperPos>=3)
+ {
+ byte *UpperData=DestData+UpperPos;
+ unsigned int UpperByte=*UpperData;
+ unsigned int UpperLeftByte=*(UpperData-3);
+ Predicted=PrevByte+UpperByte-UpperLeftByte;
+ int pa=abs((int)(Predicted-PrevByte));
+ int pb=abs((int)(Predicted-UpperByte));
+ int pc=abs((int)(Predicted-UpperLeftByte));
+ if (pa<=pb && pa<=pc)
+ Predicted=PrevByte;
+ else
+ if (pb<=pc)
+ Predicted=UpperByte;
+ else
+ Predicted=UpperLeftByte;
+ }
+ else
+ Predicted=PrevByte;
+ DestData[I]=PrevByte=(byte)(Predicted-*(SrcData++));
+ }
+ }
+ for (int I=PosR,Border=DataSize-2;I<Border;I+=3)
+ {
+ byte G=DestData[I+1];
+ DestData[I]+=G;
+ DestData[I+2]+=G;
+ }
+ }
+ break;
+ case VMSF_AUDIO:
+ {
+ int DataSize=R[4],Channels=R[0];
+ byte *SrcData=Mem,*DestData=SrcData+DataSize;
+ SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
+ if (DataSize>=VM_GLOBALMEMADDR/2)
+ break;
+ for (int CurChannel=0;CurChannel<Channels;CurChannel++)
+ {
+ unsigned int PrevByte=0,PrevDelta=0,Dif[7];
+ int D1=0,D2=0,D3;
+ int K1=0,K2=0,K3=0;
+ memset(Dif,0,sizeof(Dif));
+
+ for (int I=CurChannel,ByteCount=0;I<DataSize;I+=Channels,ByteCount++)
+ {
+ D3=D2;
+ D2=PrevDelta-D1;
+ D1=PrevDelta;
+
+ unsigned int Predicted=8*PrevByte+K1*D1+K2*D2+K3*D3;
+ Predicted=(Predicted>>3) & 0xff;
+
+ unsigned int CurByte=*(SrcData++);
+
+ Predicted-=CurByte;
+ DestData[I]=Predicted;
+ PrevDelta=(signed char)(Predicted-PrevByte);
+ PrevByte=Predicted;
+
+ int D=((signed char)CurByte)<<3;
+
+ Dif[0]+=abs(D);
+ Dif[1]+=abs(D-D1);
+ Dif[2]+=abs(D+D1);
+ Dif[3]+=abs(D-D2);
+ Dif[4]+=abs(D+D2);
+ Dif[5]+=abs(D-D3);
+ Dif[6]+=abs(D+D3);
+
+ if ((ByteCount & 0x1f)==0)
+ {
+ unsigned int MinDif=Dif[0],NumMinDif=0;
+ Dif[0]=0;
+ for (int J=1;J<sizeof(Dif)/sizeof(Dif[0]);J++)
+ {
+ if (Dif[J]<MinDif)
+ {
+ MinDif=Dif[J];
+ NumMinDif=J;
+ }
+ Dif[J]=0;
+ }
+ switch(NumMinDif)
+ {
+ case 1: if (K1>=-16) K1--; break;
+ case 2: if (K1 < 16) K1++; break;
+ case 3: if (K2>=-16) K2--; break;
+ case 4: if (K2 < 16) K2++; break;
+ case 5: if (K3>=-16) K3--; break;
+ case 6: if (K3 < 16) K3++; break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case VMSF_UPCASE:
+ {
+ int DataSize=R[4],SrcPos=0,DestPos=DataSize;
+ if (DataSize>=VM_GLOBALMEMADDR/2)
+ break;
+ while (SrcPos<DataSize)
+ {
+ byte CurByte=Mem[SrcPos++];
+ if (CurByte==2 && (CurByte=Mem[SrcPos++])!=2)
+ CurByte-=32;
+ Mem[DestPos++]=CurByte;
+ }
+ SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c],DestPos-DataSize);
+ SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
+ }
+ break;
+ }
+}
+
+
+unsigned int RarVM::FilterItanium_GetBits(byte *Data,int BitPos,int BitCount)
+{
+ int InAddr=BitPos/8;
+ int InBit=BitPos&7;
+ unsigned int BitField=(uint)Data[InAddr++];
+ BitField|=(uint)Data[InAddr++] << 8;
+ BitField|=(uint)Data[InAddr++] << 16;
+ BitField|=(uint)Data[InAddr] << 24;
+ BitField >>= InBit;
+ return(BitField & (0xffffffff>>(32-BitCount)));
+}
+
+
+void RarVM::FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos,
+ int BitCount)
+{
+ int InAddr=BitPos/8;
+ int InBit=BitPos&7;
+ unsigned int AndMask=0xffffffff>>(32-BitCount);
+ AndMask=~(AndMask<<InBit);
+
+ BitField<<=InBit;
+
+ for (int I=0;I<4;I++)
+ {
+ Data[InAddr+I]&=AndMask;
+ Data[InAddr+I]|=BitField;
+ AndMask=(AndMask>>8)|0xff000000;
+ BitField>>=8;
+ }
+}
+#endif
diff --git a/unrar/unrar/rarvm.hpp b/unrar/unrar/rarvm.hpp
new file mode 100644
index 0000000..0a6ff8a
--- /dev/null
+++ b/unrar/unrar/rarvm.hpp
@@ -0,0 +1,109 @@
+#ifndef _RAR_VM_
+#define _RAR_VM_
+
+#define VM_STANDARDFILTERS
+
+#ifndef SFX_MODULE
+#define VM_OPTIMIZE
+#endif
+
+
+#define VM_MEMSIZE 0x40000
+#define VM_MEMMASK (VM_MEMSIZE-1)
+#define VM_GLOBALMEMADDR 0x3C000
+#define VM_GLOBALMEMSIZE 0x2000
+#define VM_FIXEDGLOBALSIZE 64
+
+enum VM_Commands
+{
+ VM_MOV, VM_CMP, VM_ADD, VM_SUB, VM_JZ, VM_JNZ, VM_INC, VM_DEC,
+ VM_JMP, VM_XOR, VM_AND, VM_OR, VM_TEST, VM_JS, VM_JNS, VM_JB,
+ VM_JBE, VM_JA, VM_JAE, VM_PUSH, VM_POP, VM_CALL, VM_RET, VM_NOT,
+ VM_SHL, VM_SHR, VM_SAR, VM_NEG, VM_PUSHA,VM_POPA, VM_PUSHF,VM_POPF,
+ VM_MOVZX,VM_MOVSX,VM_XCHG, VM_MUL, VM_DIV, VM_ADC, VM_SBB, VM_PRINT,
+
+#ifdef VM_OPTIMIZE
+ VM_MOVB, VM_MOVD, VM_CMPB, VM_CMPD,
+
+ VM_ADDB, VM_ADDD, VM_SUBB, VM_SUBD, VM_INCB, VM_INCD, VM_DECB, VM_DECD,
+ VM_NEGB, VM_NEGD,
+#endif
+
+ VM_STANDARD
+};
+
+enum VM_StandardFilters {
+ VMSF_NONE, VMSF_E8, VMSF_E8E9, VMSF_ITANIUM, VMSF_RGB, VMSF_AUDIO,
+ VMSF_DELTA, VMSF_UPCASE
+};
+
+enum VM_Flags {VM_FC=1,VM_FZ=2,VM_FS=0x80000000};
+
+enum VM_OpType {VM_OPREG,VM_OPINT,VM_OPREGMEM,VM_OPNONE};
+
+struct VM_PreparedOperand
+{
+ VM_OpType Type;
+ uint Data;
+ uint Base;
+ uint *Addr;
+};
+
+struct VM_PreparedCommand
+{
+ VM_Commands OpCode;
+ bool ByteMode;
+ VM_PreparedOperand Op1,Op2;
+};
+
+
+struct VM_PreparedProgram
+{
+ VM_PreparedProgram() {AltCmd=NULL;}
+
+ Array<VM_PreparedCommand> Cmd;
+ VM_PreparedCommand *AltCmd;
+ int CmdCount;
+
+ Array<byte> GlobalData;
+ Array<byte> StaticData; // static data contained in DB operators
+ uint InitR[7];
+
+ byte *FilteredData;
+ unsigned int FilteredDataSize;
+};
+
+class RarVM:private BitInput
+{
+ private:
+ inline uint GetValue(bool ByteMode,uint *Addr);
+ inline void SetValue(bool ByteMode,uint *Addr,uint Value);
+ inline uint* GetOperand(VM_PreparedOperand *CmdOp);
+ void DecodeArg(VM_PreparedOperand &Op,bool ByteMode);
+#ifdef VM_OPTIMIZE
+ void Optimize(VM_PreparedProgram *Prg);
+#endif
+ bool ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize);
+#ifdef VM_STANDARDFILTERS
+ VM_StandardFilters IsStandardFilter(byte *Code,int CodeSize);
+ void ExecuteStandardFilter(VM_StandardFilters FilterType);
+ unsigned int FilterItanium_GetBits(byte *Data,int BitPos,int BitCount);
+ void FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos,
+ int BitCount);
+#endif
+
+ byte *Mem;
+ uint R[8];
+ uint Flags;
+ public:
+ RarVM();
+ ~RarVM();
+ void Init();
+ void Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg);
+ void Execute(VM_PreparedProgram *Prg);
+ void SetLowEndianValue(uint *Addr,uint Value);
+ void SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize);
+ static uint ReadData(BitInput &Inp);
+};
+
+#endif
diff --git a/unrar/unrar/rarvmtbl.cpp b/unrar/unrar/rarvmtbl.cpp
new file mode 100644
index 0000000..b5e6c72
--- /dev/null
+++ b/unrar/unrar/rarvmtbl.cpp
@@ -0,0 +1,53 @@
+#define VMCF_OP0 0
+#define VMCF_OP1 1
+#define VMCF_OP2 2
+#define VMCF_OPMASK 3
+#define VMCF_BYTEMODE 4
+#define VMCF_JUMP 8
+#define VMCF_PROC 16
+#define VMCF_USEFLAGS 32
+#define VMCF_CHFLAGS 64
+
+static byte VM_CmdFlags[]=
+{
+ /* VM_MOV */ VMCF_OP2 | VMCF_BYTEMODE ,
+ /* VM_CMP */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_ADD */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_SUB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_JZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_JNZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_INC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_DEC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_JMP */ VMCF_OP1 | VMCF_JUMP ,
+ /* VM_XOR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_AND */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_OR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_TEST */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_JS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_JNS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_JB */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_JBE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_JA */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_JAE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
+ /* VM_PUSH */ VMCF_OP1 ,
+ /* VM_POP */ VMCF_OP1 ,
+ /* VM_CALL */ VMCF_OP1 | VMCF_PROC ,
+ /* VM_RET */ VMCF_OP0 | VMCF_PROC ,
+ /* VM_NOT */ VMCF_OP1 | VMCF_BYTEMODE ,
+ /* VM_SHL */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_SHR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_SAR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_NEG */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
+ /* VM_PUSHA */ VMCF_OP0 ,
+ /* VM_POPA */ VMCF_OP0 ,
+ /* VM_PUSHF */ VMCF_OP0 | VMCF_USEFLAGS ,
+ /* VM_POPF */ VMCF_OP0 | VMCF_CHFLAGS ,
+ /* VM_MOVZX */ VMCF_OP2 ,
+ /* VM_MOVSX */ VMCF_OP2 ,
+ /* VM_XCHG */ VMCF_OP2 | VMCF_BYTEMODE ,
+ /* VM_MUL */ VMCF_OP2 | VMCF_BYTEMODE ,
+ /* VM_DIV */ VMCF_OP2 | VMCF_BYTEMODE ,
+ /* VM_ADC */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS ,
+ /* VM_SBB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS ,
+ /* VM_PRINT */ VMCF_OP0
+};
diff --git a/unrar/unrar/rawread.cpp b/unrar/unrar/rawread.cpp
new file mode 100644
index 0000000..bbba948
--- /dev/null
+++ b/unrar/unrar/rawread.cpp
@@ -0,0 +1,126 @@
+#include "rar.hpp"
+
+RawRead::RawRead(File *SrcFile)
+{
+ RawRead::SrcFile=SrcFile;
+ ReadPos=0;
+ DataSize=0;
+#ifndef SHELL_EXT
+ Crypt=NULL;
+#endif
+}
+
+
+void RawRead::Read(int Size)
+{
+#if !defined(SHELL_EXT) && !defined(NOCRYPT)
+ if (Crypt!=NULL)
+ {
+ int CurSize=Data.Size();
+ int SizeToRead=Size-(CurSize-DataSize);
+ if (SizeToRead>0)
+ {
+ int AlignedReadSize=SizeToRead+((~SizeToRead+1)&0xf);
+ Data.Add(AlignedReadSize);
+ int ReadSize=SrcFile->Read(&Data[CurSize],AlignedReadSize);
+ Crypt->DecryptBlock(&Data[CurSize],AlignedReadSize);
+ DataSize+=ReadSize==0 ? 0:Size;
+ }
+ else
+ DataSize+=Size;
+ }
+ else
+#endif
+ if (Size!=0)
+ {
+ Data.Add(Size);
+ DataSize+=SrcFile->Read(&Data[DataSize],Size);
+ }
+}
+
+
+void RawRead::Read(byte *SrcData,int Size)
+{
+ if (Size!=0)
+ {
+ Data.Add(Size);
+ memcpy(&Data[DataSize],SrcData,Size);
+ DataSize+=Size;
+ }
+}
+
+
+void RawRead::Get(byte &Field)
+{
+ if (ReadPos<DataSize)
+ {
+ Field=Data[ReadPos];
+ ReadPos++;
+ }
+ else
+ Field=0;
+}
+
+
+void RawRead::Get(ushort &Field)
+{
+ if (ReadPos+1<DataSize)
+ {
+ Field=Data[ReadPos]+(Data[ReadPos+1]<<8);
+ ReadPos+=2;
+ }
+ else
+ Field=0;
+}
+
+
+void RawRead::Get(uint &Field)
+{
+ if (ReadPos+3<DataSize)
+ {
+ Field=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
+ (Data[ReadPos+3]<<24);
+ ReadPos+=4;
+ }
+ else
+ Field=0;
+}
+
+
+void RawRead::Get8(Int64 &Field)
+{
+ uint Low,High;
+ Get(Low);
+ Get(High);
+ Field=int32to64(High,Low);
+}
+
+
+void RawRead::Get(byte *Field,int Size)
+{
+ if (ReadPos+Size-1<DataSize)
+ {
+ memcpy(Field,&Data[ReadPos],Size);
+ ReadPos+=Size;
+ }
+ else
+ memset(Field,0,Size);
+}
+
+
+void RawRead::Get(wchar *Field,int Size)
+{
+ if (ReadPos+2*Size-1<DataSize)
+ {
+ RawToWide(&Data[ReadPos],Field,Size);
+ ReadPos+=2*Size;
+ }
+ else
+ memset(Field,0,2*Size);
+}
+
+
+uint RawRead::GetCRC(bool ProcessedOnly)
+{
+ return(DataSize>2 ? CRC(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2):0xffffffff);
+}
diff --git a/unrar/unrar/rawread.hpp b/unrar/unrar/rawread.hpp
new file mode 100644
index 0000000..47c2bbc
--- /dev/null
+++ b/unrar/unrar/rawread.hpp
@@ -0,0 +1,32 @@
+#ifndef _RAR_RAWREAD_
+#define _RAR_RAWREAD_
+
+class RawRead
+{
+ private:
+ Array<byte> Data;
+ File *SrcFile;
+ int DataSize;
+ int ReadPos;
+#ifndef SHELL_EXT
+ CryptData *Crypt;
+#endif
+ public:
+ RawRead(File *SrcFile);
+ void Read(int Size);
+ void Read(byte *SrcData,int Size);
+ void Get(byte &Field);
+ void Get(ushort &Field);
+ void Get(uint &Field);
+ void Get8(Int64 &Field);
+ void Get(byte *Field,int Size);
+ void Get(wchar *Field,int Size);
+ uint GetCRC(bool ProcessedOnly);
+ int Size() {return DataSize;}
+ int PaddedSize() {return Data.Size()-DataSize;}
+#ifndef SHELL_EXT
+ void SetCrypt(CryptData *Crypt) {RawRead::Crypt=Crypt;}
+#endif
+};
+
+#endif
diff --git a/unrar/unrar/rdwrfn.cpp b/unrar/unrar/rdwrfn.cpp
new file mode 100644
index 0000000..2454377
--- /dev/null
+++ b/unrar/unrar/rdwrfn.cpp
@@ -0,0 +1,264 @@
+#include "rar.hpp"
+
+ComprDataIO::ComprDataIO()
+{
+ Init();
+}
+
+
+void ComprDataIO::Init()
+{
+ UnpackFromMemory=false;
+ UnpackToMemory=false;
+ UnpPackedSize=0;
+ ShowProgress=true;
+ TestMode=false;
+ SkipUnpCRC=false;
+ PackVolume=false;
+ UnpVolume=false;
+ NextVolumeMissing=false;
+ SrcFile=NULL;
+ DestFile=NULL;
+ UnpWrSize=0;
+ Command=NULL;
+ Encryption=0;
+ Decryption=0;
+ TotalPackRead=0;
+ CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=0;
+ PackFileCRC=UnpFileCRC=PackedCRC=0xffffffff;
+ LastPercent=-1;
+ SubHead=NULL;
+ SubHeadPos=NULL;
+ CurrentCommand=0;
+ ProcessedArcSize=TotalArcSize=0;
+}
+
+
+
+
+int ComprDataIO::UnpRead(byte *Addr,uint Count)
+{
+ int RetCode=0,TotalRead=0;
+ byte *ReadAddr;
+ ReadAddr=Addr;
+ while (Count > 0)
+ {
+ Archive *SrcArc=(Archive *)SrcFile;
+
+ uint ReadSize=(Count>UnpPackedSize) ? int64to32(UnpPackedSize):Count;
+ if (UnpackFromMemory)
+ {
+ memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize);
+ RetCode=UnpackFromMemorySize;
+ UnpackFromMemorySize=0;
+ }
+ else
+ {
+ if (!SrcFile->IsOpened())
+ return(-1);
+ RetCode=SrcFile->Read(ReadAddr,ReadSize);
+ FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->NewLhd;
+ if (hd->Flags & LHD_SPLIT_AFTER)
+ PackedCRC=CRC(PackedCRC,ReadAddr,ReadSize);
+ }
+ CurUnpRead+=RetCode;
+ TotalRead+=RetCode;
+#ifndef NOVOLUME
+ // these variable are not used below in NOVOLUME mode, so it is better
+ // to exclude these commands to avoid compiler warnings
+ ReadAddr+=RetCode;
+ Count-=RetCode;
+#endif
+ UnpPackedSize-=RetCode;
+ if (UnpPackedSize == 0 && UnpVolume)
+ {
+#ifndef NOVOLUME
+ if (!MergeArchive(*SrcArc,this,true,CurrentCommand))
+#endif
+ {
+ NextVolumeMissing=true;
+ return(-1);
+ }
+ }
+ else
+ break;
+ }
+ Archive *SrcArc=(Archive *)SrcFile;
+ if (SrcArc!=NULL)
+ ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize);
+ if (RetCode!=-1)
+ {
+ RetCode=TotalRead;
+#ifndef NOCRYPT
+ if (Decryption)
+#ifndef SFX_MODULE
+ if (Decryption<20)
+ Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE);
+ else
+ if (Decryption==20)
+ for (uint I=0;I<RetCode;I+=16)
+ Decrypt.DecryptBlock20(&Addr[I]);
+ else
+#endif
+ {
+ int CryptSize=(RetCode & 0xf)==0 ? RetCode:((RetCode & ~0xf)+16);
+ Decrypt.DecryptBlock(Addr,CryptSize);
+ }
+#endif
+ }
+ Wait();
+ return(RetCode);
+}
+
+
+void ComprDataIO::UnpWrite(byte *Addr,uint Count)
+{
+#ifdef RARDLL
+ RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
+ if (Cmd->DllOpMode!=RAR_SKIP)
+ {
+ if (Cmd->Callback!=NULL &&
+ Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LONG)Addr,Count)==-1)
+ ErrHandler.Exit(USER_BREAK);
+ if (Cmd->ProcessDataProc!=NULL)
+ {
+#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
+ _EBX=_ESP;
+#endif
+ int RetCode=Cmd->ProcessDataProc(Addr,Count);
+#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
+ _ESP=_EBX;
+#endif
+ if (RetCode==0)
+ ErrHandler.Exit(USER_BREAK);
+ }
+ }
+#endif
+ UnpWrAddr=Addr;
+ UnpWrSize=Count;
+ if (UnpackToMemory)
+ {
+ if (Count <= UnpackToMemorySize)
+ {
+ memcpy(UnpackToMemoryAddr,Addr,Count);
+ UnpackToMemoryAddr+=Count;
+ UnpackToMemorySize-=Count;
+ }
+ }
+ else
+ if (!TestMode)
+ DestFile->Write(Addr,Count);
+ CurUnpWrite+=Count;
+ if (!SkipUnpCRC)
+#ifndef SFX_MODULE
+ if (((Archive *)SrcFile)->OldFormat)
+ UnpFileCRC=OldCRC((ushort)UnpFileCRC,Addr,Count);
+ else
+#endif
+ UnpFileCRC=CRC(UnpFileCRC,Addr,Count);
+ ShowUnpWrite();
+ Wait();
+}
+
+
+
+
+
+
+void ComprDataIO::ShowUnpRead(Int64 ArcPos,Int64 ArcSize)
+{
+ if (ShowProgress && SrcFile!=NULL)
+ {
+ Archive *SrcArc=(Archive *)SrcFile;
+ RAROptions *Cmd=SrcArc->GetRAROptions();
+ if (TotalArcSize!=0)
+ ArcSize=TotalArcSize;
+ ArcPos+=ProcessedArcSize;
+ if (!SrcArc->Volume)
+ {
+ int CurPercent=ToPercent(ArcPos,ArcSize);
+ if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
+ {
+ mprintf("\b\b\b\b%3d%%",CurPercent);
+ LastPercent=CurPercent;
+ }
+ }
+ }
+}
+
+
+void ComprDataIO::ShowUnpWrite()
+{
+}
+
+
+
+
+
+
+
+
+void ComprDataIO::SetFiles(File *SrcFile,File *DestFile)
+{
+ if (SrcFile!=NULL)
+ ComprDataIO::SrcFile=SrcFile;
+ if (DestFile!=NULL)
+ ComprDataIO::DestFile=DestFile;
+ LastPercent=-1;
+}
+
+
+void ComprDataIO::GetUnpackedData(byte **Data,uint *Size)
+{
+ *Data=UnpWrAddr;
+ *Size=UnpWrSize;
+}
+
+
+void ComprDataIO::SetEncryption(int Method,char *Password,byte *Salt,bool Encrypt,bool HandsOffHash)
+{
+ if (Encrypt)
+ {
+ Encryption=*Password ? Method:0;
+#ifndef NOCRYPT
+ Crypt.SetCryptKeys(Password,Salt,Encrypt,false,HandsOffHash);
+#endif
+ }
+ else
+ {
+ Decryption=*Password ? Method:0;
+#ifndef NOCRYPT
+ Decrypt.SetCryptKeys(Password,Salt,Encrypt,Method<29,HandsOffHash);
+#endif
+ }
+}
+
+
+#if !defined(SFX_MODULE) && !defined(NOCRYPT)
+void ComprDataIO::SetAV15Encryption()
+{
+ Decryption=15;
+ Decrypt.SetAV15Encryption();
+}
+#endif
+
+
+#if !defined(SFX_MODULE) && !defined(NOCRYPT)
+void ComprDataIO::SetCmt13Encryption()
+{
+ Decryption=13;
+ Decrypt.SetCmt13Encryption();
+}
+#endif
+
+
+
+
+void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size)
+{
+ UnpackToMemory=true;
+ UnpackToMemoryAddr=Addr;
+ UnpackToMemorySize=Size;
+}
+
+
diff --git a/unrar/unrar/rdwrfn.hpp b/unrar/unrar/rdwrfn.hpp
new file mode 100644
index 0000000..8313627
--- /dev/null
+++ b/unrar/unrar/rdwrfn.hpp
@@ -0,0 +1,83 @@
+#ifndef _RAR_DATAIO_
+#define _RAR_DATAIO_
+
+class CmdAdd;
+class Unpack;
+
+
+class ComprDataIO
+{
+ private:
+ void ShowUnpRead(Int64 ArcPos,Int64 ArcSize);
+ void ShowUnpWrite();
+
+
+ bool UnpackFromMemory;
+ uint UnpackFromMemorySize;
+ byte *UnpackFromMemoryAddr;
+
+ bool UnpackToMemory;
+ uint UnpackToMemorySize;
+ byte *UnpackToMemoryAddr;
+
+ uint UnpWrSize;
+ byte *UnpWrAddr;
+
+ Int64 UnpPackedSize;
+
+ bool ShowProgress;
+ bool TestMode;
+ bool SkipUnpCRC;
+
+ File *SrcFile;
+ File *DestFile;
+
+ CmdAdd *Command;
+
+ FileHeader *SubHead;
+ Int64 *SubHeadPos;
+
+#ifndef NOCRYPT
+ CryptData Crypt;
+ CryptData Decrypt;
+#endif
+
+
+ int LastPercent;
+
+ char CurrentCommand;
+
+ public:
+ ComprDataIO();
+ void Init();
+ int UnpRead(byte *Addr,uint Count);
+ void UnpWrite(byte *Addr,uint Count);
+ void EnableShowProgress(bool Show) {ShowProgress=Show;}
+ void GetUnpackedData(byte **Data,uint *Size);
+ void SetPackedSizeToRead(Int64 Size) {UnpPackedSize=Size;}
+ void SetTestMode(bool Mode) {TestMode=Mode;}
+ void SetSkipUnpCRC(bool Skip) {SkipUnpCRC=Skip;}
+ void SetFiles(File *SrcFile,File *DestFile);
+ void SetCommand(CmdAdd *Cmd) {Command=Cmd;}
+ void SetSubHeader(FileHeader *hd,Int64 *Pos) {SubHead=hd;SubHeadPos=Pos;}
+ void SetEncryption(int Method,char *Password,byte *Salt,bool Encrypt,bool HandsOffHash);
+ void SetAV15Encryption();
+ void SetCmt13Encryption();
+ void SetUnpackToMemory(byte *Addr,uint Size);
+ void SetCurrentCommand(char Cmd) {CurrentCommand=Cmd;}
+
+ bool PackVolume;
+ bool UnpVolume;
+ bool NextVolumeMissing;
+ Int64 TotalPackRead;
+ Int64 UnpArcSize;
+ Int64 CurPackRead,CurPackWrite,CurUnpRead,CurUnpWrite;
+ Int64 ProcessedArcSize,TotalArcSize;
+
+ uint PackFileCRC,UnpFileCRC,PackedCRC;
+
+ int Encryption;
+ int Decryption;
+};
+
+#endif
diff --git a/unrar/unrar/readme.txt b/unrar/unrar/readme.txt
new file mode 100644
index 0000000..41ee05c
--- /dev/null
+++ b/unrar/unrar/readme.txt
@@ -0,0 +1,63 @@
+
+ Portable UnRAR version
+
+
+ 1. General
+
+ This package includes freeware Unrar C++ source and a few makefiles
+ (makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source
+ is subset of RAR and generated from RAR source automatically,
+ by a small program removing blocks like '#ifndef UNRAR ... #endif'.
+ Such method is not perfect and you may find some RAR related
+ stuff unnecessary in Unrar, especially in header files.
+
+ If you wish to port Unrar to a new platform, you may need to edit
+ '#define LITTLE_ENDIAN' in os.hpp and data type definitions
+ in rartypes.hpp.
+
+ if computer architecture does not allow not aligned data access,
+ you need to undefine ALLOW_NOT_ALIGNED_INT and define
+ STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory
+ requirements.
+
+ If you use Borland C++ makefile (makefile.bcc), you need to define
+ BASEPATHCC environment (or makefile) variable containing
+ the path to Borland C++ installation.
+
+ Makefile.unix contains numerous compiler option sets.
+ GCC Linux is selected by default. If you need to compile Unrar
+ for other platforms, uncomment corresponding lines.
+
+
+ 2. Unrar binaries
+
+ If you compiled Unrar for OS, which is not present in "Downloads"
+ and "RAR extras" on www.rarlab.com, we will appreciate if you send
+ us the compiled executable to place it to our site.
+
+
+ 3. Acknowledgements
+
+ This source includes parts of code written by the following authors:
+
+ Dmitry Shkarin PPMII v.H text compression
+ Dmitry Subbotin Carryless rangecoder
+ Szymon Stefanek AES encryption
+ Brian Gladman AES encryption
+ Steve Reid SHA-1 hash function
+ Marcus Herbert makefile.unix file
+ Tomasz Klim fixes for libunrar.so
+ Robert Riebisch makefile.dj and patches for DJGPP
+
+
+ 4. Legal stuff
+
+ Unrar source may be used in any software to handle RAR archives
+ without limitations free of charge, but cannot be used to re-create
+ the RAR compression algorithm, which is proprietary. Distribution
+ of modified Unrar source in separate form or as a part of other
+ software is permitted, provided that it is clearly stated in
+ the documentation and source comments that the code may not be used
+ to develop a RAR (WinRAR) compatible archiver.
+
+ More detailed license text is available in license.txt.
diff --git a/unrar/unrar/recvol.cpp b/unrar/unrar/recvol.cpp
new file mode 100644
index 0000000..0296b02
--- /dev/null
+++ b/unrar/unrar/recvol.cpp
@@ -0,0 +1,367 @@
+#include "rar.hpp"
+
+#define RECVOL_BUFSIZE 0x800
+
+RecVolumes::RecVolumes()
+{
+ Buf.Alloc(RECVOL_BUFSIZE*256);
+ memset(SrcFile,0,sizeof(SrcFile));
+}
+
+
+RecVolumes::~RecVolumes()
+{
+ for (int I=0;I<sizeof(SrcFile)/sizeof(SrcFile[0]);I++)
+ delete SrcFile[I];
+}
+
+
+
+
+bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
+ const wchar *NameW,bool Silent)
+{
+ char ArcName[NM];
+ wchar ArcNameW[NM];
+ strcpy(ArcName,Name);
+ strcpyw(ArcNameW,NameW);
+ char *Ext=GetExt(ArcName);
+ bool NewStyle=false;
+ bool RevName=Ext!=NULL && stricomp(Ext,".rev")==0;
+ if (RevName)
+ {
+ for (int DigitGroup=0;Ext>ArcName && DigitGroup<3;Ext--)
+ if (!isdigit(*Ext))
+ if (isdigit(*(Ext-1)) && (*Ext=='_' || DigitGroup<2))
+ DigitGroup++;
+ else
+ if (DigitGroup<2)
+ {
+ NewStyle=true;
+ break;
+ }
+ while (isdigit(*Ext) && Ext>ArcName+1)
+ Ext--;
+ strcpy(Ext,"*.*");
+ FindFile Find;
+ Find.SetMask(ArcName);
+ struct FindData FD;
+ while (Find.Next(&FD))
+ {
+ Archive Arc(Cmd);
+ if (Arc.WOpen(FD.Name,FD.NameW) && Arc.IsArchive(true))
+ {
+ strcpy(ArcName,FD.Name);
+ *ArcNameW=0;
+ break;
+ }
+ }
+ }
+
+ Archive Arc(Cmd);
+ if (!Arc.WCheckOpen(ArcName,ArcNameW))
+ return(false);
+ if (!Arc.Volume)
+ {
+#ifndef SILENT
+ Log(ArcName,St(MNotVolume),ArcName);
+#endif
+ return(false);
+ }
+ bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING);
+ Arc.Close();
+ char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering);
+ char RecVolMask[NM];
+ strcpy(RecVolMask,ArcName);
+ int BaseNamePartLength=VolNumStart-ArcName;
+ strcpy(RecVolMask+BaseNamePartLength,"*.rev");
+
+#ifndef SILENT
+ Int64 RecFileSize=0;
+#endif
+ FindFile Find;
+ Find.SetMask(RecVolMask);
+ struct FindData RecData;
+ int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0;
+ char PrevName[NM];
+ while (Find.Next(&RecData))
+ {
+ char *Name=RecData.Name;
+ int P[3];
+ if (!RevName && !NewStyle)
+ {
+ NewStyle=true;
+ char *Dot=GetExt(Name);
+ if (Dot!=NULL)
+ {
+ int LineCount=0;
+ Dot--;
+ while (Dot>Name && *Dot!='.')
+ {
+ if (*Dot=='_')
+ LineCount++;
+ Dot--;
+ }
+ if (LineCount==2)
+ NewStyle=false;
+ }
+ }
+ if (NewStyle)
+ {
+ File CurFile;
+ CurFile.TOpen(Name);
+ CurFile.Seek(0,SEEK_END);
+ Int64 Length=CurFile.Tell();
+ CurFile.Seek(Length-7,SEEK_SET);
+ for (int I=0;I<3;I++)
+ P[2-I]=CurFile.GetByte()+1;
+ uint FileCRC=0;
+ for (int I=0;I<4;I++)
+ FileCRC|=CurFile.GetByte()<<(I*8);
+ if (FileCRC!=CalcFileCRC(&CurFile,Length-4))
+ {
+#ifndef SILENT
+ mprintf(St(MCRCFailed),Name);
+#endif
+ continue;
+ }
+ }
+ else
+ {
+ char *Dot=GetExt(Name);
+ if (Dot==NULL)
+ continue;
+ bool WrongParam=false;
+ for (int I=0;I<sizeof(P)/sizeof(P[0]);I++)
+ {
+ do
+ {
+ Dot--;
+ } while (isdigit(*Dot) && Dot>=Name+BaseNamePartLength);
+ P[I]=atoi(Dot+1);
+ if (P[I]==0 || P[I]>255)
+ WrongParam=true;
+ }
+ if (WrongParam)
+ continue;
+ }
+ if (P[1]+P[2]>255)
+ continue;
+ if (RecVolNumber!=0 && RecVolNumber!=P[1] || FileNumber!=0 && FileNumber!=P[2])
+ {
+#ifndef SILENT
+ Log(NULL,St(MRecVolDiffSets),Name,PrevName);
+#endif
+ return(false);
+ }
+ RecVolNumber=P[1];
+ FileNumber=P[2];
+ strcpy(PrevName,Name);
+ File *NewFile=new File;
+ NewFile->TOpen(Name);
+ SrcFile[FileNumber+P[0]-1]=NewFile;
+ FoundRecVolumes++;
+#ifndef SILENT
+ if (RecFileSize==0)
+ RecFileSize=NewFile->FileLength();
+#endif
+ }
+#ifndef SILENT
+ if (!Silent || FoundRecVolumes!=0)
+ {
+ mprintf(St(MRecVolFound),FoundRecVolumes);
+ }
+#endif
+ if (FoundRecVolumes==0)
+ return(false);
+
+ bool WriteFlags[256];
+ memset(WriteFlags,0,sizeof(WriteFlags));
+
+ char LastVolName[NM];
+ *LastVolName=0;
+
+ for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++)
+ {
+ Archive *NewFile=new Archive;
+ bool ValidVolume=FileExist(ArcName);
+ if (ValidVolume)
+ {
+ NewFile->TOpen(ArcName);
+ ValidVolume=NewFile->IsArchive(false);
+ if (ValidVolume)
+ {
+ while (NewFile->ReadHeader()!=0)
+ {
+ if (NewFile->GetHeaderType()==ENDARC_HEAD)
+ {
+ if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 &&
+ NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos))
+ {
+ ValidVolume=false;
+#ifndef SILENT
+ mprintf(St(MCRCFailed),ArcName);
+#endif
+ }
+ break;
+ }
+ NewFile->SeekToNext();
+ }
+ }
+ if (!ValidVolume)
+ {
+ NewFile->Close();
+ char NewName[NM];
+ strcpy(NewName,ArcName);
+ strcat(NewName,".bad");
+#ifndef SILENT
+ mprintf(St(MBadArc),ArcName);
+ mprintf(St(MRenaming),ArcName,NewName);
+#endif
+ rename(ArcName,NewName);
+ }
+ NewFile->Seek(0,SEEK_SET);
+ }
+ if (!ValidVolume)
+ {
+ NewFile->TCreate(ArcName);
+ WriteFlags[CurArcNum]=true;
+ MissingVolumes++;
+
+ if (CurArcNum==FileNumber-1)
+ strcpy(LastVolName,ArcName);
+
+#ifndef SILENT
+ mprintf(St(MAbsNextVol),ArcName);
+#endif
+ }
+ SrcFile[CurArcNum]=(File*)NewFile;
+ NextVolumeName(ArcName,!NewNumbering);
+ }
+
+#ifndef SILENT
+ mprintf(St(MRecVolMissing),MissingVolumes);
+#endif
+
+ if (MissingVolumes==0)
+ {
+#ifndef SILENT
+ mprintf(St(MRecVolAllExist));
+#endif
+ return(false);
+ }
+
+ if (MissingVolumes>FoundRecVolumes)
+ {
+#ifndef SILENT
+ mprintf(St(MRecVolCannotFix));
+#endif
+ return(false);
+ }
+#ifndef SILENT
+ mprintf(St(MReconstructing));
+#endif
+
+ RSCoder RSC(RecVolNumber);
+
+ int TotalFiles=FileNumber+RecVolNumber;
+ int Erasures[256],EraSize=0;
+
+ for (int I=0;I<TotalFiles;I++)
+ if (WriteFlags[I] || SrcFile[I]==NULL)
+ Erasures[EraSize++]=I;
+
+#ifndef SILENT
+ Int64 ProcessedSize=0;
+#ifndef GUI
+ int LastPercent=-1;
+ mprintf(" ");
+#endif
+#endif
+ int RecCount=0;
+
+ while (true)
+ {
+ if ((++RecCount & 15)==0)
+ Wait();
+ int MaxRead=0;
+ for (int I=0;I<TotalFiles;I++)
+ if (WriteFlags[I] || SrcFile[I]==NULL)
+ memset(&Buf[I*RECVOL_BUFSIZE],0,RECVOL_BUFSIZE);
+ else
+ {
+ int ReadSize=SrcFile[I]->Read(&Buf[I*RECVOL_BUFSIZE],RECVOL_BUFSIZE);
+ if (ReadSize!=RECVOL_BUFSIZE)
+ memset(&Buf[I*RECVOL_BUFSIZE+ReadSize],0,RECVOL_BUFSIZE-ReadSize);
+ if (ReadSize>MaxRead)
+ MaxRead=ReadSize;
+ }
+ if (MaxRead==0)
+ break;
+#ifndef SILENT
+ int CurPercent=ToPercent(ProcessedSize,RecFileSize);
+ if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
+ {
+ mprintf("\b\b\b\b%3d%%",CurPercent);
+ LastPercent=CurPercent;
+ }
+ ProcessedSize+=MaxRead;
+#endif
+ for (int BufPos=0;BufPos<MaxRead;BufPos++)
+ {
+ byte Data[256];
+ for (int I=0;I<TotalFiles;I++)
+ Data[I]=Buf[I*RECVOL_BUFSIZE+BufPos];
+ RSC.Decode(Data,TotalFiles,Erasures,EraSize);
+ for (int I=0;I<EraSize;I++)
+ Buf[Erasures[I]*RECVOL_BUFSIZE+BufPos]=Data[Erasures[I]];
+/*
+ for (int I=0;I<FileNumber;I++)
+ Buf[I*RECVOL_BUFSIZE+BufPos]=Data[I];
+*/
+ }
+ for (int I=0;I<FileNumber;I++)
+ if (WriteFlags[I])
+ SrcFile[I]->Write(&Buf[I*RECVOL_BUFSIZE],MaxRead);
+ }
+ for (int I=0;I<RecVolNumber+FileNumber;I++)
+ if (SrcFile[I]!=NULL)
+ {
+ File *CurFile=SrcFile[I];
+ if (NewStyle && WriteFlags[I])
+ {
+ Int64 Length=CurFile->Tell();
+ CurFile->Seek(Length-7,SEEK_SET);
+ for (int J=0;J<7;J++)
+ CurFile->PutByte(0);
+ }
+ CurFile->Close();
+ SrcFile[I]=NULL;
+ }
+ if (*LastVolName)
+ {
+ Archive Arc(Cmd);
+ if (Arc.Open(LastVolName,NULL,false,true) && Arc.IsArchive(true) &&
+ Arc.SearchBlock(ENDARC_HEAD))
+ {
+ Arc.Seek(Arc.NextBlockPos,SEEK_SET);
+ char Buf[8192];
+ int ReadSize=Arc.Read(Buf,sizeof(Buf));
+ int ZeroCount=0;
+ while (ZeroCount<ReadSize && Buf[ZeroCount]==0)
+ ZeroCount++;
+ if (ZeroCount==ReadSize)
+ {
+ Arc.Seek(Arc.NextBlockPos,SEEK_SET);
+ Arc.Truncate();
+ }
+ }
+ }
+#if !defined(GUI) && !defined(SILENT)
+ if (!Cmd->DisablePercentage)
+ mprintf("\b\b\b\b100%%");
+ if (!Silent && !Cmd->DisableDone)
+ mprintf(St(MDone));
+#endif
+ return(true);
+}
diff --git a/unrar/unrar/recvol.hpp b/unrar/unrar/recvol.hpp
new file mode 100644
index 0000000..5a0abe5
--- /dev/null
+++ b/unrar/unrar/recvol.hpp
@@ -0,0 +1,16 @@
+#ifndef _RAR_RECVOL_
+#define _RAR_RECVOL_
+
+class RecVolumes
+{
+ private:
+ File *SrcFile[256];
+ Array<byte> Buf;
+ public:
+ RecVolumes();
+ ~RecVolumes();
+ void Make(RAROptions *Cmd,char *ArcName,wchar *ArcNameW);
+ bool Restore(RAROptions *Cmd,const char *Name,const wchar *NameW,bool Silent);
+};
+
+#endif
diff --git a/unrar/unrar/resource.cpp b/unrar/unrar/resource.cpp
new file mode 100644
index 0000000..f2a4657
--- /dev/null
+++ b/unrar/unrar/resource.cpp
@@ -0,0 +1,12 @@
+#include "rar.hpp"
+
+
+
+#if !defined(SILENT) || !defined(RARDLL)
+const char *St(MSGID StringId)
+{
+ return(StringId);
+}
+#endif
+
+
diff --git a/unrar/unrar/resource.hpp b/unrar/unrar/resource.hpp
new file mode 100644
index 0000000..581b34b
--- /dev/null
+++ b/unrar/unrar/resource.hpp
@@ -0,0 +1,14 @@
+#ifndef _RAR_RESOURCE_
+#define _RAR_RESOURCE_
+
+#if defined(SILENT) && defined(RARDLL)
+#define St(x) ("")
+#else
+const char *St(MSGID StringId);
+#endif
+
+
+inline const char *StT(MSGID StringId) {return(St(StringId));}
+
+
+#endif
diff --git a/unrar/unrar/rijndael.cpp b/unrar/unrar/rijndael.cpp
new file mode 100644
index 0000000..d0d71b9
--- /dev/null
+++ b/unrar/unrar/rijndael.cpp
@@ -0,0 +1,298 @@
+/**************************************************************************
+ * This code is based on Szymon Stefanek AES implementation: *
+ * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-cpplib.tar.gz *
+ * *
+ * Dynamic tables generation is based on the Brian Gladman work: *
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael *
+ **************************************************************************/
+#include "rar.hpp"
+
+const int uKeyLenInBytes=16, m_uRounds=10;
+
+static byte S[256],S5[256],rcon[30];
+static byte T1[256][4],T2[256][4],T3[256][4],T4[256][4];
+static byte T5[256][4],T6[256][4],T7[256][4],T8[256][4];
+static byte U1[256][4],U2[256][4],U3[256][4],U4[256][4];
+
+
+inline void Xor128(byte *dest,const byte *arg1,const byte *arg2)
+{
+#if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
+ ((uint32*)dest)[0]=((uint32*)arg1)[0]^((uint32*)arg2)[0];
+ ((uint32*)dest)[1]=((uint32*)arg1)[1]^((uint32*)arg2)[1];
+ ((uint32*)dest)[2]=((uint32*)arg1)[2]^((uint32*)arg2)[2];
+ ((uint32*)dest)[3]=((uint32*)arg1)[3]^((uint32*)arg2)[3];
+#else
+ for (int I=0;I<16;I++)
+ dest[I]=arg1[I]^arg2[I];
+#endif
+}
+
+
+inline void Xor128(byte *dest,const byte *arg1,const byte *arg2,
+ const byte *arg3,const byte *arg4)
+{
+#if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
+ (*(uint32*)dest)=(*(uint32*)arg1)^(*(uint32*)arg2)^(*(uint32*)arg3)^(*(uint32*)arg4);
+#else
+ for (int I=0;I<4;I++)
+ dest[I]=arg1[I]^arg2[I]^arg3[I]^arg4[I];
+#endif
+}
+
+
+inline void Copy128(byte *dest,const byte *src)
+{
+#if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
+ ((uint32*)dest)[0]=((uint32*)src)[0];
+ ((uint32*)dest)[1]=((uint32*)src)[1];
+ ((uint32*)dest)[2]=((uint32*)src)[2];
+ ((uint32*)dest)[3]=((uint32*)src)[3];
+#else
+ for (int I=0;I<16;I++)
+ dest[I]=src[I];
+#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// API
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Rijndael::Rijndael()
+{
+ if (S[0]==0)
+ GenerateTables();
+}
+
+
+void Rijndael::init(Direction dir,const byte * key,byte * initVector)
+{
+ m_direction = dir;
+
+ byte keyMatrix[_MAX_KEY_COLUMNS][4];
+
+ for(uint i = 0;i < uKeyLenInBytes;i++)
+ keyMatrix[i >> 2][i & 3] = key[i];
+
+ for(int i = 0;i < MAX_IV_SIZE;i++)
+ m_initVector[i] = initVector[i];
+
+ keySched(keyMatrix);
+
+ if(m_direction == Decrypt)
+ keyEncToDec();
+}
+
+
+
+int Rijndael::blockDecrypt(const byte *input, int inputLen, byte *outBuffer)
+{
+ if (input == 0 || inputLen <= 0)
+ return 0;
+
+ byte block[16], iv[4][4];
+ memcpy(iv,m_initVector,16);
+
+ int numBlocks=inputLen/16;
+ for (int i = numBlocks; i > 0; i--)
+ {
+ decrypt(input, block);
+ Xor128(block,block,(byte*)iv);
+#if STRICT_ALIGN
+ memcpy(iv, input, 16);
+ memcpy(outBuf, block, 16);
+#else
+ Copy128((byte*)iv,input);
+ Copy128(outBuffer,block);
+#endif
+ input += 16;
+ outBuffer += 16;
+ }
+
+ memcpy(m_initVector,iv,16);
+
+ return 16*numBlocks;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// ALGORITHM
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void Rijndael::keySched(byte key[_MAX_KEY_COLUMNS][4])
+{
+ int j,rconpointer = 0;
+
+ // Calculate the necessary round keys
+ // The number of calculations depends on keyBits and blockBits
+ int uKeyColumns = m_uRounds - 6;
+
+ byte tempKey[_MAX_KEY_COLUMNS][4];
+
+ // Copy the input key to the temporary key matrix
+
+ memcpy(tempKey,key,sizeof(tempKey));
+
+ int r = 0;
+ int t = 0;
+
+ // copy values into round key array
+ for(j = 0;(j < uKeyColumns) && (r <= m_uRounds); )
+ {
+ for(;(j < uKeyColumns) && (t < 4); j++, t++)
+ for (int k=0;k<4;k++)
+ m_expandedKey[r][t][k]=tempKey[j][k];
+
+ if(t == 4)
+ {
+ r++;
+ t = 0;
+ }
+ }
+
+ while(r <= m_uRounds)
+ {
+ tempKey[0][0] ^= S[tempKey[uKeyColumns-1][1]];
+ tempKey[0][1] ^= S[tempKey[uKeyColumns-1][2]];
+ tempKey[0][2] ^= S[tempKey[uKeyColumns-1][3]];
+ tempKey[0][3] ^= S[tempKey[uKeyColumns-1][0]];
+ tempKey[0][0] ^= rcon[rconpointer++];
+
+ if (uKeyColumns != 8)
+ for(j = 1; j < uKeyColumns; j++)
+ for (int k=0;k<4;k++)
+ tempKey[j][k] ^= tempKey[j-1][k];
+ else
+ {
+ for(j = 1; j < uKeyColumns/2; j++)
+ for (int k=0;k<4;k++)
+ tempKey[j][k] ^= tempKey[j-1][k];
+
+ tempKey[uKeyColumns/2][0] ^= S[tempKey[uKeyColumns/2 - 1][0]];
+ tempKey[uKeyColumns/2][1] ^= S[tempKey[uKeyColumns/2 - 1][1]];
+ tempKey[uKeyColumns/2][2] ^= S[tempKey[uKeyColumns/2 - 1][2]];
+ tempKey[uKeyColumns/2][3] ^= S[tempKey[uKeyColumns/2 - 1][3]];
+ for(j = uKeyColumns/2 + 1; j < uKeyColumns; j++)
+ for (int k=0;k<4;k++)
+ tempKey[j][k] ^= tempKey[j-1][k];
+ }
+ for(j = 0; (j < uKeyColumns) && (r <= m_uRounds); )
+ {
+ for(; (j < uKeyColumns) && (t < 4); j++, t++)
+ for (int k=0;k<4;k++)
+ m_expandedKey[r][t][k] = tempKey[j][k];
+ if(t == 4)
+ {
+ r++;
+ t = 0;
+ }
+ }
+ }
+}
+
+void Rijndael::keyEncToDec()
+{
+ for(int r = 1; r < m_uRounds; r++)
+ {
+ byte n_expandedKey[4][4];
+ for (int i=0;i<4;i++)
+ for (int j=0;j<4;j++)
+ {
+ byte *w=m_expandedKey[r][j];
+ n_expandedKey[j][i]=U1[w[0]][i]^U2[w[1]][i]^U3[w[2]][i]^U4[w[3]][i];
+ }
+ memcpy(m_expandedKey[r],n_expandedKey,sizeof(m_expandedKey[0]));
+ }
+}
+
+
+void Rijndael::decrypt(const byte a[16], byte b[16])
+{
+ int r;
+ byte temp[4][4];
+
+ Xor128((byte*)temp,(byte*)a,(byte*)m_expandedKey[m_uRounds]);
+
+ Xor128(b, T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
+ Xor128(b+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
+ Xor128(b+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
+ Xor128(b+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
+
+ for(r = m_uRounds-1; r > 1; r--)
+ {
+ Xor128((byte*)temp,(byte*)b,(byte*)m_expandedKey[r]);
+ Xor128(b, T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
+ Xor128(b+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
+ Xor128(b+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
+ Xor128(b+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
+ }
+
+ Xor128((byte*)temp,(byte*)b,(byte*)m_expandedKey[1]);
+ b[ 0] = S5[temp[0][0]];
+ b[ 1] = S5[temp[3][1]];
+ b[ 2] = S5[temp[2][2]];
+ b[ 3] = S5[temp[1][3]];
+ b[ 4] = S5[temp[1][0]];
+ b[ 5] = S5[temp[0][1]];
+ b[ 6] = S5[temp[3][2]];
+ b[ 7] = S5[temp[2][3]];
+ b[ 8] = S5[temp[2][0]];
+ b[ 9] = S5[temp[1][1]];
+ b[10] = S5[temp[0][2]];
+ b[11] = S5[temp[3][3]];
+ b[12] = S5[temp[3][0]];
+ b[13] = S5[temp[2][1]];
+ b[14] = S5[temp[1][2]];
+ b[15] = S5[temp[0][3]];
+ Xor128((byte*)b,(byte*)b,(byte*)m_expandedKey[0]);
+}
+
+#define ff_poly 0x011b
+#define ff_hi 0x80
+
+#define FFinv(x) ((x) ? pow[255 - log[x]]: 0)
+
+#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0)
+#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0)
+#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0)
+#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0)
+#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0)
+#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0)
+#define fwd_affine(x) \
+ (w = (uint)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), (byte)(0x63^(w^(w>>8))))
+
+#define inv_affine(x) \
+ (w = (uint)x, w = (w<<1)^(w<<3)^(w<<6), (byte)(0x05^(w^(w>>8))))
+
+void Rijndael::GenerateTables()
+{
+ unsigned char pow[512],log[256];
+ int i = 0, w = 1;
+ do
+ {
+ pow[i] = (byte)w;
+ pow[i + 255] = (byte)w;
+ log[w] = (byte)i++;
+ w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0);
+ } while (w != 1);
+
+ for (int i = 0,w = 1; i < sizeof(rcon)/sizeof(rcon[0]); i++)
+ {
+ rcon[i] = w;
+ w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
+ }
+ for(int i = 0; i < 256; ++i)
+ {
+ unsigned char b=S[i]=fwd_affine(FFinv((byte)i));
+ T1[i][1]=T1[i][2]=T2[i][2]=T2[i][3]=T3[i][0]=T3[i][3]=T4[i][0]=T4[i][1]=b;
+ T1[i][0]=T2[i][1]=T3[i][2]=T4[i][3]=FFmul02(b);
+ T1[i][3]=T2[i][0]=T3[i][1]=T4[i][2]=FFmul03(b);
+ S5[i] = b = FFinv(inv_affine((byte)i));
+ U1[b][3]=U2[b][0]=U3[b][1]=U4[b][2]=T5[i][3]=T6[i][0]=T7[i][1]=T8[i][2]=FFmul0b(b);
+ U1[b][1]=U2[b][2]=U3[b][3]=U4[b][0]=T5[i][1]=T6[i][2]=T7[i][3]=T8[i][0]=FFmul09(b);
+ U1[b][2]=U2[b][3]=U3[b][0]=U4[b][1]=T5[i][2]=T6[i][3]=T7[i][0]=T8[i][1]=FFmul0d(b);
+ U1[b][0]=U2[b][1]=U3[b][2]=U4[b][3]=T5[i][0]=T6[i][1]=T7[i][2]=T8[i][3]=FFmul0e(b);
+ }
+}
diff --git a/unrar/unrar/rijndael.hpp b/unrar/unrar/rijndael.hpp
new file mode 100644
index 0000000..6a8edde
--- /dev/null
+++ b/unrar/unrar/rijndael.hpp
@@ -0,0 +1,37 @@
+#ifndef _RIJNDAEL_H_
+#define _RIJNDAEL_H_
+
+/**************************************************************************
+ * This code is based on Szymon Stefanek AES implementation: *
+ * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-cpplib.tar.gz *
+ * *
+ * Dynamic tables generation is based on the Brian Gladman's work: *
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael *
+ **************************************************************************/
+
+#define _MAX_KEY_COLUMNS (256/32)
+#define _MAX_ROUNDS 14
+#define MAX_IV_SIZE 16
+
+class Rijndael
+{
+ public:
+ enum Direction { Encrypt , Decrypt };
+ private:
+ void keySched(byte key[_MAX_KEY_COLUMNS][4]);
+ void keyEncToDec();
+ void encrypt(const byte a[16], byte b[16]);
+ void decrypt(const byte a[16], byte b[16]);
+ void GenerateTables();
+
+ Direction m_direction;
+ byte m_initVector[MAX_IV_SIZE];
+ byte m_expandedKey[_MAX_ROUNDS+1][4][4];
+ public:
+ Rijndael();
+ void init(Direction dir,const byte *key,byte *initVector);
+ int blockEncrypt(const byte *input, int inputLen, byte *outBuffer);
+ int blockDecrypt(const byte *input, int inputLen, byte *outBuffer);
+};
+
+#endif // _RIJNDAEL_H_
diff --git a/unrar/unrar/rs.cpp b/unrar/unrar/rs.cpp
new file mode 100644
index 0000000..9eed7a2
--- /dev/null
+++ b/unrar/unrar/rs.cpp
@@ -0,0 +1,143 @@
+#include "rar.hpp"
+
+#define Clean(D,S) {for (int I=0;I<(S);I++) (D)[I]=0;}
+
+RSCoder::RSCoder(int ParSize)
+{
+ RSCoder::ParSize=ParSize;
+ FirstBlockDone=false;
+ gfInit();
+ pnInit();
+}
+
+
+void RSCoder::gfInit()
+{
+ for (int I=0,J=1;I<MAXPAR;I++)
+ {
+ gfLog[J]=I;
+ gfExp[I]=J;
+ if ((J<<=1)&256)
+ J^=285;
+ }
+ for (int I=MAXPAR;I<MAXPOL;I++)
+ gfExp[I]=gfExp[I-MAXPAR];
+}
+
+
+inline int RSCoder::gfMult(int a,int b)
+{
+ return(a==0 || b == 0 ? 0:gfExp[gfLog[a]+gfLog[b]]);
+}
+
+
+void RSCoder::pnInit()
+{
+ int p1[MAXPAR+1],p2[MAXPAR+1];
+
+ Clean(p2,ParSize);
+ p2[0]=1;
+ for (int I=1;I<=ParSize;I++)
+ {
+ Clean(p1,ParSize);
+ p1[0]=gfExp[I];
+ p1[1]=1;
+ pnMult(p1,p2,GXPol);
+ for (int J=0;J<ParSize;J++)
+ p2[J]=GXPol[J];
+ }
+}
+
+
+void RSCoder::pnMult(int *p1,int *p2,int *r)
+{
+ Clean(r,ParSize);
+ for (int I=0;I<ParSize;I++)
+ if (p1[I]!=0)
+ for(int J=0;J<ParSize-I;J++)
+ r[I+J]^=gfMult(p1[I],p2[J]);
+}
+
+
+void RSCoder::Encode(byte *Data,int DataSize,byte *DestData)
+{
+ int ShiftReg[MAXPAR+1];
+
+ Clean(ShiftReg,ParSize+1);
+ for (int I=0;I<DataSize;I++)
+ {
+ int D=Data[I]^ShiftReg[ParSize-1];
+ for (int J=ParSize-1;J>0;J--)
+ ShiftReg[J]=ShiftReg[J-1]^gfMult(GXPol[J],D);
+ ShiftReg[0]=gfMult(GXPol[0],D);
+ }
+ for (int I=0;I<ParSize;I++)
+ DestData[I]=ShiftReg[ParSize-I-1];
+}
+
+
+bool RSCoder::Decode(byte *Data,int DataSize,int *EraLoc,int EraSize)
+{
+ int SynData[MAXPOL];
+ bool AllZeroes=true;
+ for (int I=0;I<ParSize;I++)
+ {
+ int Sum=Data[0],J=1,Exp=gfExp[I+1];
+ for (;J+8<=DataSize;J+=8)
+ {
+ Sum=Data[J]^gfMult(Exp,Sum);
+ Sum=Data[J+1]^gfMult(Exp,Sum);
+ Sum=Data[J+2]^gfMult(Exp,Sum);
+ Sum=Data[J+3]^gfMult(Exp,Sum);
+ Sum=Data[J+4]^gfMult(Exp,Sum);
+ Sum=Data[J+5]^gfMult(Exp,Sum);
+ Sum=Data[J+6]^gfMult(Exp,Sum);
+ Sum=Data[J+7]^gfMult(Exp,Sum);
+ }
+ for (;J<DataSize;J++)
+ Sum=Data[J]^gfMult(Exp,Sum);
+ if ((SynData[I]=Sum)!=0)
+ AllZeroes=false;
+ }
+ if (AllZeroes)
+ return(true);
+
+ if (!FirstBlockDone)
+ {
+ FirstBlockDone=true;
+ Clean(PolB,ParSize+1);
+ PolB[0]=1;
+ for (int EraPos=0;EraPos<EraSize;EraPos++)
+ for (int I=ParSize,M=gfExp[DataSize-EraLoc[EraPos]-1];I>0;I--)
+ PolB[I]^=gfMult(M,PolB[I-1]);
+
+ ErrCount=0;
+ for (int Root=MAXPAR-DataSize;Root<MAXPAR+1;Root++)
+ {
+ int Sum=0;
+ for (int B=0;B<ParSize+1;B++)
+ Sum^=gfMult(gfExp[(B*Root)%MAXPAR],PolB[B]);
+ if (Sum==0)
+ {
+ Dn[ErrCount]=0;
+ for (int I=1;I<ParSize+1;I+=2)
+ Dn[ErrCount]^= gfMult(PolB[I],gfExp[Root*(I-1)%MAXPAR]);
+ ErrorLocs[ErrCount++]=MAXPAR-Root;
+ }
+ }
+ }
+
+ int PolD[MAXPOL];
+ pnMult(PolB,SynData,PolD);
+ if ((ErrCount<=ParSize) && ErrCount>0)
+ for (int I=0;I<ErrCount;I++)
+ {
+ int Loc=ErrorLocs[I],DLoc=MAXPAR-Loc,N=0;
+ for (int J=0;J<ParSize;J++)
+ N^=gfMult(PolD[J],gfExp[DLoc*J%MAXPAR]);
+ int DataPos=DataSize-Loc-1;
+ if (DataPos>=0 && DataPos<DataSize)
+ Data[DataPos]^=gfMult(N,gfExp[MAXPAR-gfLog[Dn[I]]]);
+ }
+ return(ErrCount<=ParSize);
+}
diff --git a/unrar/unrar/rs.hpp b/unrar/unrar/rs.hpp
new file mode 100644
index 0000000..2f099f0
--- /dev/null
+++ b/unrar/unrar/rs.hpp
@@ -0,0 +1,32 @@
+#ifndef _RAR_RS_
+#define _RAR_RS_
+
+#define MAXPAR 255
+#define MAXPOL 512
+
+class RSCoder
+{
+ private:
+ void gfInit();
+ int gfMult(int a,int b);
+ void pnInit();
+ void pnMult(int *p1,int *p2,int *r);
+
+ int gfExp[MAXPOL];
+ int gfLog[MAXPAR+1];
+
+ int GXPol[MAXPOL*2];
+
+ int ErrorLocs[MAXPAR+1],ErrCount;
+ int Dn[MAXPAR+1];
+
+ int ParSize;
+ int PolB[MAXPOL];
+ bool FirstBlockDone;
+ public:
+ RSCoder(int ParSize);
+ void Encode(byte *Data,int DataSize,byte *DestData);
+ bool Decode(byte *Data,int DataSize,int *EraLoc,int EraSize);
+};
+
+#endif
diff --git a/unrar/unrar/savepos.cpp b/unrar/unrar/savepos.cpp
new file mode 100644
index 0000000..e46c4e6
--- /dev/null
+++ b/unrar/unrar/savepos.cpp
@@ -0,0 +1,15 @@
+#include "rar.hpp"
+
+SaveFilePos::SaveFilePos(File &SaveFile)
+{
+ SaveFilePos::SaveFile=&SaveFile;
+ SavePos=SaveFile.Tell();
+ CloseCount=SaveFile.CloseCount;
+}
+
+
+SaveFilePos::~SaveFilePos()
+{
+ if (CloseCount==SaveFile->CloseCount)
+ SaveFile->Seek(SavePos,SEEK_SET);
+}
diff --git a/unrar/unrar/savepos.hpp b/unrar/unrar/savepos.hpp
new file mode 100644
index 0000000..303550a
--- /dev/null
+++ b/unrar/unrar/savepos.hpp
@@ -0,0 +1,15 @@
+#ifndef _RAR_SAVEPOS_
+#define _RAR_SAVEPOS_
+
+class SaveFilePos
+{
+ private:
+ File *SaveFile;
+ Int64 SavePos;
+ uint CloseCount;
+ public:
+ SaveFilePos(File &SaveFile);
+ ~SaveFilePos();
+};
+
+#endif
diff --git a/unrar/unrar/scantree.cpp b/unrar/unrar/scantree.cpp
new file mode 100644
index 0000000..416de6d
--- /dev/null
+++ b/unrar/unrar/scantree.cpp
@@ -0,0 +1,292 @@
+#include "rar.hpp"
+
+ScanTree::ScanTree(StringList *FileMasks,int Recurse,bool GetLinks,int GetDirs)
+{
+ ScanTree::FileMasks=FileMasks;
+ ScanTree::Recurse=Recurse;
+ ScanTree::GetLinks=GetLinks;
+ ScanTree::GetDirs=GetDirs;
+
+ SetAllMaskDepth=0;
+ *CurMask=0;
+ *CurMaskW=0;
+ memset(FindStack,0,sizeof(FindStack));
+ Depth=0;
+ Errors=0;
+ FastFindFile=false;
+ *ErrArcName=0;
+ Cmd=NULL;
+}
+
+
+ScanTree::~ScanTree()
+{
+ for (int I=Depth;I>=0;I--)
+ if (FindStack[I]!=NULL)
+ delete FindStack[I];
+}
+
+
+int ScanTree::GetNext(FindData *FindData)
+{
+ if (Depth<0)
+ return(SCAN_DONE);
+
+ int FindCode;
+ while (1)
+ {
+ if ((*CurMask==0 || FastFindFile && Depth==0) && !PrepareMasks())
+ return(SCAN_DONE);
+ FindCode=FindProc(FindData);
+ if (FindCode==SCAN_ERROR)
+ {
+ Errors++;
+ continue;
+ }
+ if (FindCode==SCAN_NEXT)
+ continue;
+ if (FindCode==SCAN_SUCCESS && FindData->IsDir && GetDirs==SCAN_SKIPDIRS)
+ continue;
+ if (FindCode==SCAN_DONE && PrepareMasks())
+ continue;
+ break;
+ }
+ return(FindCode);
+}
+
+
+bool ScanTree::PrepareMasks()
+{
+ if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
+ return(false);
+ CurMask[ASIZE(CurMask)-1]=0;
+ CurMaskW[ASIZE(CurMaskW)-1]=0;
+#ifdef _WIN_32
+ UnixSlashToDos(CurMask);
+#endif
+ char *Name=PointToName(CurMask);
+ if (*Name==0)
+ strcat(CurMask,MASKALL);
+ if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
+ {
+ AddEndSlash(CurMask);
+ strcat(CurMask,MASKALL);
+ }
+ SpecPathLength=Name-CurMask;
+// if (SpecPathLength>1)
+// SpecPathLength--;
+
+ bool WideName=(*CurMaskW!=0);
+
+ if (WideName)
+ {
+ wchar *NameW=PointToName(CurMaskW);
+ if (*NameW==0)
+ strcatw(CurMaskW,MASKALLW);
+ if (NameW[0]=='.' && (NameW[1]==0 || NameW[1]=='.' && NameW[2]==0))
+ {
+ AddEndSlash(CurMaskW);
+ strcatw(CurMaskW,MASKALLW);
+ }
+ SpecPathLengthW=NameW-CurMaskW;
+ }
+ else
+ {
+ wchar WideMask[NM];
+ CharToWide(CurMask,WideMask);
+ SpecPathLengthW=PointToName(WideMask)-WideMask;
+ }
+ Depth=0;
+
+ strcpy(OrigCurMask,CurMask);
+ strcpyw(OrigCurMaskW,CurMaskW);
+
+ return(true);
+}
+
+
+int ScanTree::FindProc(FindData *FindData)
+{
+ if (*CurMask==0)
+ return(SCAN_NEXT);
+ FastFindFile=false;
+ if (FindStack[Depth]==NULL)
+ {
+ bool Wildcards=IsWildcard(CurMask,CurMaskW);
+ bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
+ bool IsDir=FindCode && FindData->IsDir;
+ bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
+ Wildcards && Recurse==RECURSE_WILDCARDS);
+ if (Depth==0)
+ SearchAllInRoot=SearchAll;
+ if (SearchAll || Wildcards)
+ {
+ FindStack[Depth]=new FindFile;
+ char SearchMask[NM];
+ strcpy(SearchMask,CurMask);
+ if (SearchAll)
+ strcpy(PointToName(SearchMask),MASKALL);
+ FindStack[Depth]->SetMask(SearchMask);
+ if (*CurMaskW)
+ {
+ wchar SearchMaskW[NM];
+ strcpyw(SearchMaskW,CurMaskW);
+ if (SearchAll)
+ strcpyw(PointToName(SearchMaskW),MASKALLW);
+ FindStack[Depth]->SetMaskW(SearchMaskW);
+ }
+ }
+ else
+ {
+ FastFindFile=true;
+ if (!FindCode)
+ {
+ if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
+ return(SCAN_NEXT);
+ ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
+ return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
+ }
+ }
+ }
+
+ if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
+ {
+ bool Error=FindData->Error;
+
+#ifdef _WIN_32
+ if (Error)
+ {
+ // Do not display an error if we cannot scan contents of reparse
+ // point. Vista contains a lot of reparse (or junction) points,
+ // which are not accessible.
+ if ((FindData->FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
+ Error=false;
+
+ // Do not display an error if we cannot scan contents of
+ // "System Volume Information" folder. Normally it is not accessible.
+ if (strstr(CurMask,"System Volume Information\\")!=NULL)
+ Error=false;
+ }
+#endif
+
+ if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
+ Error=false;
+
+#ifndef SILENT
+ if (Error)
+ {
+ Log(NULL,St(MScanError),CurMask);
+ }
+#endif
+
+ char DirName[NM];
+ wchar DirNameW[NM];
+ *DirName=0;
+ *DirNameW=0;
+
+ delete FindStack[Depth];
+ FindStack[Depth--]=NULL;
+ while (Depth>=0 && FindStack[Depth]==NULL)
+ Depth--;
+ if (Depth < 0)
+ {
+ if (Error)
+ Errors++;
+ return(SCAN_DONE);
+ }
+ char *Slash=strrchrd(CurMask,CPATHDIVIDER);
+ if (Slash!=NULL)
+ {
+ char Mask[NM];
+ strcpy(Mask,Slash);
+ if (Depth<SetAllMaskDepth)
+ strcpy(Mask+1,PointToName(OrigCurMask));
+ *Slash=0;
+ strcpy(DirName,CurMask);
+ char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
+ if (PrevSlash==NULL)
+ strcpy(CurMask,Mask+1);
+ else
+ strcpy(PrevSlash,Mask);
+ }
+
+ if (*CurMaskW!=0)
+ {
+ wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER);
+ if (Slash!=NULL)
+ {
+ wchar Mask[NM];
+ strcpyw(Mask,Slash);
+ if (Depth<SetAllMaskDepth)
+ strcpyw(Mask+1,PointToName(OrigCurMaskW));
+ *Slash=0;
+ strcpyw(DirNameW,CurMaskW);
+ wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER);
+ if (PrevSlash==NULL)
+ strcpyw(CurMaskW,Mask+1);
+ else
+ strcpyw(PrevSlash,Mask);
+ }
+#ifndef _WIN_CE
+ if (LowAscii(CurMaskW))
+ *CurMaskW=0;
+#endif
+ }
+ if (GetDirs==SCAN_GETDIRSTWICE &&
+ FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir)
+ return(Error ? SCAN_ERROR:SCAN_SUCCESS);
+ return(Error ? SCAN_ERROR:SCAN_NEXT);
+ }
+
+ if (FindData->IsDir)
+ {
+ if (!FastFindFile && Depth==0 && !SearchAllInRoot)
+ return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);
+
+// if (GetDirs==SCAN_GETCURDIRS && Depth==0 && !SearchAllInRoot)
+// return(SCAN_SUCCESS);
+
+ char Mask[NM];
+ bool MaskAll=FastFindFile;
+
+// bool MaskAll=CmpName(CurMask,FindData->Name,MATCH_NAMES);
+
+ strcpy(Mask,MaskAll ? MASKALL:PointToName(CurMask));
+ strcpy(CurMask,FindData->Name);
+
+ if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
+ {
+#ifndef SILENT
+ Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
+ Log(NULL,St(MPathTooLong));
+#endif
+ return(SCAN_ERROR);
+ }
+
+ AddEndSlash(CurMask);
+ strcat(CurMask,Mask);
+
+ if (*CurMaskW && *FindData->NameW==0)
+ CharToWide(FindData->Name,FindData->NameW);
+ if (*FindData->NameW!=0)
+ {
+ wchar Mask[NM];
+ if (FastFindFile)
+ strcpyw(Mask,MASKALLW);
+ else
+ if (*CurMaskW)
+ strcpyw(Mask,PointToName(CurMaskW));
+ else
+ CharToWide(PointToName(CurMask),Mask);
+ strcpyw(CurMaskW,FindData->NameW);
+ AddEndSlash(CurMaskW);
+ strcatw(CurMaskW,Mask);
+ }
+ Depth++;
+ if (MaskAll)
+ SetAllMaskDepth=Depth;
+ }
+ if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
+ return(SCAN_NEXT);
+ return(SCAN_SUCCESS);
+}
diff --git a/unrar/unrar/scantree.hpp b/unrar/unrar/scantree.hpp
new file mode 100644
index 0000000..2f206ba
--- /dev/null
+++ b/unrar/unrar/scantree.hpp
@@ -0,0 +1,52 @@
+#ifndef _RAR_SCANTREE_
+#define _RAR_SCANTREE_
+
+enum { RECURSE_NONE=0,RECURSE_ALWAYS,RECURSE_WILDCARDS };
+enum { SCAN_SKIPDIRS=0,SCAN_GETDIRS,SCAN_GETDIRSTWICE,SCAN_GETCURDIRS };
+enum { SCAN_SUCCESS,SCAN_DONE,SCAN_ERROR,SCAN_NEXT };
+
+#define MAXSCANDEPTH (NM/2)
+
+class CommandData;
+
+class ScanTree
+{
+ private:
+ bool PrepareMasks();
+ int FindProc(FindData *FindData);
+
+ FindFile *FindStack[MAXSCANDEPTH];
+ int Depth;
+
+ int SetAllMaskDepth;
+
+ StringList *FileMasks;
+ int Recurse;
+ bool GetLinks;
+ int GetDirs;
+ int Errors;
+
+ char CurMask[NM];
+ wchar CurMaskW[NM];
+ char OrigCurMask[NM];
+ wchar OrigCurMaskW[NM];
+ bool SearchAllInRoot;
+ bool FastFindFile;
+ int SpecPathLength;
+ int SpecPathLengthW;
+
+ char ErrArcName[NM];
+
+ CommandData *Cmd;
+ public:
+ ScanTree(StringList *FileMasks,int Recurse,bool GetLinks,int GetDirs);
+ ~ScanTree();
+ int GetNext(FindData *FindData);
+ int GetSpecPathLength() {return(SpecPathLength);};
+ int GetSpecPathLengthW() {return(SpecPathLengthW);};
+ int GetErrors() {return(Errors);};
+ void SetErrArcName(const char *Name) {strcpy(ErrArcName,Name);}
+ void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;}
+};
+
+#endif
diff --git a/unrar/unrar/sha1.cpp b/unrar/unrar/sha1.cpp
new file mode 100644
index 0000000..686ff94
--- /dev/null
+++ b/unrar/unrar/sha1.cpp
@@ -0,0 +1,231 @@
+#include "rar.hpp"
+
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
+ #if defined(_M_IX86) || defined(_M_I86) || defined(__alpha)
+ #define LITTLE_ENDIAN
+ #else
+ #error "LITTLE_ENDIAN or BIG_ENDIAN must be defined"
+ #endif
+#endif
+
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) {z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);}
+#define R1(v,w,x,y,z,i) {z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);}
+#define R2(v,w,x,y,z,i) {z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);}
+#define R3(v,w,x,y,z,i) {z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);}
+#define R4(v,w,x,y,z,i) {z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);}
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(uint32 state[5], unsigned char buffer[64], bool handsoff)
+{
+ uint32 a, b, c, d, e;
+ typedef union {
+ unsigned char c[64];
+ uint32 l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+static unsigned char workspace[64];
+ if (handsoff)
+ {
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+ }
+ else
+ block = (CHAR64LONG16*)buffer;
+#ifdef SFX_MODULE
+ static int pos[80][5];
+ static bool pinit=false;
+ if (!pinit)
+ {
+ for (int I=0,P=0;I<80;I++,P=(P ? P-1:4))
+ {
+ pos[I][0]=P;
+ pos[I][1]=(P+1)%5;
+ pos[I][2]=(P+2)%5;
+ pos[I][3]=(P+3)%5;
+ pos[I][4]=(P+4)%5;
+ }
+ pinit=true;
+ }
+ uint32 s[5];
+ for (int I=0;I<sizeof(s)/sizeof(s[0]);I++)
+ s[I]=state[I];
+
+ for (int I=0;I<16;I++)
+ R0(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
+ for (int I=16;I<20;I++)
+ R1(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
+ for (int I=20;I<40;I++)
+ R2(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
+ for (int I=40;I<60;I++)
+ R3(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
+ for (int I=60;I<80;I++)
+ R4(s[pos[I][0]],s[pos[I][1]],s[pos[I][2]],s[pos[I][3]],s[pos[I][4]],I);
+
+ for (int I=0;I<sizeof(s)/sizeof(s[0]);I++)
+ state[I]+=s[I];
+#else
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+ memset(&a,0,sizeof(a));
+#endif
+}
+
+
+/* Initialize new context */
+
+void hash_initial(hash_context* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+void hash_process( hash_context * context, unsigned char * data, unsigned len,
+ bool handsoff )
+{
+unsigned int i, j;
+uint blen = ((uint)len)<<3;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += blen) < blen ) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer, handsoff);
+ for ( ; i + 63 < len; i += 64) {
+#ifdef ALLOW_NOT_ALIGNED_INT
+ SHA1Transform(context->state, &data[i], handsoff);
+#else
+ unsigned char buffer[64];
+ memcpy(buffer,data+i,sizeof(buffer));
+ SHA1Transform(context->state, buffer, handsoff);
+ memcpy(data+i,buffer,sizeof(buffer));
+#endif
+#ifdef BIG_ENDIAN
+ if (!handsoff)
+ {
+ unsigned char *d=data+i;
+ for (int k=0;k<64;k+=4)
+ {
+ byte b0=d[k],b1=d[k+1];
+ d[k]=d[k+3];
+ d[k+1]=d[k+2];
+ d[k+2]=b1;
+ d[k+3]=b0;
+ }
+ }
+#endif
+ }
+ j = 0;
+ }
+ else i = 0;
+ if (len > i)
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void hash_final( hash_context* context, uint32 digest[5], bool handsoff)
+{
+uint i, j;
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ unsigned char ch=(unsigned char)'\200';
+ hash_process(context, &ch, 1, handsoff);
+ while ((context->count[0] & 504) != 448) {
+ ch=0;
+ hash_process(context, &ch, 1, handsoff);
+ }
+ hash_process(context, finalcount, 8, handsoff); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 5; i++) {
+ digest[i] = context->state[i] & 0xffffffff;
+ }
+ /* Wipe variables */
+ memset(&i,0,sizeof(i));
+ memset(&j,0,sizeof(j));
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+ if (handsoff)
+ SHA1Transform(context->state, context->buffer, true);
+}
+
+
diff --git a/unrar/unrar/sha1.hpp b/unrar/unrar/sha1.hpp
new file mode 100644
index 0000000..155c62a
--- /dev/null
+++ b/unrar/unrar/sha1.hpp
@@ -0,0 +1,17 @@
+#ifndef _RAR_SHA1_
+#define _RAR_SHA1_
+
+#define HW 5
+
+typedef struct {
+ uint32 state[5];
+ uint32 count[2];
+ unsigned char buffer[64];
+} hash_context;
+
+void hash_initial( hash_context * c );
+void hash_process( hash_context * c, unsigned char * data, unsigned len,
+ bool handsoff);
+void hash_final( hash_context * c, uint32[HW], bool handsoff);
+
+#endif
diff --git a/unrar/unrar/smallfn.cpp b/unrar/unrar/smallfn.cpp
new file mode 100644
index 0000000..51997c5
--- /dev/null
+++ b/unrar/unrar/smallfn.cpp
@@ -0,0 +1,23 @@
+#include "rar.hpp"
+
+int ToPercent(Int64 N1,Int64 N2)
+{
+ if (N2<N1)
+ return(100);
+ return(ToPercentUnlim(N1,N2));
+}
+
+/* allows percent larger than 100 */
+int ToPercentUnlim(Int64 N1,Int64 N2)
+{
+ if (N2==0)
+ return(0);
+ return(int64to32(N1*100/N2));
+}
+
+
+void RARInitData()
+{
+ InitCRC();
+ ErrHandler.Clean();
+}
diff --git a/unrar/unrar/smallfn.hpp b/unrar/unrar/smallfn.hpp
new file mode 100644
index 0000000..83266f0
--- /dev/null
+++ b/unrar/unrar/smallfn.hpp
@@ -0,0 +1,8 @@
+#ifndef _RAR_SMALLFN_
+#define _RAR_SMALLFN_
+
+int ToPercent(Int64 N1,Int64 N2);
+int ToPercentUnlim(Int64 N1,Int64 N2);
+void RARInitData();
+
+#endif
diff --git a/unrar/unrar/strfn.cpp b/unrar/unrar/strfn.cpp
new file mode 100644
index 0000000..4c22799
--- /dev/null
+++ b/unrar/unrar/strfn.cpp
@@ -0,0 +1,199 @@
+#include "rar.hpp"
+
+const char *NullToEmpty(const char *Str)
+{
+ return(Str==NULL ? "":Str);
+}
+
+
+const wchar *NullToEmpty(const wchar *Str)
+{
+ return(Str==NULL ? L"":Str);
+}
+
+
+char *IntNameToExt(const char *Name)
+{
+ static char OutName[NM];
+ IntToExt(Name,OutName);
+ return(OutName);
+}
+
+
+void ExtToInt(const char *Src,char *Dest)
+{
+#if defined(_WIN_32)
+ CharToOem(Src,Dest);
+#else
+ if (Dest!=Src)
+ strcpy(Dest,Src);
+#endif
+}
+
+
+void IntToExt(const char *Src,char *Dest)
+{
+#if defined(_WIN_32)
+ OemToChar(Src,Dest);
+#else
+ if (Dest!=Src)
+ strcpy(Dest,Src);
+#endif
+}
+
+
+char* strlower(char *Str)
+{
+#ifdef _WIN_32
+ CharLower((LPTSTR)Str);
+#else
+ for (char *ChPtr=Str;*ChPtr;ChPtr++)
+ *ChPtr=(char)loctolower(*ChPtr);
+#endif
+ return(Str);
+}
+
+
+char* strupper(char *Str)
+{
+#ifdef _WIN_32
+ CharUpper((LPTSTR)Str);
+#else
+ for (char *ChPtr=Str;*ChPtr;ChPtr++)
+ *ChPtr=(char)loctoupper(*ChPtr);
+#endif
+ return(Str);
+}
+
+
+int stricomp(const char *Str1,const char *Str2)
+{
+ char S1[NM*2],S2[NM*2];
+ strncpyz(S1,Str1,ASIZE(S1));
+ strncpyz(S2,Str2,ASIZE(S2));
+ return(strcmp(strupper(S1),strupper(S2)));
+}
+
+
+int strnicomp(const char *Str1,const char *Str2,int N)
+{
+ char S1[NM*2],S2[NM*2];
+ strncpyz(S1,Str1,ASIZE(S1));
+ strncpyz(S2,Str2,ASIZE(S2));
+ return(strncmp(strupper(S1),strupper(S2),N));
+}
+
+
+char* RemoveEOL(char *Str)
+{
+ for (int I=strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--)
+ Str[I]=0;
+ return(Str);
+}
+
+
+char* RemoveLF(char *Str)
+{
+ for (int I=strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--)
+ Str[I]=0;
+ return(Str);
+}
+
+
+unsigned int loctolower(byte ch)
+{
+#ifdef _WIN_32
+ return((int)CharLower((LPTSTR)ch));
+#else
+ return(tolower(ch));
+#endif
+}
+
+
+unsigned int loctoupper(byte ch)
+{
+#ifdef _WIN_32
+ return((int)CharUpper((LPTSTR)ch));
+#else
+ return(toupper(ch));
+#endif
+}
+
+
+// toupper with English only results. Avoiding Turkish i -> I conversion
+// problem
+int etoupper(int ch)
+{
+ if (ch=='i')
+ return('I');
+ return(toupper(ch));
+}
+
+
+
+
+
+
+bool LowAscii(const char *Str)
+{
+ for (int I=0;Str[I]!=0;I++)
+ if ((byte)Str[I]<32 || (byte)Str[I]>127)
+ return(false);
+ return(true);
+}
+
+
+bool LowAscii(const wchar *Str)
+{
+ for (int I=0;Str[I]!=0;I++)
+ if (Str[I]<32 || Str[I]>127)
+ return(false);
+ return(true);
+}
+
+
+
+
+int stricompc(const char *Str1,const char *Str2)
+{
+#if defined(_UNIX)
+ return(strcmp(Str1,Str2));
+#else
+ return(stricomp(Str1,Str2));
+#endif
+}
+
+
+#ifndef SFX_MODULE
+int stricompcw(const wchar *Str1,const wchar *Str2)
+{
+#if defined(_UNIX)
+ return(strcmpw(Str1,Str2));
+#else
+ return(stricmpw(Str1,Str2));
+#endif
+}
+#endif
+
+
+// safe strncpy: copies maxlen-1 max and always returns zero terminated dest
+char* strncpyz(char *dest, const char *src, size_t maxlen)
+{
+ if (maxlen>0)
+ {
+ strncpy(dest,src,maxlen-1);
+ dest[maxlen-1]=0;
+ }
+ return(dest);
+}
+
+// safe strncpyw: copies maxlen-1 max and always returns zero terminated dest
+wchar* strncpyzw(wchar *dest, const wchar *src, size_t maxlen)
+{
+ if (maxlen>0)
+ {
+ strncpyw(dest,src,maxlen-1);
+ dest[maxlen-1]=0;
+ }
+ return(dest);
+}
diff --git a/unrar/unrar/strfn.hpp b/unrar/unrar/strfn.hpp
new file mode 100644
index 0000000..a167667
--- /dev/null
+++ b/unrar/unrar/strfn.hpp
@@ -0,0 +1,34 @@
+#ifndef _RAR_STRFN_
+#define _RAR_STRFN_
+
+const char *NullToEmpty(const char *Str);
+const wchar *NullToEmpty(const wchar *Str);
+char *IntNameToExt(const char *Name);
+void ExtToInt(const char *Src,char *Dest);
+void IntToExt(const char *Src,char *Dest);
+char* strlower(char *Str);
+char* strupper(char *Str);
+int stricomp(const char *Str1,const char *Str2);
+int strnicomp(const char *Str1,const char *Str2,int N);
+char* RemoveEOL(char *Str);
+char* RemoveLF(char *Str);
+unsigned int loctolower(byte ch);
+unsigned int loctoupper(byte ch);
+
+char* strncpyz(char *dest, const char *src, size_t maxlen);
+wchar* strncpyzw(wchar *dest, const wchar *src, size_t maxlen);
+
+int etoupper(int ch);
+
+
+
+bool LowAscii(const char *Str);
+bool LowAscii(const wchar *Str);
+
+
+int stricompc(const char *Str1,const char *Str2);
+#ifndef SFX_MODULE
+int stricompcw(const wchar *Str1,const wchar *Str2);
+#endif
+
+#endif
diff --git a/unrar/unrar/strlist.cpp b/unrar/unrar/strlist.cpp
new file mode 100644
index 0000000..86cace5
--- /dev/null
+++ b/unrar/unrar/strlist.cpp
@@ -0,0 +1,191 @@
+#include "rar.hpp"
+
+StringList::StringList()
+{
+ Reset();
+}
+
+
+StringList::~StringList()
+{
+}
+
+
+void StringList::Reset()
+{
+ Rewind();
+ StringData.Reset();
+ StringDataW.Reset();
+ PosDataW.Reset();
+ StringsCount=0;
+ SavePosNumber=0;
+}
+
+
+unsigned int StringList::AddString(const char *Str)
+{
+ return(AddString(Str,NULL));
+}
+
+
+unsigned int StringList::AddString(const char *Str,const wchar *StrW)
+{
+ int PrevSize=StringData.Size();
+ StringData.Add(strlen(Str)+1);
+ strcpy(&StringData[PrevSize],Str);
+ if (StrW!=NULL && *StrW!=0)
+ {
+ int PrevPos=PosDataW.Size();
+ PosDataW.Add(1);
+ PosDataW[PrevPos]=PrevSize;
+
+ int PrevSizeW=StringDataW.Size();
+ StringDataW.Add(strlenw(StrW)+1);
+ strcpyw(&StringDataW[PrevSizeW],StrW);
+ }
+ StringsCount++;
+ return(PrevSize);
+}
+
+
+bool StringList::GetString(char *Str,int MaxLength)
+{
+ return(GetString(Str,NULL,MaxLength));
+}
+
+
+bool StringList::GetString(char *Str,wchar *StrW,int MaxLength)
+{
+ char *StrPtr;
+ wchar *StrPtrW;
+ if (Str==NULL || !GetString(&StrPtr,&StrPtrW))
+ return(false);
+ strncpy(Str,StrPtr,MaxLength);
+ if (StrW!=NULL)
+ strncpyw(StrW,NullToEmpty(StrPtrW),MaxLength);
+ return(true);
+}
+
+
+#ifndef SFX_MODULE
+bool StringList::GetString(char *Str,wchar *StrW,int MaxLength,int StringNum)
+{
+ SavePosition();
+ Rewind();
+ bool RetCode=true;
+ while (StringNum-- >=0)
+ if (!GetString(Str,StrW,MaxLength))
+ {
+ RetCode=false;
+ break;
+ }
+ RestorePosition();
+ return(RetCode);
+}
+#endif
+
+
+char* StringList::GetString()
+{
+ char *Str;
+ GetString(&Str,NULL);
+ return(Str);
+}
+
+
+
+bool StringList::GetString(char **Str,wchar **StrW)
+{
+ if (CurPos>=StringData.Size())
+ {
+ *Str=NULL;
+ return(false);
+ }
+ *Str=&StringData[CurPos];
+ if (PosDataItem<PosDataW.Size() && PosDataW[PosDataItem]==CurPos)
+ {
+ PosDataItem++;
+ if (StrW!=NULL)
+ *StrW=&StringDataW[CurPosW];
+ CurPosW+=strlenw(&StringDataW[CurPosW])+1;
+ }
+ else
+ if (StrW!=NULL)
+ *StrW=NULL;
+ CurPos+=strlen(*Str)+1;
+ return(true);
+}
+
+
+char* StringList::GetString(unsigned int StringPos)
+{
+ if (StringPos>=StringData.Size())
+ return(NULL);
+ return(&StringData[StringPos]);
+}
+
+
+void StringList::Rewind()
+{
+ CurPos=0;
+ CurPosW=0;
+ PosDataItem=0;
+}
+
+
+int StringList::GetBufferSize()
+{
+ return(StringData.Size()+StringDataW.Size());
+}
+
+
+#ifndef SFX_MODULE
+bool StringList::Search(char *Str,wchar *StrW,bool CaseSensitive)
+{
+ SavePosition();
+ Rewind();
+ bool Found=false;
+ char *CurStr;
+ wchar *CurStrW;
+ while (GetString(&CurStr,&CurStrW))
+ {
+ if ((CaseSensitive ? strcmp(Str,CurStr):stricomp(Str,CurStr))!=0)
+ continue;
+ if (StrW!=NULL && CurStrW!=NULL)
+ if ((CaseSensitive ? strcmpw(StrW,CurStrW):stricmpw(StrW,CurStrW))!=0)
+ continue;
+ Found=true;
+ break;
+ }
+ RestorePosition();
+ return(Found);
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void StringList::SavePosition()
+{
+ if (SavePosNumber<sizeof(SaveCurPos)/sizeof(SaveCurPos[0]))
+ {
+ SaveCurPos[SavePosNumber]=CurPos;
+ SaveCurPosW[SavePosNumber]=CurPosW;
+ SavePosDataItem[SavePosNumber]=PosDataItem;
+ SavePosNumber++;
+ }
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void StringList::RestorePosition()
+{
+ if (SavePosNumber>0)
+ {
+ SavePosNumber--;
+ CurPos=SaveCurPos[SavePosNumber];
+ CurPosW=SaveCurPosW[SavePosNumber];
+ PosDataItem=SavePosDataItem[SavePosNumber];
+ }
+}
+#endif
diff --git a/unrar/unrar/strlist.hpp b/unrar/unrar/strlist.hpp
new file mode 100644
index 0000000..c4d3b01
--- /dev/null
+++ b/unrar/unrar/strlist.hpp
@@ -0,0 +1,39 @@
+#ifndef _RAR_STRLIST_
+#define _RAR_STRLIST_
+
+class StringList
+{
+ private:
+ Array<char> StringData;
+ unsigned int CurPos;
+
+ Array<wchar> StringDataW;
+ unsigned int CurPosW;
+
+ Array<int> PosDataW;
+ uint PosDataItem;
+
+ uint StringsCount;
+
+ uint SaveCurPos[16],SaveCurPosW[16],SavePosDataItem[16],SavePosNumber;
+ public:
+ StringList();
+ ~StringList();
+ void Reset();
+ unsigned int AddString(const char *Str);
+ unsigned int AddString(const char *Str,const wchar *StrW);
+ bool GetString(char *Str,int MaxLength);
+ bool GetString(char *Str,wchar *StrW,int MaxLength);
+ bool GetString(char *Str,wchar *StrW,int MaxLength,int StringNum);
+ char* GetString();
+ bool GetString(char **Str,wchar **StrW);
+ char* GetString(unsigned int StringPos);
+ void Rewind();
+ unsigned int ItemsCount() {return(StringsCount);};
+ int GetBufferSize();
+ bool Search(char *Str,wchar *StrW,bool CaseSensitive);
+ void SavePosition();
+ void RestorePosition();
+};
+
+#endif
diff --git a/unrar/unrar/suballoc.cpp b/unrar/unrar/suballoc.cpp
new file mode 100644
index 0000000..0d42de5
--- /dev/null
+++ b/unrar/unrar/suballoc.cpp
@@ -0,0 +1,258 @@
+/****************************************************************************
+ * This file is part of PPMd project *
+ * Written and distributed to public domain by Dmitry Shkarin 1997, *
+ * 1999-2000 *
+ * Contents: memory allocation routines *
+ ****************************************************************************/
+
+SubAllocator::SubAllocator()
+{
+ Clean();
+}
+
+
+void SubAllocator::Clean()
+{
+ SubAllocatorSize=0;
+}
+
+
+inline void SubAllocator::InsertNode(void* p,int indx)
+{
+ ((RAR_NODE*) p)->next=FreeList[indx].next;
+ FreeList[indx].next=(RAR_NODE*) p;
+}
+
+
+inline void* SubAllocator::RemoveNode(int indx)
+{
+ RAR_NODE* RetVal=FreeList[indx].next;
+ FreeList[indx].next=RetVal->next;
+ return RetVal;
+}
+
+
+inline uint SubAllocator::U2B(int NU)
+{
+ return /*8*NU+4*NU*/UNIT_SIZE*NU;
+}
+
+
+/*
+ calculate RAR_MEM_BLK + Items address. Real RAR_MEM_BLK size must be
+ equal to UNIT_SIZE, so we cannot just add Items to RAR_MEM_BLK address
+*/
+inline RAR_MEM_BLK* SubAllocator::MBPtr(RAR_MEM_BLK *BasePtr,int Items)
+{
+ return((RAR_MEM_BLK*)( ((byte *)(BasePtr))+U2B(Items) ));
+}
+
+
+inline void SubAllocator::SplitBlock(void* pv,int OldIndx,int NewIndx)
+{
+ int i, UDiff=Indx2Units[OldIndx]-Indx2Units[NewIndx];
+ byte* p=((byte*) pv)+U2B(Indx2Units[NewIndx]);
+ if (Indx2Units[i=Units2Indx[UDiff-1]] != UDiff)
+ {
+ InsertNode(p,--i);
+ p += U2B(i=Indx2Units[i]);
+ UDiff -= i;
+ }
+ InsertNode(p,Units2Indx[UDiff-1]);
+}
+
+
+
+
+void SubAllocator::StopSubAllocator()
+{
+ if ( SubAllocatorSize )
+ {
+ SubAllocatorSize=0;
+ rarfree(HeapStart);
+ }
+}
+
+
+bool SubAllocator::StartSubAllocator(int SASize)
+{
+ uint t=SASize << 20;
+ if (SubAllocatorSize == t)
+ return TRUE;
+ StopSubAllocator();
+ uint AllocSize=t/FIXED_UNIT_SIZE*UNIT_SIZE+UNIT_SIZE;
+#ifdef STRICT_ALIGNMENT_REQUIRED
+ AllocSize+=UNIT_SIZE;
+#endif
+ if ((HeapStart=(byte *)rarmalloc(AllocSize)) == NULL)
+ {
+ ErrHandler.MemoryError();
+ return FALSE;
+ }
+ HeapEnd=HeapStart+AllocSize-UNIT_SIZE;
+ SubAllocatorSize=t;
+ return TRUE;
+}
+
+
+void SubAllocator::InitSubAllocator()
+{
+ int i, k;
+ memset(FreeList,0,sizeof(FreeList));
+ pText=HeapStart;
+ uint Size2=FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7);
+ uint RealSize2=Size2/FIXED_UNIT_SIZE*UNIT_SIZE;
+ uint Size1=SubAllocatorSize-Size2;
+ uint RealSize1=Size1/FIXED_UNIT_SIZE*UNIT_SIZE+Size1%FIXED_UNIT_SIZE;
+#ifdef STRICT_ALIGNMENT_REQUIRED
+ if (Size1%FIXED_UNIT_SIZE!=0)
+ RealSize1+=UNIT_SIZE-Size1%FIXED_UNIT_SIZE;
+#endif
+ HiUnit=HeapStart+SubAllocatorSize;
+ LoUnit=UnitsStart=HeapStart+RealSize1;
+ FakeUnitsStart=HeapStart+Size1;
+ HiUnit=LoUnit+RealSize2;
+ for (i=0,k=1;i < N1 ;i++,k += 1)
+ Indx2Units[i]=k;
+ for (k++;i < N1+N2 ;i++,k += 2)
+ Indx2Units[i]=k;
+ for (k++;i < N1+N2+N3 ;i++,k += 3)
+ Indx2Units[i]=k;
+ for (k++;i < N1+N2+N3+N4;i++,k += 4)
+ Indx2Units[i]=k;
+ for (GlueCount=k=i=0;k < 128;k++)
+ {
+ i += (Indx2Units[i] < k+1);
+ Units2Indx[k]=i;
+ }
+}
+
+
+inline void SubAllocator::GlueFreeBlocks()
+{
+ RAR_MEM_BLK s0, * p, * p1;
+ int i, k, sz;
+ if (LoUnit != HiUnit)
+ *LoUnit=0;
+ for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++)
+ while ( FreeList[i].next )
+ {
+ p=(RAR_MEM_BLK*)RemoveNode(i);
+ p->insertAt(&s0);
+ p->Stamp=0xFFFF;
+ p->NU=Indx2Units[i];
+ }
+ for (p=s0.next;p != &s0;p=p->next)
+ while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU < 0x10000)
+ {
+ p1->remove();
+ p->NU += p1->NU;
+ }
+ while ((p=s0.next) != &s0)
+ {
+ for (p->remove(), sz=p->NU;sz > 128;sz -= 128, p=MBPtr(p,128))
+ InsertNode(p,N_INDEXES-1);
+ if (Indx2Units[i=Units2Indx[sz-1]] != sz)
+ {
+ k=sz-Indx2Units[--i];
+ InsertNode(MBPtr(p,sz-k),k-1);
+ }
+ InsertNode(p,i);
+ }
+}
+
+void* SubAllocator::AllocUnitsRare(int indx)
+{
+ if ( !GlueCount )
+ {
+ GlueCount = 255;
+ GlueFreeBlocks();
+ if ( FreeList[indx].next )
+ return RemoveNode(indx);
+ }
+ int i=indx;
+ do
+ {
+ if (++i == N_INDEXES)
+ {
+ GlueCount--;
+ i=U2B(Indx2Units[indx]);
+ int j=FIXED_UNIT_SIZE*Indx2Units[indx];
+ if (FakeUnitsStart-pText > j)
+ {
+ FakeUnitsStart-=j;
+ UnitsStart -= i;
+ return(UnitsStart);
+ }
+ return(NULL);
+ }
+ } while ( !FreeList[i].next );
+ void* RetVal=RemoveNode(i);
+ SplitBlock(RetVal,i,indx);
+ return RetVal;
+}
+
+
+inline void* SubAllocator::AllocUnits(int NU)
+{
+ int indx=Units2Indx[NU-1];
+ if ( FreeList[indx].next )
+ return RemoveNode(indx);
+ void* RetVal=LoUnit;
+ LoUnit += U2B(Indx2Units[indx]);
+ if (LoUnit <= HiUnit)
+ return RetVal;
+ LoUnit -= U2B(Indx2Units[indx]);
+ return AllocUnitsRare(indx);
+}
+
+
+void* SubAllocator::AllocContext()
+{
+ if (HiUnit != LoUnit)
+ return (HiUnit -= UNIT_SIZE);
+ if ( FreeList->next )
+ return RemoveNode(0);
+ return AllocUnitsRare(0);
+}
+
+
+void* SubAllocator::ExpandUnits(void* OldPtr,int OldNU)
+{
+ int i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1];
+ if (i0 == i1)
+ return OldPtr;
+ void* ptr=AllocUnits(OldNU+1);
+ if ( ptr )
+ {
+ memcpy(ptr,OldPtr,U2B(OldNU));
+ InsertNode(OldPtr,i0);
+ }
+ return ptr;
+}
+
+
+void* SubAllocator::ShrinkUnits(void* OldPtr,int OldNU,int NewNU)
+{
+ int i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1];
+ if (i0 == i1)
+ return OldPtr;
+ if ( FreeList[i1].next )
+ {
+ void* ptr=RemoveNode(i1);
+ memcpy(ptr,OldPtr,U2B(NewNU));
+ InsertNode(OldPtr,i0);
+ return ptr;
+ }
+ else
+ {
+ SplitBlock(OldPtr,i0,i1);
+ return OldPtr;
+ }
+}
+
+
+void SubAllocator::FreeUnits(void* ptr,int OldNU)
+{
+ InsertNode(ptr,Units2Indx[OldNU-1]);
+}
diff --git a/unrar/unrar/suballoc.hpp b/unrar/unrar/suballoc.hpp
new file mode 100644
index 0000000..474ee59
--- /dev/null
+++ b/unrar/unrar/suballoc.hpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * This file is part of PPMd project *
+ * Written and distributed to public domain by Dmitry Shkarin 1997, *
+ * 1999-2000 *
+ * Contents: interface to memory allocation routines *
+ ****************************************************************************/
+#if !defined(_SUBALLOC_H_)
+#define _SUBALLOC_H_
+
+const int N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4;
+const int N_INDEXES=N1+N2+N3+N4;
+
+#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT_REQUIRED)
+#define _PACK_ATTR __attribute__ ((packed))
+#else
+#define _PACK_ATTR
+#endif /* defined(__GNUC__) */
+
+#ifndef STRICT_ALIGNMENT_REQUIRED
+#pragma pack(1)
+#endif
+
+struct RAR_MEM_BLK
+{
+ ushort Stamp, NU;
+ RAR_MEM_BLK* next, * prev;
+ void insertAt(RAR_MEM_BLK* p)
+ {
+ next=(prev=p)->next;
+ p->next=next->prev=this;
+ }
+ void remove()
+ {
+ prev->next=next;
+ next->prev=prev;
+ }
+} _PACK_ATTR;
+
+#ifndef STRICT_ALIGNMENT_REQUIRED
+#ifdef _AIX
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+#endif
+
+
+struct RAR_NODE
+{
+ RAR_NODE* next;
+};
+
+class SubAllocator
+{
+ private:
+ inline void InsertNode(void* p,int indx);
+ inline void* RemoveNode(int indx);
+ inline uint U2B(int NU);
+ inline void SplitBlock(void* pv,int OldIndx,int NewIndx);
+ uint GetUsedMemory();
+ inline void GlueFreeBlocks();
+ void* AllocUnitsRare(int indx);
+ inline RAR_MEM_BLK* MBPtr(RAR_MEM_BLK *BasePtr,int Items);
+
+ long SubAllocatorSize;
+ byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
+ byte *HeapStart,*LoUnit, *HiUnit;
+ struct RAR_NODE FreeList[N_INDEXES];
+ public:
+ SubAllocator();
+ ~SubAllocator() {StopSubAllocator();}
+ void Clean();
+ bool StartSubAllocator(int SASize);
+ void StopSubAllocator();
+ void InitSubAllocator();
+ inline void* AllocContext();
+ inline void* AllocUnits(int NU);
+ inline void* ExpandUnits(void* ptr,int OldNU);
+ inline void* ShrinkUnits(void* ptr,int OldNU,int NewNU);
+ inline void FreeUnits(void* ptr,int OldNU);
+ long GetAllocatedMemory() {return(SubAllocatorSize);};
+
+ byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
+};
+
+
+#endif /* !defined(_SUBALLOC_H_) */
diff --git a/unrar/unrar/system.cpp b/unrar/unrar/system.cpp
new file mode 100644
index 0000000..d5de22e
--- /dev/null
+++ b/unrar/unrar/system.cpp
@@ -0,0 +1,96 @@
+#include "rar.hpp"
+
+#ifndef _WIN_CE
+static int SleepTime=0;
+
+void InitSystemOptions(int SleepTime)
+{
+ ::SleepTime=SleepTime;
+}
+#endif
+
+
+#if !defined(SFX_MODULE) && !defined(_WIN_CE)
+
+void SetPriority(int Priority)
+{
+#ifdef _WIN_32
+ uint PriorityClass;
+ int PriorityLevel;
+ if (Priority<1 || Priority>15)
+ return;
+
+ if (Priority==1)
+ {
+ PriorityClass=IDLE_PRIORITY_CLASS;
+ PriorityLevel=THREAD_PRIORITY_IDLE;
+ }
+ else
+ if (Priority<7)
+ {
+ PriorityClass=IDLE_PRIORITY_CLASS;
+ PriorityLevel=Priority-4;
+ }
+ else
+ if (Priority==7)
+ {
+ PriorityClass=BELOW_NORMAL_PRIORITY_CLASS;
+ PriorityLevel=THREAD_PRIORITY_ABOVE_NORMAL;
+ }
+ else
+ if (Priority<10)
+ {
+ PriorityClass=NORMAL_PRIORITY_CLASS;
+ PriorityLevel=Priority-7;
+ }
+ else
+ if (Priority==10)
+ {
+ PriorityClass=ABOVE_NORMAL_PRIORITY_CLASS;
+ PriorityLevel=THREAD_PRIORITY_NORMAL;
+ }
+ else
+ {
+ PriorityClass=HIGH_PRIORITY_CLASS;
+ PriorityLevel=Priority-13;
+ }
+ SetPriorityClass(GetCurrentProcess(),PriorityClass);
+ SetThreadPriority(GetCurrentThread(),PriorityLevel);
+
+// background mode for Vista, too slow for real life use
+// if (WinNT()>=6 && Priority==1)
+// SetPriorityClass(GetCurrentProcess(),PROCESS_MODE_BACKGROUND_BEGIN);
+
+#endif
+}
+#endif
+
+
+void Wait()
+{
+#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
+ if (SleepTime!=0)
+ Sleep(SleepTime);
+#endif
+}
+
+
+
+
+#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
+
+void Shutdown()
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tkp;
+ if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
+ {
+ LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
+ tkp.PrivilegeCount = 1;
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
+ }
+ ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE|EWX_POWEROFF,SHTDN_REASON_FLAG_PLANNED);
+}
+#endif
diff --git a/unrar/unrar/system.hpp b/unrar/unrar/system.hpp
new file mode 100644
index 0000000..d98e5a2
--- /dev/null
+++ b/unrar/unrar/system.hpp
@@ -0,0 +1,26 @@
+#ifndef _RAR_SYSTEM_
+#define _RAR_SYSTEM_
+
+#ifdef _WIN_32
+#ifndef BELOW_NORMAL_PRIORITY_CLASS
+#define BELOW_NORMAL_PRIORITY_CLASS 0x00004000
+#define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
+#endif
+#ifndef PROCESS_MODE_BACKGROUND_BEGIN
+#define PROCESS_MODE_BACKGROUND_BEGIN 0x00100000
+#define PROCESS_MODE_BACKGROUND_END 0x00200000
+#endif
+#ifndef SHTDN_REASON_MAJOR_APPLICATION
+#define SHTDN_REASON_MAJOR_APPLICATION 0x00040000
+#define SHTDN_REASON_FLAG_PLANNED 0x80000000
+#define SHTDN_REASON_MINOR_MAINTENANCE 0x00000001
+#endif
+#endif
+
+void InitSystemOptions(int SleepTime);
+void SetPriority(int Priority);
+void Wait();
+bool EmailFile(char *FileName,char *MailTo);
+void Shutdown();
+
+#endif
diff --git a/unrar/unrar/timefn.cpp b/unrar/unrar/timefn.cpp
new file mode 100644
index 0000000..d11c663
--- /dev/null
+++ b/unrar/unrar/timefn.cpp
@@ -0,0 +1,288 @@
+#include "rar.hpp"
+
+RarTime::RarTime()
+{
+ Reset();
+}
+
+#ifdef _WIN_32
+RarTime& RarTime::operator =(FILETIME &ft)
+{
+ FILETIME lft,zft;
+ FileTimeToLocalFileTime(&ft,&lft);
+ SYSTEMTIME st;
+ FileTimeToSystemTime(&lft,&st);
+ rlt.Year=st.wYear;
+ rlt.Month=st.wMonth;
+ rlt.Day=st.wDay;
+ rlt.Hour=st.wHour;
+ rlt.Minute=st.wMinute;
+ rlt.Second=st.wSecond;
+ rlt.wDay=st.wDayOfWeek;
+ rlt.yDay=rlt.Day-1;
+ for (int I=1;I<rlt.Month;I++)
+ {
+ static int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
+ rlt.yDay+=mdays[I-1];
+ }
+ if (rlt.Month>2 && IsLeapYear(rlt.Year))
+ rlt.yDay++;
+
+ st.wMilliseconds=0;
+ SystemTimeToFileTime(&st,&zft);
+ rlt.Reminder=lft.dwLowDateTime-zft.dwLowDateTime;
+ return(*this);
+}
+
+
+void RarTime::GetWin32(FILETIME *ft)
+{
+ SYSTEMTIME st;
+ st.wYear=rlt.Year;
+ st.wMonth=rlt.Month;
+ st.wDay=rlt.Day;
+ st.wHour=rlt.Hour;
+ st.wMinute=rlt.Minute;
+ st.wSecond=rlt.Second;
+ st.wMilliseconds=0;
+ FILETIME lft;
+ SystemTimeToFileTime(&st,&lft);
+ lft.dwLowDateTime+=rlt.Reminder;
+ if (lft.dwLowDateTime<rlt.Reminder)
+ lft.dwHighDateTime++;
+ LocalFileTimeToFileTime(&lft,ft);
+}
+#endif
+
+
+#if defined(_UNIX) || defined(_EMX)
+RarTime& RarTime::operator =(time_t ut)
+{
+ struct tm *t;
+ t=localtime(&ut);
+
+ rlt.Year=t->tm_year+1900;
+ rlt.Month=t->tm_mon+1;
+ rlt.Day=t->tm_mday;
+ rlt.Hour=t->tm_hour;
+ rlt.Minute=t->tm_min;
+ rlt.Second=t->tm_sec;
+ rlt.Reminder=0;
+ rlt.wDay=t->tm_wday;
+ rlt.yDay=t->tm_yday;
+ return(*this);
+}
+
+
+time_t RarTime::GetUnix()
+{
+ struct tm t;
+
+ t.tm_sec=rlt.Second;
+ t.tm_min=rlt.Minute;
+ t.tm_hour=rlt.Hour;
+ t.tm_mday=rlt.Day;
+ t.tm_mon=rlt.Month-1;
+ t.tm_year=rlt.Year-1900;
+ t.tm_isdst=-1;
+ return(mktime(&t));
+}
+#endif
+
+
+Int64 RarTime::GetRaw()
+{
+ if (!IsSet())
+ return(0);
+#ifdef _WIN_32
+ FILETIME ft;
+ GetWin32(&ft);
+ return(int32to64(ft.dwHighDateTime,ft.dwLowDateTime));
+#elif defined(_UNIX) || defined(_EMX)
+ time_t ut=GetUnix();
+ return(int32to64(0,ut)*10000000+rlt.Reminder);
+#else
+ return(0);
+#endif
+}
+
+
+#ifndef SFX_MODULE
+void RarTime::SetRaw(Int64 RawTime)
+{
+#ifdef _WIN_32
+ FILETIME ft;
+ ft.dwHighDateTime=int64to32(RawTime>>32);
+ ft.dwLowDateTime=int64to32(RawTime);
+ *this=ft;
+#elif defined(_UNIX) || defined(_EMX)
+ time_t ut=int64to32(RawTime/10000000);
+ *this=ut;
+ rlt.Reminder=int64to32(RawTime%10000000);
+#endif
+}
+#endif
+
+
+bool RarTime::operator == (RarTime &rt)
+{
+ return(rlt.Year==rt.rlt.Year && rlt.Month==rt.rlt.Month &&
+ rlt.Day==rt.rlt.Day && rlt.Hour==rt.rlt.Hour &&
+ rlt.Minute==rt.rlt.Minute && rlt.Second==rt.rlt.Second &&
+ rlt.Reminder==rt.rlt.Reminder);
+}
+
+
+bool RarTime::operator < (RarTime &rt)
+{
+ return(GetRaw()<rt.GetRaw());
+}
+
+
+bool RarTime::operator <= (RarTime &rt)
+{
+ return(*this<rt || *this==rt);
+}
+
+
+bool RarTime::operator > (RarTime &rt)
+{
+ return(GetRaw()>rt.GetRaw());
+}
+
+
+bool RarTime::operator >= (RarTime &rt)
+{
+ return(*this>rt || *this==rt);
+}
+
+
+uint RarTime::GetDos()
+{
+ uint DosTime=(rlt.Second/2)|(rlt.Minute<<5)|(rlt.Hour<<11)|
+ (rlt.Day<<16)|(rlt.Month<<21)|((rlt.Year-1980)<<25);
+ return(DosTime);
+}
+
+
+void RarTime::SetDos(uint DosTime)
+{
+ rlt.Second=(DosTime & 0x1f)*2;
+ rlt.Minute=(DosTime>>5) & 0x3f;
+ rlt.Hour=(DosTime>>11) & 0x1f;
+ rlt.Day=(DosTime>>16) & 0x1f;
+ rlt.Month=(DosTime>>21) & 0x0f;
+ rlt.Year=(DosTime>>25)+1980;
+ rlt.Reminder=0;
+}
+
+
+#if !defined(GUI) || !defined(SFX_MODULE)
+void RarTime::GetText(char *DateStr,bool FullYear)
+{
+ if (FullYear)
+ sprintf(DateStr,"%02u-%02u-%u %02u:%02u",rlt.Day,rlt.Month,rlt.Year,rlt.Hour,rlt.Minute);
+ else
+ sprintf(DateStr,"%02u-%02u-%02u %02u:%02u",rlt.Day,rlt.Month,rlt.Year%100,rlt.Hour,rlt.Minute);
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void RarTime::SetIsoText(char *TimeText)
+{
+ int Field[6];
+ memset(Field,0,sizeof(Field));
+ for (int DigitCount=0;*TimeText!=0;TimeText++)
+ if (isdigit(*TimeText))
+ {
+ int FieldPos=DigitCount<4 ? 0:(DigitCount-4)/2+1;
+ if (FieldPos<sizeof(Field)/sizeof(Field[0]))
+ Field[FieldPos]=Field[FieldPos]*10+*TimeText-'0';
+ DigitCount++;
+ }
+ rlt.Second=Field[5];
+ rlt.Minute=Field[4];
+ rlt.Hour=Field[3];
+ rlt.Day=Field[2]==0 ? 1:Field[2];
+ rlt.Month=Field[1]==0 ? 1:Field[1];
+ rlt.Year=Field[0];
+ rlt.Reminder=0;
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void RarTime::SetAgeText(char *TimeText)
+{
+ uint Seconds=0,Value=0;
+ for (int I=0;TimeText[I]!=0;I++)
+ {
+ int Ch=TimeText[I];
+ if (isdigit(Ch))
+ Value=Value*10+Ch-'0';
+ else
+ {
+ switch(etoupper(Ch))
+ {
+ case 'D':
+ Seconds+=Value*24*3600;
+ break;
+ case 'H':
+ Seconds+=Value*3600;
+ break;
+ case 'M':
+ Seconds+=Value*60;
+ break;
+ case 'S':
+ Seconds+=Value;
+ break;
+ }
+ Value=0;
+ }
+ }
+ SetCurrentTime();
+ Int64 RawTime=GetRaw();
+ SetRaw(RawTime-int32to64(0,Seconds)*10000000);
+}
+#endif
+
+
+#ifndef SFX_MODULE
+void RarTime::SetCurrentTime()
+{
+#ifdef _WIN_32
+ FILETIME ft;
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st,&ft);
+ *this=ft;
+#else
+ time_t st;
+ time(&st);
+ *this=st;
+#endif
+}
+#endif
+
+
+#if !defined(SFX_MODULE) && !defined(_WIN_CE)
+const char *GetMonthName(int Month)
+{
+#ifdef SILENT
+ return("");
+#else
+ static MSGID MonthID[]={
+ MMonthJan,MMonthFeb,MMonthMar,MMonthApr,MMonthMay,MMonthJun,
+ MMonthJul,MMonthAug,MMonthSep,MMonthOct,MMonthNov,MMonthDec
+ };
+ return(St(MonthID[Month]));
+#endif
+}
+#endif
+
+
+bool IsLeapYear(int Year)
+{
+ return((Year&3)==0 && (Year%100!=0 || Year%400==0));
+}
diff --git a/unrar/unrar/timefn.hpp b/unrar/unrar/timefn.hpp
new file mode 100644
index 0000000..9ab5032
--- /dev/null
+++ b/unrar/unrar/timefn.hpp
@@ -0,0 +1,57 @@
+#ifndef _RAR_TIMEFN_
+#define _RAR_TIMEFN_
+
+struct RarLocalTime
+{
+ uint Year;
+ uint Month;
+ uint Day;
+ uint Hour;
+ uint Minute;
+ uint Second;
+ uint Reminder;
+ uint wDay;
+ uint yDay;
+};
+
+
+class RarTime
+{
+ private:
+ Int64 GetRaw();
+ void SetRaw(Int64 RawTime);
+
+ RarLocalTime rlt;
+
+ Int64 Time;
+ public:
+ RarTime();
+#ifdef _WIN_32
+ RarTime& operator =(FILETIME &ft);
+ void GetWin32(FILETIME *ft);
+#endif
+#if defined(_UNIX) || defined(_EMX)
+ RarTime& operator =(time_t ut);
+ time_t GetUnix();
+#endif
+ bool operator == (RarTime &rt);
+ bool operator < (RarTime &rt);
+ bool operator <= (RarTime &rt);
+ bool operator > (RarTime &rt);
+ bool operator >= (RarTime &rt);
+ void GetLocal(RarLocalTime *lt) {*lt=rlt;}
+ void SetLocal(RarLocalTime *lt) {rlt=*lt;}
+ uint GetDos();
+ void SetDos(uint DosTime);
+ void GetText(char *DateStr,bool FullYear);
+ void SetIsoText(char *TimeText);
+ void SetAgeText(char *TimeText);
+ void SetCurrentTime();
+ void Reset() {rlt.Year=0;}
+ bool IsSet() {return(rlt.Year!=0);}
+};
+
+const char *GetMonthName(int Month);
+bool IsLeapYear(int Year);
+
+#endif
diff --git a/unrar/unrar/ulinks.cpp b/unrar/unrar/ulinks.cpp
new file mode 100644
index 0000000..b8d6aa5
--- /dev/null
+++ b/unrar/unrar/ulinks.cpp
@@ -0,0 +1,32 @@
+#include "rar.hpp"
+
+
+
+int ExtractLink(ComprDataIO &DataIO,Archive &Arc,char *DestName,uint &LinkCRC,bool Create)
+{
+#if defined(SAVE_LINKS) && defined(_UNIX)
+ char FileName[NM];
+ if (IsLink(Arc.NewLhd.FileAttr))
+ {
+ int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1);
+ DataIO.UnpRead((byte *)FileName,DataSize);
+ FileName[DataSize]=0;
+ if (Create)
+ {
+ CreatePath(DestName,NULL,true);
+ if (symlink(FileName,DestName)==-1)
+ if (errno==EEXIST)
+ Log(Arc.FileName,St(MSymLinkExists),DestName);
+ else
+ {
+ Log(Arc.FileName,St(MErrCreateLnk),DestName);
+ ErrHandler.SetErrorCode(WARNING);
+ }
+ }
+ int NameSize=Min(DataSize,strlen(FileName));
+ LinkCRC=CRC(0xffffffff,FileName,NameSize);
+ return(1);
+ }
+#endif
+ return(0);
+}
diff --git a/unrar/unrar/ulinks.hpp b/unrar/unrar/ulinks.hpp
new file mode 100644
index 0000000..69b0e9f
--- /dev/null
+++ b/unrar/unrar/ulinks.hpp
@@ -0,0 +1,9 @@
+#ifndef _RAR_ULINKS_
+#define _RAR_ULINKS_
+
+void SaveLinkData(ComprDataIO &DataIO,Archive &TempArc,FileHeader &hd,
+ char *Name);
+int ExtractLink(ComprDataIO &DataIO,Archive &Arc,char *DestName,
+ uint &LinkCRC,bool Create);
+
+#endif
diff --git a/unrar/unrar/unicode.cpp b/unrar/unrar/unicode.cpp
new file mode 100644
index 0000000..83d1187
--- /dev/null
+++ b/unrar/unrar/unicode.cpp
@@ -0,0 +1,493 @@
+#include "rar.hpp"
+
+#if defined(_EMX) && !defined(_DJGPP)
+#include "unios2.cpp"
+#endif
+
+bool WideToChar(const wchar *Src,char *Dest,int DestSize)
+{
+ bool RetCode=true;
+#ifdef _WIN_32
+ if (WideCharToMultiByte(CP_ACP,0,Src,-1,Dest,DestSize,NULL,NULL)==0)
+ RetCode=false;
+#else
+#ifdef _APPLE
+ WideToUtf(Src,Dest,DestSize);
+#else
+#ifdef MBFUNCTIONS
+
+ if (wcstombs(Dest,Src,DestSize)==(size_t)-1)
+ RetCode=false;
+
+ if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlenw(Src)<NM)
+ {
+ /* Workaround for strange Linux Unicode functions bug.
+ Some of wcstombs and mbstowcs implementations in some situations
+ (we are yet to find out what it depends on) can return an empty
+ string and success code if buffer size value is too large.
+ */
+ return(WideToChar(Src,Dest,NM));
+ }
+
+#else
+ if (UnicodeEnabled())
+ {
+#if defined(_EMX) && !defined(_DJGPP)
+ int len=Min(strlenw(Src)+1,DestSize-1);
+ if (uni_fromucs((UniChar*)Src,len,Dest,(size_t*)&DestSize)==-1 ||
+ DestSize>len*2)
+ RetCode=false;
+ Dest[DestSize]=0;
+#endif
+ }
+ else
+ for (int I=0;I<DestSize;I++)
+ {
+ Dest[I]=(char)Src[I];
+ if (Src[I]==0)
+ break;
+ }
+#endif
+#endif
+#endif
+ return(RetCode);
+}
+
+
+bool CharToWide(const char *Src,wchar *Dest,int DestSize)
+{
+ bool RetCode=true;
+#ifdef _WIN_32
+ if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,DestSize)==0)
+ RetCode=false;
+#else
+#ifdef _APPLE
+ UtfToWide(Src,Dest,DestSize);
+#else
+#ifdef MBFUNCTIONS
+
+ if (mbstowcs(Dest,Src,DestSize)==(size_t)-1)
+ RetCode=false;
+
+ if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)<NM)
+ {
+ /* Workaround for strange Linux Unicode functions bug.
+ Some of wcstombs and mbstowcs implementations in some situations
+ (we are yet to find out what it depends on) can return an empty
+ string and success code if buffer size value is too large.
+ */
+ return(CharToWide(Src,Dest,NM));
+ }
+#else
+ if (UnicodeEnabled())
+ {
+#if defined(_EMX) && !defined(_DJGPP)
+ int len=Min(strlen(Src)+1,DestSize-1);
+ if (uni_toucs((char*)Src,len,(UniChar*)Dest,(size_t*)&DestSize)==-1 ||
+ DestSize>len)
+ DestSize=0;
+ RetCode=false;
+#endif
+ }
+ else
+ for (int I=0;I<DestSize;I++)
+ {
+ Dest[I]=(wchar_t)Src[I];
+ if (Src[I]==0)
+ break;
+ }
+#endif
+#endif
+#endif
+ return(RetCode);
+}
+
+
+byte* WideToRaw(const wchar *Src,byte *Dest,int DestSize)
+{
+ for (int I=0;I<DestSize;I++,Src++)
+ {
+ Dest[I*2]=(byte)*Src;
+ Dest[I*2+1]=(byte)(*Src>>8);
+ if (*Src==0)
+ break;
+ }
+ return(Dest);
+}
+
+
+wchar* RawToWide(const byte *Src,wchar *Dest,int DestSize)
+{
+ for (int I=0;I<DestSize;I++)
+ if ((Dest[I]=Src[I*2]+(Src[I*2+1]<<8))==0)
+ break;
+ return(Dest);
+}
+
+
+void WideToUtf(const wchar *Src,char *Dest,int DestSize)
+{
+ DestSize--;
+ while (*Src!=0 && --DestSize>=0)
+ {
+ uint c=*(Src++);
+ if (c<0x80)
+ *(Dest++)=c;
+ else
+ if (c<0x800 && --DestSize>=0)
+ {
+ *(Dest++)=(0xc0|(c>>6));
+ *(Dest++)=(0x80|(c&0x3f));
+ }
+ else
+ if (c<0x10000 && (DestSize-=2)>=0)
+ {
+ *(Dest++)=(0xe0|(c>>12));
+ *(Dest++)=(0x80|((c>>6)&0x3f));
+ *(Dest++)=(0x80|(c&0x3f));
+ }
+ else
+ if (c < 0x200000 && (DestSize-=3)>=0)
+ {
+ *(Dest++)=(0xf0|(c>>18));
+ *(Dest++)=(0x80|((c>>12)&0x3f));
+ *(Dest++)=(0x80|((c>>6)&0x3f));
+ *(Dest++)=(0x80|(c&0x3f));
+ }
+ }
+ *Dest=0;
+}
+
+
+void UtfToWide(const char *Src,wchar *Dest,int DestSize)
+{
+ DestSize--;
+ while (*Src!=0)
+ {
+ uint c=(byte)*(Src++),d;
+ if (c<0x80)
+ d=c;
+ else
+ if ((c>>5)==6)
+ {
+ if ((*Src&0xc0)!=0x80)
+ break;
+ d=((c&0x1f)<<6)|(*Src&0x3f);
+ Src++;
+ }
+ else
+ if ((c>>4)==14)
+ {
+ if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80)
+ break;
+ d=((c&0xf)<<12)|((Src[0]&0x3f)<<6)|(Src[1]&0x3f);
+ Src+=2;
+ }
+ else
+ if ((c>>3)==30)
+ {
+ if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80 || (Src[2]&0xc0)!=0x80)
+ break;
+ d=((c&7)<<18)|((Src[0]&0x3f)<<12)|((Src[1]&0x3f)<<6)|(Src[2]&0x3f);
+ Src+=3;
+ }
+ else
+ break;
+ if (--DestSize<0)
+ break;
+ if (d>0xffff)
+ {
+ if (--DestSize<0 || d>0x10ffff)
+ break;
+ *(Dest++)=((d-0x10000)>>10)+0xd800;
+ *(Dest++)=(d&0x3ff)+0xdc00;
+ }
+ else
+ *(Dest++)=d;
+ }
+ *Dest=0;
+}
+
+
+bool UnicodeEnabled()
+{
+#ifdef UNICODE_SUPPORTED
+ #ifdef _EMX
+ return(uni_ready);
+ #else
+ return(true);
+ #endif
+#else
+ return(false);
+#endif
+}
+
+
+int strlenw(const wchar *str)
+{
+ int length=0;
+ while (*(str++)!=0)
+ length++;
+ return(length);
+}
+
+
+wchar* strcpyw(wchar *dest,const wchar *src)
+{
+ do {
+ *(dest++)=*src;
+ } while (*(src++)!=0);
+ return(dest);
+}
+
+
+wchar* strncpyw(wchar *dest,const wchar *src,int n)
+{
+ do {
+ *(dest++)=*src;
+ } while (*(src++)!=0 && --n > 0);
+ return(dest);
+}
+
+
+wchar* strcatw(wchar *dest,const wchar *src)
+{
+ return(strcpyw(dest+strlenw(dest),src));
+}
+
+
+#ifndef SFX_MODULE
+wchar* strncatw(wchar *dest,const wchar *src,int n)
+{
+ dest+=strlenw(dest);
+ while (true)
+ if (--n<0)
+ {
+ *dest=0;
+ break;
+ }
+ else
+ if ((*(dest++)=*(src++))==0)
+ break;
+ return(dest);
+}
+#endif
+
+
+int strcmpw(const wchar *s1,const wchar *s2)
+{
+ while (*s1==*s2)
+ {
+ if (*s1==0)
+ return(0);
+ s1++;
+ s2++;
+ }
+ return(*s1<*s2 ? -1:1);
+}
+
+
+int strncmpw(const wchar *s1,const wchar *s2,int n)
+{
+ while (n-->0)
+ {
+ if (*s1<*s2)
+ return(-1);
+ if (*s1>*s2)
+ return(-1);
+ if (*s1==0)
+ break;
+ s1++;
+ s2++;
+ }
+ return(0);
+}
+
+
+#ifndef SFX_MODULE
+int stricmpw(const wchar *s1,const wchar *s2)
+{
+ char Ansi1[NM*sizeof(wchar)],Ansi2[NM*sizeof(wchar)];
+ WideToChar(s1,Ansi1,sizeof(Ansi1));
+ WideToChar(s2,Ansi2,sizeof(Ansi2));
+ return(stricomp(Ansi1,Ansi2));
+}
+#endif
+
+
+#if !defined(SFX_MODULE) && !defined(_WIN_CE)
+inline int strnicmpw_w2c(const wchar *s1,const wchar *s2,int n)
+{
+ wchar Wide1[NM*2],Wide2[NM*2];
+ strncpyw(Wide1,s1,sizeof(Wide1)/sizeof(Wide1[0])-1);
+ strncpyw(Wide2,s2,sizeof(Wide2)/sizeof(Wide2[0])-1);
+ Wide1[Min(sizeof(Wide1)/sizeof(Wide1[0])-1,n)]=0;
+ Wide2[Min(sizeof(Wide2)/sizeof(Wide2[0])-1,n)]=0;
+ char Ansi1[NM*2],Ansi2[NM*2];
+ WideToChar(Wide1,Ansi1,sizeof(Ansi1));
+ WideToChar(Wide2,Ansi2,sizeof(Ansi2));
+ return(stricomp(Ansi1,Ansi2));
+}
+#endif
+
+
+#ifndef SFX_MODULE
+int strnicmpw(const wchar *s1,const wchar *s2,int n)
+{
+ return(strnicmpw_w2c(s1,s2,n));
+}
+#endif
+
+
+wchar* strchrw(const wchar *s,int c)
+{
+ while (*s)
+ {
+ if (*s==c)
+ return((wchar *)s);
+ s++;
+ }
+ return(NULL);
+}
+
+
+wchar* strrchrw(const wchar *s,int c)
+{
+ for (int I=strlenw(s)-1;I>=0;I--)
+ if (s[I]==c)
+ return((wchar *)(s+I));
+ return(NULL);
+}
+
+
+wchar* strpbrkw(const wchar *s1,const wchar *s2)
+{
+ while (*s1)
+ {
+ if (strchrw(s2,*s1)!=NULL)
+ return((wchar *)s1);
+ s1++;
+ }
+ return(NULL);
+}
+
+
+#ifndef SFX_MODULE
+wchar* strlowerw(wchar *Str)
+{
+ for (wchar *ChPtr=Str;*ChPtr;ChPtr++)
+ if (*ChPtr<128)
+ *ChPtr=loctolower(*ChPtr);
+ return(Str);
+}
+#endif
+
+
+#ifndef SFX_MODULE
+wchar* strupperw(wchar *Str)
+{
+ for (wchar *ChPtr=Str;*ChPtr;ChPtr++)
+ if (*ChPtr<128)
+ *ChPtr=loctoupper(*ChPtr);
+ return(Str);
+}
+#endif
+
+
+#ifndef SFX_MODULE
+int toupperw(int ch)
+{
+ return((ch<128) ? loctoupper(ch):ch);
+}
+#endif
+
+
+int atoiw(const wchar *s)
+{
+ int n=0;
+ while (*s>='0' && *s<='9')
+ {
+ n=n*10+(*s-'0');
+ s++;
+ }
+ return(n);
+}
+
+
+#ifdef DBCS_SUPPORTED
+SupportDBCS gdbcs;
+
+SupportDBCS::SupportDBCS()
+{
+ Init();
+}
+
+
+void SupportDBCS::Init()
+{
+ CPINFO CPInfo;
+ GetCPInfo(CP_ACP,&CPInfo);
+ DBCSMode=CPInfo.MaxCharSize > 1;
+ for (int I=0;I<sizeof(IsLeadByte)/sizeof(IsLeadByte[0]);I++)
+ IsLeadByte[I]=IsDBCSLeadByte(I);
+}
+
+
+char* SupportDBCS::charnext(const char *s)
+{
+ return (char *)(IsLeadByte[*s] ? s+2:s+1);
+}
+
+
+uint SupportDBCS::strlend(const char *s)
+{
+ uint Length=0;
+ while (*s!=0)
+ {
+ if (IsLeadByte[*s])
+ s+=2;
+ else
+ s++;
+ Length++;
+ }
+ return(Length);
+}
+
+
+char* SupportDBCS::strchrd(const char *s, int c)
+{
+ while (*s!=0)
+ if (IsLeadByte[*s])
+ s+=2;
+ else
+ if (*s==c)
+ return((char *)s);
+ else
+ s++;
+ return(NULL);
+}
+
+
+void SupportDBCS::copychrd(char *dest,const char *src)
+{
+ dest[0]=src[0];
+ if (IsLeadByte[src[0]])
+ dest[1]=src[1];
+}
+
+
+char* SupportDBCS::strrchrd(const char *s, int c)
+{
+ const char *found=NULL;
+ while (*s!=0)
+ if (IsLeadByte[*s])
+ s+=2;
+ else
+ {
+ if (*s==c)
+ found=s;
+ s++;
+ }
+ return((char *)found);
+}
+#endif
diff --git a/unrar/unrar/unicode.hpp b/unrar/unrar/unicode.hpp
new file mode 100644
index 0000000..8175c00
--- /dev/null
+++ b/unrar/unrar/unicode.hpp
@@ -0,0 +1,82 @@
+#ifndef _RAR_UNICODE_
+#define _RAR_UNICODE_
+
+#ifndef _EMX
+#define MBFUNCTIONS
+#endif
+
+#if defined(MBFUNCTIONS) || defined(_WIN_32) || defined(_EMX) && !defined(_DJGPP)
+#define UNICODE_SUPPORTED
+#endif
+
+#ifdef _WIN_32
+#define DBCS_SUPPORTED
+#endif
+
+#ifdef _EMX
+int uni_init(int codepage);
+int uni_done();
+#endif
+
+bool WideToChar(const wchar *Src,char *Dest,int DestSize=0x1000000);
+bool CharToWide(const char *Src,wchar *Dest,int DestSize=0x1000000);
+byte* WideToRaw(const wchar *Src,byte *Dest,int DestSize=0x1000000);
+wchar* RawToWide(const byte *Src,wchar *Dest,int DestSize=0x1000000);
+void WideToUtf(const wchar *Src,char *Dest,int DestSize);
+void UtfToWide(const char *Src,wchar *Dest,int DestSize);
+bool UnicodeEnabled();
+
+int strlenw(const wchar *str);
+wchar* strcpyw(wchar *dest,const wchar *src);
+wchar* strncpyw(wchar *dest,const wchar *src,int n);
+wchar* strcatw(wchar *dest,const wchar *src);
+wchar* strncatw(wchar *dest,const wchar *src,int n);
+int strcmpw(const wchar *s1,const wchar *s2);
+int strncmpw(const wchar *s1,const wchar *s2,int n);
+int stricmpw(const wchar *s1,const wchar *s2);
+int strnicmpw(const wchar *s1,const wchar *s2,int n);
+wchar *strchrw(const wchar *s,int c);
+wchar* strrchrw(const wchar *s,int c);
+wchar* strpbrkw(const wchar *s1,const wchar *s2);
+wchar* strlowerw(wchar *Str);
+wchar* strupperw(wchar *Str);
+int toupperw(int ch);
+int atoiw(const wchar *s);
+
+#ifdef DBCS_SUPPORTED
+class SupportDBCS
+{
+ public:
+ SupportDBCS();
+ void Init();
+
+ char* charnext(const char *s);
+ uint strlend(const char *s);
+ char *strchrd(const char *s, int c);
+ char *strrchrd(const char *s, int c);
+ void copychrd(char *dest,const char *src);
+
+ bool IsLeadByte[256];
+ bool DBCSMode;
+};
+
+extern SupportDBCS gdbcs;
+
+inline char* charnext(const char *s) {return (char *)(gdbcs.DBCSMode ? gdbcs.charnext(s):s+1);}
+inline uint strlend(const char *s) {return (uint)(gdbcs.DBCSMode ? gdbcs.strlend(s):strlen(s));}
+inline char* strchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strchrd(s,c):strchr(s,c));}
+inline char* strrchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strrchrd(s,c):strrchr(s,c));}
+inline void copychrd(char *dest,const char *src) {if (gdbcs.DBCSMode) gdbcs.copychrd(dest,src); else *dest=*src;}
+inline bool IsDBCSMode() {return(gdbcs.DBCSMode);}
+inline void InitDBCS() {gdbcs.Init();}
+
+#else
+#define charnext(s) ((s)+1)
+#define strlend strlen
+#define strchrd strchr
+#define strrchrd strrchr
+#define IsDBCSMode() (true)
+inline void copychrd(char *dest,const char *src) {*dest=*src;}
+#endif
+
+#endif
diff --git a/unrar/unrar/unios2.cpp b/unrar/unrar/unios2.cpp
new file mode 100644
index 0000000..1261473
--- /dev/null
+++ b/unrar/unrar/unios2.cpp
@@ -0,0 +1,128 @@
+// (c) 2001,2004 by Max Alekseyev
+// ver. 2.1
+
+#include <stddef.h>
+
+#define INCL_DOSMODULEMGR
+#include <os2.h>
+
+typedef void* UconvObject;
+typedef unsigned short UniChar;
+
+int uni_init(int codepage);
+
+int uni_done();
+
+int uni_toucs( /* translate to Unicode */
+ char*, /* I - input string */
+ size_t, /* I - length of input string (chars) */
+ UniChar*, /* O - output Unicode string */
+ size_t* ); /* O - length of output string (UniChars) */
+
+int uni_fromucs( /* translate from Unicode */
+ UniChar*, /* I - input Unicode string */
+ size_t, /* I - length of input string (UniChars) */
+ char*, /* O - output string */
+ size_t* ); /* O - length of output string (chars) */
+
+/* IMPLEMENTATION */
+
+static int (*uniMapCpToUcsCp) (
+ unsigned long, /* I - Codepage to convert */
+ UniChar*, /* O - Output buffer */
+ size_t ); /* I - UniChars in output buffer */
+
+static int (*uniCreateUconvObject) (
+ UniChar*, /* I - Unicode name of uconv table */
+ UconvObject* );/* O - Uconv object handle */
+
+static int (*uniFreeUconvObject) (
+ UconvObject ); /* I - Uconv object handle */
+
+static int (*uniUconvToUcs) (
+ UconvObject, /* I - Uconv object handle */
+ void**, /* IO - Input buffer */
+ size_t*, /* IO - Input buffer size (bytes) */
+ UniChar**, /* IO - Output buffer size */
+ size_t*, /* IO - Output size (chars) */
+ size_t* ); /* IO - Substitution count */
+
+static int (*uniUconvFromUcs) (
+ UconvObject, /* I - Uconv object handle */
+ UniChar**, /* IO - Input buffer */
+ size_t*, /* IO - Input buffer size (bytes) */
+ void**, /* IO - Output buffer size */
+ size_t*, /* IO - Output size (chars) */
+ size_t* ); /* IO - Substitution count */
+
+static int uni_ready = 0;
+static HMODULE uni_UCONV;
+static UconvObject uni_obj;
+
+int uni_init(int codepage) {
+ UniChar unistr[256];
+
+ uni_ready = 0;
+
+ if(!&DosLoadModule) {
+ /* DOS enviroment detected */
+ return -1;
+ }
+
+ if( DosLoadModule(0,0,(PCSZ)"UCONV",&uni_UCONV) ) {
+ /* no Unicode API found (obsolete OS/2 version) */
+ return -2;
+ }
+
+ if( !DosQueryProcAddr(uni_UCONV,0,(PCSZ)"UniMapCpToUcsCp", (PPFN)&uniMapCpToUcsCp ) &&
+ !DosQueryProcAddr(uni_UCONV,0,(PCSZ)"UniUconvToUcs", (PPFN)&uniUconvToUcs ) &&
+ !DosQueryProcAddr(uni_UCONV,0,(PCSZ)"UniUconvFromUcs", (PPFN)&uniUconvFromUcs ) &&
+ !DosQueryProcAddr(uni_UCONV,0,(PCSZ)"UniCreateUconvObject",(PPFN)&uniCreateUconvObject) &&
+ !DosQueryProcAddr(uni_UCONV,0,(PCSZ)"UniFreeUconvObject", (PPFN)&uniFreeUconvObject )
+ ) {
+ unistr[0] = 0;
+ if( (!codepage || !uniMapCpToUcsCp(codepage, unistr, 256)) && !uniCreateUconvObject(unistr,&uni_obj) ) {
+ uni_ready = 1;
+ return 0;
+ }
+ }
+ DosFreeModule(uni_UCONV);
+ return -2;
+}
+
+int uni_toucs(char* src, size_t srclen, UniChar* dst, size_t* dstlen) {
+ size_t srcbytes, srcsize, dstsize, subsc=0;
+
+ if(!uni_ready) return -1;
+
+ dstsize = srcbytes = srclen * sizeof(UniChar);
+
+ if( uniUconvToUcs(uni_obj,(void**)&src,&srclen,&dst,&dstsize,&subsc) ) {
+ return -1;
+ }
+ *dstlen = srcbytes - dstsize;
+ return 0;
+}
+
+int uni_fromucs(UniChar* src, size_t srclen, char* dst, size_t* dstlen) {
+ size_t srcbytes, srcsize, dstsize, subsc=0;
+
+ if(!uni_ready) return -1;
+
+ dstsize = srcbytes = *dstlen;
+
+ if( uniUconvFromUcs(uni_obj,&src,&srclen,(void**)&dst,&dstsize,&subsc) ) {
+ return -1;
+ }
+ *dstlen = srcbytes - dstsize;
+ return 0;
+}
+
+int uni_done() {
+ if( uni_ready ) {
+ uniFreeUconvObject(uni_obj);
+ DosFreeModule(uni_UCONV);
+ uni_ready = 0;
+ }
+ return 0;
+}
diff --git a/unrar/unrar/unpack.cpp b/unrar/unrar/unpack.cpp
new file mode 100644
index 0000000..1b239ca
--- /dev/null
+++ b/unrar/unrar/unpack.cpp
@@ -0,0 +1,1004 @@
+#include "rar.hpp"
+
+#include "coder.cpp"
+#include "suballoc.cpp"
+#include "model.cpp"
+#ifndef SFX_MODULE
+#include "unpack15.cpp"
+#include "unpack20.cpp"
+#endif
+
+Unpack::Unpack(ComprDataIO *DataIO)
+{
+ UnpIO=DataIO;
+ Window=NULL;
+ ExternalWindow=false;
+ Suspended=false;
+ UnpAllBuf=false;
+ UnpSomeRead=false;
+}
+
+
+Unpack::~Unpack()
+{
+ if (Window!=NULL && !ExternalWindow)
+ delete[] Window;
+ InitFilters();
+}
+
+
+void Unpack::Init(byte *Window)
+{
+ if (Window==NULL)
+ {
+ Unpack::Window=new byte[MAXWINSIZE];
+#ifndef ALLOW_EXCEPTIONS
+ if (Unpack::Window==NULL)
+ ErrHandler.MemoryError();
+#endif
+ }
+ else
+ {
+ Unpack::Window=Window;
+ ExternalWindow=true;
+ }
+ UnpInitData(false);
+
+#ifndef SFX_MODULE
+ // RAR 1.5 decompression initialization
+ OldUnpInitData(false);
+ InitHuff();
+#endif
+}
+
+
+void Unpack::DoUnpack(int Method,bool Solid)
+{
+ switch(Method)
+ {
+#ifndef SFX_MODULE
+ case 15: // rar 1.5 compression
+ Unpack15(Solid);
+ break;
+ case 20: // rar 2.x compression
+ case 26: // files larger than 2GB
+ Unpack20(Solid);
+ break;
+#endif
+ case 29: // rar 3.x compression
+ case 36: // alternative hash
+ Unpack29(Solid);
+ break;
+ }
+}
+
+
+inline void Unpack::InsertOldDist(unsigned int Distance)
+{
+ OldDist[3]=OldDist[2];
+ OldDist[2]=OldDist[1];
+ OldDist[1]=OldDist[0];
+ OldDist[0]=Distance;
+}
+
+
+inline void Unpack::InsertLastMatch(unsigned int Length,unsigned int Distance)
+{
+ LastDist=Distance;
+ LastLength=Length;
+}
+
+
+void Unpack::CopyString(unsigned int Length,unsigned int Distance)
+{
+ unsigned int DestPtr=UnpPtr-Distance;
+ if (DestPtr<MAXWINSIZE-260 && UnpPtr<MAXWINSIZE-260)
+ {
+ Window[UnpPtr++]=Window[DestPtr++];
+ while (--Length>0)
+ Window[UnpPtr++]=Window[DestPtr++];
+ }
+ else
+ while (Length--)
+ {
+ Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK];
+ UnpPtr=(UnpPtr+1) & MAXWINMASK;
+ }
+}
+
+
+int Unpack::DecodeNumber(struct Decode *Dec)
+{
+ unsigned int Bits;
+ unsigned int BitField=getbits() & 0xfffe;
+ if (BitField<Dec->DecodeLen[8])
+ if (BitField<Dec->DecodeLen[4])
+ if (BitField<Dec->DecodeLen[2])
+ if (BitField<Dec->DecodeLen[1])
+ Bits=1;
+ else
+ Bits=2;
+ else
+ if (BitField<Dec->DecodeLen[3])
+ Bits=3;
+ else
+ Bits=4;
+ else
+ if (BitField<Dec->DecodeLen[6])
+ if (BitField<Dec->DecodeLen[5])
+ Bits=5;
+ else
+ Bits=6;
+ else
+ if (BitField<Dec->DecodeLen[7])
+ Bits=7;
+ else
+ Bits=8;
+ else
+ if (BitField<Dec->DecodeLen[12])
+ if (BitField<Dec->DecodeLen[10])
+ if (BitField<Dec->DecodeLen[9])
+ Bits=9;
+ else
+ Bits=10;
+ else
+ if (BitField<Dec->DecodeLen[11])
+ Bits=11;
+ else
+ Bits=12;
+ else
+ if (BitField<Dec->DecodeLen[14])
+ if (BitField<Dec->DecodeLen[13])
+ Bits=13;
+ else
+ Bits=14;
+ else
+ Bits=15;
+
+ addbits(Bits);
+ unsigned int N=Dec->DecodePos[Bits]+((BitField-Dec->DecodeLen[Bits-1])>>(16-Bits));
+ if (N>=Dec->MaxNum)
+ N=0;
+ return(Dec->DecodeNum[N]);
+}
+
+
+void Unpack::Unpack29(bool Solid)
+{
+ static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
+ static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
+ static int DDecode[DC];
+ static byte DBits[DC];
+ static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
+ static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
+ static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
+ unsigned int Bits;
+
+ if (DDecode[1]==0)
+ {
+ int Dist=0,BitLength=0,Slot=0;
+ for (int I=0;I<sizeof(DBitLengthCounts)/sizeof(DBitLengthCounts[0]);I++,BitLength++)
+ for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
+ {
+ DDecode[Slot]=Dist;
+ DBits[Slot]=BitLength;
+ }
+ }
+
+ FileExtracted=true;
+
+ if (!Suspended)
+ {
+ UnpInitData(Solid);
+ if (!UnpReadBuf())
+ return;
+ if ((!Solid || !TablesRead) && !ReadTables())
+ return;
+ }
+
+ while (true)
+ {
+ UnpPtr&=MAXWINMASK;
+
+ if (InAddr>ReadBorder)
+ {
+ if (!UnpReadBuf())
+ break;
+ }
+ if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr)
+ {
+ UnpWriteBuf();
+ if (WrittenFileSize>DestUnpSize)
+ return;
+ if (Suspended)
+ {
+ FileExtracted=false;
+ return;
+ }
+ }
+ if (UnpBlockType==BLOCK_PPM)
+ {
+ int Ch=PPM.DecodeChar();
+ if (Ch==-1)
+ {
+ PPM.CleanUp();
+
+ // turn off PPM compression mode in case of error, so UnRAR will
+ // call PPM.DecodeInit in case it needs to turn it on back later.
+ UnpBlockType=BLOCK_LZ;
+ break;
+ }
+ if (Ch==PPMEscChar)
+ {
+ int NextCh=PPM.DecodeChar();
+ if (NextCh==0)
+ {
+ if (!ReadTables())
+ break;
+ continue;
+ }
+ if (NextCh==2 || NextCh==-1)
+ break;
+ if (NextCh==3)
+ {
+ if (!ReadVMCodePPM())
+ break;
+ continue;
+ }
+ if (NextCh==4)
+ {
+ unsigned int Distance=0,Length;
+ bool Failed=false;
+ for (int I=0;I<4 && !Failed;I++)
+ {
+ int Ch=PPM.DecodeChar();
+ if (Ch==-1)
+ Failed=true;
+ else
+ if (I==3)
+ Length=(byte)Ch;
+ else
+ Distance=(Distance<<8)+(byte)Ch;
+ }
+ if (Failed)
+ break;
+ CopyString(Length+32,Distance+2);
+ continue;
+ }
+ if (NextCh==5)
+ {
+ int Length=PPM.DecodeChar();
+ if (Length==-1)
+ break;
+ CopyString(Length+4,1);
+ continue;
+ }
+ }
+ Window[UnpPtr++]=Ch;
+ continue;
+ }
+
+ int Number=DecodeNumber((struct Decode *)&LD);
+ if (Number<256)
+ {
+ Window[UnpPtr++]=(byte)Number;
+ continue;
+ }
+ if (Number>=271)
+ {
+ int Length=LDecode[Number-=271]+3;
+ if ((Bits=LBits[Number])>0)
+ {
+ Length+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+
+ int DistNumber=DecodeNumber((struct Decode *)&DD);
+ unsigned int Distance=DDecode[DistNumber]+1;
+ if ((Bits=DBits[DistNumber])>0)
+ {
+ if (DistNumber>9)
+ {
+ if (Bits>4)
+ {
+ Distance+=((getbits()>>(20-Bits))<<4);
+ addbits(Bits-4);
+ }
+ if (LowDistRepCount>0)
+ {
+ LowDistRepCount--;
+ Distance+=PrevLowDist;
+ }
+ else
+ {
+ int LowDist=DecodeNumber((struct Decode *)&LDD);
+ if (LowDist==16)
+ {
+ LowDistRepCount=LOW_DIST_REP_COUNT-1;
+ Distance+=PrevLowDist;
+ }
+ else
+ {
+ Distance+=LowDist;
+ PrevLowDist=LowDist;
+ }
+ }
+ }
+ else
+ {
+ Distance+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+ }
+
+ if (Distance>=0x2000)
+ {
+ Length++;
+ if (Distance>=0x40000L)
+ Length++;
+ }
+
+ InsertOldDist(Distance);
+ InsertLastMatch(Length,Distance);
+ CopyString(Length,Distance);
+ continue;
+ }
+ if (Number==256)
+ {
+ if (!ReadEndOfBlock())
+ break;
+ continue;
+ }
+ if (Number==257)
+ {
+ if (!ReadVMCode())
+ break;
+ continue;
+ }
+ if (Number==258)
+ {
+ if (LastLength!=0)
+ CopyString(LastLength,LastDist);
+ continue;
+ }
+ if (Number<263)
+ {
+ int DistNum=Number-259;
+ unsigned int Distance=OldDist[DistNum];
+ for (int I=DistNum;I>0;I--)
+ OldDist[I]=OldDist[I-1];
+ OldDist[0]=Distance;
+
+ int LengthNumber=DecodeNumber((struct Decode *)&RD);
+ int Length=LDecode[LengthNumber]+2;
+ if ((Bits=LBits[LengthNumber])>0)
+ {
+ Length+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+ InsertLastMatch(Length,Distance);
+ CopyString(Length,Distance);
+ continue;
+ }
+ if (Number<272)
+ {
+ unsigned int Distance=SDDecode[Number-=263]+1;
+ if ((Bits=SDBits[Number])>0)
+ {
+ Distance+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+ InsertOldDist(Distance);
+ InsertLastMatch(2,Distance);
+ CopyString(2,Distance);
+ continue;
+ }
+ }
+ UnpWriteBuf();
+}
+
+
+bool Unpack::ReadEndOfBlock()
+{
+ unsigned int BitField=getbits();
+ bool NewTable,NewFile=false;
+ if (BitField & 0x8000)
+ {
+ NewTable=true;
+ addbits(1);
+ }
+ else
+ {
+ NewFile=true;
+ NewTable=(BitField & 0x4000);
+ addbits(2);
+ }
+ TablesRead=!NewTable;
+ return !(NewFile || NewTable && !ReadTables());
+}
+
+
+bool Unpack::ReadVMCode()
+{
+ unsigned int FirstByte=getbits()>>8;
+ addbits(8);
+ int Length=(FirstByte & 7)+1;
+ if (Length==7)
+ {
+ Length=(getbits()>>8)+7;
+ addbits(8);
+ }
+ else
+ if (Length==8)
+ {
+ Length=getbits();
+ addbits(16);
+ }
+ Array<byte> VMCode(Length);
+ for (int I=0;I<Length;I++)
+ {
+ if (InAddr>=ReadTop-1 && !UnpReadBuf() && I<Length-1)
+ return(false);
+ VMCode[I]=getbits()>>8;
+ addbits(8);
+ }
+ return(AddVMCode(FirstByte,&VMCode[0],Length));
+}
+
+
+bool Unpack::ReadVMCodePPM()
+{
+ unsigned int FirstByte=PPM.DecodeChar();
+ if ((int)FirstByte==-1)
+ return(false);
+ int Length=(FirstByte & 7)+1;
+ if (Length==7)
+ {
+ int B1=PPM.DecodeChar();
+ if (B1==-1)
+ return(false);
+ Length=B1+7;
+ }
+ else
+ if (Length==8)
+ {
+ int B1=PPM.DecodeChar();
+ if (B1==-1)
+ return(false);
+ int B2=PPM.DecodeChar();
+ if (B2==-1)
+ return(false);
+ Length=B1*256+B2;
+ }
+ Array<byte> VMCode(Length);
+ for (int I=0;I<Length;I++)
+ {
+ int Ch=PPM.DecodeChar();
+ if (Ch==-1)
+ return(false);
+ VMCode[I]=Ch;
+ }
+ return(AddVMCode(FirstByte,&VMCode[0],Length));
+}
+
+
+bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
+{
+ BitInput Inp;
+ Inp.InitBitInput();
+ memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
+ VM.Init();
+
+ uint FiltPos;
+ if (FirstByte & 0x80)
+ {
+ FiltPos=RarVM::ReadData(Inp);
+ if (FiltPos==0)
+ InitFilters();
+ else
+ FiltPos--;
+ }
+ else
+ FiltPos=LastFilter; // use the same filter as last time
+
+ if (FiltPos>Filters.Size() || FiltPos>OldFilterLengths.Size())
+ return(false);
+ LastFilter=FiltPos;
+ bool NewFilter=(FiltPos==Filters.Size());
+
+ UnpackFilter *StackFilter=new UnpackFilter; // new filter for PrgStack
+
+ UnpackFilter *Filter;
+ if (NewFilter) // new filter code, never used before since VM reset
+ {
+ // too many different filters, corrupt archive
+ if (FiltPos>1024)
+ return(false);
+
+ Filters.Add(1);
+ Filters[Filters.Size()-1]=Filter=new UnpackFilter;
+ StackFilter->ParentFilter=Filters.Size()-1;
+ OldFilterLengths.Add(1);
+ Filter->ExecCount=0;
+ }
+ else // filter was used in the past
+ {
+ Filter=Filters[FiltPos];
+ StackFilter->ParentFilter=FiltPos;
+ Filter->ExecCount++;
+ }
+
+ int EmptyCount=0;
+ for (int I=0;I<PrgStack.Size();I++)
+ {
+ PrgStack[I-EmptyCount]=PrgStack[I];
+ if (PrgStack[I]==NULL)
+ EmptyCount++;
+ if (EmptyCount>0)
+ PrgStack[I]=NULL;
+ }
+ if (EmptyCount==0)
+ {
+ PrgStack.Add(1);
+ EmptyCount=1;
+ }
+ int StackPos=PrgStack.Size()-EmptyCount;
+ PrgStack[StackPos]=StackFilter;
+ StackFilter->ExecCount=Filter->ExecCount;
+
+ uint BlockStart=RarVM::ReadData(Inp);
+ if (FirstByte & 0x40)
+ BlockStart+=258;
+ StackFilter->BlockStart=(BlockStart+UnpPtr)&MAXWINMASK;
+ if (FirstByte & 0x20)
+ StackFilter->BlockLength=RarVM::ReadData(Inp);
+ else
+ StackFilter->BlockLength=FiltPos<OldFilterLengths.Size() ? OldFilterLengths[FiltPos]:0;
+ StackFilter->NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MAXWINMASK)<=BlockStart;
+
+// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
+
+ OldFilterLengths[FiltPos]=StackFilter->BlockLength;
+
+ memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
+ StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
+ StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
+ StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
+
+ if (FirstByte & 0x10) // set registers to optional parameters if any
+ {
+ unsigned int InitMask=Inp.fgetbits()>>9;
+ Inp.faddbits(7);
+ for (int I=0;I<7;I++)
+ if (InitMask & (1<<I))
+ StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp);
+ }
+
+ if (NewFilter)
+ {
+ uint VMCodeSize=RarVM::ReadData(Inp);
+ if (VMCodeSize>=0x10000 || VMCodeSize==0)
+ return(false);
+ Array<byte> VMCode(VMCodeSize);
+ for (int I=0;I<VMCodeSize;I++)
+ {
+ if (Inp.Overflow(3))
+ return(false);
+ VMCode[I]=Inp.fgetbits()>>8;
+ Inp.faddbits(8);
+ }
+ VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
+ }
+ StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
+ StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
+
+ int StaticDataSize=Filter->Prg.StaticData.Size();
+ if (StaticDataSize>0 && StaticDataSize<VM_GLOBALMEMSIZE)
+ {
+ // read statically defined data contained in DB commands
+ StackFilter->Prg.StaticData.Add(StaticDataSize);
+ memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
+ }
+
+ if (StackFilter->Prg.GlobalData.Size()<VM_FIXEDGLOBALSIZE)
+ {
+ StackFilter->Prg.GlobalData.Reset();
+ StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
+ }
+ byte *GlobalData=&StackFilter->Prg.GlobalData[0];
+ for (int I=0;I<7;I++)
+ VM.SetLowEndianValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
+ VM.SetLowEndianValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
+ VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
+ VM.SetLowEndianValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
+ memset(&GlobalData[0x30],0,16);
+
+ if (FirstByte & 8) // put data block passed as parameter if any
+ {
+ if (Inp.Overflow(3))
+ return(false);
+ uint DataSize=RarVM::ReadData(Inp);
+ if (DataSize>VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE)
+ return(false);
+ unsigned int CurSize=StackFilter->Prg.GlobalData.Size();
+ if (CurSize<DataSize+VM_FIXEDGLOBALSIZE)
+ StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
+ byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE];
+ for (int I=0;I<DataSize;I++)
+ {
+ if (Inp.Overflow(3))
+ return(false);
+ GlobalData[I]=Inp.fgetbits()>>8;
+ Inp.faddbits(8);
+ }
+ }
+ return(true);
+}
+
+
+bool Unpack::UnpReadBuf()
+{
+ int DataSize=ReadTop-InAddr;
+ if (DataSize<0)
+ return(false);
+ if (InAddr>BitInput::MAX_SIZE/2)
+ {
+ if (DataSize>0)
+ memmove(InBuf,InBuf+InAddr,DataSize);
+ InAddr=0;
+ ReadTop=DataSize;
+ }
+ else
+ DataSize=ReadTop;
+ int ReadCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf);
+ if (ReadCode>0)
+ ReadTop+=ReadCode;
+ ReadBorder=ReadTop-30;
+ return(ReadCode!=-1);
+}
+
+
+void Unpack::UnpWriteBuf()
+{
+ unsigned int WrittenBorder=WrPtr;
+ unsigned int WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
+ for (int I=0;I<PrgStack.Size();I++)
+ {
+ UnpackFilter *flt=PrgStack[I];
+ if (flt==NULL)
+ continue;
+ if (flt->NextWindow)
+ {
+ flt->NextWindow=false;
+ continue;
+ }
+ unsigned int BlockStart=flt->BlockStart;
+ unsigned int BlockLength=flt->BlockLength;
+ if (((BlockStart-WrittenBorder)&MAXWINMASK)<WriteSize)
+ {
+ if (WrittenBorder!=BlockStart)
+ {
+ UnpWriteArea(WrittenBorder,BlockStart);
+ WrittenBorder=BlockStart;
+ WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
+ }
+ if (BlockLength<=WriteSize)
+ {
+ unsigned int BlockEnd=(BlockStart+BlockLength)&MAXWINMASK;
+ if (BlockStart<BlockEnd || BlockEnd==0)
+ VM.SetMemory(0,Window+BlockStart,BlockLength);
+ else
+ {
+ unsigned int FirstPartLength=MAXWINSIZE-BlockStart;
+ VM.SetMemory(0,Window+BlockStart,FirstPartLength);
+ VM.SetMemory(FirstPartLength,Window,BlockEnd);
+ }
+
+ VM_PreparedProgram *ParentPrg=&Filters[flt->ParentFilter]->Prg;
+ VM_PreparedProgram *Prg=&flt->Prg;
+
+ if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // copy global data from previous script execution if any
+ Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
+ memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+
+ ExecuteCode(Prg);
+
+ if (Prg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // save global data for next script execution
+ if (ParentPrg->GlobalData.Size()<Prg->GlobalData.Size())
+ ParentPrg->GlobalData.Alloc(Prg->GlobalData.Size());
+ memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+ else
+ ParentPrg->GlobalData.Reset();
+
+ byte *FilteredData=Prg->FilteredData;
+ unsigned int FilteredDataSize=Prg->FilteredDataSize;
+
+ delete PrgStack[I];
+ PrgStack[I]=NULL;
+ while (I+1<PrgStack.Size())
+ {
+ UnpackFilter *NextFilter=PrgStack[I+1];
+ if (NextFilter==NULL || NextFilter->BlockStart!=BlockStart ||
+ NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow)
+ break;
+
+ // apply several filters to same data block
+
+ VM.SetMemory(0,FilteredData,FilteredDataSize);
+
+ VM_PreparedProgram *ParentPrg=&Filters[NextFilter->ParentFilter]->Prg;
+ VM_PreparedProgram *NextPrg=&NextFilter->Prg;
+
+ if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // copy global data from previous script execution if any
+ NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
+ memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+
+ ExecuteCode(NextPrg);
+
+ if (NextPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // save global data for next script execution
+ if (ParentPrg->GlobalData.Size()<NextPrg->GlobalData.Size())
+ ParentPrg->GlobalData.Alloc(NextPrg->GlobalData.Size());
+ memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+ else
+ ParentPrg->GlobalData.Reset();
+
+ FilteredData=NextPrg->FilteredData;
+ FilteredDataSize=NextPrg->FilteredDataSize;
+ I++;
+ delete PrgStack[I];
+ PrgStack[I]=NULL;
+ }
+ UnpIO->UnpWrite(FilteredData,FilteredDataSize);
+ UnpSomeRead=true;
+ WrittenFileSize+=FilteredDataSize;
+ WrittenBorder=BlockEnd;
+ WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
+ }
+ else
+ {
+ for (int J=I;J<PrgStack.Size();J++)
+ {
+ UnpackFilter *flt=PrgStack[J];
+ if (flt!=NULL && flt->NextWindow)
+ flt->NextWindow=false;
+ }
+ WrPtr=WrittenBorder;
+ return;
+ }
+ }
+ }
+
+ UnpWriteArea(WrittenBorder,UnpPtr);
+ WrPtr=UnpPtr;
+}
+
+
+void Unpack::ExecuteCode(VM_PreparedProgram *Prg)
+{
+ if (Prg->GlobalData.Size()>0)
+ {
+ Prg->InitR[6]=int64to32(WrittenFileSize);
+ VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
+ VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
+ VM.Execute(Prg);
+ }
+}
+
+
+void Unpack::UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr)
+{
+ if (EndPtr!=StartPtr)
+ UnpSomeRead=true;
+ if (EndPtr<StartPtr)
+ {
+ UnpWriteData(&Window[StartPtr],-StartPtr & MAXWINMASK);
+ UnpWriteData(Window,EndPtr);
+ UnpAllBuf=true;
+ }
+ else
+ UnpWriteData(&Window[StartPtr],EndPtr-StartPtr);
+}
+
+
+void Unpack::UnpWriteData(byte *Data,int Size)
+{
+ if (WrittenFileSize>=DestUnpSize)
+ return;
+ int WriteSize=Size;
+ Int64 LeftToWrite=DestUnpSize-WrittenFileSize;
+ if (WriteSize>LeftToWrite)
+ WriteSize=int64to32(LeftToWrite);
+ UnpIO->UnpWrite(Data,WriteSize);
+ WrittenFileSize+=Size;
+}
+
+
+bool Unpack::ReadTables()
+{
+ byte BitLength[BC];
+ unsigned char Table[HUFF_TABLE_SIZE];
+ if (InAddr>ReadTop-25)
+ if (!UnpReadBuf())
+ return(false);
+ faddbits((8-InBit)&7);
+ unsigned int BitField=fgetbits();
+ if (BitField & 0x8000)
+ {
+ UnpBlockType=BLOCK_PPM;
+ return(PPM.DecodeInit(this,PPMEscChar));
+ }
+ UnpBlockType=BLOCK_LZ;
+
+ PrevLowDist=0;
+ LowDistRepCount=0;
+
+ if (!(BitField & 0x4000))
+ memset(UnpOldTable,0,sizeof(UnpOldTable));
+ faddbits(2);
+
+ for (int I=0;I<BC;I++)
+ {
+ int Length=(byte)(fgetbits() >> 12);
+ faddbits(4);
+ if (Length==15)
+ {
+ int ZeroCount=(byte)(fgetbits() >> 12);
+ faddbits(4);
+ if (ZeroCount==0)
+ BitLength[I]=15;
+ else
+ {
+ ZeroCount+=2;
+ while (ZeroCount-- > 0 && I<sizeof(BitLength)/sizeof(BitLength[0]))
+ BitLength[I++]=0;
+ I--;
+ }
+ }
+ else
+ BitLength[I]=Length;
+ }
+ MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
+
+ const int TableSize=HUFF_TABLE_SIZE;
+ for (int I=0;I<TableSize;)
+ {
+ if (InAddr>ReadTop-5)
+ if (!UnpReadBuf())
+ return(false);
+ int Number=DecodeNumber((struct Decode *)&BD);
+ if (Number<16)
+ {
+ Table[I]=(Number+UnpOldTable[I]) & 0xf;
+ I++;
+ }
+ else
+ if (Number<18)
+ {
+ int N;
+ if (Number==16)
+ {
+ N=(fgetbits() >> 13)+3;
+ faddbits(3);
+ }
+ else
+ {
+ N=(fgetbits() >> 9)+11;
+ faddbits(7);
+ }
+ while (N-- > 0 && I<TableSize)
+ {
+ Table[I]=Table[I-1];
+ I++;
+ }
+ }
+ else
+ {
+ int N;
+ if (Number==18)
+ {
+ N=(fgetbits() >> 13)+3;
+ faddbits(3);
+ }
+ else
+ {
+ N=(fgetbits() >> 9)+11;
+ faddbits(7);
+ }
+ while (N-- > 0 && I<TableSize)
+ Table[I++]=0;
+ }
+ }
+ TablesRead=true;
+ if (InAddr>ReadTop)
+ return(false);
+ MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
+ MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
+ MakeDecodeTables(&Table[NC+DC],(struct Decode *)&LDD,LDC);
+ MakeDecodeTables(&Table[NC+DC+LDC],(struct Decode *)&RD,RC);
+ memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
+ return(true);
+}
+
+
+void Unpack::UnpInitData(int Solid)
+{
+ if (!Solid)
+ {
+ TablesRead=false;
+ memset(OldDist,0,sizeof(OldDist));
+ OldDistPtr=0;
+ LastDist=LastLength=0;
+// memset(Window,0,MAXWINSIZE);
+ memset(UnpOldTable,0,sizeof(UnpOldTable));
+ memset(&LD,0,sizeof(LD));
+ memset(&DD,0,sizeof(DD));
+ memset(&LDD,0,sizeof(LDD));
+ memset(&RD,0,sizeof(RD));
+ memset(&BD,0,sizeof(BD));
+ UnpPtr=WrPtr=0;
+ PPMEscChar=2;
+ UnpBlockType=BLOCK_LZ;
+
+ InitFilters();
+ }
+ InitBitInput();
+ WrittenFileSize=0;
+ ReadTop=0;
+ ReadBorder=0;
+#ifndef SFX_MODULE
+ UnpInitData20(Solid);
+#endif
+}
+
+
+void Unpack::InitFilters()
+{
+ OldFilterLengths.Reset();
+ LastFilter=0;
+
+ for (int I=0;I<Filters.Size();I++)
+ delete Filters[I];
+ Filters.Reset();
+ for (int I=0;I<PrgStack.Size();I++)
+ delete PrgStack[I];
+ PrgStack.Reset();
+}
+
+
+void Unpack::MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size)
+{
+ int LenCount[16],TmpPos[16],I;
+ long M,N;
+ memset(LenCount,0,sizeof(LenCount));
+ memset(Dec->DecodeNum,0,Size*sizeof(*Dec->DecodeNum));
+ for (I=0;I<Size;I++)
+ LenCount[LenTab[I] & 0xF]++;
+
+ LenCount[0]=0;
+ for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
+ {
+ N=2*(N+LenCount[I]);
+ M=N<<(15-I);
+ if (M>0xFFFF)
+ M=0xFFFF;
+ Dec->DecodeLen[I]=(unsigned int)M;
+ TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
+ }
+
+ for (I=0;I<Size;I++)
+ if (LenTab[I]!=0)
+ Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
+ Dec->MaxNum=Size;
+}
diff --git a/unrar/unrar/unpack.hpp b/unrar/unrar/unpack.hpp
new file mode 100644
index 0000000..75df302
--- /dev/null
+++ b/unrar/unrar/unpack.hpp
@@ -0,0 +1,217 @@
+#ifndef _RAR_UNPACK_
+#define _RAR_UNPACK_
+
+enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
+
+struct Decode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[2];
+};
+
+struct LitDecode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[NC];
+};
+
+struct DistDecode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[DC];
+};
+
+struct LowDistDecode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[LDC];
+};
+
+struct RepDecode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[RC];
+};
+
+struct BitDecode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[BC];
+};
+
+struct UnpackFilter
+{
+ unsigned int BlockStart;
+ unsigned int BlockLength;
+ unsigned int ExecCount;
+ bool NextWindow;
+
+ // position of parent filter in Filters array used as prototype for filter
+ // in PrgStack array. Not defined for filters in Filters array.
+ unsigned int ParentFilter;
+
+ VM_PreparedProgram Prg;
+};
+
+/***************************** Unpack v 2.0 *********************************/
+struct MultDecode
+{
+ unsigned int MaxNum;
+ unsigned int DecodeLen[16];
+ unsigned int DecodePos[16];
+ unsigned int DecodeNum[MC20];
+};
+
+struct AudioVariables
+{
+ int K1,K2,K3,K4,K5;
+ int D1,D2,D3,D4;
+ int LastDelta;
+ unsigned int Dif[11];
+ unsigned int ByteCount;
+ int LastChar;
+};
+/***************************** Unpack v 2.0 *********************************/
+
+
+class Unpack:private BitInput
+{
+ private:
+ friend class Pack;
+
+ void Unpack29(bool Solid);
+ bool UnpReadBuf();
+ void UnpWriteBuf();
+ void ExecuteCode(VM_PreparedProgram *Prg);
+ void UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr);
+ void UnpWriteData(byte *Data,int Size);
+ bool ReadTables();
+ void MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size);
+ int DecodeNumber(struct Decode *Dec);
+ void CopyString();
+ inline void InsertOldDist(unsigned int Distance);
+ inline void InsertLastMatch(unsigned int Length,unsigned int Distance);
+ void UnpInitData(int Solid);
+ void CopyString(unsigned int Length,unsigned int Distance);
+ bool ReadEndOfBlock();
+ bool ReadVMCode();
+ bool ReadVMCodePPM();
+ bool AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize);
+ void InitFilters();
+
+ ComprDataIO *UnpIO;
+ ModelPPM PPM;
+ int PPMEscChar;
+
+ RarVM VM;
+
+ /* Filters code, one entry per filter */
+ Array<UnpackFilter*> Filters;
+
+ /* Filters stack, several entrances of same filter are possible */
+ Array<UnpackFilter*> PrgStack;
+
+ /* lengths of preceding blocks, one length per filter. Used to reduce
+ size required to write block length if lengths are repeating */
+ Array<int> OldFilterLengths;
+
+ int LastFilter;
+
+ bool TablesRead;
+ struct LitDecode LD;
+ struct DistDecode DD;
+ struct LowDistDecode LDD;
+ struct RepDecode RD;
+ struct BitDecode BD;
+
+ unsigned int OldDist[4],OldDistPtr;
+ unsigned int LastDist,LastLength;
+
+ unsigned int UnpPtr,WrPtr;
+
+ int ReadTop;
+ int ReadBorder;
+
+ unsigned char UnpOldTable[HUFF_TABLE_SIZE];
+
+ int UnpBlockType;
+
+ byte *Window;
+ bool ExternalWindow;
+
+
+ Int64 DestUnpSize;
+
+ bool Suspended;
+ bool UnpAllBuf;
+ bool UnpSomeRead;
+ Int64 WrittenFileSize;
+ bool FileExtracted;
+
+ int PrevLowDist,LowDistRepCount;
+
+/***************************** Unpack v 1.5 *********************************/
+ void Unpack15(bool Solid);
+ void ShortLZ();
+ void LongLZ();
+ void HuffDecode();
+ void GetFlagsBuf();
+ void OldUnpInitData(int Solid);
+ void InitHuff();
+ void CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace);
+ void OldCopyString(unsigned int Distance,unsigned int Length);
+ unsigned int DecodeNum(int Num,unsigned int StartPos,
+ unsigned int *DecTab,unsigned int *PosTab);
+ void OldUnpWriteBuf();
+
+ unsigned int ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
+ unsigned int Place[256],PlaceA[256],PlaceB[256],PlaceC[256];
+ unsigned int NToPl[256],NToPlB[256],NToPlC[256];
+ unsigned int FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
+ int Buf60,NumHuf,StMode,LCount,FlagsCnt;
+ unsigned int Nhfb,Nlzb,MaxDist3;
+/***************************** Unpack v 1.5 *********************************/
+
+/***************************** Unpack v 2.0 *********************************/
+ void Unpack20(bool Solid);
+ struct MultDecode MD[4];
+ unsigned char UnpOldTable20[MC20*4];
+ int UnpAudioBlock,UnpChannels,UnpCurChannel,UnpChannelDelta;
+ void CopyString20(unsigned int Length,unsigned int Distance);
+ bool ReadTables20();
+ void UnpInitData20(int Solid);
+ void ReadLastTables();
+ byte DecodeAudio(int Delta);
+ struct AudioVariables AudV[4];
+/***************************** Unpack v 2.0 *********************************/
+
+ public:
+ Unpack(ComprDataIO *DataIO);
+ ~Unpack();
+ void Init(byte *Window=NULL);
+ void DoUnpack(int Method,bool Solid);
+ bool IsFileExtracted() {return(FileExtracted);}
+ void SetDestSize(Int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
+ void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;}
+
+ unsigned int GetChar()
+ {
+ if (InAddr>BitInput::MAX_SIZE-30)
+ UnpReadBuf();
+ return(InBuf[InAddr++]);
+ }
+};
+
+#endif
diff --git a/unrar/unrar/unpack15.cpp b/unrar/unrar/unpack15.cpp
new file mode 100644
index 0000000..170085b
--- /dev/null
+++ b/unrar/unrar/unpack15.cpp
@@ -0,0 +1,511 @@
+#define STARTL1 2
+static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
+ 0xee00,0xf000,0xf200,0xf200,0xffff};
+static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
+
+#define STARTL2 3
+static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
+ 0xf000,0xf200,0xf240,0xffff};
+static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
+
+#define STARTHF0 4
+static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
+ 0xf200,0xf200,0xffff};
+static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
+
+
+#define STARTHF1 5
+static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
+ 0xf7e0,0xffff};
+static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
+
+
+#define STARTHF2 5
+static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
+ 0xffff,0xffff};
+static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
+
+
+#define STARTHF3 6
+static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
+ 0xffff};
+static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
+
+
+#define STARTHF4 8
+static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
+static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
+
+
+void Unpack::Unpack15(bool Solid)
+{
+ if (Suspended)
+ UnpPtr=WrPtr;
+ else
+ {
+ UnpInitData(Solid);
+ OldUnpInitData(Solid);
+ UnpReadBuf();
+ if (!Solid)
+ {
+ InitHuff();
+ UnpPtr=0;
+ }
+ else
+ UnpPtr=WrPtr;
+ --DestUnpSize;
+ }
+ if (DestUnpSize>=0)
+ {
+ GetFlagsBuf();
+ FlagsCnt=8;
+ }
+
+ while (DestUnpSize>=0)
+ {
+ UnpPtr&=MAXWINMASK;
+
+ if (InAddr>ReadTop-30 && !UnpReadBuf())
+ break;
+ if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
+ {
+ OldUnpWriteBuf();
+ if (Suspended)
+ return;
+ }
+ if (StMode)
+ {
+ HuffDecode();
+ continue;
+ }
+
+ if (--FlagsCnt < 0)
+ {
+ GetFlagsBuf();
+ FlagsCnt=7;
+ }
+
+ if (FlagBuf & 0x80)
+ {
+ FlagBuf<<=1;
+ if (Nlzb > Nhfb)
+ LongLZ();
+ else
+ HuffDecode();
+ }
+ else
+ {
+ FlagBuf<<=1;
+ if (--FlagsCnt < 0)
+ {
+ GetFlagsBuf();
+ FlagsCnt=7;
+ }
+ if (FlagBuf & 0x80)
+ {
+ FlagBuf<<=1;
+ if (Nlzb > Nhfb)
+ HuffDecode();
+ else
+ LongLZ();
+ }
+ else
+ {
+ FlagBuf<<=1;
+ ShortLZ();
+ }
+ }
+ }
+ OldUnpWriteBuf();
+}
+
+
+void Unpack::OldUnpWriteBuf()
+{
+ if (UnpPtr!=WrPtr)
+ UnpSomeRead=true;
+ if (UnpPtr<WrPtr)
+ {
+ UnpIO->UnpWrite(&Window[WrPtr],-WrPtr & MAXWINMASK);
+ UnpIO->UnpWrite(Window,UnpPtr);
+ UnpAllBuf=true;
+ }
+ else
+ UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
+ WrPtr=UnpPtr;
+}
+
+
+#define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos])
+#define GetShortLen2(pos) ((pos)==3 ? Buf60+3:ShortLen2[pos])
+
+void Unpack::ShortLZ()
+{
+ static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
+ static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
+ 0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
+ static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
+ static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
+ 0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
+
+
+ unsigned int Length,SaveLength;
+ unsigned int LastDistance;
+ unsigned int Distance;
+ int DistancePlace;
+ NumHuf=0;
+
+ unsigned int BitField=fgetbits();
+ if (LCount==2)
+ {
+ faddbits(1);
+ if (BitField >= 0x8000)
+ {
+ OldCopyString((unsigned int)LastDist,LastLength);
+ return;
+ }
+ BitField <<= 1;
+ LCount=0;
+ }
+
+ BitField>>=8;
+
+// not thread safe, replaced by GetShortLen1 and GetShortLen2 macro
+// ShortLen1[1]=ShortLen2[3]=Buf60+3;
+
+ if (AvrLn1<37)
+ {
+ for (Length=0;;Length++)
+ if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0)
+ break;
+ faddbits(GetShortLen1(Length));
+ }
+ else
+ {
+ for (Length=0;;Length++)
+ if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0)
+ break;
+ faddbits(GetShortLen2(Length));
+ }
+
+ if (Length >= 9)
+ {
+ if (Length == 9)
+ {
+ LCount++;
+ OldCopyString((unsigned int)LastDist,LastLength);
+ return;
+ }
+ if (Length == 14)
+ {
+ LCount=0;
+ Length=DecodeNum(fgetbits(),STARTL2,DecL2,PosL2)+5;
+ Distance=(fgetbits()>>1) | 0x8000;
+ faddbits(15);
+ LastLength=Length;
+ LastDist=Distance;
+ OldCopyString(Distance,Length);
+ return;
+ }
+
+ LCount=0;
+ SaveLength=Length;
+ Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
+ Length=DecodeNum(fgetbits(),STARTL1,DecL1,PosL1)+2;
+ if (Length==0x101 && SaveLength==10)
+ {
+ Buf60 ^= 1;
+ return;
+ }
+ if (Distance > 256)
+ Length++;
+ if (Distance >= MaxDist3)
+ Length++;
+
+ OldDist[OldDistPtr++]=Distance;
+ OldDistPtr = OldDistPtr & 3;
+ LastLength=Length;
+ LastDist=Distance;
+ OldCopyString(Distance,Length);
+ return;
+ }
+
+ LCount=0;
+ AvrLn1 += Length;
+ AvrLn1 -= AvrLn1 >> 4;
+
+ DistancePlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
+ Distance=ChSetA[DistancePlace];
+ if (--DistancePlace != -1)
+ {
+ PlaceA[Distance]--;
+ LastDistance=ChSetA[DistancePlace];
+ PlaceA[LastDistance]++;
+ ChSetA[DistancePlace+1]=LastDistance;
+ ChSetA[DistancePlace]=Distance;
+ }
+ Length+=2;
+ OldDist[OldDistPtr++] = ++Distance;
+ OldDistPtr = OldDistPtr & 3;
+ LastLength=Length;
+ LastDist=Distance;
+ OldCopyString(Distance,Length);
+}
+
+
+void Unpack::LongLZ()
+{
+ unsigned int Length;
+ unsigned int Distance;
+ unsigned int DistancePlace,NewDistancePlace;
+ unsigned int OldAvr2,OldAvr3;
+
+ NumHuf=0;
+ Nlzb+=16;
+ if (Nlzb > 0xff)
+ {
+ Nlzb=0x90;
+ Nhfb >>= 1;
+ }
+ OldAvr2=AvrLn2;
+
+ unsigned int BitField=fgetbits();
+ if (AvrLn2 >= 122)
+ Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
+ else
+ if (AvrLn2 >= 64)
+ Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
+ else
+ if (BitField < 0x100)
+ {
+ Length=BitField;
+ faddbits(16);
+ }
+ else
+ {
+ for (Length=0;((BitField<<Length)&0x8000)==0;Length++)
+ ;
+ faddbits(Length+1);
+ }
+
+ AvrLn2 += Length;
+ AvrLn2 -= AvrLn2 >> 5;
+
+ BitField=fgetbits();
+ if (AvrPlcB > 0x28ff)
+ DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
+ else
+ if (AvrPlcB > 0x6ff)
+ DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
+ else
+ DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
+
+ AvrPlcB += DistancePlace;
+ AvrPlcB -= AvrPlcB >> 8;
+ while (1)
+ {
+ Distance = ChSetB[DistancePlace & 0xff];
+ NewDistancePlace = NToPlB[Distance++ & 0xff]++;
+ if (!(Distance & 0xff))
+ CorrHuff(ChSetB,NToPlB);
+ else
+ break;
+ }
+
+ ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
+ ChSetB[NewDistancePlace]=Distance;
+
+ Distance=((Distance & 0xff00) | (fgetbits() >> 8)) >> 1;
+ faddbits(7);
+
+ OldAvr3=AvrLn3;
+ if (Length!=1 && Length!=4)
+ if (Length==0 && Distance <= MaxDist3)
+ {
+ AvrLn3++;
+ AvrLn3 -= AvrLn3 >> 8;
+ }
+ else
+ if (AvrLn3 > 0)
+ AvrLn3--;
+ Length+=3;
+ if (Distance >= MaxDist3)
+ Length++;
+ if (Distance <= 256)
+ Length+=8;
+ if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40)
+ MaxDist3=0x7f00;
+ else
+ MaxDist3=0x2001;
+ OldDist[OldDistPtr++]=Distance;
+ OldDistPtr = OldDistPtr & 3;
+ LastLength=Length;
+ LastDist=Distance;
+ OldCopyString(Distance,Length);
+}
+
+
+void Unpack::HuffDecode()
+{
+ unsigned int CurByte,NewBytePlace;
+ unsigned int Length;
+ unsigned int Distance;
+ int BytePlace;
+
+ unsigned int BitField=fgetbits();
+
+ if (AvrPlc > 0x75ff)
+ BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
+ else
+ if (AvrPlc > 0x5dff)
+ BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
+ else
+ if (AvrPlc > 0x35ff)
+ BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
+ else
+ if (AvrPlc > 0x0dff)
+ BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
+ else
+ BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
+ BytePlace&=0xff;
+ if (StMode)
+ {
+ if (BytePlace==0 && BitField > 0xfff)
+ BytePlace=0x100;
+ if (--BytePlace==-1)
+ {
+ BitField=fgetbits();
+ faddbits(1);
+ if (BitField & 0x8000)
+ {
+ NumHuf=StMode=0;
+ return;
+ }
+ else
+ {
+ Length = (BitField & 0x4000) ? 4 : 3;
+ faddbits(1);
+ Distance=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
+ Distance = (Distance << 5) | (fgetbits() >> 11);
+ faddbits(5);
+ OldCopyString(Distance,Length);
+ return;
+ }
+ }
+ }
+ else
+ if (NumHuf++ >= 16 && FlagsCnt==0)
+ StMode=1;
+ AvrPlc += BytePlace;
+ AvrPlc -= AvrPlc >> 8;
+ Nhfb+=16;
+ if (Nhfb > 0xff)
+ {
+ Nhfb=0x90;
+ Nlzb >>= 1;
+ }
+
+ Window[UnpPtr++]=(byte)(ChSet[BytePlace]>>8);
+ --DestUnpSize;
+
+ while (1)
+ {
+ CurByte=ChSet[BytePlace];
+ NewBytePlace=NToPl[CurByte++ & 0xff]++;
+ if ((CurByte & 0xff) > 0xa1)
+ CorrHuff(ChSet,NToPl);
+ else
+ break;
+ }
+
+ ChSet[BytePlace]=ChSet[NewBytePlace];
+ ChSet[NewBytePlace]=CurByte;
+}
+
+
+void Unpack::GetFlagsBuf()
+{
+ unsigned int Flags,NewFlagsPlace;
+ unsigned int FlagsPlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
+
+ while (1)
+ {
+ Flags=ChSetC[FlagsPlace];
+ FlagBuf=Flags>>8;
+ NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
+ if ((Flags & 0xff) != 0)
+ break;
+ CorrHuff(ChSetC,NToPlC);
+ }
+
+ ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
+ ChSetC[NewFlagsPlace]=Flags;
+}
+
+
+void Unpack::OldUnpInitData(int Solid)
+{
+ if (!Solid)
+ {
+ AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
+ AvrPlc=0x3500;
+ MaxDist3=0x2001;
+ Nhfb=Nlzb=0x80;
+ }
+ FlagsCnt=0;
+ FlagBuf=0;
+ StMode=0;
+ LCount=0;
+ ReadTop=0;
+}
+
+
+void Unpack::InitHuff()
+{
+ for (unsigned int I=0;I<256;I++)
+ {
+ Place[I]=PlaceA[I]=PlaceB[I]=I;
+ PlaceC[I]=(~I+1) & 0xff;
+ ChSet[I]=ChSetB[I]=I<<8;
+ ChSetA[I]=I;
+ ChSetC[I]=((~I+1) & 0xff)<<8;
+ }
+ memset(NToPl,0,sizeof(NToPl));
+ memset(NToPlB,0,sizeof(NToPlB));
+ memset(NToPlC,0,sizeof(NToPlC));
+ CorrHuff(ChSetB,NToPlB);
+}
+
+
+void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace)
+{
+ int I,J;
+ for (I=7;I>=0;I--)
+ for (J=0;J<32;J++,CharSet++)
+ *CharSet=(*CharSet & ~0xff) | I;
+ memset(NumToPlace,0,sizeof(NToPl));
+ for (I=6;I>=0;I--)
+ NumToPlace[I]=(7-I)*32;
+}
+
+
+void Unpack::OldCopyString(unsigned int Distance,unsigned int Length)
+{
+ DestUnpSize-=Length;
+ while (Length--)
+ {
+ Window[UnpPtr]=Window[(UnpPtr-Distance) & MAXWINMASK];
+ UnpPtr=(UnpPtr+1) & MAXWINMASK;
+ }
+}
+
+
+unsigned int Unpack::DecodeNum(int Num,unsigned int StartPos,
+ unsigned int *DecTab,unsigned int *PosTab)
+{
+ int I;
+ for (Num&=0xfff0,I=0;DecTab[I]<=Num;I++)
+ StartPos++;
+ faddbits(StartPos);
+ return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]);
+}
diff --git a/unrar/unrar/unpack20.cpp b/unrar/unrar/unpack20.cpp
new file mode 100644
index 0000000..ce0ab1f
--- /dev/null
+++ b/unrar/unrar/unpack20.cpp
@@ -0,0 +1,370 @@
+#include "rar.hpp"
+
+void Unpack::CopyString20(unsigned int Length,unsigned int Distance)
+{
+ LastDist=OldDist[OldDistPtr++ & 3]=Distance;
+ LastLength=Length;
+ DestUnpSize-=Length;
+
+ unsigned int DestPtr=UnpPtr-Distance;
+ if (DestPtr<MAXWINSIZE-300 && UnpPtr<MAXWINSIZE-300)
+ {
+ Window[UnpPtr++]=Window[DestPtr++];
+ Window[UnpPtr++]=Window[DestPtr++];
+ while (Length>2)
+ {
+ Length--;
+ Window[UnpPtr++]=Window[DestPtr++];
+ }
+ }
+ else
+ while (Length--)
+ {
+ Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK];
+ UnpPtr=(UnpPtr+1) & MAXWINMASK;
+ }
+}
+
+
+void Unpack::Unpack20(bool Solid)
+{
+ static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
+ static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
+ static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
+ static unsigned char DBits[]= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
+ static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
+ static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
+ unsigned int Bits;
+
+ if (Suspended)
+ UnpPtr=WrPtr;
+ else
+ {
+ UnpInitData(Solid);
+ if (!UnpReadBuf())
+ return;
+ if (!Solid)
+ if (!ReadTables20())
+ return;
+ --DestUnpSize;
+ }
+
+ while (is64plus(DestUnpSize))
+ {
+ UnpPtr&=MAXWINMASK;
+
+ if (InAddr>ReadTop-30)
+ if (!UnpReadBuf())
+ break;
+ if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
+ {
+ OldUnpWriteBuf();
+ if (Suspended)
+ return;
+ }
+ if (UnpAudioBlock)
+ {
+ int AudioNumber=DecodeNumber((struct Decode *)&MD[UnpCurChannel]);
+
+ if (AudioNumber==256)
+ {
+ if (!ReadTables20())
+ break;
+ continue;
+ }
+ Window[UnpPtr++]=DecodeAudio(AudioNumber);
+ if (++UnpCurChannel==UnpChannels)
+ UnpCurChannel=0;
+ --DestUnpSize;
+ continue;
+ }
+
+ int Number=DecodeNumber((struct Decode *)&LD);
+ if (Number<256)
+ {
+ Window[UnpPtr++]=(byte)Number;
+ --DestUnpSize;
+ continue;
+ }
+ if (Number>269)
+ {
+ int Length=LDecode[Number-=270]+3;
+ if ((Bits=LBits[Number])>0)
+ {
+ Length+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+
+ int DistNumber=DecodeNumber((struct Decode *)&DD);
+ unsigned int Distance=DDecode[DistNumber]+1;
+ if ((Bits=DBits[DistNumber])>0)
+ {
+ Distance+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+
+ if (Distance>=0x2000)
+ {
+ Length++;
+ if (Distance>=0x40000L)
+ Length++;
+ }
+
+ CopyString20(Length,Distance);
+ continue;
+ }
+ if (Number==269)
+ {
+ if (!ReadTables20())
+ break;
+ continue;
+ }
+ if (Number==256)
+ {
+ CopyString20(LastLength,LastDist);
+ continue;
+ }
+ if (Number<261)
+ {
+ unsigned int Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
+ int LengthNumber=DecodeNumber((struct Decode *)&RD);
+ int Length=LDecode[LengthNumber]+2;
+ if ((Bits=LBits[LengthNumber])>0)
+ {
+ Length+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+ if (Distance>=0x101)
+ {
+ Length++;
+ if (Distance>=0x2000)
+ {
+ Length++;
+ if (Distance>=0x40000)
+ Length++;
+ }
+ }
+ CopyString20(Length,Distance);
+ continue;
+ }
+ if (Number<270)
+ {
+ unsigned int Distance=SDDecode[Number-=261]+1;
+ if ((Bits=SDBits[Number])>0)
+ {
+ Distance+=getbits()>>(16-Bits);
+ addbits(Bits);
+ }
+ CopyString20(2,Distance);
+ continue;
+ }
+ }
+ ReadLastTables();
+ OldUnpWriteBuf();
+}
+
+
+bool Unpack::ReadTables20()
+{
+ byte BitLength[BC20];
+ unsigned char Table[MC20*4];
+ int TableSize,N,I;
+ if (InAddr>ReadTop-25)
+ if (!UnpReadBuf())
+ return(false);
+ unsigned int BitField=getbits();
+ UnpAudioBlock=(BitField & 0x8000);
+
+ if (!(BitField & 0x4000))
+ memset(UnpOldTable20,0,sizeof(UnpOldTable20));
+ addbits(2);
+
+ if (UnpAudioBlock)
+ {
+ UnpChannels=((BitField>>12) & 3)+1;
+ if (UnpCurChannel>=UnpChannels)
+ UnpCurChannel=0;
+ addbits(2);
+ TableSize=MC20*UnpChannels;
+ }
+ else
+ TableSize=NC20+DC20+RC20;
+
+ for (I=0;I<BC20;I++)
+ {
+ BitLength[I]=(byte)(getbits() >> 12);
+ addbits(4);
+ }
+ MakeDecodeTables(BitLength,(struct Decode *)&BD,BC20);
+ I=0;
+ while (I<TableSize)
+ {
+ if (InAddr>ReadTop-5)
+ if (!UnpReadBuf())
+ return(false);
+ int Number=DecodeNumber((struct Decode *)&BD);
+ if (Number<16)
+ {
+ Table[I]=(Number+UnpOldTable20[I]) & 0xf;
+ I++;
+ }
+ else
+ if (Number==16)
+ {
+ N=(getbits() >> 14)+3;
+ addbits(2);
+ while (N-- > 0 && I<TableSize)
+ {
+ Table[I]=Table[I-1];
+ I++;
+ }
+ }
+ else
+ {
+ if (Number==17)
+ {
+ N=(getbits() >> 13)+3;
+ addbits(3);
+ }
+ else
+ {
+ N=(getbits() >> 9)+11;
+ addbits(7);
+ }
+ while (N-- > 0 && I<TableSize)
+ Table[I++]=0;
+ }
+ }
+ if (InAddr>ReadTop)
+ return(true);
+ if (UnpAudioBlock)
+ for (I=0;I<UnpChannels;I++)
+ MakeDecodeTables(&Table[I*MC20],(struct Decode *)&MD[I],MC20);
+ else
+ {
+ MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC20);
+ MakeDecodeTables(&Table[NC20],(struct Decode *)&DD,DC20);
+ MakeDecodeTables(&Table[NC20+DC20],(struct Decode *)&RD,RC20);
+ }
+ memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20));
+ return(true);
+}
+
+
+void Unpack::ReadLastTables()
+{
+ if (ReadTop>=InAddr+5)
+ if (UnpAudioBlock)
+ {
+ if (DecodeNumber((struct Decode *)&MD[UnpCurChannel])==256)
+ ReadTables20();
+ }
+ else
+ if (DecodeNumber((struct Decode *)&LD)==269)
+ ReadTables20();
+}
+
+
+void Unpack::UnpInitData20(int Solid)
+{
+ if (!Solid)
+ {
+ UnpAudioBlock=UnpChannelDelta=UnpCurChannel=0;
+ UnpChannels=1;
+
+ memset(AudV,0,sizeof(AudV));
+ memset(UnpOldTable20,0,sizeof(UnpOldTable20));
+ memset(MD,0,sizeof(MD));
+ }
+}
+
+
+byte Unpack::DecodeAudio(int Delta)
+{
+ struct AudioVariables *V=&AudV[UnpCurChannel];
+ V->ByteCount++;
+ V->D4=V->D3;
+ V->D3=V->D2;
+ V->D2=V->LastDelta-V->D1;
+ V->D1=V->LastDelta;
+ int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta;
+ PCh=(PCh>>3) & 0xFF;
+
+ unsigned int Ch=PCh-Delta;
+
+ int D=((signed char)Delta)<<3;
+
+ V->Dif[0]+=abs(D);
+ V->Dif[1]+=abs(D-V->D1);
+ V->Dif[2]+=abs(D+V->D1);
+ V->Dif[3]+=abs(D-V->D2);
+ V->Dif[4]+=abs(D+V->D2);
+ V->Dif[5]+=abs(D-V->D3);
+ V->Dif[6]+=abs(D+V->D3);
+ V->Dif[7]+=abs(D-V->D4);
+ V->Dif[8]+=abs(D+V->D4);
+ V->Dif[9]+=abs(D-UnpChannelDelta);
+ V->Dif[10]+=abs(D+UnpChannelDelta);
+
+ UnpChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
+ V->LastChar=Ch;
+
+ if ((V->ByteCount & 0x1F)==0)
+ {
+ unsigned int MinDif=V->Dif[0],NumMinDif=0;
+ V->Dif[0]=0;
+ for (int I=1;I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++)
+ {
+ if (V->Dif[I]<MinDif)
+ {
+ MinDif=V->Dif[I];
+ NumMinDif=I;
+ }
+ V->Dif[I]=0;
+ }
+ switch(NumMinDif)
+ {
+ case 1:
+ if (V->K1>=-16)
+ V->K1--;
+ break;
+ case 2:
+ if (V->K1<16)
+ V->K1++;
+ break;
+ case 3:
+ if (V->K2>=-16)
+ V->K2--;
+ break;
+ case 4:
+ if (V->K2<16)
+ V->K2++;
+ break;
+ case 5:
+ if (V->K3>=-16)
+ V->K3--;
+ break;
+ case 6:
+ if (V->K3<16)
+ V->K3++;
+ break;
+ case 7:
+ if (V->K4>=-16)
+ V->K4--;
+ break;
+ case 8:
+ if (V->K4<16)
+ V->K4++;
+ break;
+ case 9:
+ if (V->K5>=-16)
+ V->K5--;
+ break;
+ case 10:
+ if (V->K5<16)
+ V->K5++;
+ break;
+ }
+ }
+ return((byte)Ch);
+}
diff --git a/unrar/unrar/uowners.cpp b/unrar/unrar/uowners.cpp
new file mode 100644
index 0000000..c906059
--- /dev/null
+++ b/unrar/unrar/uowners.cpp
@@ -0,0 +1,80 @@
+
+
+void ExtractUnixOwner(Archive &Arc,char *FileName)
+{
+ if (Arc.HeaderCRC!=Arc.UOHead.HeadCRC)
+ {
+ Log(Arc.FileName,St(MOwnersBroken),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ struct passwd *pw;
+ if ((pw=getpwnam(Arc.UOHead.OwnerName))==NULL)
+ {
+ Log(Arc.FileName,St(MErrGetOwnerID),Arc.UOHead.OwnerName);
+ ErrHandler.SetErrorCode(WARNING);
+ return;
+ }
+ uid_t OwnerID=pw->pw_uid;
+
+ struct group *gr;
+ if ((gr=getgrnam(Arc.UOHead.GroupName))==NULL)
+ {
+ Log(Arc.FileName,St(MErrGetGroupID),Arc.UOHead.GroupName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+ uint Attr=GetFileAttr(FileName,NULL);
+ gid_t GroupID=gr->gr_gid;
+#if defined(SAVE_LINKS) && !defined(_APPLE)
+ if (lchown(FileName,OwnerID,GroupID)!=0)
+#else
+ if (chown(FileName,OwnerID,GroupID)!=0)
+#endif
+ {
+ Log(Arc.FileName,St(MSetOwnersError),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ }
+ SetFileAttr(FileName,NULL,Attr);
+}
+
+
+void ExtractUnixOwnerNew(Archive &Arc,char *FileName)
+{
+ char *OwnerName=(char *)&Arc.SubHead.SubData[0];
+ int OwnerSize=strlen(OwnerName)+1;
+ int GroupSize=Arc.SubHead.SubData.Size()-OwnerSize;
+ char GroupName[NM];
+ strncpy(GroupName,(char *)&Arc.SubHead.SubData[OwnerSize],GroupSize);
+ GroupName[GroupSize]=0;
+
+ struct passwd *pw;
+ if ((pw=getpwnam(OwnerName))==NULL)
+ {
+ Log(Arc.FileName,St(MErrGetOwnerID),OwnerName);
+ ErrHandler.SetErrorCode(WARNING);
+ return;
+ }
+ uid_t OwnerID=pw->pw_uid;
+
+ struct group *gr;
+ if ((gr=getgrnam(GroupName))==NULL)
+ {
+ Log(Arc.FileName,St(MErrGetGroupID),GroupName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+ uint Attr=GetFileAttr(FileName,NULL);
+ gid_t GroupID=gr->gr_gid;
+#if defined(SAVE_LINKS) && !defined(_APPLE)
+ if (lchown(FileName,OwnerID,GroupID)!=0)
+#else
+ if (chown(FileName,OwnerID,GroupID)!=0)
+#endif
+ {
+ Log(Arc.FileName,St(MSetOwnersError),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ }
+ SetFileAttr(FileName,NULL,Attr);
+}
diff --git a/unrar/unrar/version.hpp b/unrar/unrar/version.hpp
new file mode 100644
index 0000000..d29ecec
--- /dev/null
+++ b/unrar/unrar/version.hpp
@@ -0,0 +1,6 @@
+#define RARVER_MAJOR 3
+#define RARVER_MINOR 71
+#define RARVER_BETA 1
+#define RARVER_DAY 10
+#define RARVER_MONTH 9
+#define RARVER_YEAR 2007
diff --git a/unrar/unrar/volume.cpp b/unrar/unrar/volume.cpp
new file mode 100644
index 0000000..9a79662
--- /dev/null
+++ b/unrar/unrar/volume.cpp
@@ -0,0 +1,221 @@
+#include "rar.hpp"
+
+
+
+
+bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Command)
+{
+ RAROptions *Cmd=Arc.GetRAROptions();
+
+ int HeaderType=Arc.GetHeaderType();
+ FileHeader *hd=HeaderType==NEWSUB_HEAD ? &Arc.SubHead:&Arc.NewLhd;
+ bool SplitHeader=(HeaderType==FILE_HEAD || HeaderType==NEWSUB_HEAD) &&
+ (hd->Flags & LHD_SPLIT_AFTER)!=0;
+
+ if (DataIO!=NULL && SplitHeader && hd->UnpVer>=20 &&
+ hd->FileCRC!=0xffffffff && DataIO->PackedCRC!=~hd->FileCRC)
+ {
+ Log(Arc.FileName,St(MDataBadCRC),hd->FileName,Arc.FileName);
+ }
+
+ Int64 PosBeforeClose=Arc.Tell();
+ Arc.Close();
+
+ char NextName[NM];
+ wchar NextNameW[NM];
+ *NextNameW=0;
+ strcpy(NextName,Arc.FileName);
+ NextVolumeName(NextName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
+
+ if (*Arc.FileNameW!=0)
+ {
+ // Copy incremented trailing low ASCII volume name part to Unicode name.
+ // It is simpler than also implementing Unicode version of NextVolumeName.
+
+ strcpyw(NextNameW,Arc.FileNameW);
+ char *NumPtr=GetVolNumPart(NextName);
+
+ // moving to first digit in volume number
+ while (NumPtr>NextName && isdigit(*NumPtr) && isdigit(*(NumPtr-1)))
+ NumPtr--;
+
+ // also copy the first character before volume number,
+ // because it can be changed when going from .r99 to .s00
+ if (NumPtr>NextName)
+ NumPtr--;
+
+ int CharsToCopy=strlen(NextName)-(NumPtr-NextName);
+ int DestPos=strlenw(NextNameW)-CharsToCopy;
+ if (DestPos>0)
+ {
+ CharToWide(NumPtr,NextNameW+DestPos,ASIZE(NextNameW)-DestPos-1);
+ NextNameW[ASIZE(NextNameW)-1]=0;
+ }
+ }
+
+#if !defined(SFX_MODULE) && !defined(RARDLL)
+ bool RecoveryDone=false;
+#endif
+ bool FailedOpen=false,OldSchemeTested=false;
+
+ while (!Arc.Open(NextName,NextNameW))
+ {
+ if (!OldSchemeTested)
+ {
+ char AltNextName[NM];
+ strcpy(AltNextName,Arc.FileName);
+ NextVolumeName(AltNextName,true);
+ OldSchemeTested=true;
+ if (Arc.Open(AltNextName))
+ {
+ strcpy(NextName,AltNextName);
+ *NextNameW=0;
+ break;
+ }
+ }
+#ifdef RARDLL
+ if (Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL ||
+ Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LONG)NextName,RAR_VOL_ASK)==-1)
+ {
+ Cmd->DllError=ERAR_EOPEN;
+ FailedOpen=true;
+ break;
+ }
+ if (Cmd->ChangeVolProc!=NULL)
+ {
+#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
+ _EBX=_ESP;
+#endif
+ int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);
+#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
+ _ESP=_EBX;
+#endif
+ if (RetCode==0)
+ {
+ Cmd->DllError=ERAR_EOPEN;
+ FailedOpen=true;
+ break;
+ }
+ }
+#else // RARDLL
+
+#if !defined(SFX_MODULE) && !defined(_WIN_CE)
+ if (!RecoveryDone)
+ {
+ RecVolumes RecVol;
+ RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true);
+ RecoveryDone=true;
+ continue;
+ }
+#endif
+
+#ifndef GUI
+ if (!Cmd->VolumePause && !IsRemovable(NextName))
+ {
+ FailedOpen=true;
+ break;
+ }
+#endif
+#ifndef SILENT
+ if (Cmd->AllYes || !AskNextVol(NextName))
+#endif
+ {
+ FailedOpen=true;
+ break;
+ }
+#endif // RARDLL
+ *NextNameW=0;
+ }
+ if (FailedOpen)
+ {
+#if !defined(SILENT) && !defined(_WIN_CE)
+ Log(Arc.FileName,St(MAbsNextVol),NextName);
+#endif
+ Arc.Open(Arc.FileName,Arc.FileNameW);
+ Arc.Seek(PosBeforeClose,SEEK_SET);
+ return(false);
+ }
+ Arc.CheckArc(true);
+#ifdef RARDLL
+ if (Cmd->Callback!=NULL &&
+ Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LONG)NextName,RAR_VOL_NOTIFY)==-1)
+ return(false);
+ if (Cmd->ChangeVolProc!=NULL)
+ {
+#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
+ _EBX=_ESP;
+#endif
+ int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_NOTIFY);
+#if defined(_WIN_32) && !defined(_MSC_VER) && !defined(__MINGW32__)
+ _ESP=_EBX;
+#endif
+ if (RetCode==0)
+ return(false);
+ }
+#endif
+
+ if (Command=='T' || Command=='X' || Command=='E')
+ mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);
+ if (SplitHeader)
+ Arc.SearchBlock(HeaderType);
+ else
+ Arc.ReadHeader();
+ if (Arc.GetHeaderType()==FILE_HEAD)
+ {
+ Arc.ConvertAttributes();
+ Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
+ }
+#ifndef GUI
+ if (ShowFileName)
+ {
+ char OutName[NM];
+ IntToExt(Arc.NewLhd.FileName,OutName);
+#ifdef UNICODE_SUPPORTED
+ bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
+ if (WideName)
+ {
+ wchar NameW[NM];
+ ConvertPath(Arc.NewLhd.FileNameW,NameW);
+ char Name[NM];
+ if (WideToChar(NameW,Name) && IsNameUsable(Name))
+ strcpy(OutName,Name);
+ }
+#endif
+ mprintf(St(MExtrPoints),OutName);
+ if (!Cmd->DisablePercentage)
+ mprintf(" ");
+ }
+#endif
+ if (DataIO!=NULL)
+ {
+ if (HeaderType==ENDARC_HEAD)
+ DataIO->UnpVolume=false;
+ else
+ {
+ DataIO->UnpVolume=(hd->Flags & LHD_SPLIT_AFTER);
+ DataIO->SetPackedSizeToRead(hd->FullPackSize);
+ }
+#ifdef SFX_MODULE
+ DataIO->UnpArcSize=Arc.FileLength();
+ DataIO->CurUnpRead=0;
+#endif
+ DataIO->PackedCRC=0xffffffff;
+// DataIO->SetFiles(&Arc,NULL);
+ }
+ return(true);
+}
+
+
+
+
+
+
+#ifndef SILENT
+bool AskNextVol(char *ArcName)
+{
+ eprintf(St(MAskNextVol),ArcName);
+ if (Ask(St(MContinueQuit))==2)
+ return(false);
+ return(true);
+}
+#endif
diff --git a/unrar/unrar/volume.hpp b/unrar/unrar/volume.hpp
new file mode 100644
index 0000000..6465340
--- /dev/null
+++ b/unrar/unrar/volume.hpp
@@ -0,0 +1,11 @@
+#ifndef _RAR_VOLUME_
+#define _RAR_VOLUME_
+
+void SplitArchive(Archive &Arc,FileHeader *fh,Int64 *HeaderPos,
+ ComprDataIO *DataIO);
+bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,
+ char Command);
+void SetVolWrite(Archive &Dest,Int64 VolSize);
+bool AskNextVol(char *ArcName);
+
+#endif
diff --git a/unrar/unrar/win32acl.cpp b/unrar/unrar/win32acl.cpp
new file mode 100644
index 0000000..37fb22b
--- /dev/null
+++ b/unrar/unrar/win32acl.cpp
@@ -0,0 +1,127 @@
+static void SetPrivileges();
+
+static bool ReadSacl=false;
+
+
+
+#ifndef SFX_MODULE
+void ExtractACL(Archive &Arc,char *FileName,wchar *FileNameW)
+{
+ if (!WinNT())
+ return;
+
+ SetPrivileges();
+
+ if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
+ {
+ Log(Arc.FileName,St(MACLBroken),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
+ {
+ Log(Arc.FileName,St(MACLUnknown),FileName);
+ ErrHandler.SetErrorCode(WARNING);
+ return;
+ }
+
+ ComprDataIO DataIO;
+ Unpack Unpack(&DataIO);
+ Unpack.Init();
+
+ Array<unsigned char> UnpData(Arc.EAHead.UnpSize);
+ DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize);
+ DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize);
+ DataIO.EnableShowProgress(false);
+ DataIO.SetFiles(&Arc,NULL);
+ Unpack.SetDestSize(Arc.EAHead.UnpSize);
+ Unpack.DoUnpack(Arc.EAHead.UnpVer,false);
+
+ if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
+ {
+ Log(Arc.FileName,St(MACLBroken),FileName);
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ SECURITY_INFORMATION si=OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
+ DACL_SECURITY_INFORMATION;
+ if (ReadSacl)
+ si|=SACL_SECURITY_INFORMATION;
+ SECURITY_DESCRIPTOR *sd=(SECURITY_DESCRIPTOR *)&UnpData[0];
+
+ int SetCode;
+ if (FileNameW!=NULL)
+ SetCode=SetFileSecurityW(FileNameW,si,sd);
+ else
+ SetCode=SetFileSecurity(FileName,si,sd);
+
+ if (!SetCode)
+ {
+ Log(Arc.FileName,St(MACLSetError),FileName);
+ ErrHandler.SysErrMsg();
+ ErrHandler.SetErrorCode(WARNING);
+ }
+}
+#endif
+
+
+void ExtractACLNew(Archive &Arc,char *FileName,wchar *FileNameW)
+{
+ if (!WinNT())
+ return;
+
+ Array<byte> SubData;
+ if (!Arc.ReadSubData(&SubData,NULL))
+ return;
+
+ SetPrivileges();
+
+ SECURITY_INFORMATION si=OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|
+ DACL_SECURITY_INFORMATION;
+ if (ReadSacl)
+ si|=SACL_SECURITY_INFORMATION;
+ SECURITY_DESCRIPTOR *sd=(SECURITY_DESCRIPTOR *)&SubData[0];
+
+ int SetCode;
+ if (FileNameW!=NULL)
+ SetCode=SetFileSecurityW(FileNameW,si,sd);
+ else
+ SetCode=SetFileSecurity(FileName,si,sd);
+
+ if (!SetCode)
+ {
+ Log(Arc.FileName,St(MACLSetError),FileName);
+ ErrHandler.SysErrMsg();
+ ErrHandler.SetErrorCode(WARNING);
+ }
+}
+
+
+void SetPrivileges()
+{
+ static bool InitDone=false;
+ if (InitDone)
+ return;
+ InitDone=true;
+
+ HANDLE hToken;
+
+ if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
+ return;
+
+ TOKEN_PRIVILEGES tp;
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (LookupPrivilegeValue(NULL,SE_SECURITY_NAME,&tp.Privileges[0].Luid))
+ if (AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+ GetLastError() == ERROR_SUCCESS)
+ ReadSacl=true;
+
+ if (LookupPrivilegeValue(NULL,SE_RESTORE_NAME,&tp.Privileges[0].Luid))
+ AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
+
+ CloseHandle(hToken);
+}
diff --git a/unrar/unrar/win32stm.cpp b/unrar/unrar/win32stm.cpp
new file mode 100644
index 0000000..7909291
--- /dev/null
+++ b/unrar/unrar/win32stm.cpp
@@ -0,0 +1,154 @@
+
+
+
+#ifndef SFX_MODULE
+void ExtractStreams(Archive &Arc,char *FileName,wchar *FileNameW)
+{
+ if (!WinNT())
+ return;
+
+ if (Arc.HeaderCRC!=Arc.StreamHead.HeadCRC)
+ {
+#ifndef SILENT
+ Log(Arc.FileName,St(MStreamBroken),FileName);
+#endif
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ if (Arc.StreamHead.Method<0x31 || Arc.StreamHead.Method>0x35 || Arc.StreamHead.UnpVer>PACK_VER)
+ {
+#ifndef SILENT
+ Log(Arc.FileName,St(MStreamUnknown),FileName);
+#endif
+ ErrHandler.SetErrorCode(WARNING);
+ return;
+ }
+
+ char StreamName[NM+2];
+ if (FileName[0]!=0 && FileName[1]==0)
+ {
+ strcpy(StreamName,".\\");
+ strcpy(StreamName+2,FileName);
+ }
+ else
+ strcpy(StreamName,FileName);
+ if (strlen(StreamName)+strlen((char *)Arc.StreamHead.StreamName)>=sizeof(StreamName) ||
+ Arc.StreamHead.StreamName[0]!=':')
+ {
+#ifndef SILENT
+ Log(Arc.FileName,St(MStreamBroken),FileName);
+#endif
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ ConvertPath((char *)Arc.StreamHead.StreamName+1,(char *)Arc.StreamHead.StreamName+1);
+
+ strcat(StreamName,(char *)Arc.StreamHead.StreamName);
+
+ FindData fd;
+ bool Found=FindFile::FastFind(FileName,FileNameW,&fd);
+
+ if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
+ SetFileAttr(FileName,FileNameW,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY);
+
+ File CurFile;
+ if (CurFile.WCreate(StreamName))
+ {
+ ComprDataIO DataIO;
+ Unpack Unpack(&DataIO);
+ Unpack.Init();
+
+ Array<unsigned char> UnpData(Arc.StreamHead.UnpSize);
+ DataIO.SetPackedSizeToRead(Arc.StreamHead.DataSize);
+ DataIO.EnableShowProgress(false);
+ DataIO.SetFiles(&Arc,&CurFile);
+ Unpack.SetDestSize(Arc.StreamHead.UnpSize);
+ Unpack.DoUnpack(Arc.StreamHead.UnpVer,false);
+
+ if (Arc.StreamHead.StreamCRC!=~DataIO.UnpFileCRC)
+ {
+#ifndef SILENT
+ Log(Arc.FileName,St(MStreamBroken),StreamName);
+#endif
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ }
+ else
+ CurFile.Close();
+ }
+ File HostFile;
+ if (Found && HostFile.Open(FileName,FileNameW,true,true))
+ SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
+ &fd.ftLastWriteTime);
+ if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
+ SetFileAttr(FileName,FileNameW,fd.FileAttr);
+}
+#endif
+
+
+void ExtractStreamsNew(Archive &Arc,char *FileName,wchar *FileNameW)
+{
+ if (!WinNT())
+ return;
+
+ wchar NameW[NM];
+ if (FileNameW!=NULL && *FileNameW!=0)
+ strcpyw(NameW,FileNameW);
+ else
+ CharToWide(FileName,NameW);
+ wchar StreamNameW[NM+2];
+ if (NameW[0]!=0 && NameW[1]==0)
+ {
+ strcpyw(StreamNameW,L".\\");
+ strcpyw(StreamNameW+2,NameW);
+ }
+ else
+ strcpyw(StreamNameW,NameW);
+
+ wchar *DestName=StreamNameW+strlenw(StreamNameW);
+ byte *SrcName=&Arc.SubHead.SubData[0];
+ int DestSize=Arc.SubHead.SubData.Size()/2;
+
+ if (strlenw(StreamNameW)+DestSize>=sizeof(StreamNameW)/sizeof(StreamNameW[0]))
+ {
+#if !defined(SILENT) && !defined(SFX_MODULE)
+ Log(Arc.FileName,St(MStreamBroken),FileName);
+#endif
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ RawToWide(SrcName,DestName,DestSize);
+ DestName[DestSize]=0;
+
+ if (*DestName!=':')
+ {
+#if !defined(SILENT) && !defined(SFX_MODULE)
+ Log(Arc.FileName,St(MStreamBroken),FileName);
+#endif
+ ErrHandler.SetErrorCode(CRC_ERROR);
+ return;
+ }
+
+ ConvertPath(DestName+1,DestName+1);
+
+ FindData fd;
+ bool Found=FindFile::FastFind(FileName,FileNameW,&fd);
+
+ if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
+ SetFileAttr(FileName,FileNameW,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY);
+ char StreamName[NM];
+ WideToChar(StreamNameW,StreamName);
+ File CurFile;
+ if (CurFile.WCreate(StreamName,StreamNameW) && Arc.ReadSubData(NULL,&CurFile))
+ CurFile.Close();
+ File HostFile;
+ if (Found && HostFile.Open(FileName,FileNameW,true,true))
+ SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
+ &fd.ftLastWriteTime);
+
+ // Restoring original file attributes. Important if file was read only
+ // or did not have "Archive" attribute
+ SetFileAttr(FileName,FileNameW,fd.FileAttr);
+}
diff --git a/unrar/vfs_types.h b/unrar/vfs_types.h
new file mode 120000
index 0000000..c2235a2
--- /dev/null
+++ b/unrar/vfs_types.h
@@ -0,0 +1 @@
+../common/vfs_types.h \ No newline at end of file
diff --git a/unrar/vfsutils.c b/unrar/vfsutils.c
new file mode 120000
index 0000000..5d9e2a2
--- /dev/null
+++ b/unrar/vfsutils.c
@@ -0,0 +1 @@
+../common/vfsutils.c \ No newline at end of file
diff --git a/unrar/vfsutils.h b/unrar/vfsutils.h
new file mode 120000
index 0000000..e8911d5
--- /dev/null
+++ b/unrar/vfsutils.h
@@ -0,0 +1 @@
+../common/vfsutils.h \ No newline at end of file