From 16f738ecee689c6feb2acb7e4ef4d9bb4144ae7d Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sun, 8 Jun 2008 11:04:43 +0200 Subject: Initial commit --- unrar/COPYING | 339 ++++++ unrar/Makefile | 67 ++ unrar/Makefile.unrar | 39 + unrar/README | 43 + unrar/rarlog.cpp | 69 ++ unrar/rarlog.hpp | 13 + unrar/strutils.c | 1 + unrar/strutils.h | 1 + unrar/treepath_vfs.c | 1 + unrar/treepath_vfs.h | 1 + unrar/treepathutils.c | 1 + unrar/treepathutils.h | 1 + unrar/unrar.c | 734 +++++++++++++ unrar/unrar/arccmt.cpp | 215 ++++ unrar/unrar/archive.cpp | 267 +++++ unrar/unrar/archive.hpp | 126 +++ unrar/unrar/arcread.cpp | 653 +++++++++++ unrar/unrar/array.hpp | 122 +++ unrar/unrar/beosea.cpp | 113 ++ unrar/unrar/cmddata.cpp | 1287 ++++++++++++++++++++++ unrar/unrar/cmddata.hpp | 57 + unrar/unrar/coder.cpp | 47 + unrar/unrar/coder.hpp | 24 + unrar/unrar/compress.hpp | 36 + unrar/unrar/consio.cpp | 289 +++++ unrar/unrar/consio.hpp | 46 + unrar/unrar/crc.cpp | 61 ++ unrar/unrar/crc.hpp | 10 + unrar/unrar/crypt.cpp | 381 +++++++ unrar/unrar/crypt.hpp | 62 ++ unrar/unrar/dll.cpp | 365 +++++++ unrar/unrar/dll.def | 12 + unrar/unrar/dll.hpp | 138 +++ unrar/unrar/encname.cpp | 57 + unrar/unrar/encname.hpp | 20 + unrar/unrar/errhnd.cpp | 374 +++++++ unrar/unrar/errhnd.hpp | 62 ++ unrar/unrar/extinfo.cpp | 76 ++ unrar/unrar/extinfo.hpp | 8 + unrar/unrar/extract.cpp | 873 +++++++++++++++ unrar/unrar/extract.hpp | 42 + unrar/unrar/filcreat.cpp | 239 ++++ unrar/unrar/filcreat.hpp | 13 + unrar/unrar/file.cpp | 689 ++++++++++++ unrar/unrar/file.hpp | 100 ++ unrar/unrar/filefn.cpp | 570 ++++++++++ unrar/unrar/filefn.hpp | 41 + unrar/unrar/filestr.cpp | 145 +++ unrar/unrar/filestr.hpp | 8 + unrar/unrar/find.cpp | 296 +++++ unrar/unrar/find.hpp | 48 + unrar/unrar/getbits.cpp | 24 + unrar/unrar/getbits.hpp | 38 + unrar/unrar/global.cpp | 4 + unrar/unrar/global.hpp | 14 + unrar/unrar/headers.hpp | 306 ++++++ unrar/unrar/int64.cpp | 274 +++++ unrar/unrar/int64.hpp | 86 ++ unrar/unrar/isnt.cpp | 17 + unrar/unrar/isnt.hpp | 6 + unrar/unrar/license.txt | 40 + unrar/unrar/list.cpp | 388 +++++++ unrar/unrar/list.hpp | 6 + unrar/unrar/loclang.hpp | 349 ++++++ unrar/unrar/log.cpp | 24 + unrar/unrar/log.hpp | 18 + unrar/unrar/makefile.bcc | 501 +++++++++ unrar/unrar/makefile.cygmin | 54 + unrar/unrar/makefile.dj | 50 + unrar/unrar/makefile.dmc | 54 + unrar/unrar/makefile.msc | 564 ++++++++++ unrar/unrar/makefile.unix | 119 ++ unrar/unrar/match.cpp | 262 +++++ unrar/unrar/match.hpp | 12 + unrar/unrar/model.cpp | 610 +++++++++++ unrar/unrar/model.hpp | 132 +++ unrar/unrar/msc.dep | 2532 +++++++++++++++++++++++++++++++++++++++++++ unrar/unrar/options.cpp | 28 + unrar/unrar/options.hpp | 142 +++ unrar/unrar/os.hpp | 241 ++++ unrar/unrar/os2ea.cpp | 94 ++ unrar/unrar/pathfn.cpp | 714 ++++++++++++ unrar/unrar/pathfn.hpp | 46 + unrar/unrar/rar.cpp | 144 +++ unrar/unrar/rar.hpp | 80 ++ unrar/unrar/rardefs.hpp | 24 + unrar/unrar/rarfn.hpp | 7 + unrar/unrar/rarlang.hpp | 10 + unrar/unrar/raros.hpp | 41 + unrar/unrar/rartypes.hpp | 21 + unrar/unrar/rarvm.cpp | 1109 +++++++++++++++++++ unrar/unrar/rarvm.hpp | 109 ++ unrar/unrar/rarvmtbl.cpp | 53 + unrar/unrar/rawread.cpp | 126 +++ unrar/unrar/rawread.hpp | 32 + unrar/unrar/rdwrfn.cpp | 264 +++++ unrar/unrar/rdwrfn.hpp | 83 ++ unrar/unrar/readme.txt | 63 ++ unrar/unrar/recvol.cpp | 367 +++++++ unrar/unrar/recvol.hpp | 16 + unrar/unrar/resource.cpp | 12 + unrar/unrar/resource.hpp | 14 + unrar/unrar/rijndael.cpp | 298 +++++ unrar/unrar/rijndael.hpp | 37 + unrar/unrar/rs.cpp | 143 +++ unrar/unrar/rs.hpp | 32 + unrar/unrar/savepos.cpp | 15 + unrar/unrar/savepos.hpp | 15 + unrar/unrar/scantree.cpp | 292 +++++ unrar/unrar/scantree.hpp | 52 + unrar/unrar/sha1.cpp | 231 ++++ unrar/unrar/sha1.hpp | 17 + unrar/unrar/smallfn.cpp | 23 + unrar/unrar/smallfn.hpp | 8 + unrar/unrar/strfn.cpp | 199 ++++ unrar/unrar/strfn.hpp | 34 + unrar/unrar/strlist.cpp | 191 ++++ unrar/unrar/strlist.hpp | 39 + unrar/unrar/suballoc.cpp | 258 +++++ unrar/unrar/suballoc.hpp | 87 ++ unrar/unrar/system.cpp | 96 ++ unrar/unrar/system.hpp | 26 + unrar/unrar/timefn.cpp | 288 +++++ unrar/unrar/timefn.hpp | 57 + unrar/unrar/ulinks.cpp | 32 + unrar/unrar/ulinks.hpp | 9 + unrar/unrar/unicode.cpp | 493 +++++++++ unrar/unrar/unicode.hpp | 82 ++ unrar/unrar/unios2.cpp | 128 +++ unrar/unrar/unpack.cpp | 1004 +++++++++++++++++ unrar/unrar/unpack.hpp | 217 ++++ unrar/unrar/unpack15.cpp | 511 +++++++++ unrar/unrar/unpack20.cpp | 370 +++++++ unrar/unrar/uowners.cpp | 80 ++ unrar/unrar/version.hpp | 6 + unrar/unrar/volume.cpp | 221 ++++ unrar/unrar/volume.hpp | 11 + unrar/unrar/win32acl.cpp | 127 +++ unrar/unrar/win32stm.cpp | 154 +++ unrar/vfs_types.h | 1 + unrar/vfsutils.c | 1 + unrar/vfsutils.h | 1 + 142 files changed, 25492 insertions(+) create mode 100644 unrar/COPYING create mode 100644 unrar/Makefile create mode 100644 unrar/Makefile.unrar create mode 100644 unrar/README create mode 100644 unrar/rarlog.cpp create mode 100644 unrar/rarlog.hpp create mode 120000 unrar/strutils.c create mode 120000 unrar/strutils.h create mode 120000 unrar/treepath_vfs.c create mode 120000 unrar/treepath_vfs.h create mode 120000 unrar/treepathutils.c create mode 120000 unrar/treepathutils.h create mode 100644 unrar/unrar.c create mode 100644 unrar/unrar/arccmt.cpp create mode 100644 unrar/unrar/archive.cpp create mode 100644 unrar/unrar/archive.hpp create mode 100644 unrar/unrar/arcread.cpp create mode 100644 unrar/unrar/array.hpp create mode 100644 unrar/unrar/beosea.cpp create mode 100644 unrar/unrar/cmddata.cpp create mode 100644 unrar/unrar/cmddata.hpp create mode 100644 unrar/unrar/coder.cpp create mode 100644 unrar/unrar/coder.hpp create mode 100644 unrar/unrar/compress.hpp create mode 100644 unrar/unrar/consio.cpp create mode 100644 unrar/unrar/consio.hpp create mode 100644 unrar/unrar/crc.cpp create mode 100644 unrar/unrar/crc.hpp create mode 100644 unrar/unrar/crypt.cpp create mode 100644 unrar/unrar/crypt.hpp create mode 100644 unrar/unrar/dll.cpp create mode 100644 unrar/unrar/dll.def create mode 100644 unrar/unrar/dll.hpp create mode 100644 unrar/unrar/encname.cpp create mode 100644 unrar/unrar/encname.hpp create mode 100644 unrar/unrar/errhnd.cpp create mode 100644 unrar/unrar/errhnd.hpp create mode 100644 unrar/unrar/extinfo.cpp create mode 100644 unrar/unrar/extinfo.hpp create mode 100644 unrar/unrar/extract.cpp create mode 100644 unrar/unrar/extract.hpp create mode 100644 unrar/unrar/filcreat.cpp create mode 100644 unrar/unrar/filcreat.hpp create mode 100644 unrar/unrar/file.cpp create mode 100644 unrar/unrar/file.hpp create mode 100644 unrar/unrar/filefn.cpp create mode 100644 unrar/unrar/filefn.hpp create mode 100644 unrar/unrar/filestr.cpp create mode 100644 unrar/unrar/filestr.hpp create mode 100644 unrar/unrar/find.cpp create mode 100644 unrar/unrar/find.hpp create mode 100644 unrar/unrar/getbits.cpp create mode 100644 unrar/unrar/getbits.hpp create mode 100644 unrar/unrar/global.cpp create mode 100644 unrar/unrar/global.hpp create mode 100644 unrar/unrar/headers.hpp create mode 100644 unrar/unrar/int64.cpp create mode 100644 unrar/unrar/int64.hpp create mode 100644 unrar/unrar/isnt.cpp create mode 100644 unrar/unrar/isnt.hpp create mode 100644 unrar/unrar/license.txt create mode 100644 unrar/unrar/list.cpp create mode 100644 unrar/unrar/list.hpp create mode 100644 unrar/unrar/loclang.hpp create mode 100644 unrar/unrar/log.cpp create mode 100644 unrar/unrar/log.hpp create mode 100644 unrar/unrar/makefile.bcc create mode 100644 unrar/unrar/makefile.cygmin create mode 100644 unrar/unrar/makefile.dj create mode 100644 unrar/unrar/makefile.dmc create mode 100644 unrar/unrar/makefile.msc create mode 100644 unrar/unrar/makefile.unix create mode 100644 unrar/unrar/match.cpp create mode 100644 unrar/unrar/match.hpp create mode 100644 unrar/unrar/model.cpp create mode 100644 unrar/unrar/model.hpp create mode 100644 unrar/unrar/msc.dep create mode 100644 unrar/unrar/options.cpp create mode 100644 unrar/unrar/options.hpp create mode 100644 unrar/unrar/os.hpp create mode 100644 unrar/unrar/os2ea.cpp create mode 100644 unrar/unrar/pathfn.cpp create mode 100644 unrar/unrar/pathfn.hpp create mode 100644 unrar/unrar/rar.cpp create mode 100644 unrar/unrar/rar.hpp create mode 100644 unrar/unrar/rardefs.hpp create mode 100644 unrar/unrar/rarfn.hpp create mode 100644 unrar/unrar/rarlang.hpp create mode 100644 unrar/unrar/raros.hpp create mode 100644 unrar/unrar/rartypes.hpp create mode 100644 unrar/unrar/rarvm.cpp create mode 100644 unrar/unrar/rarvm.hpp create mode 100644 unrar/unrar/rarvmtbl.cpp create mode 100644 unrar/unrar/rawread.cpp create mode 100644 unrar/unrar/rawread.hpp create mode 100644 unrar/unrar/rdwrfn.cpp create mode 100644 unrar/unrar/rdwrfn.hpp create mode 100644 unrar/unrar/readme.txt create mode 100644 unrar/unrar/recvol.cpp create mode 100644 unrar/unrar/recvol.hpp create mode 100644 unrar/unrar/resource.cpp create mode 100644 unrar/unrar/resource.hpp create mode 100644 unrar/unrar/rijndael.cpp create mode 100644 unrar/unrar/rijndael.hpp create mode 100644 unrar/unrar/rs.cpp create mode 100644 unrar/unrar/rs.hpp create mode 100644 unrar/unrar/savepos.cpp create mode 100644 unrar/unrar/savepos.hpp create mode 100644 unrar/unrar/scantree.cpp create mode 100644 unrar/unrar/scantree.hpp create mode 100644 unrar/unrar/sha1.cpp create mode 100644 unrar/unrar/sha1.hpp create mode 100644 unrar/unrar/smallfn.cpp create mode 100644 unrar/unrar/smallfn.hpp create mode 100644 unrar/unrar/strfn.cpp create mode 100644 unrar/unrar/strfn.hpp create mode 100644 unrar/unrar/strlist.cpp create mode 100644 unrar/unrar/strlist.hpp create mode 100644 unrar/unrar/suballoc.cpp create mode 100644 unrar/unrar/suballoc.hpp create mode 100644 unrar/unrar/system.cpp create mode 100644 unrar/unrar/system.hpp create mode 100644 unrar/unrar/timefn.cpp create mode 100644 unrar/unrar/timefn.hpp create mode 100644 unrar/unrar/ulinks.cpp create mode 100644 unrar/unrar/ulinks.hpp create mode 100644 unrar/unrar/unicode.cpp create mode 100644 unrar/unrar/unicode.hpp create mode 100644 unrar/unrar/unios2.cpp create mode 100644 unrar/unrar/unpack.cpp create mode 100644 unrar/unrar/unpack.hpp create mode 100644 unrar/unrar/unpack15.cpp create mode 100644 unrar/unrar/unpack20.cpp create mode 100644 unrar/unrar/uowners.cpp create mode 100644 unrar/unrar/version.hpp create mode 100644 unrar/unrar/volume.cpp create mode 100644 unrar/unrar/volume.hpp create mode 100644 unrar/unrar/win32acl.cpp create mode 100644 unrar/unrar/win32stm.cpp create mode 120000 unrar/vfs_types.h create mode 120000 unrar/vfsutils.c create mode 120000 unrar/vfsutils.h (limited to 'unrar') 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. + + + Copyright (C) + + 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. + + , 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 +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 +#include +#include +#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 + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 *CmtData,Array *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 *CmtData,Array *CmtDataW) +{ + bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE; + if (!ReadSubData(CmtData,NULL)) + return(0); + int CmtSize=CmtData->Size(); + if (Unicode) + { + CmtSize/=2; + Array 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 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 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 Buffer(MAXSFXSIZE); + long CurPos=int64to32(Tell()); + int ReadSize=Read(&Buffer[0],Buffer.Size()-16); + for (int I=0;I0 && CurPos<28 && ReadSize>31) + { + char *D=&Buffer[28-CurPos]; + if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58) + continue; + } + SFXSize=CurPos+I; + Seek(SFXSize,SEEK_SET); + if (!OldFormat) + Read(MarkHead.Mark,SIZEOF_MARKHEAD); + break; + } + if (SFXSize==0) + return(false); + } + ReadHeader(); + SeekToNext(); +#ifndef SFX_MODULE + if (OldFormat) + { + NewMhd.Flags=OldMhd.Flags & 0x3f; + NewMhd.HeadSize=OldMhd.HeadSize; + } + else +#endif + { + if (HeaderCRC!=NewMhd.HeadCRC) + { +#ifndef SHELL_EXT + Log(FileName,St(MLogMainHead)); +#endif + Alarm(); + if (!EnableBroken) + return(false); + } + } + Volume=(NewMhd.Flags & MHD_VOLUME); + Solid=(NewMhd.Flags & MHD_SOLID)!=0; + MainComment=(NewMhd.Flags & MHD_COMMENT)!=0; + Locked=(NewMhd.Flags & MHD_LOCK)!=0; + Signed=(NewMhd.PosAV!=0); + Protected=(NewMhd.Flags & MHD_PROTECT)!=0; + Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0; + + 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 &TimeData); + +#if !defined(SHELL_EXT) && !defined(NOCRYPT) + CryptData HeadersCrypt; + byte HeadersSalt[SALT_SIZE]; +#endif +#ifndef SHELL_EXT + ComprDataIO SubDataIO; + byte SubDataSalt[SALT_SIZE]; +#endif + RAROptions *Cmd,DummyCmd; + + MarkHeader MarkHead; + OldMainHeader OldMhd; + + int RecoverySectors; + Int64 RecoveryPos; + + RarTime LatestTime; + int LastReadBlock; + int CurHeaderType; + + bool SilentOpen; + public: + Archive(RAROptions *InitCmd=NULL); + bool IsArchive(bool EnableBroken); + int SearchBlock(int BlockType); + int SearchSubBlock(const char *Type); + int ReadBlock(int BlockType); + void WriteBlock(int BlockType,BaseBlock *wb=NULL); + int PrepareNamesToWrite(char *Name,wchar *NameW,char *DestName,byte *DestNameW); + void SetLhdSize(); + int ReadHeader(); + void CheckArc(bool EnableBroken); + void CheckOpen(char *Name,wchar *NameW=NULL); + bool WCheckOpen(char *Name,wchar *NameW=NULL); + bool TestLock(int Mode); + void MakeTemp(); + void CopyMainHeader(Archive &Src,bool CopySFX=true,char *NameToDisplay=NULL); + bool ProcessToFileHead(Archive &Src,bool LastBlockAdded, + Pack *Pack=NULL,const char *SkipName=NULL); + void TmpToArc(Archive &Src); + void CloseNew(int AdjustRecovery,bool CloseVolume); + void WriteEndBlock(bool CloseVolume); + void CopyFileRecord(Archive &Src); + void CopyArchiveData(Archive &Src); + bool GetComment(Array *CmtData,Array *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 *UnpData,File *DestFile); + int GetHeaderType() {return(CurHeaderType);}; + int ReadCommentData(Array *CmtData,Array *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.HeadSizePackSize); + Raw.Get(hd->UnpSize); + Raw.Get(hd->HostOS); + Raw.Get(hd->FileCRC); + Raw.Get(hd->FileTime); + Raw.Get(hd->UnpVer); + Raw.Get(hd->Method); + Raw.Get(hd->NameSize); + Raw.Get(hd->FileAttr); + if (hd->Flags & LHD_LARGE) + { + Raw.Get(hd->HighPackSize); + Raw.Get(hd->HighUnpSize); + } + else + { + hd->HighPackSize=hd->HighUnpSize=0; + if (hd->UnpSize==0xffffffff) + { + hd->UnpSize=int64to32(INT64MAX); + hd->HighUnpSize=int64to32(INT64MAX>>32); + } + } + hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize); + hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize); + + char FileName[NM*4]; + int NameSize=Min(hd->NameSize,sizeof(FileName)-1); + Raw.Get((byte *)FileName,NameSize); + FileName[NameSize]=0; + + 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;JSetLocal(&rlt); + } + } + NextBlockPos+=hd->FullPackSize; + bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0; + HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff; + if (hd->HeadCRC!=HeaderCRC) + { + if (hd->HeadType==NEWSUB_HEAD) + strcat(hd->FileName,"- ???"); + BrokenFileHeader=true; + ErrHandler.SetErrorCode(WARNING); +#ifndef SHELL_EXT + Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName)); + Alarm(); +#endif + } + } + break; +#ifndef SFX_MODULE + case COMM_HEAD: + *(BaseBlock *)&CommHead=ShortBlock; + Raw.Get(CommHead.UnpSize); + Raw.Get(CommHead.UnpVer); + Raw.Get(CommHead.Method); + Raw.Get(CommHead.CommCRC); + break; + case SIGN_HEAD: + *(BaseBlock *)&SignHead=ShortBlock; + Raw.Get(SignHead.CreationTime); + Raw.Get(SignHead.ArcNameSize); + Raw.Get(SignHead.UserNameSize); + break; + case AV_HEAD: + *(BaseBlock *)&AVHead=ShortBlock; + Raw.Get(AVHead.UnpVer); + Raw.Get(AVHead.Method); + Raw.Get(AVHead.AVVer); + Raw.Get(AVHead.AVInfoCRC); + break; + case PROTECT_HEAD: + *(BaseBlock *)&ProtectHead=ShortBlock; + Raw.Get(ProtectHead.DataSize); + Raw.Get(ProtectHead.Version); + Raw.Get(ProtectHead.RecSectors); + Raw.Get(ProtectHead.TotalBlocks); + Raw.Get(ProtectHead.Mark,8); + NextBlockPos+=ProtectHead.DataSize; + RecoverySectors=ProtectHead.RecSectors; + break; + case SUB_HEAD: + *(BaseBlock *)&SubBlockHead=ShortBlock; + Raw.Get(SubBlockHead.DataSize); + NextBlockPos+=SubBlockHead.DataSize; + Raw.Get(SubBlockHead.SubType); + Raw.Get(SubBlockHead.Level); + switch(SubBlockHead.SubType) + { + case UO_HEAD: + *(SubBlockHeader *)&UOHead=SubBlockHead; + Raw.Get(UOHead.OwnerNameSize); + Raw.Get(UOHead.GroupNameSize); + if (UOHead.OwnerNameSize>NM-1) + UOHead.OwnerNameSize=NM-1; + if (UOHead.GroupNameSize>NM-1) + UOHead.GroupNameSize=NM-1; + Raw.Get((byte *)UOHead.OwnerName,UOHead.OwnerNameSize); + Raw.Get((byte *)UOHead.GroupName,UOHead.GroupNameSize); + UOHead.OwnerName[UOHead.OwnerNameSize]=0; + UOHead.GroupName[UOHead.GroupNameSize]=0; + break; + case MAC_HEAD: + *(SubBlockHeader *)&MACHead=SubBlockHead; + Raw.Get(MACHead.fileType); + Raw.Get(MACHead.fileCreator); + break; + case EA_HEAD: + case BEEA_HEAD: + case NTACL_HEAD: + *(SubBlockHeader *)&EAHead=SubBlockHead; + Raw.Get(EAHead.UnpSize); + Raw.Get(EAHead.UnpVer); + Raw.Get(EAHead.Method); + Raw.Get(EAHead.EACRC); + break; + case STREAM_HEAD: + *(SubBlockHeader *)&StreamHead=SubBlockHead; + Raw.Get(StreamHead.UnpSize); + Raw.Get(StreamHead.UnpVer); + Raw.Get(StreamHead.Method); + Raw.Get(StreamHead.StreamCRC); + Raw.Get(StreamHead.StreamNameSize); + if (StreamHead.StreamNameSize>NM-1) + StreamHead.StreamNameSize=NM-1; + Raw.Get((byte *)StreamHead.StreamName,StreamHead.StreamNameSize); + StreamHead.StreamName[StreamHead.StreamNameSize]=0; + break; + } + break; +#endif + default: + if (ShortBlock.Flags & LONG_BLOCK) + { + uint DataSize; + Raw.Get(DataSize); + NextBlockPos+=DataSize; + } + break; + } + HeaderCRC=~Raw.GetCRC(false)&0xffff; + CurHeaderType=ShortBlock.HeadType; + if (Decrypt) + { + NextBlockPos+=Raw.PaddedSize()+SALT_SIZE; + + if (ShortBlock.HeadCRC!=HeaderCRC) + { + bool Recovered=false; + if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0) + { + SaveFilePos SavePos(*this); + Int64 Length=Tell(); + Seek(Length-7,SEEK_SET); + Recovered=true; + for (int J=0;J<7;J++) + if (GetByte()!=0) + Recovered=false; + } + if (!Recovered) + { +#ifndef SILENT + Log(FileName,St(MEncrBadCRC),FileName); +#endif + Close(); + + BrokenFileHeader=true; + ErrHandler.SetErrorCode(CRC_ERROR); + return(0); +// ErrHandler.Exit(CRC_ERROR); + } + } + } + + if (NextBlockPos<=CurBlockPos) + { +#ifndef SHELL_EXT + Log(FileName,St(MLogFileHead),"???"); +#endif + BrokenFileHeader=true; + ErrHandler.SetErrorCode(CRC_ERROR); + return(0); + } + return(Raw.Size()); +} + + +#ifndef SFX_MODULE +int Archive::ReadOldHeader() +{ + RawRead Raw(this); + if (CurBlockPos<=SFXSize) + { + Raw.Read(SIZEOF_OLDMHD); + Raw.Get(OldMhd.Mark,4); + Raw.Get(OldMhd.HeadSize); + Raw.Get(OldMhd.Flags); + NextBlockPos=CurBlockPos+OldMhd.HeadSize; + CurHeaderType=MAIN_HEAD; + } + else + { + OldFileHeader OldLhd; + Raw.Read(SIZEOF_OLDLHD); + NewLhd.HeadType=FILE_HEAD; + Raw.Get(NewLhd.PackSize); + Raw.Get(NewLhd.UnpSize); + Raw.Get(OldLhd.FileCRC); + Raw.Get(NewLhd.HeadSize); + Raw.Get(NewLhd.FileTime); + Raw.Get(OldLhd.FileAttr); + Raw.Get(OldLhd.Flags); + Raw.Get(OldLhd.UnpVer); + Raw.Get(OldLhd.NameSize); + Raw.Get(OldLhd.Method); + + NewLhd.Flags=OldLhd.Flags|LONG_BLOCK; + NewLhd.UnpVer=(OldLhd.UnpVer==2) ? 13 : 10; + NewLhd.Method=OldLhd.Method+0x30; + NewLhd.NameSize=OldLhd.NameSize; + NewLhd.FileAttr=OldLhd.FileAttr; + NewLhd.FileCRC=OldLhd.FileCRC; + NewLhd.FullPackSize=NewLhd.PackSize; + NewLhd.FullUnpSize=NewLhd.UnpSize; + + NewLhd.mtime.SetDos(NewLhd.FileTime); + NewLhd.ctime.Reset(); + NewLhd.atime.Reset(); + NewLhd.arctime.Reset(); + + Raw.Read(OldLhd.NameSize); + Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize); + NewLhd.FileName[OldLhd.NameSize]=0; + ConvertNameCase(NewLhd.FileName); + *NewLhd.FileNameW=0; + + if (Raw.Size()!=0) + NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize; + CurHeaderType=FILE_HEAD; + } + return(NextBlockPos>CurBlockPos ? Raw.Size():0); +} +#endif + + +void Archive::ConvertNameCase(char *Name) +{ + if (Cmd->ConvertNames==NAMES_UPPERCASE) + { + IntToExt(Name,Name); + strupper(Name); + ExtToInt(Name,Name); + } + if (Cmd->ConvertNames==NAMES_LOWERCASE) + { + IntToExt(Name,Name); + strlower(Name); + ExtToInt(Name,Name); + } +} + + +#ifndef SFX_MODULE +void Archive::ConvertNameCase(wchar *Name) +{ + if (Cmd->ConvertNames==NAMES_UPPERCASE) + strupperw(Name); + if (Cmd->ConvertNames==NAMES_LOWERCASE) + strlowerw(Name); +} +#endif + + +bool Archive::IsArcDir() +{ + return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY); +} + + +bool Archive::IsArcLabel() +{ + return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8)); +} + + +void Archive::ConvertAttributes() +{ +#if defined(_WIN_32) || defined(_EMX) + switch(NewLhd.HostOS) + { + case HOST_MSDOS: + case HOST_OS2: + case HOST_WIN32: + break; + case HOST_UNIX: + case HOST_BEOS: + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x10; + else + NewLhd.FileAttr=0x20; + break; + default: + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x10; + else + NewLhd.FileAttr=0x20; + break; + } +#endif +#ifdef _UNIX + static mode_t mask = (mode_t) -1; + + if (mask == (mode_t) -1) + { + mask = umask(022); + umask(mask); + } + switch(NewLhd.HostOS) + { + case HOST_MSDOS: + case HOST_OS2: + case HOST_WIN32: + if (NewLhd.FileAttr & 0x10) + NewLhd.FileAttr=0x41ff & ~mask; + else + if (NewLhd.FileAttr & 1) + NewLhd.FileAttr=0x8124 & ~mask; + else + NewLhd.FileAttr=0x81b6 & ~mask; + break; + case HOST_UNIX: + case HOST_BEOS: + break; + default: + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x41ff & ~mask; + else + NewLhd.FileAttr=0x81b6 & ~mask; + break; + } +#endif +} + + +void Archive::ConvertUnknownHeader() +{ + if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10)) + NewLhd.Flags|=LHD_DIRECTORY; + if (NewLhd.HostOS>=HOST_MAX) + { + if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) + NewLhd.FileAttr=0x10; + else + NewLhd.FileAttr=0x20; + } + for (char *s=NewLhd.FileName;*s!=0;s=charnext(s)) + { + if (*s=='/' || *s=='\\') + *s=CPATHDIVIDER; +#if defined(_APPLE) && !defined(UNICODE_SUPPORTED) + if ((byte)*s<32 || (byte)*s>127) + *s='_'; +#endif + } + for (wchar *s=NewLhd.FileNameW;*s!=0;s++) + if (*s=='/' || *s=='\\') + *s=CPATHDIVIDER; +} + + +#ifndef SHELL_EXT +bool Archive::ReadSubData(Array *UnpData,File *DestFile) +{ + if (HeaderCRC!=SubHead.HeadCRC) + { +#ifndef SHELL_EXT + Log(FileName,St(MSubHeadCorrupt)); +#endif + ErrHandler.SetErrorCode(CRC_ERROR); + return(false); + } + if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>/*PACK_VER*/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 Array +{ + private: + T *Buffer; + int BufSize; + int AllocSize; + public: + Array(); + Array(int Size); + ~Array(); + inline void CleanData(); + inline T& operator [](int Item); + inline int Size(); + void Add(int Items); + void Alloc(int Items); + void Reset(); + void operator = (Array &Src); + void Push(T Item); + T* Addr() {return(Buffer);} +}; + +template void Array::CleanData() +{ + Buffer=NULL; + BufSize=0; + AllocSize=0; +} + + +template Array::Array() +{ + CleanData(); +} + + +template Array::Array(int Size) +{ + Buffer=(T *)rarmalloc(sizeof(T)*Size); + if (Buffer==NULL && Size!=0) + ErrHandler.MemoryError(); + + AllocSize=BufSize=Size; +} + + +template Array::~Array() +{ + if (Buffer!=NULL) + rarfree(Buffer); +} + + +template inline T& Array::operator [](int Item) +{ + return(Buffer[Item]); +} + + +template inline int Array::Size() +{ + return(BufSize); +} + + +template void Array::Add(int Items) +{ + BufSize+=Items; + if (BufSize>AllocSize) + { + int Suggested=AllocSize+AllocSize/4+32; + int NewSize=Max(BufSize,Suggested); + + Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T)); + if (Buffer==NULL) + ErrHandler.MemoryError(); + AllocSize=NewSize; + } +} + + +template void Array::Alloc(int Items) +{ + if (Items>AllocSize) + Add(Items-BufSize); + else + BufSize=Items; +} + + +template void Array::Reset() +{ + if (Buffer!=NULL) + { + rarfree(Buffer); + Buffer=NULL; + } + BufSize=0; + AllocSize=0; +} + + +template void Array::operator =(Array &Src) +{ + Reset(); + Alloc(Src.BufSize); + if (Src.BufSize!=0) + memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T)); +} + + +template void Array::Push(T Item) +{ + Add(1); + (*this)[Size()-1]=Item; +} + +#endif diff --git a/unrar/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 UnpData(Arc.EAHead.UnpSize); + DataIO.SetUnpackToMemory(&UnpData[0],Arc.EAHead.UnpSize); + DataIO.SetPackedSizeToRead(Arc.EAHead.DataSize); + DataIO.EnableShowProgress(false); + DataIO.SetFiles(&Arc,NULL); + Unpack.SetDestSize(Arc.EAHead.UnpSize); + Unpack.DoUnpack(Arc.EAHead.UnpVer,false); + + if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC) + { + Log(Arc.FileName,St(MEABroken),FileName); + ErrHandler.SetErrorCode(CRC_ERROR); + return; + } + int fd = open(FileName,O_WRONLY); + if (fd==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + return; + } + + int AttrPos=0; + while (AttrPos=sizeof(Name)) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + memcpy(Name,CurItem+10,NameSize); + Name[NameSize]=0; + if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + AttrPos+=10+NameSize+Size; + } + close(fd); + mprintf(St(MShowEA)); +} + + +void ExtractBeEANew(Archive &Arc,char *FileName) +{ + Array SubData; + if (!Arc.ReadSubData(&SubData,NULL)) + return; + + int fd = open(FileName,O_WRONLY); + if (fd==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + return; + } + + int AttrPos=0; + while (AttrPos=sizeof(Name)) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + memcpy(Name,CurItem+10,NameSize); + Name[NameSize]=0; + if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1) + { + Log(Arc.FileName,St(MCannotSetEA),FileName); + ErrHandler.SetErrorCode(WARNING); + break; + } + AttrPos+=10+NameSize+Size; + } + close(fd); + mprintf(St(MShowEA)); +} + diff --git a/unrar/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='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;IAddString(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;IRewind(); + 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;IGetChar()); +} + + +void RangeCoder::InitDecoder(Unpack *UnpackRead) +{ + RangeCoder::UnpackRead=UnpackRead; + + low=code=0; + range=uint(-1); + for (int i=0;i < 4;i++) + code=(code << 8) | GetChar(); +} + + +#define ARI_DEC_NORMALIZE(code,low,range,read) \ +{ \ + while ((low^(low+range))GetChar(); \ + range <<= 8; \ + low <<= 8; \ + } \ +} + + +inline int RangeCoder::GetCurrentCount() +{ + return (code-low)/(range /= SubRange.scale); +} + + +inline uint RangeCoder::GetCurrentShiftCount(uint SHIFT) +{ + return (code-low)/(range >>= SHIFT); +} + + +inline void RangeCoder::Decode() +{ + low += range*SubRange.LowCount; + range *= SubRange.HighCount-SubRange.LowCount; +} diff --git a/unrar/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)4 ? "\n":" "):", "); + int KeyPos=ItemKeyPos[I]; + for (int J=0;J>1)^0xEDB88320L : (C>>1); + CRCTab[I]=C; + } +} + + +uint CRC(uint StartCRC,const void *Addr,uint Size) +{ + if (CRCTab[1]==0) + InitCRC(); + byte *Data=(byte *)Addr; +#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && 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>8); + return(StartCRC); +} + +#ifndef SFX_MODULE +ushort OldCRC(ushort StartCRC,const void *Addr,uint Size) +{ + byte *Data=(byte *)Addr; + for (int I=0;I>15))&0xffff; + } + return(StartCRC); +} +#endif diff --git a/unrar/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>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>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 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>6) + { + case 0: + NameW[DecPos++]=EncName[EncPos++]; + break; + case 1: + NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8); + break; + case 2: + NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8); + EncPos+=2; + break; + case 3: + { + int Length=EncName[EncPos++]; + if (Length & 0x80) + { + byte Correction=EncName[EncPos++]; + for (Length=(Length&0x7f)+2;Length>0 && DecPos0 && DecPosMAXPATH) + { + Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAXPATH); + } + } +#endif + SysErrMsg(); +#endif +} + + +void ErrorHandler::ReadErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + ErrMsg(ArcName,St(MErrRead),FileName); + SysErrMsg(); +#endif +} + + +void ErrorHandler::WriteErrorMsg(const char *ArcName,const char *FileName) +{ +#ifndef SILENT + ErrMsg(ArcName,St(MErrWrite),FileName); + SysErrMsg(); +#endif +} + + +void ErrorHandler::Exit(int ExitCode) +{ +#ifndef SFX_MODULE + Alarm(); +#endif + Throw(ExitCode); +} + + +#ifndef GUI +void ErrorHandler::ErrMsg(const char *ArcName,const char *fmt,...) +{ + safebuf char Msg[NM+1024]; + va_list argptr; + va_start(argptr,fmt); + vsprintf(Msg,fmt,argptr); + va_end(argptr); +#ifdef _WIN_32 + if (UserBreak) + Sleep(5000); +#endif + Alarm(); + if (*Msg) + { + Log(ArcName,"\n%s",Msg); + mprintf("\n%s\n",St(MProgAborted)); + } +} +#endif + + +void ErrorHandler::SetErrorCode(int Code) +{ + switch(Code) + { + case WARNING: + case USER_BREAK: + if (ExitCode==SUCCESS) + ExitCode=Code; + break; + case FATAL_ERROR: + if (ExitCode==SUCCESS || ExitCode==WARNING) + ExitCode=FATAL_ERROR; + break; + default: + ExitCode=Code; + break; + } + ErrCount++; +} + + +#if !defined(GUI) && !defined(_SFX_RTL_) +#ifdef _WIN_32 +BOOL __stdcall ProcessSignal(DWORD SigType) +#else +#if defined(__sun) +extern "C" +#endif +void _stdfunction ProcessSignal(int SigType) +#endif +{ +#ifdef _WIN_32 + if (SigType==CTRL_LOGOFF_EVENT) + return(TRUE); +#endif + UserBreak=true; + mprintf(St(MBreak)); + for (int I=0;!File::RemoveCreated() && I<3;I++) + { +#ifdef _WIN_32 + Sleep(100); +#endif + } +#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE) + ExtRes.UnloadDLL(); +#endif + exit(USER_BREAK); +#ifdef _WIN_32 + return(TRUE); +#endif +} +#endif + + +void ErrorHandler::SetSignalHandlers(bool Enable) +{ + EnableBreak=Enable; +#if !defined(GUI) && !defined(_SFX_RTL_) +#ifdef _WIN_32 + SetConsoleCtrlHandler(Enable ? ProcessSignal:NULL,TRUE); +// signal(SIGBREAK,Enable ? ProcessSignal:SIG_IGN); +#else + signal(SIGINT,Enable ? ProcessSignal:SIG_IGN); + signal(SIGTERM,Enable ? ProcessSignal:SIG_IGN); +#endif +#endif +} + + +void ErrorHandler::Throw(int Code) +{ + if (Code==USER_BREAK && !EnableBreak) + return; + ErrHandler.SetErrorCode(Code); +#ifdef ALLOW_EXCEPTIONS + throw Code; +#else + File::RemoveCreated(); + exit(Code); +#endif +} + + +void ErrorHandler::SysErrMsg() +{ +#if !defined(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 Buffer(0x10000); + while (1) + { + unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size()); + if (Code==0 || (int)Code==-1) + break; + Code=Code=0) + DestUnpSize-=Code; + } +} + diff --git a/unrar/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;ISize && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff) + ErrHandler.WriteErrorFAT(FileName); +#endif + if (ErrHandler.AskRepeatWrite(FileName)) + { +#ifndef _WIN_32 + clearerr(hFile); +#endif + if (Written0) + Seek(Tell()-Written,SEEK_SET); + continue; + } + ErrHandler.WriteError(NULL,FileName); + } + break; + } + LastWrite=true; +} + + +int File::Read(void *Data,int Size) +{ + Int64 FilePos; + if (IgnoreReadErrors) + FilePos=Tell(); + int ReadSize; + while (true) + { + ReadSize=DirectRead(Data,Size); + if (ReadSize==-1) + { + ErrorType=FILE_READERROR; + if (AllowExceptions) + if (IgnoreReadErrors) + { + ReadSize=0; + for (int I=0;IMaxDeviceRead) + Size=MaxDeviceRead; + hFile=GetStdHandle(STD_INPUT_HANDLE); +#else + hFile=stdin; +#endif + } +#endif +#ifdef _WIN_32 + DWORD Read; + if (!ReadFile(hFile,Data,Size,&Read,NULL)) + { + if (IsDevice() && Size>MaxDeviceRead) + return(DirectRead(Data,MaxDeviceRead)); + if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE) + return(0); + return(-1); + } + return(Read); +#else + if (LastWrite) + { + fflush(hFile); + LastWrite=false; + } + clearerr(hFile); + int ReadSize=fread(Data,1,Size,hFile); + if (ferror(hFile)) + return(-1); + return(ReadSize); +#endif +} + + +void File::Seek(Int64 Offset,int Method) +{ + if (!RawSeek(Offset,Method) && AllowExceptions) + ErrHandler.SeekError(FileName); +} + + +bool File::RawSeek(Int64 Offset,int Method) +{ + if (hFile==BAD_HANDLE) + return(true); + if (!is64plus(Offset) && Method!=SEEK_SET) + { + Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset; + Method=SEEK_SET; + } +#ifdef _WIN_32 + LONG HighDist=int64to32(Offset>>32); + if (SetFilePointer(hFile,int64to32(Offset),&HighDist,Method)==0xffffffff && + GetLastError()!=NO_ERROR) + return(false); +#else + LastWrite=false; +#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;ISetExceptions(false); + bool Success; + if (CreatedFiles[I]->NewFile) + Success=CreatedFiles[I]->Delete(); + else + Success=CreatedFiles[I]->Close(); + if (Success) + CreatedFiles[I]=NULL; + else + RetCode=false; + } + RemoveCreatedActive--; + return(RetCode); +} + + +#ifndef SFX_MODULE +long File::Copy(File &Dest,Int64 Length) +{ + Array Buffer(0x10000); + long CopySize=0; + bool CopyAll=(Length==INT64ERR); + + while (CopyAll || Length>0) + { + Wait(); + int SizeToRead=(!CopyAll && Length=NM || *s==0) + IgnoreAscii=true; + if (Wide && (PosW>=NM || PathW[PosW]==0) || !Wide && IgnoreAscii) + break; + if (Wide && PathW[PosW]==CPATHDIVIDER || !Wide && *s==CPATHDIVIDER) + { + wchar *DirPtrW=NULL,DirNameW[NM]; + if (Wide) + { + strncpyw(DirNameW,PathW,PosW); + DirNameW[PosW]=0; + DirPtrW=DirNameW; + } + char DirName[NM]; + if (IgnoreAscii) + WideToChar(DirPtrW,DirName); + else + { +#ifndef DBCS_SUPPORTED + if (*s!=CPATHDIVIDER) + for (const char *n=s;*n!=0 && n-PathIsSet(); + bool sc=ftc!=NULL && ftc->IsSet(); + bool sa=fta!=NULL && fta->IsSet(); + + 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(®s,0,sizeof(regs)); + regs.h.ah=0x36; + regs.h.dl=Drive; +#ifdef _DJGPP + int86 (0x21,®s,&outregs); +#else + _int86 (0x21,®s,&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 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 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 DataW(Data.Size()/2+1); + for (int I=2;I 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;IError=false; + if (*FindMask==0) + return(false); +#ifdef _WIN_32 + if (FirstCall) + { + if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE) + return(false); + } + else + if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE) + return(false); +#else + if (FirstCall) + { + char DirName[NM]; + strcpy(DirName,FindMask); + RemoveNameFromPath(DirName); + if (*DirName==0) + strcpy(DirName,"."); +/* + else + { + int Length=strlen(DirName); + if (Length>1 && DirName[Length-1]==CPATHDIVIDER && (Length!=3 || !IsDriveDiv(DirName[1]))) + DirName[Length-1]=0; + } +*/ + if ((dirp=opendir(DirName))==NULL) + { + fd->Error=(errno!=ENOENT); + return(false); + } + } + while (1) + { + struct dirent *ent=readdir(dirp); + if (ent==NULL) + return(false); + if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0) + continue; + if (CmpName(FindMask,ent->d_name,MATCH_NAMES)) + { + char FullName[NM]; + strcpy(FullName,FindMask); + *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 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 (Int64 n1,Int64 n2) +{ + return((int)n1.HighPart>(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart>n2.LowPart); +} + + +bool operator < (Int64 n1,Int64 n2) +{ + return((int)n1.HighPart<(int)n2.HighPart || n1.HighPart==n2.HighPart && n1.LowPart= (Int64 n1,Int64 n2) +{ + return(n1>n2 || n1==n2); +} + + +bool operator <= (Int64 n1,Int64 n2) +{ + return(n1='0' && *Str<='9') + { + n=n*10+*Str-'0'; + Str++; + } + return(n); +} diff --git a/unrar/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 (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",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 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 - - " +#define MUNRARTitle1 "\nUsage: unrar - - " +#define MRARTitle2 "\n <@listfiles...> " +#define MCHelpCmd "\n\n" +#define MCHelpCmdA "\n a Add files to archive" +#define MCHelpCmdC "\n c Add archive comment" +#define MCHelpCmdCF "\n cf Add files comment" +#define 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]= Find string in archives" +#define MCHelpCmdK "\n k Lock archive" +#define MCHelpCmdL "\n l[t,b] List archive [technical, bare]" +#define MCHelpCmdM "\n m[f] Move to archive [files only]" +#define MCHelpCmdP "\n p Print file to stdout" +#define MCHelpCmdR "\n r Repair archive" +#define MCHelpCmdRC "\n rc Reconstruct missing volumes" +#define MCHelpCmdRN "\n rn Rename archived files" +#define MCHelpCmdRR "\n rr[N] Add data recovery record" +#define MCHelpCmdRV "\n rv[N] Create recovery volumes" +#define MCHelpCmdS "\n s[name|-] Convert archive to or from SFX" +#define MCHelpCmdT "\n t Test archive files" +#define MCHelpCmdU "\n u Update files in archive" +#define MCHelpCmdV "\n v[t,b] Verbosely list archive [technical,bare]" +#define MCHelpCmdX "\n x Extract files with full path" +#define MCHelpSw "\n\n" +#define MCHelpSwm "\n - Stop switches scanning" +#define MCHelpSwAC "\n ac Clear Archive attribute after compression or extraction" +#define MCHelpSwAD "\n ad Append archive name to destination path" +#define MCHelpSwAG "\n ag[format] Generate archive name using the current date" +#define MCHelpSwAO "\n ao Add files with Archive attribute set" +#define MCHelpSwAP "\n ap Set path inside archive" +#define MCHelpSwAS "\n as Synchronize archive contents" +#define MCHelpSwAV "\n av Put authenticity verification (registered versions only)" +#define MCHelpSwAVm "\n av- Disable authenticity verification check" +#define MCHelpSwCm "\n c- Disable comments show" +#define MCHelpSwCFGm "\n cfg- Disable read configuration" +#define MCHelpSwCL "\n cl Convert names to lower case" +#define MCHelpSwCU "\n cu Convert names to upper case" +#define MCHelpSwDF "\n df Delete files after archiving" +#define MCHelpSwDH "\n dh Open shared files" +#define MCHelpSwDS "\n ds Disable name sort for solid archive" +#define MCHelpSwEa "\n e[+] Set file exclude and include attributes" +#define MCHelpSwED "\n ed Do not add empty directories" +#define MCHelpSwEE "\n ee Do not save and extract extended attributes" +#define MCHelpSwEN "\n en Do not put 'end of archive' block" +#define MCHelpSwEP "\n ep Exclude paths from names" +#define MCHelpSwEP1 "\n ep1 Exclude base directory from names" +#define MCHelpSwEP2 "\n ep2 Expand paths to full" +#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter" +#define MCHelpSwF "\n f Freshen files" +#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers" +#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages" +#define MCHelpSwIEML "\n ieml[addr] Send archive by email" +#define MCHelpSwIERR "\n ierr Send all messages to stderr" +#define MCHelpSwILOG "\n ilog[name] Log errors to file (registered versions only)" +#define MCHelpSwINUL "\n inul Disable all messages" +#define MCHelpSwIOFF "\n ioff Turn PC off after completing an operation" +#define MCHelpSwISND "\n isnd Enable sound" +#define MCHelpSwK "\n k Lock archive" +#define MCHelpSwKB "\n kb Keep broken extracted files" +#define MCHelpSwMn "\n m<0..5> Set compression level (0-store...3-default...5-maximal)" +#define MCHelpSwMC "\n mc Set advanced compression parameters" +#define MCHelpSwMD "\n md Dictionary size in KB (64,128,256,512,1024,2048,4096 or A-G)" +#define MCHelpSwMS "\n ms[ext;ext] Specify file types to store" +#define MCHelpSwMT "\n mt Set the number of threads" +#define MCHelpSwN "\n n Include only specified file" +#define MCHelpSwNa "\n n@ Read file names to include from stdin" +#define MCHelpSwNal "\n n@ Include files in specified list file" +#define MCHelpSwOp "\n o+ Overwrite existing files" +#define MCHelpSwOm "\n o- Do not overwrite existing files" +#define MCHelpSwOC "\n oc Set NTFS Compressed attribute" +#define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file" +#define 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

[:] Set priority (0-default,1-min..15-max) and sleep time in ms" +#define MCHelpSwRR "\n rr[N] Add data recovery record" +#define MCHelpSwRV "\n rv[N] Create recovery volumes" +#define MCHelpSwS "\n s[,v[-],e] Create solid archive" +#define MCHelpSwSm "\n s- Disable solid archiving" +#define MCHelpSwSC "\n sc[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 Process files with size less than specified" +#define MCHelpSwSM "\n sm 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