124 Commits

Author SHA1 Message Date
cataphract
d7d4f10f7f Tagging release 2.0.0 (only difference to the release tarball being the version number 2.0.0-dev having been changed to 2.0.0).
git-svn-id: http://svn.php.net/repository/pecl/rar/tags/RELEASE_2_0_0@298214 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-20 12:48:08 +00:00
cataphract
0f76b938a4 Preparing for 2.0.0 release.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298212 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-20 12:26:15 +00:00
cataphract
670290aad1 Renamed RarArchive::list() to RarArchive::getEntries() (see bug #17025). The old name of the method can be activated by defining RAR_ARCHIVE_LIST_ALIAS.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298209 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-20 11:32:30 +00:00
johannes
82d3711a99 s,function_entry,zend_function_entry,
As announced in http://news.php.net/php.pecl.dev/7123


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@297236 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-31 20:39:48 +00:00
cataphract
af49aafb1d Listed files added in the previous commit to package.xml.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@295911 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-07 00:50:00 +00:00
cataphract
7288320a37 Fixed infinite loop when opening files with missing volumes.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@295909 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-07 00:43:31 +00:00
cataphract
fc23699737 Fixed config.w32 for static configurations.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293697 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-18 11:04:24 +00:00
cataphract
fffcb9d508 Updated bundled UnRAR lib to 3.9.7. Deleted two redundant files.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293691 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-18 04:09:51 +00:00
cataphract
79afa19815 Fixed RarException::isUsingExceptions parsing a boolean argument into a long, which made the value depend on uninitialized data.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293642 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-17 09:53:07 +00:00
cataphract
02855820f7 Fixed test 32 (trivial).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293638 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-17 08:54:43 +00:00
cataphract
5f7b823e40 Fixed two bugs:
RarArchive get iterator on closed file caused crash.
rararch_it_current_data was copying the address of a stack allocated variable. Only caught this when testing on release PHP 5.2 under Linux.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293637 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-17 08:46:30 +00:00
cataphract
59437d527f package.xml: Release Candidate versions must have upper-case RC, not
lower-case rc


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293626 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-16 20:55:07 +00:00
cataphract
9be4e1e0e3 package.xml updated.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293625 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-16 20:52:17 +00:00
cataphract
7089587b9e Fixed memory leaks.
Tab -> space in package.xml

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292721 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-28 17:41:29 +00:00
cataphract
43dc0541aa Fixed missing definitions in 5.2.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292701 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-27 19:34:35 +00:00
cataphract
36b2b5d2fc Hopefully fixed non-ZTS compilation.
Fixed test #34.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292692 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-27 15:58:53 +00:00
cataphract
4e2dc20b2d Renamed rar_solid_get to rar_solid_is.
RarException::setUsingExceptions no longer returns anything.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292614 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-24 20:28:10 +00:00
cataphract
61183fa339 Fixed prototypes and header missing.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292612 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-24 18:53:36 +00:00
cataphract
7da530c6e3 Added error handling with exceptions.
Introduction of RarException.
Added rar_solid_get
RarEntry and RarArchive cannot be instantiated in user space.
Quite some refactoring.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292412 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-21 14:04:56 +00:00
cataphract
b7794e851d Fixed line endings, added svn properties on rararch.c
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292391 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-21 00:40:56 +00:00
cataphract
444ee4b790 RarArchive made traversable.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292194 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-16 10:49:54 +00:00
tony2001
51b5b9b267 state the truth
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291943 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-10 10:38:46 +00:00
cataphract
65758585af Restored LPARAM to long and let's hope sizeof(long) == sizeof(void*) in non-windows platforms.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291824 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 16:48:43 +00:00
cataphract
5966259561 Reverted accidental package.xml change.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291823 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 16:17:17 +00:00
cataphract
67d29529f1 Fix for Linux compilation.
Tests correction and relaxation where required.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291822 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 16:08:33 +00:00
cataphract
e09548cd2f Hopefully fixed VC6 compilation, added two more tests and updated package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291820 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 15:34:13 +00:00
cataphract
6faef72502 Fixed RarArchive::getEntry not working.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291805 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 07:42:17 +00:00
cataphract
c39465fa08 Fixed an obvious mistake.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291802 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 06:36:53 +00:00
cataphract
633a15f4b4 Refactoring/added RarArchive class.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291800 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 06:12:39 +00:00
cataphract
c4432e6c4b Hopefully fixed non-windows building.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291730 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-05 01:16:36 +00:00
cataphract
81934056d0 Proper support for encrypted files.
Restored C-like feof semantics.
Added tests with encrypted files and unix directories and links.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291532 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-01 00:38:02 +00:00
cataphract
896a5d3a91 Same as last commit, but this time with the correct changes...
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291452 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 19:21:06 +00:00
cataphract
a153f2ba84 Correct fixes for tests in PHP 5.2.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291451 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 19:05:05 +00:00
cataphract
6c8276f3c8 Fixed PHP 5.2 branch compatibility.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291450 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 19:00:18 +00:00
cataphract
380eb4fd06 Fixed typo.
Fixed package.xml.
Promoted to beta.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291447 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 17:59:29 +00:00
cataphract
c502332f09 Updated package.xml and CREDITS. Release 2.0.0snap29112009
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291442 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 17:34:07 +00:00
cataphract
e64419b1c3 Fixed two memory leaks reported by the zend engine.
Fixed expected output of test 021 to work in linux.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291440 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 16:17:48 +00:00
cataphract
a9d71e2adb Added missing prototype in rarentry.c. Currently a no-op since the usage of the function was below its definition.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291421 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 13:24:57 +00:00
cataphract
c56f0c4ad9 rarentry.c: added header, added svn properties and wrapped in an extern C in case of compilation with a C++ compiler.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291420 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 13:19:02 +00:00
cataphract
6de793130a Refactoring.
Added a bunch of constants to RarEntry.
Fixed possible crash with empty RAR files (though WinRAR doesn't let you create empty RAR files)
Added __toString method
All RarEntry properties are now private.
Made most methods not implementation dependent.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291411 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 03:41:11 +00:00
cataphract
ba66f77e5f Test for RarEntry::getStream() with diectories.
feof marked right after creation of stream if it can right then be determined that there are no bytes to be read. These are not C feof semantics, but I can find no documentation that says this is forbidden.
_rar_list_files now doesn't call realloc every time it processes a header (allocates powers of 2), thus improving performance.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291326 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-26 01:40:14 +00:00
cataphract
f93c189947 Added RarEntry::isDirectory().
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291303 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-25 11:22:03 +00:00
cataphract
5ba817d02c Test #012 had to be further relaxed.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291222 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 19:27:23 +00:00
cataphract
3655bf9e21 Fixed test #016 (file count correct). It's irrelevant that the file
count is correct because you won't be able to extract the files that 
ended up with the same wide file name, but now the test passes...
Test #012 still wouldn't pass, so it was relaxed.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291221 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 19:26:03 +00:00
cataphract
3254b497a2 Fixed bug in unrarlib that makes tests 012 and 016 fail less miserably.
On dll.cpp on line 193, CharToWide is called but the return value is 
not checked. CharToWide calls mbstowcs(), which stops when an invalid 
multibyte sequence is encountered and returns -1. So the string will be 
truncated until before the invalid sequence and Dest buffer will not be 
L'\0'-terminated unless you happened to fill RARHeaderDataEx with 0's 
before (for instance, if you called calloc to allocate the memory).
Fixed by checking the return value and force try to do the conversion 
via UtfToWide, which handles the conversion more gracefully (ignores 
invalid sequences).


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291220 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 18:42:59 +00:00
cataphract
da1c055202 Hopefully fixed tests #012 and #016 in platforms with 32-bit wchar_t.
Arc->FilenameW could have invalid unicode characters that were discarded when converted into multi-byte UTF-8 string.
Then _rar_find_file would convert UTF-8 back to multi-character and compare with Arc->FilenameW, thus failing. Now Arc->FilenameW is fixed before the comparison by removing its invalid characters.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291199 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 13:01:20 +00:00
cataphract
d3ffa6d3ba Small corrections.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291166 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 00:49:10 +00:00
cataphract
8d24ef1195 Added tests for solid archives and archives with the store method.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291147 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 19:48:03 +00:00
cataphract
84d8d1c93f Fixed volumes opened with middle volumes showing files continued from previous volume with incorrect packed and unpacked sizes. Though that is the behavior of WinRAR, I prefer not to show files continued from previous volume altogether.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291145 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 18:57:37 +00:00
cataphract
22be3d8ee9 Fixed integer division by 0 in a different way from last commit. This method also saves unnecessary calls to RARProcessFileChunk.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291142 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 16:07:39 +00:00
cataphract
397d6de791 Refactoring.
Interim fix for crash in test 12. It would be nice to know what's going on.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291126 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 03:14:09 +00:00
cataphract
6d00347ddd Fixed PECL bug #9649 - resource is now destroyed regardless of the le->refcount
Fixed consistency between RarEntry::getName and RarEntry::getStream, which exposed integer division by zero.
Teste #012 now fails.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291119 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-21 18:56:40 +00:00
cataphract
1401a0604c Had removed arginfo inadvertedly. That accident was fixed.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291116 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-21 15:17:17 +00:00
cataphract
d033b8f836 PHP 5.2 compatibility and linux compilability.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291113 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-21 12:09:39 +00:00
cataphract
b15940e101 Fixed svn:keywords for rar_stream.cpp
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291093 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 15:52:33 +00:00
cataphract
829e402dbb Fixed phpinfo version information.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291092 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 15:48:40 +00:00
cataphract
48c55f71ea Added test to ::getStream() with corrupted file.
Fixed incoherence between ::getName() and rar_entry_get and added test for that.
Restructured ::extract(), now with relative paths fixed for the second argument.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291089 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 14:58:48 +00:00
felipe
9876090ea6 - Added arginfo
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291071 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 11:56:32 +00:00
cataphract
3a71ec0c0f Fixed the config files.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291047 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 23:40:02 +00:00
cataphract
c52d6a92a6 Stream support added. Still missing tests with corrupted files.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291023 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 18:45:31 +00:00
cataphract
8f65391767 Handles unicode filenames (uses UTF-8 external encoding).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291015 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 17:32:04 +00:00
cataphract
3f841aca84 Test 004.phpt relied on undocumented behavior that had been broken in the last commit. Old behavior emulated, test now passes without modifications.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291012 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 16:35:45 +00:00
cataphract
d39e216566 Fixed the relative path bug for RarEntry::extract()
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291009 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 16:18:21 +00:00
cataphract
ed74b331d8 Fixed by pecl bug #8821 by using expand_filepath.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290966 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 05:42:39 +00:00
cataphract
36e67a3493 Fixed warning message not being shown when rar_entry_get was called with a file that did not exist.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290965 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 04:23:22 +00:00
cataphract
d6673b97fd Fixed pecl bug #9470 by changing the list method (now there can be multiple entries per file).
Added rar_comment_get.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290964 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 04:02:37 +00:00
cataphract
04ac7f6eba changed type from HANDLE back to void * (change had broken non-windows compilation).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290945 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 21:22:00 +00:00
cataphract
a4b1479338 Fixed compilation.
Updated code to use extended unrar lib structures.
rar_open gives more detailed error messages on failure. Updated tests accordingly.
Changed version from 2.0-dev to 2.0.0-dev, as I understand that's the convention.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290943 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 21:12:27 +00:00
cataphract
d528906ec7 Made some modifications to the unrar lib in order to allow partial and resumable extraction. It is not complete (probably crashes on corrupted files, for instance), but it should NOT break the functionality currently implemented in the Rar extension.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290924 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 17:46:10 +00:00
cataphract
3c08bc522f Previous commit had inadvertedly eaten away two slashes. Fixed.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290916 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 14:56:13 +00:00
cataphract
dc4037e8ed Fixed build in linux by adding two headers that handle os-dependent
stuff.
Added -Wno-write-strings to suppress warning about deprecated conversion from string constant to ‘char*’.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290915 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 14:23:48 +00:00
cataphract
b79060c741 Updated bundled unrar lib to version 3.90 or 3.9.6 depending on whether the download file name of version.hpp is correct...
Changed version number to 2.0-dev

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290883 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-17 19:26:03 +00:00
cataphract
2ea98f9c07 php_rar now compiles on Windows.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290872 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-17 16:12:40 +00:00
gwynne
40b585bc2f fix a huge number of wrong MIME types. UGH.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@284003 c90b9560-bf6c-de11-be94-00142212c4b1
2009-07-13 12:15:13 +00:00
tony2001
62ebac8d88 update my email
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@264972 c90b9560-bf6c-de11-be94-00142212c4b1
2008-08-16 10:16:46 +00:00
sfox
cf7947cbbd - Bring the majority of PECL extensions into line with macro/x.x.x versioning.
- Please use the -dev tag during the development cycle so that snapshots can easily be distinguished from releases.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@256498 c90b9560-bf6c-de11-be94-00142212c4b1
2008-03-31 10:10:01 +00:00
tony2001
f6900cb024 update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@253819 c90b9560-bf6c-de11-be94-00142212c4b1
2008-02-26 13:29:00 +00:00
tony2001
fa8c1c8aa8 updated UnRar to version 3.7.8
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@253818 c90b9560-bf6c-de11-be94-00142212c4b1
2008-02-26 13:27:57 +00:00
tony2001
4d7c5fc2c4 add UnRAR version to phpinfo() output
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@253817 c90b9560-bf6c-de11-be94-00142212c4b1
2008-02-26 13:27:25 +00:00
tony2001
10d2444b31 fix protos (thanks to Philip)
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@247309 c90b9560-bf6c-de11-be94-00142212c4b1
2007-11-29 21:12:55 +00:00
tony2001
63e0df6078 ifdef safe_mode and fix build with HEAD
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241940 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-30 10:35:10 +00:00
tony2001
54ac112b0d use PHPs flock() on AIX
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241421 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-17 10:08:54 +00:00
tony2001
9ec063426c no point to keep it forever..
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241275 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-15 18:26:30 +00:00
tony2001
1d4ad5767b prepare to 1.0.0
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241273 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-15 17:12:54 +00:00
tony2001
0866f20178 nuke unused variable
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241211 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-14 09:14:22 +00:00
tony2001
5db1495374 convert to 2.0, update & prepare to 1.0.0 release
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241187 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-13 21:48:26 +00:00
tony2001
75f63eae35 updated unRar to version 3.7.6
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241183 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-13 21:39:53 +00:00
tony2001
5f0d4b1516 fix bug #11430 (rar_extract() doesn't close handles gracefully)
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@238531 c90b9560-bf6c-de11-be94-00142212c4b1
2007-06-25 11:59:11 +00:00
tony2001
7430bfae21 update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@229866 c90b9560-bf6c-de11-be94-00142212c4b1
2007-02-15 15:07:14 +00:00
tony2001
3010bc351e upgrade to 3.7.3
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@229865 c90b9560-bf6c-de11-be94-00142212c4b1
2007-02-15 15:05:54 +00:00
tony2001
bfaaaa95fe update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@221632 c90b9560-bf6c-de11-be94-00142212c4b1
2006-10-12 16:09:56 +00:00
tony2001
379f5d1d43 fix PECL bug #9002
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@221631 c90b9560-bf6c-de11-be94-00142212c4b1
2006-10-12 16:07:47 +00:00
tony2001
f45fb54b0a path is always not NULL
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@220163 c90b9560-bf6c-de11-be94-00142212c4b1
2006-09-18 10:48:48 +00:00
tony2001
e4d1885168 update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@220148 c90b9560-bf6c-de11-be94-00142212c4b1
2006-09-17 21:18:50 +00:00
tony2001
b5cecfd421 add some more error messages
nuke dead code
use new parameter parsing API
update tests


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@220147 c90b9560-bf6c-de11-be94-00142212c4b1
2006-09-17 21:14:53 +00:00
tony2001
57f518d804 add tests
remove file missing in unrar 3.6.8


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


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


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


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@180383 c90b9560-bf6c-de11-be94-00142212c4b1
2005-02-21 20:19:42 +00:00
fmk
80af4abe5a fix debug build on win32
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@174922 c90b9560-bf6c-de11-be94-00142212c4b1
2004-12-16 20:23:12 +00:00
tony2001
890f103f50 release 0.2
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@173958 c90b9560-bf6c-de11-be94-00142212c4b1
2004-12-02 13:06:58 +00:00
edink
101fddb80a Older nmake does't like double backslashed in the path
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@173404 c90b9560-bf6c-de11-be94-00142212c4b1
2004-11-23 20:48:08 +00:00
tony2001
8a59dd703c add .cvsignore
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@172293 c90b9560-bf6c-de11-be94-00142212c4b1
2004-11-08 21:34:45 +00:00
tony2001
7a18c6a556 fix small shared module build issue
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@167972 c90b9560-bf6c-de11-be94-00142212c4b1
2004-09-04 12:53:45 +00:00
tony2001
c1a3d3d0a7 add OS constants
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@167966 c90b9560-bf6c-de11-be94-00142212c4b1
2004-09-04 12:21:50 +00:00
169 changed files with 8387 additions and 5600 deletions

View File

@@ -1 +1,2 @@
Antony Dovgal
RAR
Antony Dovgal, Gustavo Lopes

View File

View File

@@ -2,23 +2,23 @@ dnl $Id$
dnl config.m4 for extension rar
PHP_ARG_ENABLE(rar, whether to enable rar support,
[ --enable-rar Enable rar support])
[ --enable-rar Enable rar support])
unrar_sources="unrar/rar.cpp unrar/strlist.cpp unrar/strfn.cpp \
unrar/pathfn.cpp unrar/int64.cpp unrar/savepos.cpp \
unrar/global.cpp unrar/file.cpp unrar/filefn.cpp \
unrar/filcreat.cpp unrar/archive.cpp unrar/arcread.cpp \
unrar/unicode.cpp unrar/system.cpp unrar/isnt.cpp \
unrar/crypt.cpp unrar/crc.cpp unrar/rawread.cpp \
unrar/encname.cpp unrar/resource.cpp unrar/match.cpp \
unrar/timefn.cpp unrar/rdwrfn.cpp unrar/consio.cpp \
unrar/options.cpp unrar/ulinks.cpp unrar/errhnd.cpp \
unrar/rarvm.cpp unrar/rijndael.cpp unrar/getbits.cpp \
unrar/sha1.cpp unrar/extinfo.cpp unrar/extract.cpp \
unrar/volume.cpp unrar/find.cpp \
unrar/unpack.cpp unrar/cmddata.cpp unrar/dll.cpp \
unrar/filestr.cpp unrar/recvol.cpp unrar/rs.cpp \
unrar/scantree.cpp"
unrar/pathfn.cpp unrar/smallfn.cpp unrar/savepos.cpp \
unrar/global.cpp unrar/file.cpp unrar/filefn.cpp \
unrar/filcreat.cpp unrar/archive.cpp unrar/arcread.cpp \
unrar/unicode.cpp unrar/system.cpp unrar/isnt.cpp \
unrar/crypt.cpp unrar/crc.cpp unrar/rawread.cpp \
unrar/encname.cpp unrar/resource.cpp unrar/match.cpp \
unrar/timefn.cpp unrar/rdwrfn.cpp unrar/consio.cpp \
unrar/options.cpp unrar/ulinks.cpp unrar/errhnd.cpp \
unrar/rarvm.cpp unrar/rijndael.cpp unrar/getbits.cpp \
unrar/sha1.cpp unrar/extinfo.cpp unrar/extract.cpp \
unrar/volume.cpp unrar/find.cpp \
unrar/unpack.cpp unrar/cmddata.cpp unrar/dll.cpp \
unrar/filestr.cpp unrar/recvol.cpp unrar/rs.cpp \
unrar/scantree.cpp unrar/log.cpp unrar/extractchunk.cpp"
if test "$PHP_RAR" != "no"; then
PHP_REQUIRE_CXX
@@ -26,6 +26,6 @@ if test "$PHP_RAR" != "no"; then
PHP_SUBST(RAR_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", RAR_SHARED_LIBADD)
PHP_NEW_EXTENSION(rar, rar.cpp $unrar_sources, $ext_shared,,-I@ext_srcdir@/unrar)
PHP_NEW_EXTENSION(rar, rar.c rar_error.c rararch.c rarentry.c rar_stream.c $unrar_sources, $ext_shared,,-DRARDLL -DGUI -DSILENT -Wno-write-strings -I@ext_srcdir@/unrar)
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
fi

View File

@@ -4,23 +4,23 @@
ARG_ENABLE("rar", "Rar support", "no");
if (PHP_RAR != "no") {
EXTENSION("rar", "rar.cpp");
ADD_SOURCES(configure_module_dirname + "/unrar", "rar.cpp \
strlist.cpp strfn.cpp pathfn.cpp int64.cpp \
savepos.cpp global.cpp file.cpp filefn.cpp \
filcreat.cpp archive.cpp arcread.cpp unicode.cpp \
system.cpp isnt.cpp crypt.cpp crc.cpp \
rawread.cpp encname.cpp resource.cpp match.cpp \
timefn.cpp rdwrfn.cpp consio.cpp options.cpp \
ulinks.cpp errhnd.cpp rarvm.cpp rijndael.cpp \
getbits.cpp sha1.cpp extinfo.cpp extract.cpp \
volume.cpp find.cpp unpack.cpp cmddata.cpp \
dll.cpp filestr.cpp recvol.cpp rs.cpp \
scantree.cpp", "rar");
if (!PHP_RAR_SHARED) {
ADD_DEF_FILE(configure_module_dirname + "\\unrar\\dll.def");
}
EXTENSION("rar", "rar.c rar_error.c rararch.c rarentry.c rar_stream.c", PHP_RAR_SHARED, "/DRARDLL /DGUI /DSILENT /EHsc /D_WSTDIO_DEFINED");
ADD_SOURCES(configure_module_dirname + "/unrar",
"rar.cpp strlist.cpp strfn.cpp \
pathfn.cpp smallfn.cpp savepos.cpp \
global.cpp file.cpp filefn.cpp \
filcreat.cpp archive.cpp arcread.cpp \
unicode.cpp system.cpp isnt.cpp \
crypt.cpp crc.cpp rawread.cpp \
encname.cpp resource.cpp match.cpp \
timefn.cpp rdwrfn.cpp consio.cpp \
options.cpp ulinks.cpp errhnd.cpp \
rarvm.cpp rijndael.cpp getbits.cpp \
sha1.cpp extinfo.cpp extract.cpp \
volume.cpp find.cpp \
unpack.cpp cmddata.cpp dll.cpp \
filestr.cpp recvol.cpp rs.cpp \
scantree.cpp extractchunk.cpp log.cpp", "rar");
AC_DEFINE("HAVE_RAR", 1, "Rar support");
}

View File

@@ -1,161 +1,393 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<package>
<name>rar</name>
<summary>rar extension</summary>
<description>
Rar is a powerful and effective archiver, which was
created by Eugene Roshal and became rather popular quite fast.
This extension gives you possibility to read Rar archives.
</description>
<license>PHP License</license>
<maintainers>
<maintainer>
<user>tony2001</user>
<name>Antony Dovgal</name>
<email>tony2001@phpclub.net</email>
</maintainer>
</maintainers>
<release>
<version>0.1</version>
<date>2004-06-11</date>
<state>alpha</state>
<notes>
1) Initial release
</notes>
</release>
<filelist>
<dir role="src" name="/">
<file role="doc">CREDITS</file>
<file role="doc">example.php</file>
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.5.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
<name>rar</name>
<channel>pecl.php.net</channel>
<summary>rar extension</summary>
<description>PHP extension for reading RAR archives using bundled unRAR library.
</description>
<file role="src">config.m4</file>
<file role="src">php_rar.h</file>
<file role="src">rar.cpp</file>
<dir role="src" name="/unrar/">
<lead>
<name>Gustavo Lopes</name>
<user>cataphract</user>
<email>cataphract@php.net</email>
<active>yes</active>
</lead>
<file role="doc">LICENSE.txt</file>
<file role="doc">README.txt</file>
<developer>
<name>Antony Dovgal</name>
<user>tony2001</user>
<email>tony@daylessday.org</email>
<active>no</active>
</developer>
<file role="src">arccmt.cpp</file>
<file role="src">archive.cpp</file>
<file role="src">archive.hpp</file>
<file role="src">arcread.cpp</file>
<file role="src">array.hpp</file>
<file role="src">beosea.cpp</file>
<file role="src">cmddata.cpp</file>
<file role="src">cmddata.hpp</file>
<file role="src">coder.cpp</file>
<file role="src">coder.hpp</file>
<file role="src">compress.hpp</file>
<file role="src">consio.cpp</file>
<file role="src">consio.hpp</file>
<file role="src">crc.cpp</file>
<file role="src">crc.hpp</file>
<file role="src">crypt.cpp</file>
<file role="src">crypt.hpp</file>
<file role="src">dll.cpp</file>
<file role="src">dll.def</file>
<file role="src">dll.hpp</file>
<file role="src">encname.cpp</file>
<file role="src">encname.hpp</file>
<file role="src">errhnd.cpp</file>
<file role="src">errhnd.hpp</file>
<file role="src">extinfo.cpp</file>
<file role="src">extinfo.hpp</file>
<file role="src">extract.cpp</file>
<file role="src">extract.hpp</file>
<file role="src">filcreat.cpp</file>
<file role="src">filcreat.hpp</file>
<file role="src">file.cpp</file>
<file role="src">filefn.cpp</file>
<file role="src">filefn.hpp</file>
<file role="src">file.hpp</file>
<file role="src">filestr.cpp</file>
<file role="src">filestr.hpp</file>
<file role="src">find.cpp</file>
<file role="src">find.hpp</file>
<file role="src">getbits.cpp</file>
<file role="src">getbits.hpp</file>
<file role="src">global.cpp</file>
<file role="src">global.hpp</file>
<file role="src">headers.hpp</file>
<file role="src">int64.cpp</file>
<file role="src">int64.hpp</file>
<file role="src">isnt.cpp</file>
<file role="src">isnt.hpp</file>
<file role="src">list.cpp</file>
<file role="src">list.hpp</file>
<file role="src">loclang.hpp</file>
<file role="src">log.cpp</file>
<file role="src">log.hpp</file>
<file role="src">match.cpp</file>
<file role="src">match.hpp</file>
<file role="src">memfree.hpp</file>
<file role="src">model.cpp</file>
<file role="src">model.hpp</file>
<file role="src">msc.dep</file>
<file role="src">options.cpp</file>
<file role="src">options.hpp</file>
<file role="src">os2ea.cpp</file>
<file role="src">os.hpp</file>
<file role="src">pathfn.cpp</file>
<file role="src">pathfn.hpp</file>
<file role="src">rar.cpp</file>
<file role="src">rardefs.hpp</file>
<file role="src">rarfn.hpp</file>
<file role="src">rar.hpp</file>
<file role="src">rarlang.hpp</file>
<file role="src">raros.hpp</file>
<file role="src">rartypes.hpp</file>
<file role="src">rarvm.cpp</file>
<file role="src">rarvm.hpp</file>
<file role="src">rarvmtbl.cpp</file>
<file role="src">rawread.cpp</file>
<file role="src">rawread.hpp</file>
<file role="src">rdwrfn.cpp</file>
<file role="src">rdwrfn.hpp</file>
<file role="src">recvol.cpp</file>
<file role="src">recvol.hpp</file>
<file role="src">resource.cpp</file>
<file role="src">resource.hpp</file>
<file role="src">rijndael.cpp</file>
<file role="src">rijndael.hpp</file>
<file role="src">rs.cpp</file>
<file role="src">rs.hpp</file>
<file role="src">savepos.cpp</file>
<file role="src">savepos.hpp</file>
<file role="src">scantree.cpp</file>
<file role="src">scantree.hpp</file>
<file role="src">sha1.cpp</file>
<file role="src">sha1.hpp</file>
<file role="src">smallfn.cpp</file>
<file role="src">smallfn.hpp</file>
<file role="src">strfn.cpp</file>
<file role="src">strfn.hpp</file>
<file role="src">strlist.cpp</file>
<file role="src">strlist.hpp</file>
<file role="src">suballoc.cpp</file>
<file role="src">suballoc.hpp</file>
<file role="src">system.cpp</file>
<file role="src">system.hpp</file>
<file role="src">timefn.cpp</file>
<file role="src">timefn.hpp</file>
<file role="src">ulinks.cpp</file>
<file role="src">ulinks.hpp</file>
<file role="src">unicode.cpp</file>
<file role="src">unicode.hpp</file>
<file role="src">unpack15.cpp</file>
<file role="src">unpack20.cpp</file>
<file role="src">unpack.cpp</file>
<file role="src">unpack.hpp</file>
<file role="src">uowners.cpp</file>
<file role="src">version.hpp</file>
<file role="src">volume.cpp</file>
<file role="src">volume.hpp</file>
<file role="src">win32acl.cpp</file>
<file role="src">win32stm.cpp</file>
</dir>
</dir>
</filelist>
<date>2010-04-20</date>
<time>13:00:00</time>
<version>
<release>2.0.0</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>Changes with respect to release 2.0.0RC1:
- Fixed infinite loop when opening RAR archive missing a volume (later report in bug #17177).
- Fixed bug #17025 (changed the name of method RarArchive::list into RarArchive::getEntries). If backwards compatibility with the release candidate is required, RarArchive::list can be reintroduced by defining RAR_ARCHIVE_LIST_ALIAS.
Incompatible changes with respect to release 1.0.0:
PHP Support:
- Support for PHP 4.3 dropped. PHP 5.2.x or 5.3.x is required.
API backwards incompatible changes:
- Handles unicode filenames (uses UTF-8 external encoding). The file names inside the RAR archives are always returned in UTF-8. This will probably break your scripts.
- Calling rar_close/RarArchive::close() invalidates RarEntry objects (actually, only extraction is forbidden, but don't rely on it).
For the other changes, see the changelog for version 2.0.0RC1.
</notes>
<contents>
<dir name="/">
<dir name="tests">
<file name="001.phpt" role="test" />
<file name="002.phpt" role="test" />
<file name="003.phpt" role="test" />
<file name="004.phpt" role="test" />
<file name="005.phpt" role="test" />
<file name="006.phpt" role="test" />
<file name="007.phpt" role="test" />
<file name="008.phpt" role="test" />
<file name="009.phpt" role="test" />
<file name="010.phpt" role="test" />
<file name="011.phpt" role="test" />
<file name="012.phpt" role="test" />
<file name="013.phpt" role="test" />
<file name="014.phpt" role="test" />
<file name="015.phpt" role="test" />
<file name="016.phpt" role="test" />
<file name="017.phpt" role="test" />
<file name="018.phpt" role="test" />
<file name="019.phpt" role="test" />
<file name="020.phpt" role="test" />
<file name="021.phpt" role="test" />
<file name="022.phpt" role="test" />
<file name="023.phpt" role="test" />
<file name="024.phpt" role="test" />
<file name="025.phpt" role="test" />
<file name="026.phpt" role="test" />
<file name="027.phpt" role="test" />
<file name="028.phpt" role="test" />
<file name="029.phpt" role="test" />
<file name="030.phpt" role="test" />
<file name="031.phpt" role="test" />
<file name="032.phpt" role="test" />
<file name="033.phpt" role="test" />
<file name="034.phpt" role="test" />
<file name="035.phpt" role="test" />
<file name="036.phpt" role="test" />
<file name="037.phpt" role="test" />
<file name="038.phpt" role="test" />
<file name="039.phpt" role="test" />
<file name="commented.rar" role="test" />
<file name="corrupted.rar" role="test" />
<file name="directories.rar" role="test" />
<file name="dirlink_unix.rar" role="test" />
<file name="encrypted_headers.rar" role="test" />
<file name="encrypted_only_files.rar" role="test" />
<file name="latest_winrar.rar" role="test" />
<file name="linux_rar.rar" role="test" />
<file name="multi_broken.part1.rar" role="test" />
<file name="multi.part1.rar" role="test" />
<file name="multi.part2.rar" role="test" />
<file name="multi.part3.rar" role="test" />
<file name="rar_notrar.rar" role="test" />
<file name="rar_unicode.rar" role="test" />
<file name="solid.rar" role="test" />
<file name="store_method.rar" role="test" />
</dir> <!-- /tests -->
<dir name="unrar">
<file name="arccmt.cpp" role="src" />
<file name="archive.cpp" role="src" />
<file name="archive.hpp" role="src" />
<file name="arcread.cpp" role="src" />
<file name="array.hpp" role="src" />
<file name="beosea.cpp" role="src" />
<file name="cmddata.cpp" role="src" />
<file name="cmddata.hpp" role="src" />
<file name="coder.cpp" role="src" />
<file name="coder.hpp" role="src" />
<file name="compress.hpp" role="src" />
<file name="consio.cpp" role="src" />
<file name="consio.hpp" role="src" />
<file name="crc.cpp" role="src" />
<file name="crc.hpp" role="src" />
<file name="crypt.cpp" role="src" />
<file name="crypt.hpp" role="src" />
<file name="dll.cpp" role="src" />
<file name="dll.hpp" role="src" />
<file name="encname.cpp" role="src" />
<file name="encname.hpp" role="src" />
<file name="errhnd.cpp" role="src" />
<file name="errhnd.hpp" role="src" />
<file name="extinfo.cpp" role="src" />
<file name="extinfo.hpp" role="src" />
<file name="extract.cpp" role="src" />
<file name="extract.hpp" role="src" />
<file name="extractchunk.cpp" role="src" />
<file name="filcreat.cpp" role="src" />
<file name="filcreat.hpp" role="src" />
<file name="file.cpp" role="src" />
<file name="file.hpp" role="src" />
<file name="filefn.cpp" role="src" />
<file name="filefn.hpp" role="src" />
<file name="filestr.cpp" role="src" />
<file name="filestr.hpp" role="src" />
<file name="find.cpp" role="src" />
<file name="find.hpp" role="src" />
<file name="getbits.cpp" role="src" />
<file name="getbits.hpp" role="src" />
<file name="global.cpp" role="src" />
<file name="global.hpp" role="src" />
<file name="headers.hpp" role="src" />
<file name="isnt.cpp" role="src" />
<file name="isnt.hpp" role="src" />
<file name="LICENSE.txt" role="doc" />
<file name="list.cpp" role="src" />
<file name="list.hpp" role="src" />
<file name="loclang.hpp" role="src" />
<file name="log.cpp" role="src" />
<file name="log.hpp" role="src" />
<file name="match.cpp" role="src" />
<file name="match.hpp" role="src" />
<file name="model.cpp" role="src" />
<file name="model.hpp" role="src" />
<file name="options.cpp" role="src" />
<file name="options.hpp" role="src" />
<file name="os.hpp" role="src" />
<file name="os2ea.cpp" role="src" />
<file name="pathfn.cpp" role="src" />
<file name="pathfn.hpp" role="src" />
<file name="rar.cpp" role="src" />
<file name="rar.hpp" role="src" />
<file name="rardefs.hpp" role="src" />
<file name="rarlang.hpp" role="src" />
<file name="raros.hpp" role="src" />
<file name="rartypes.hpp" role="src" />
<file name="rarvm.cpp" role="src" />
<file name="rarvm.hpp" role="src" />
<file name="rarvmtbl.cpp" role="src" />
<file name="rawread.cpp" role="src" />
<file name="rawread.hpp" role="src" />
<file name="rdwrfn.cpp" role="src" />
<file name="rdwrfn.hpp" role="src" />
<file name="README.txt" role="doc" />
<file name="recvol.cpp" role="src" />
<file name="recvol.hpp" role="src" />
<file name="resource.cpp" role="src" />
<file name="resource.hpp" role="src" />
<file name="rijndael.cpp" role="src" />
<file name="rijndael.hpp" role="src" />
<file name="rs.cpp" role="src" />
<file name="rs.hpp" role="src" />
<file name="savepos.cpp" role="src" />
<file name="savepos.hpp" role="src" />
<file name="scantree.cpp" role="src" />
<file name="scantree.hpp" role="src" />
<file name="sha1.cpp" role="src" />
<file name="sha1.hpp" role="src" />
<file name="smallfn.cpp" role="src" />
<file name="smallfn.hpp" role="src" />
<file name="strfn.cpp" role="src" />
<file name="strfn.hpp" role="src" />
<file name="strlist.cpp" role="src" />
<file name="strlist.hpp" role="src" />
<file name="suballoc.cpp" role="src" />
<file name="suballoc.hpp" role="src" />
<file name="system.cpp" role="src" />
<file name="system.hpp" role="src" />
<file name="timefn.cpp" role="src" />
<file name="timefn.hpp" role="src" />
<file name="ulinks.cpp" role="src" />
<file name="ulinks.hpp" role="src" />
<file name="unicode.cpp" role="src" />
<file name="unicode.hpp" role="src" />
<file name="unios2.cpp" role="src" />
<file name="unpack.cpp" role="src" />
<file name="unpack.hpp" role="src" />
<file name="unpack15.cpp" role="src" />
<file name="unpack20.cpp" role="src" />
<file name="uowners.cpp" role="src" />
<file name="version.hpp" role="src" />
<file name="volume.cpp" role="src" />
<file name="volume.hpp" role="src" />
<file name="win32acl.cpp" role="src" />
<file name="win32stm.cpp" role="src" />
</dir> <!-- /unrar -->
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
<file name="CREDITS" role="doc" />
<file name="example.php" role="doc" />
<file name="php_rar.h" role="src" />
<file name="rar.c" role="src" />
<file name="rar_stream.c" role="src" />
<file name="rararch.c" role="src" />
<file name="rarentry.c" role="src" />
<file name="rar_error.c" role="src" />
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>5.2.0</min>
</php>
<pearinstaller>
<min>1.4.0</min>
</pearinstaller>
<extension>
<name>spl</name>
</extension>
</required>
</dependencies>
<providesextension>rar</providesextension>
<extsrcrelease />
<changelog>
<release>
<version>
<release>2.0.0RC1</release>
<api>2.0.0RC1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2010-01-17</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>Changes in respect to release 1.0.0:
PHP SUPPORT:
- Support for PHP 4.3 dropped. PHP 5.2.x or 5.3.x is required.
API BACKWARDS INCOMPATIBLE CHANGES:
- Handles unicode filenames (uses UTF-8 external encoding). The file names inside the RAR archives are always returned in UTF-8. This will probably break your scripts.
- Calling rar_close/RarArchive::close() invalidates RarEntry objects (actually, only extraction is forbidden, but don't rely on it).
API backwards compatible changes:
- Supports streaming from RAR archives. See RarEntry::getStream() method.
- Added a bunch of constants to RarEntry.
- Added RarEntry::__toString() method.
- Added RarEntry::isDirectory() method.
- Added RarEntry::isEncrypted() method.
- Added OOP interface for rar_* functions with the RarArchive class.
- Added rar_comment_get/RarArchive::getComment().
- Added RarArchive::isSolid()/rar_solid_is().
- Added RarArchive::__toString() method.
- Added RarException class.
- Exception throwing for expectable errors can be turned on by calling RarException::setUsingExceptions(). To check whether exception throwing is turned on, RarException::isUsingExceptions() can be used.
Bug fixes:
- Fixed by PECL bug #8821 (relative paths not working).
- Fixed PECL bug #9470 (wrong CRC on multi-volume archives).
- Fixed PECL bug #9649 (rar_close() not closing file descriptors if there were undestroyed RarEntry objects)
- Fixed volumes opened with middle volumes showing files continued from previous volume with incorrect packed and unpacked sizes.
- Fixed bug in UnRAR library that could cause a read out of buffer bounds on some corrupted RAR files.
- Fixed RarEntry::getPackedSize() and RarEntry::getUnpackedSize() giving incorrect results for files > 2 GiB. Still, on platforms with 32-bit integers, MAX_INT will be returned for such files, othwerwise the correct value is given.
Other changes:
- Updated bundled UnRAR library to version 3.9.7 (RAR 3.9.1).
- Changed bundled UnRAR library to allow partial file extraction.
- All RarEntry properties are now private. This doesn't break the API because those properties were never part of the contract.
- rar_open gives more detailed error messages on failure.
- Extension now uses extended UnRAR library structures.
- Added arginfo.
- Added a bunch of tests.
- A lot of refactoring and compilation as C, not C++.
</notes>
</release>
<release>
<version>
<release>1.0.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2008-02-26</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>- Upgraded bundled UnRar to version 3.7.8.
- Updated source code to use new parameter parsing API.
- Fixed PECL bug #9002 (rar_list invalidates rar resource)
- Fixed PECL bug #11430 (rar_extract() doesn't close handles gracefully)
- rar_open() now throws an error when failed to open the specified file.
</notes>
</release>
<release>
<version>
<release>0.3.1</release>
<api>0.3.1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2006-08-28</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>- Updated bundled unrar to version 3.6.8.
- Fixed PHP4 compatibility.
</notes>
</release>
<release>
<version>
<release>0.3.0</release>
<api>0.3.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2006-06-06</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>- Updated bundled unrar to version 3.6.2 (fixes compile errors with GCC4).
- Several minor fixes.
</notes>
</release>
<release>
<version>
<release>0.2</release>
<api>0.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2004-12-02</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>1) Added open_basedir and safe_mode checks.
2) Fixed Win32 build issues (thanks to Edin).
Currently only 5.x builds are available.
3) Added OS constants.
4) Fixed 0 bugs. There are no bugs, wee =)
</notes>
</release>
<release>
<version>
<release>0.1</release>
<api>0.1</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2004-06-11</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>1) Initial release
</notes>
</release>
</changelog>
</package>
<!--
vim:et:ts=1:sw=1
-->

110
php_rar.h
View File

@@ -15,12 +15,13 @@
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| It's license states, that you MUST NOT use it's code to develop |
| Its license states, that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony2001@phpclub.net> |
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
@@ -32,6 +33,8 @@
extern zend_module_entry rar_module_entry;
#define phpext_rar_ptr &rar_module_entry
#define PHP_RAR_VERSION "2.0.0-dev"
#ifdef PHP_WIN32
#define PHP_RAR_API __declspec(dllexport)
#else
@@ -42,37 +45,102 @@ extern zend_module_entry rar_module_entry;
#include "TSRM.h"
#endif
/* causes linking errors (multiple definitions) in functions
that were requested inlining but were not inlined by the compiler */
/* #include "unrar/rar.hpp */
/* only these includes are necessary anyway: */
#include "unrar/raros.hpp"
/* no need to reinclude windows.h or new.h */
#define LEAN_RAR_INCLUDES
#include "unrar/os.hpp"
#include "unrar/dll.hpp"
#include "unrar/version.hpp"
/* These are in unrar/headers.hpp, but that header depends on several other */
enum HOST_SYSTEM {
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
HOST_BEOS=5,HOST_MAX
};
//maximum comment size if 64KB
#define RAR_MAX_COMMENT_SIZE 65536
typedef struct rar {
zend_object_handle id;
int entry_count; //>= number of files
struct RARHeaderDataEx **entries;
struct RAROpenArchiveDataEx *list_open_data;
struct RAROpenArchiveDataEx *extract_open_data;
//archive handle opened with RAR_OM_LIST_INCSPLIT open mode
void *arch_handle;
char *password;
} rar_file_t;
//PHP 5.2 compatibility
#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3
# define ALLOC_PERMANENT_ZVAL(z) \
(z) = (zval*) malloc(sizeof(zval));
# define OPENBASEDIR_CHECKPATH(filename) \
(PG(safe_mode) && \
(!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) \
|| php_check_open_basedir(filename TSRMLS_CC)
# undef ZEND_BEGIN_ARG_INFO_EX
# define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
static const zend_arg_info name[] = { \
{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
#endif
/* rar.c */
PHP_MINIT_FUNCTION(rar);
PHP_MSHUTDOWN_FUNCTION(rar);
PHP_RINIT_FUNCTION(rar);
PHP_RSHUTDOWN_FUNCTION(rar);
PHP_MINFO_FUNCTION(rar);
PHP_FUNCTION(rar_bogus_ctor);
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size);
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size);
int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
const char *const utf_file_name, /* IN */
char *password, /* IN, can be null */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
);
int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2);
/* rar_error.c */
zend_class_entry *rarexception_ce_ptr;
int _rar_handle_error(int errcode TSRMLS_DC);
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC);
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...);
int _rar_using_exceptions(TSRMLS_D);
const char * _rar_error_to_string(int errcode);
void minit_rarerror(TSRMLS_D);
/* rararch.c */
int _rar_get_file_resource(zval *zval_file, rar_file_t **rar_file TSRMLS_DC);
int _rar_get_file_resource_ex(zval *zval_file, rar_file_t **rar_file, int silent TSRMLS_DC);
void minit_rararch(TSRMLS_D);
PHP_FUNCTION(rar_open);
PHP_FUNCTION(rar_list);
PHP_FUNCTION(rar_entry_get);
PHP_FUNCTION(rar_solid_is);
PHP_FUNCTION(rar_comment_get);
PHP_FUNCTION(rar_close);
PHP_METHOD(rarentry, extract);
PHP_METHOD(rarentry, getName);
PHP_METHOD(rarentry, getUnpackedSize);
PHP_METHOD(rarentry, getPackedSize);
PHP_METHOD(rarentry, getHostOs);
PHP_METHOD(rarentry, getFileTime);
PHP_METHOD(rarentry, getCrc);
PHP_METHOD(rarentry, getAttr);
PHP_METHOD(rarentry, getVersion);
PHP_METHOD(rarentry, getMethod);
/* rarentry.c */
extern zend_class_entry *rar_class_entry_ptr;
void minit_rarentry(TSRMLS_D);
void _rar_entry_to_zval(struct RARHeaderDataEx *entry, zval *object,
unsigned long packed_size TSRMLS_DC);
typedef struct rar {
int id;
int entry_count;
struct RARHeaderData **entries;
struct RAROpenArchiveData *list_handle;
struct RAROpenArchiveData *extract_handle;
void *list_data;
char *password;
} rar_file_t;
/* rar_stream.c */
php_stream *php_stream_rar_open(char *arc_name,
char *utf_file_name,
char *password,
char *mode STREAMS_DC TSRMLS_DC);
#endif /* PHP_RAR_H */

373
rar.c Normal file
View File

@@ -0,0 +1,373 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef PHP_WIN32
# include <math.h>
#endif
#include <wchar.h>
#include <php.h>
#include <php_ini.h>
#include <zend_exceptions.h>
#include <ext/standard/info.h>
#include <ext/spl/spl_exceptions.h>
#if HAVE_RAR
#include "php_rar.h"
/* {{{ Function prototypes for functions with internal linkage */
static void _rar_fix_wide(wchar_t *str);
/* }}} */
/* {{{ Functions with external linkage */
/* From unicode.cpp
* I can't use that one directy because it takes a const wchar, not wchar_t.
* And I shouldn't because it's not a public API.
*/
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size) /* {{{ */
{
long dsize= (long) dest_size;
dsize--;
while (*src != 0 && --dsize >= 0) {
uint c =*(src++);
if (c < 0x80)
*(dest++) = c;
else if (c < 0x800 && --dsize >= 0) {
*(dest++) = (0xc0 | (c >> 6));
*(dest++) = (0x80 | (c & 0x3f));
}
else if (c < 0x10000 && (dsize -= 2) >= 0) {
*(dest++) = (0xe0 | (c >> 12));
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
*(dest++) = (0x80 | (c & 0x3f));
}
else if (c < 0x200000 && (dsize -= 3) >= 0) {
*(dest++) = (0xf0 | (c >> 18));
*(dest++) = (0x80 | ((c >> 12) & 0x3f));
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
*(dest++) = (0x80 | (c & 0x3f));
}
}
*dest = 0;
}
/* }}} */
/* idem */
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size) /* {{{ */
{
long dsize = (long) dest_size;
dsize--;
while (*src != 0) {
uint c = (unsigned char) *(src++),
d;
if (c < 0x80)
d = c;
else if ((c >> 5) == 6) {
if ((*src & 0xc0) != 0x80)
break;
d=((c & 0x1f) << 6)|(*src & 0x3f);
src++;
}
else if ((c>>4)==14) {
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80)
break;
d = ((c & 0xf) << 12) | ((src[0] & 0x3f) << 6) | (src[1] & 0x3f);
src += 2;
}
else if ((c>>3)==30) {
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80)
break;
d = ((c & 7) << 18) | ((src[0] & 0x3f) << 12) | ((src[1] & 0x3f) << 6) | (src[2] & 0x3f);
src += 3;
}
else
break;
if (--dsize < 0)
break;
if (d > 0xffff) {
if (--dsize < 0 || d > 0x10ffff)
break;
*(dest++) = ((d - 0x10000) >> 10) + 0xd800;
*(dest++) = (d & 0x3ff) + 0xdc00;
}
else
*(dest++) = d;
}
*dest = 0;
}
/* }}} */
/* WARNING: It's the caller who must close the archive. */
int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
const char *const utf_file_name, /* IN */
char *password, /* IN, can be null */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
) /* {{{ */
{
int result,
process_result;
wchar_t *file_name = NULL;
int utf_file_name_len;
struct RARHeaderDataEx *used_header_data;
int retval = 0; /* success in rar parlance */
assert(open_data != NULL);
assert(utf_file_name != NULL);
assert(arc_handle != NULL);
assert(found != NULL);
*found = FALSE;
*arc_handle = NULL;
used_header_data = header_data != NULL ?
header_data :
ecalloc(1, sizeof *used_header_data);
*arc_handle = RAROpenArchiveEx(open_data);
if (*arc_handle == NULL) {
retval = open_data->OpenResult;
goto cleanup;
}
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) password);
utf_file_name_len = strlen(utf_file_name);
file_name = ecalloc(utf_file_name_len + 1, sizeof *file_name);
_rar_utf_to_wide(utf_file_name, file_name, utf_file_name_len + 1);
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
if (sizeof(wchar_t) > 2)
_rar_fix_wide(used_header_data->FileNameW);
if (wcsncmp(used_header_data->FileNameW, file_name, NM) == 0) {
*found = TRUE;
goto cleanup;
} else {
process_result = RARProcessFile(*arc_handle, RAR_SKIP, NULL, NULL);
}
if (process_result != 0) {
retval = process_result;
goto cleanup;
}
}
if (result != 0 && result != 1) {
//0 indicates success, 1 indicates normal end of file
retval = result;
goto cleanup;
}
cleanup:
if (header_data == NULL)
efree(used_header_data);
if (file_name != NULL)
efree(file_name);
return retval;
}
/* }}} */
/* Only processes password callbacks */
int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2) /* {{{ */
{
TSRMLS_FETCH();
if (msg == UCM_NEEDPASSWORD) {
//user data is the password or null if none
char *password = (char*) UserData;
if (password == NULL) {
/*php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Password needed, but it has not been specified");*/
return -1;
}
else {
strncpy((char*) P1, password, (size_t) P2);
}
}
else if (msg == UCM_CHANGEVOLUME) {
if (((int) P2) == RAR_VOL_ASK) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Volume %s was not found.", (char*) P1);
/* this means a volume is missing. return -1 to abort */
return -1;
}
}
return 0;
}
/* }}} */
PHP_FUNCTION(rar_bogus_ctor) /* {{{ */
{
/* This exception should not be thrown. The point is to add this as
* a class constructor and make it private. This code would be able to
* run only if the constructor were made public */
zend_throw_exception(spl_ce_RuntimeException,
"An object of this type cannot be created with the new operator.",
0 TSRMLS_CC);
}
/* }}} */
/* }}} */
/* {{{ Functions with internal linkage */
static void _rar_fix_wide(wchar_t *str) /* {{{ */
{
wchar_t *write,
*read;
for (write = str, read = str; *read != L'\0'; read++) {
if ((unsigned) *read <= 0x10ffff)
*(write++) = *read;
}
*write = L'\0';
}
/* }}} */
/* }}} */
#ifdef COMPILE_DL_RAR
BEGIN_EXTERN_C()
ZEND_GET_MODULE(rar)
END_EXTERN_C()
#endif
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_open, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_void_archmeth, 0, 0, 1)
ZEND_ARG_INFO(0, rarfile)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_entry_get, 0, 0, 2)
ZEND_ARG_INFO(0, rarfile)
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ rar_functions[]
*
*/
static zend_function_entry rar_functions[] = {
PHP_FE(rar_open, arginfo_rar_open)
PHP_FE(rar_list, arginfo_rar_void_archmeth)
PHP_FE(rar_entry_get, arginfo_rar_entry_get)
PHP_FE(rar_solid_is, arginfo_rar_void_archmeth)
PHP_FE(rar_comment_get, arginfo_rar_void_archmeth)
PHP_FE(rar_close, arginfo_rar_void_archmeth)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(rar)
{
minit_rararch(TSRMLS_C);
minit_rarentry(TSRMLS_C);
minit_rarerror(TSRMLS_C);
REGISTER_LONG_CONSTANT("RAR_HOST_MSDOS", HOST_MSDOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_OS2", HOST_OS2, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_WIN32", HOST_WIN32, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_UNIX", HOST_UNIX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_MACOS", HOST_MACOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_BEOS", HOST_BEOS, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(rar)
{
char version[256];
php_info_print_table_start();
php_info_print_table_header(2, "Rar support", "enabled");
php_info_print_table_row(2, "Rar EXT version", PHP_RAR_VERSION);
php_info_print_table_row(2, "Revision", "$Revision$");
#if RARVER_BETA != 0
sprintf(version,"%d.%02d beta%d patch%d %d-%d-%d", RARVER_MAJOR,
RARVER_MINOR, RARVER_BETA, RARVER_PATCH, RARVER_YEAR, RARVER_MONTH,
RARVER_DAY);
#else
sprintf(version,"%d.%02d patch%d %d-%d-%d", RARVER_MAJOR, RARVER_MINOR,
RARVER_PATCH, RARVER_YEAR, RARVER_MONTH, RARVER_DAY);
#endif
php_info_print_table_row(2, "UnRAR version", version);
php_info_print_table_end();
}
/* }}} */
/* {{{ rar_module_entry
*/
zend_module_entry rar_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"rar",
rar_functions,
PHP_MINIT(rar),
NULL,
NULL,
NULL,
PHP_MINFO(rar),
#if ZEND_MODULE_API_NO >= 20010901
PHP_RAR_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#endif /* HAVE_RAR */
#ifdef __cplusplus
}
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

738
rar.cpp
View File

@@ -1,738 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| It's license states, that you MUST NOT use it's code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony2001@phpclub.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#if HAVE_RAR
extern "C" {
#include "php_rar.h"
}
#include "unrar/rar.hpp"
static int le_rar_file;
#define le_rar_file_name "Rar"
static zend_class_entry *rar_class_entry_ptr;
/* {{{ rar_functions[]
*
*/
function_entry rar_functions[] = {
PHP_FE(rar_open, NULL)
PHP_FE(rar_list, NULL)
PHP_FE(rar_entry_get, NULL)
PHP_FE(rar_close, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_rar_class_functions[] = {
PHP_ME(rarentry, extract, NULL, 0)
PHP_ME(rarentry, getName, NULL, 0)
PHP_ME(rarentry, getUnpackedSize, NULL, 0)
PHP_ME(rarentry, getPackedSize, NULL, 0)
PHP_ME(rarentry, getHostOs, NULL, 0)
PHP_ME(rarentry, getFileTime, NULL, 0)
PHP_ME(rarentry, getCrc, NULL, 0)
PHP_ME(rarentry, getAttr, NULL, 0)
PHP_ME(rarentry, getVersion, NULL, 0)
PHP_ME(rarentry, getMethod, NULL, 0)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ rar_module_entry
*/
zend_module_entry rar_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"rar",
rar_functions,
PHP_MINIT(rar),
PHP_MSHUTDOWN(rar),
PHP_RINIT(rar), /* Replace with NULL if there's nothing to do at request start */
PHP_RSHUTDOWN(rar), /* Replace with NULL if there's nothing to do at request end */
PHP_MINFO(rar),
#if ZEND_MODULE_API_NO >= 20010901
"0.1", /* Replace with version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */
/* {{{ internal functions protos */
static void _rar_file_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
static int _rar_list_files(rar_file_t * TSRMLS_DC);
static int _rar_handle_error(int TSRMLS_DC);
static void _rar_dos_date_to_text(int, char *);
static void _rar_entry_to_zval(struct RARHeaderData *, zval * TSRMLS_DC);
static zval **_rar_entry_get_property(zval *, char *, int TSRMLS_DC);
/* }}} */
/* <internal> */
static void _rar_file_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
{
rar_file_t *rar = (rar_file_t *)rsrc->ptr;
int i = 0;
if (rar->list_data) {
RARCloseArchive(rar->list_data);
}
if (rar->password) {
efree(rar->password);
}
if (rar->entries && rar->entry_count) {
for(i = 0; i < rar->entry_count; i++) {
efree(rar->entries[i]);
}
efree(rar->entries);
rar->entry_count = 0;
}
efree(rar->list_handle->ArcName);
efree(rar->list_handle);
efree(rar->extract_handle->ArcName);
efree(rar->extract_handle);
efree(rar);
}
/* }}} */
static int _rar_get_file_resource(zval **zval_file, rar_file_t **rar_file TSRMLS_DC) /* {{{ */
{
*rar_file = (rar_file_t *) zend_fetch_resource(zval_file TSRMLS_CC, -1, le_rar_file_name, NULL, 1, le_rar_file);
if (*rar_file) {
return 1;
}
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find Rar file resource");
return 0;
}
/* }}} */
static int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
{
int result = 0;
while (result == 0) {
struct RARHeaderData entry;
result = RARReadHeader(rar->list_data, &entry);
RARProcessFile(rar->list_data, RAR_OM_LIST, NULL, NULL);
if (result == 0) {
rar->entries = (struct RARHeaderData **)erealloc(rar->entries, sizeof(struct RARHeaderData *) * (rar->entry_count + 1));
if (!rar->entries) {
return FAILURE;
}
rar->entries[rar->entry_count] = (struct RARHeaderData *)emalloc(sizeof(struct RARHeaderData));
memcpy(rar->entries[rar->entry_count], &entry, sizeof(struct RARHeaderData));
rar->entry_count++;
}
}
return result;
}
/* }}} */
static int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
{
switch (errcode) {
case 0:
/* no error */
return SUCCESS;
break;
case ERAR_END_ARCHIVE:
/* no error */
return SUCCESS;
break;
case ERAR_NO_MEMORY:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_NO_MEMORY: not enough memory");
break;
case ERAR_BAD_DATA:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_DATA");
break;
case ERAR_BAD_ARCHIVE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_ARCHIVE");
break;
case ERAR_UNKNOWN_FORMAT:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN_FORMAT");
break;
case ERAR_EOPEN:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EOPEN");
break;
case ERAR_ECREATE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECREATE");
break;
case ERAR_ECLOSE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECLOSE");
break;
case ERAR_EREAD:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EREAD");
break;
case ERAR_EWRITE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EWRITE");
break;
case ERAR_SMALL_BUF:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_SMALL_BUF");
break;
case ERAR_UNKNOWN:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN: unknown RAR error");
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown RAR error");
break;
}
return FAILURE;
}
/* }}} */
static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
{
int second, minute, hour, day, month, year;
/* following lines were taken from timefn.cpp */
second = (dos_time & 0x1f)*2;
minute = (dos_time>>5) & 0x3f;
hour = (dos_time>>11) & 0x1f;
day = (dos_time>>16) & 0x1f;
month = (dos_time>>21) & 0x0f;
year = (dos_time>>25)+1980;
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
}
/* }}} */
static void _rar_entry_to_zval(struct RARHeaderData *entry, zval *object TSRMLS_DC) /* {{{ */
{
char tmp_s [MAX_LENGTH_OF_LONG + 1];
char time[50];
add_property_string(object, "name", entry->FileName, 1);
add_property_long(object, "unpacked_size", entry->UnpSize);
add_property_long(object, "packed_size", entry->PackSize);
add_property_long(object, "host_os", entry->HostOS);
_rar_dos_date_to_text(entry->FileTime, time);
add_property_string(object, "file_time", time, 1);
sprintf(tmp_s, "%lx", entry->FileCRC);
add_property_string(object, "crc", tmp_s, 1);
add_property_long(object, "attr", entry->FileAttr);
add_property_long(object, "version", entry->UnpVer);
add_property_long(object, "method", entry->Method);
}
/* }}} */
static zval **_rar_entry_get_property(zval *id, char *name, int namelen TSRMLS_DC) /* {{{ */
{
zval **tmp;
if (zend_hash_find(Z_OBJPROP_P(id), name, namelen, (void **)&tmp) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find property %s", name);
return NULL;
}
return tmp;
}
/* }}} */
/* </internal> */
#ifdef COMPILE_DL_RAR
extern "C" {
ZEND_GET_MODULE(rar)
}
#endif
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(rar)
{
zend_class_entry rar_class_entry;
INIT_CLASS_ENTRY(rar_class_entry, "RarEntry", php_rar_class_functions);
rar_class_entry_ptr = zend_register_internal_class(&rar_class_entry TSRMLS_CC);
le_rar_file = zend_register_list_destructors_ex(_rar_file_list_dtor, NULL, le_rar_file_name, module_number);
REGISTER_LONG_CONSTANT("RAR_HOST_MSDOS", HOST_MSDOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_OS2", HOST_OS2, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_WIN32", HOST_WIN32, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_UNIX", HOST_UNIX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_MACOS", HOST_MACOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_BEOS", HOST_BEOS, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(rar)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(rar)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(rar)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(rar)
{
php_info_print_table_start();
php_info_print_table_header(2, "Rar support", "enabled");
php_info_print_table_row(2, "Revision", "$Revision$");
php_info_print_table_end();
}
/* }}} */
/* module functions */
/* {{{ proto rar_open(string filename [, string password])
Open Rar archive and return resource */
PHP_FUNCTION(rar_open)
{
zval **filename, **password;
rar_file_t *rar = NULL;
struct RARHeaderData entry;
int ac = ZEND_NUM_ARGS(), result = 0;
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &filename, &password) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(filename);
if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
RETURN_FALSE;
}
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
RETURN_FALSE;
}
rar = (rar_file_t *) emalloc(sizeof(rar_file_t));
rar->list_handle = (RAROpenArchiveData *) emalloc(sizeof(RAROpenArchiveData));
rar->list_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
rar->list_handle->OpenMode = RAR_OM_LIST;
rar->extract_handle = (RAROpenArchiveData *) emalloc(sizeof(RAROpenArchiveData));
rar->extract_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
rar->extract_handle->OpenMode = RAR_OM_EXTRACT;
rar->password = NULL;
rar->entries = NULL;
rar->entry_count = 0;
rar->list_data = RAROpenArchive(rar->list_handle);
if (rar->list_data != NULL && rar->list_handle->OpenResult == 0) {
if (ac == 2) {
rar->password = estrndup(Z_STRVAL_PP(password), Z_STRLEN_PP(password));
}
rar->id = zend_list_insert(rar,le_rar_file);
RETURN_RESOURCE(rar->id);
}
else {
efree(rar->list_handle->ArcName);
efree(rar->list_handle);
efree(rar->extract_handle->ArcName);
efree(rar->extract_handle);
efree(rar);
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_list(resource rarfile)
Return entries from the rar archive */
PHP_FUNCTION(rar_list)
{
zval **file;
rar_file_t *rar = NULL;
int i = 0;
int ac = ZEND_NUM_ARGS(), result = 0;
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
array_init(return_value);
for (i = 0; i < rar->entry_count; i++) {
zval *tmp;
MAKE_STD_ZVAL(tmp);
object_init_ex(tmp, rar_class_entry_ptr);
add_property_resource(tmp, "rarfile", rar->id);
_rar_entry_to_zval(rar->entries[i], tmp TSRMLS_CC);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp, sizeof(zval*), NULL);
}
if (!return_value) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to list files from RAR archive");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_entry_get(resource rarfile, string filename)
Return entry from the rar archive */
PHP_FUNCTION(rar_entry_get)
{
zval **file, **filename;
rar_file_t *rar = NULL;
int result = 0, i = 0;
int ac = ZEND_NUM_ARGS();
if (ac < 2 || ac > 2 || zend_get_parameters_ex(ac, &file, &filename) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
for(i = 0; i < rar->entry_count; i++){
if (strcmp(rar->entries[i]->FileName, Z_STRVAL_PP(filename)) == 0) {
object_init_ex(return_value, rar_class_entry_ptr);
add_property_resource(return_value, "rarfile", rar->id);
_rar_entry_to_zval(rar->entries[i], return_value TSRMLS_CC);
break;
}
}
if (!return_value) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find such file in RAR archive");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_close(resource rarfile)
Close Rar archive and free all resources */
PHP_FUNCTION(rar_close)
{
zval **file;
rar_file_t *rar = NULL;
int file_counter = 0;
int ac = ZEND_NUM_ARGS();
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar TSRMLS_CC)) {
RETURN_FALSE;
}
zend_list_delete(rar->id);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto RarEntry::extract(string path [, string filename ]);
Extract file from the archive */
PHP_METHOD(rarentry, extract)
{
zval **rarfile, **path, **filename, **tmp, **tmp_name;
rar_file_t *rar = NULL;
char filename_str[260];
char *path_str = NULL, *extract_to_file = NULL;
int ac = ZEND_NUM_ARGS(), resource_type = 0, result = 0, process_result = 0;
zval *entry_obj = getThis();
unsigned long data_len;
struct RARHeaderData entry;
void *extract_data;
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &path, &filename) == FAILURE ) {
WRONG_PARAM_COUNT;
}
if ((tmp = _rar_entry_get_property(entry_obj, "rarfile", sizeof("rarfile") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
rar = (rar_file_t *) zend_list_find(Z_LVAL_PP(tmp), &resource_type);
convert_to_string_ex(path);
path_str = Z_STRVAL_PP(path);
if (Z_STRLEN_PP(path) && PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(path), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
RETURN_FALSE;
}
if (Z_STRLEN_PP(path) && php_check_open_basedir(Z_STRVAL_PP(path) TSRMLS_CC)) {
RETURN_FALSE;
}
if (ac == 2) {
convert_to_string_ex(filename);
extract_to_file = Z_STRVAL_PP(filename);
if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
RETURN_FALSE;
}
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
RETURN_FALSE;
}
}
if ((tmp_name = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
if (!rar || resource_type != le_rar_file) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Rar resource identifier not found");
RETURN_FALSE;
}
extract_data = RAROpenArchive(rar->extract_handle);
if (rar->extract_handle->OpenResult == 0 && extract_data != NULL) {
if (rar->password) {
RARSetPassword(extract_data, rar->password);
}
}
else {
_rar_handle_error(rar->extract_handle->OpenResult TSRMLS_CC);
RETURN_FALSE;
}
while ((result = RARReadHeader(extract_data, &entry)) == 0) {
if (strncmp(entry.FileName,Z_STRVAL_PP(tmp_name), sizeof(entry.FileName)) == 0) {
process_result = RARProcessFile(extract_data, RAR_EXTRACT, path_str, extract_to_file);
RETURN_TRUE;
}
else {
process_result = RARProcessFile(extract_data, RAR_SKIP, NULL, NULL);
}
if (_rar_handle_error(process_result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't find file %s in archive %s", Z_STRVAL_PP(tmp_name), rar->extract_handle->ArcName);
RETURN_FALSE;
}
/* }}} */
/* {{{ proto RarEntry::getName();
Return entry name */
PHP_METHOD(rarentry, getName)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getUnpackedSize();
Return unpacked size of the entry */
PHP_METHOD(rarentry, getUnpackedSize)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "unpacked_size", sizeof("unpacked_size") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getPackedSize();
Return packed size of the entry */
PHP_METHOD(rarentry, getPackedSize)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "packed_size", sizeof("packed_size") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getHostOs();
Return host OS of the entry */
PHP_METHOD(rarentry, getHostOs)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "host_os", sizeof("host_os") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getFileTime();
Return modification time of the entry */
PHP_METHOD(rarentry, getFileTime)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "file_time", sizeof("file_time") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getCrc();
Return CRC of the entry */
PHP_METHOD(rarentry, getCrc)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "crc", sizeof("crc") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getAttr();
Return attributes of the entry */
PHP_METHOD(rarentry, getAttr)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "attr", sizeof("attr") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getVersion();
Return version of the archiver, used to create this entry */
PHP_METHOD(rarentry, getVersion)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "version", sizeof("version") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getMethod();
Return packing method */
PHP_METHOD(rarentry, getMethod)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "method", sizeof("method") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
#endif /* HAVE_RAR */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

233
rar_error.c Normal file
View File

@@ -0,0 +1,233 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <php.h>
#include <zend_exceptions.h>
#include "php_rar.h"
/* {{{ Globals with external linkage */
zend_class_entry *rarexception_ce_ptr;
/* }}} */
/* Functions with external linkage {{{ */
/* Functions with external linkage {{{ */
int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
{
return _rar_handle_error_ex("", errcode TSRMLS_CC);
}
/* }}} */
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
{
const char *err = _rar_error_to_string(errcode);
if (err == NULL) {
return SUCCESS;
}
if (_rar_using_exceptions(TSRMLS_C)) {
zend_throw_exception_ex(rarexception_ce_ptr, errcode TSRMLS_CC,
"unRAR internal error: %s%s", preamble, err);
}
else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s", preamble, err);
}
return FAILURE;
}
/* }}} */
/* Errors not related to the unRAR library */
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...) /* {{{ */
{
va_list arg;
char *message;
#ifdef ZTS
va_start(arg, TSRMLS_C);
#else
va_start(arg, format);
#endif
vspprintf(&message, 0, format, arg);
va_end(arg);
if (_rar_using_exceptions(TSRMLS_C))
zend_throw_exception(rarexception_ce_ptr, message, -1L TSRMLS_CC);
else
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
efree(message);
}
/* }}} */
int _rar_using_exceptions(TSRMLS_D)
{
zval *pval;
pval = zend_read_static_property(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, (zend_bool) 1 TSRMLS_CC);
assert(Z_TYPE_P(pval) == IS_BOOL);
return Z_BVAL_P(pval);
}
//returns a string or NULL if not an error
const char * _rar_error_to_string(int errcode) /* {{{ */
{
const char *ret;
switch (errcode) {
case 0:
/* no error */
case 1:
/* no error (comment completely read) */
case ERAR_END_ARCHIVE:
/* no error */
ret = NULL;
break;
case ERAR_NO_MEMORY:
ret = "ERAR_NO_MEMORY (not enough memory)";
break;
case ERAR_BAD_DATA:
ret = "ERAR_BAD_DATA";
break;
case ERAR_BAD_ARCHIVE:
ret = "ERAR_BAD_ARCHIVE";
break;
case ERAR_UNKNOWN_FORMAT:
ret = "ERAR_UNKNOWN_FORMAT";
break;
case ERAR_EOPEN:
ret = "ERAR_EOPEN (file open error)";
break;
case ERAR_ECREATE:
ret = "ERAR_ECREATE";
break;
case ERAR_ECLOSE:
ret = "ERAR_ECLOSE (error closing file)";
break;
case ERAR_EREAD:
ret = "ERAR_EREAD";
break;
case ERAR_EWRITE:
ret = "ERAR_EWRITE";
break;
case ERAR_SMALL_BUF:
ret = "ERAR_SMALL_BUF";
break;
case ERAR_UNKNOWN:
ret = "ERAR_UNKNOWN (unknown RAR error)";
break;
case ERAR_MISSING_PASSWORD:
ret = "ERAR_MISSING_PASSWORD (password needed but not specified)";
break;
default:
ret = "unknown RAR error (should not happen)";
break;
}
return ret;
}
/* }}} */
/* }}} */
/* {{{ proto bool RarException::setUsingExceptions(using_exceptions)
Set whether exceptions are to be used */
PHP_METHOD(rarexception, setUsingExceptions)
{
zend_bool argval;
int result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &argval) == FAILURE ) {
return;
}
result = zend_update_static_property_bool(rarexception_ce_ptr,
"usingExceptions", sizeof("usingExceptions") -1,
(long) argval TSRMLS_CC);
if (result == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could set error handling mode. This is a bug, please report it.");
return;
}
}
/* }}} */
/* {{{ proto bool RarException::isUsingExceptions()
Return whether exceptions are being used */
PHP_METHOD(rarexception, isUsingExceptions)
{
zval **pval;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE ) {
return;
}
//or zend_read_static_property, which calls zend_std_get... after chg scope
pval = zend_std_get_static_property(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, (zend_bool) 0 TSRMLS_CC);
//property always exists
assert(pval != NULL);
assert(Z_TYPE_PP(pval) == IS_BOOL);
RETURN_ZVAL(*pval, 0, 0);
}
/* }}} */
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarexception_sue, 0, 0, 1)
ZEND_ARG_INFO(0, using_exceptions)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_rarexception_void, 0)
ZEND_END_ARG_INFO()
/* }}} */
static zend_function_entry php_rarexception_class_functions[] = {
PHP_ME(rarexception, setUsingExceptions, arginfo_rarexception_sue, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(rarexception, isUsingExceptions, arginfo_rarexception_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
{NULL, NULL, NULL}
};
void minit_rarerror(TSRMLS_D) /* {{{ */
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "RarException", php_rarexception_class_functions);
rarexception_ce_ptr = zend_register_internal_class_ex(&ce,
zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
rarexception_ce_ptr->ce_flags |= ZEND_ACC_FINAL;
zend_declare_property_bool(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, 0L /* FALSE */,
ZEND_ACC_PRIVATE | ZEND_ACC_STATIC TSRMLS_CC);
}
/* }}} */
#ifdef __cplusplus
}
#endif

275
rar_stream.c Normal file
View File

@@ -0,0 +1,275 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include "php.h"
#if HAVE_RAR
#ifdef ZEND_ENGINE_2
#include <wchar.h>
#include "php_rar.h"
#include "unrar/rartypes.hpp"
#include "php_streams.h"
/* will be needed to implement a wrapper
* #include "ext/standard/file.h"
* #include "ext/standard/php_string.h"
* #include "fopen_wrappers.h"
* #include "ext/standard/url.h"
*/
typedef struct php_rar_stream_data_t {
struct RAROpenArchiveDataEx open_data;
struct RARHeaderDataEx header_data;
HANDLE rar_handle;
unsigned char *buffer;
size_t buffer_size;
size_t buffer_cont_size;
size_t buffer_pos;
uint64 cursor;
int no_more_data;
php_stream *stream;
} php_rar_stream_data, *php_rar_stream_data_P;
#define STREAM_DATA_FROM_STREAM \
php_rar_stream_data_P self = (php_rar_stream_data_P) stream->abstract;
/* {{{ php_rar_ops_read */
static size_t php_rar_ops_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
{
int n = 0;
STREAM_DATA_FROM_STREAM
size_t left = count;
if (count == 0)
return 0;
if (self->buffer != NULL && self->rar_handle != NULL) {
while (left > 0) {
size_t this_read_size;
//if nothing in the buffer or buffer already read, fill buffer
if (/*self->buffer_cont_size == 0 || > condition not necessary */
self->buffer_pos == self->buffer_cont_size)
{
int res;
self->buffer_pos = 0;
self->buffer_cont_size = 0;
/* Note: this condition is important, you cannot rely on
* having a call to RARProcessFileChunk return no data and
* break on the condition self->buffer_cont_size == 0 because
* calling RARProcessFileChunk when there's no more data to
* be read may cause an integer division by 0 in
* RangeCoder::GetCurrentCount() */
if (self->no_more_data)
break;
res = RARProcessFileChunk(self->rar_handle, self->buffer,
self->buffer_size, &self->buffer_cont_size,
&self->no_more_data);
if (_rar_handle_error(res TSRMLS_CC) == FAILURE) {
break; //finish in case of failure
}
assert(self->buffer_cont_size <= self->buffer_size);
//we did not read anything. no need to continue
if (self->buffer_cont_size == 0)
break;
}
//if we get here we have data to be read in the buffer
this_read_size = MIN(left,
self->buffer_cont_size - self->buffer_pos);
assert(this_read_size > 0);
memcpy(&buf[count-left], &self->buffer[self->buffer_pos],
this_read_size);
left -= this_read_size;
n += this_read_size;
self->buffer_pos += this_read_size;
assert(left >= 0);
}
self->cursor += n;
}
//no more data upstream and buffer already read
if (self->no_more_data && self->buffer_pos == self->buffer_cont_size)
stream->eof = 1;
if (!self->no_more_data && n == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Extraction reported as unfinished but no data read. Please report"
" this, as this is a bug.");
stream->eof = 1;
}
return n<1 ? 0 : n;
}
/* }}} */
/* {{{ php_rar_ops_write */
static size_t php_rar_ops_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Write operation not supported for RAR streams.");
if (!stream) {
return 0;
}
return count;
}
/* }}} */
/* {{{ php_rar_ops_close */
static int php_rar_ops_close(php_stream *stream, int close_handle TSRMLS_DC)
{
STREAM_DATA_FROM_STREAM
if (close_handle) {
if (self->open_data.ArcName != NULL) {
efree(self->open_data.ArcName);
self->open_data.ArcName = NULL;
}
if (self->buffer != NULL) {
efree(self->buffer);
self->buffer = NULL;
}
if (self->rar_handle != NULL) {
int res = RARCloseArchive(self->rar_handle);
if (_rar_handle_error(res TSRMLS_CC) == FAILURE) {
; //not much we can do...
}
self->rar_handle = NULL;
}
}
efree(self);
stream->abstract = NULL;
return EOF;
}
/* }}} */
/* {{{ php_rar_ops_flush */
static int php_rar_ops_flush(php_stream *stream TSRMLS_DC)
{
return 0;
}
/* }}} */
php_stream_ops php_stream_rario_ops = {
php_rar_ops_write, php_rar_ops_read,
php_rar_ops_close, php_rar_ops_flush,
"rar",
NULL, /* seek */
NULL, /* cast */
NULL, /* stat */
NULL /* set_option */
};
/* {{{ php_stream_rar_open */
php_stream *php_stream_rar_open(char *arc_name,
char *utf_file_name,
char *password,
char *mode STREAMS_DC TSRMLS_DC)
{
php_stream *stream = NULL;
php_rar_stream_data_P self = NULL;
int result,
found;
if (strncmp(mode, "r", strlen("r")) != 0) {
goto cleanup;
}
self = ecalloc(1, sizeof *self);
self->open_data.ArcName = estrdup(arc_name);
self->open_data.OpenMode = RAR_OM_EXTRACT;
result = _rar_find_file(&self->open_data, utf_file_name, password,
&self->rar_handle, &found, &self->header_data);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
goto cleanup;
}
if (!found)
_rar_handle_ext_error("Can't find file %s in archive %s" TSRMLS_CC,
utf_file_name, arc_name);
{
//no need to allocate a buffer bigger than the file uncomp size
size_t buffer_size = (size_t)
MIN((uint64) RAR_CHUNK_BUFFER_SIZE,
INT32TO64(self->header_data.UnpSizeHigh,
self->header_data.UnpSize));
int process_result = RARProcessFileChunkInit(self->rar_handle);
if (_rar_handle_error(process_result TSRMLS_CC) == FAILURE) {
goto cleanup;
}
self->buffer = emalloc(buffer_size);
self->buffer_size = buffer_size;
stream = php_stream_alloc(&php_stream_rario_ops, self, NULL, mode);
}
cleanup:
if (stream == NULL) { //failed
if (self != NULL) {
if (self->open_data.ArcName != NULL)
efree(self->open_data.ArcName);
if (self->buffer != NULL)
efree(self->buffer);
if (self->rar_handle != NULL)
RARCloseArchive(self->rar_handle);
efree(self);
}
}
return stream;
}
/* }}} */
#endif /* ZEND_ENGINE_2 */
#endif /* HAVE_RAR */
#ifdef __cplusplus
}
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

812
rararch.c Normal file
View File

@@ -0,0 +1,812 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef __cplusplus
extern "C" {
#endif
#include <php.h>
#include <zend_interfaces.h>
#include "php_rar.h"
/* {{{ Type definitions reserved for this translation unit */
typedef struct _ze_rararch_object {
zend_object parent;
rar_file_t *rar_file;
} ze_rararch_object;
typedef struct _rararch_iterator {
zend_object_iterator parent;
int index; /* index in RARHeaderEx array */
zval *value;
} rararch_iterator;
/* }}} */
/* {{{ Globals with internal linkage */
static zend_class_entry *rararch_ce_ptr;
static zend_object_handlers rararch_object_handlers;
/* }}} */
/* {{{ Function prototypes for functions with internal linkage */
static int _rar_list_files(rar_file_t * TSRMLS_DC);
static int _rar_raw_entries_to_files(rar_file_t *rar,
const wchar_t * const file, //can be NULL
int *index,
zval *target TSRMLS_DC);
static zend_object_value rararch_ce_create_object(zend_class_entry *class_type TSRMLS_DC);
static void rararch_ce_destroy_object(ze_rararch_object *object,
zend_object_handle handle TSRMLS_DC);
static void rararch_ce_free_object_storage(ze_rararch_object *object TSRMLS_DC);
/* }}} */
/* {{{ Function definitions with external linkage */
int _rar_get_file_resource(zval *zval_file, rar_file_t **rar_file TSRMLS_DC) /* {{{ */
{
return _rar_get_file_resource_ex(zval_file, rar_file, FALSE TSRMLS_CC);
}
/* }}} */
/* Receives archive zval, returns object struct.
* If silent is FALSE, it checks whether the archive is alredy closed, and if it
* is, an exception/error is raised and 0 is returned
*/
int _rar_get_file_resource_ex(zval *zval_file, rar_file_t **rar_file, int silent TSRMLS_DC) /* {{{ */
{
ze_rararch_object *zobj;
zobj = zend_object_store_get_object(zval_file TSRMLS_CC);
if (zobj == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not find object in the store. This is a bug, please report it.");
return 0;
}
*rar_file = zobj->rar_file;
if ((*rar_file)->arch_handle == NULL && !silent) { //rar_close was called
_rar_handle_ext_error("The archive is already closed." TSRMLS_CC);
return 0;
}
return 1;
}
/* }}} */
/* }}} */
/* {{{ Helper functions and preprocessor definitions */
static int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
{
int result = 0;
int capacity = 0;
while (result == 0) {
struct RARHeaderDataEx entry;
result = RARReadHeaderEx(rar->arch_handle, &entry);
//value of 2nd argument is irrelevant in RAR_OM_LIST_[SPLIT] mode
if (result == 0) {
result = RARProcessFile(rar->arch_handle, RAR_SKIP, NULL, NULL);
}
if (result == 0) {
assert(capacity >= rar->entry_count);
if (capacity == rar->entry_count) { //0, 2, 6, 14, 30...
capacity = (capacity + 1) * 2;
rar->entries = erealloc(rar->entries,
sizeof(*rar->entries) * capacity);
if (!rar->entries)
return FAILURE;
}
assert(capacity > rar->entry_count);
rar->entries[rar->entry_count] = emalloc(sizeof(*rar->entries[0]));
memcpy(rar->entries[rar->entry_count], &entry,
sizeof *rar->entries[0]);
rar->entry_count++;
}
}
return result;
}
/* }}} */
static int _rar_raw_entries_to_files(rar_file_t *rar,
const wchar_t * const file, //can be NULL
int *index, //start index, can be NULL
zval *target //array or initialized object zval
TSRMLS_DC) /* {{{ */
{
wchar_t last_name[1024] = {L'\0'};
char strict_last_name[1024] = {'\0'};
unsigned long packed_size = 0UL;
struct RARHeaderDataEx *last_entry = NULL;
int any_commit = FALSE;
int first_file_check = (index == NULL) || (*index == 0);
int target_is_obj = (file != NULL || index != NULL);
int i;
assert(rar->entry_count == 0 || rar->entries != NULL);
for (i = (index == NULL ? 0 : *index); i <= rar->entry_count; i++) {
struct RARHeaderDataEx *entry;
const wchar_t *current_name;
const char *strict_current_name;
int read_entry = (i != rar->entry_count); //whether we have a new entry this iteration
int ended_file = FALSE; //whether we've seen a file and entries for the that file have ended
int commit_file = FALSE; //whether we are creating a new zval
int has_last_entry = (*strict_last_name != '\0'); //whether we had an entry last iteration
if (read_entry) {
entry = rar->entries[i];
current_name = entry->FileNameW;
strict_current_name = entry->FileName;
/* If file is continued from previous volume, skip it, as otherwise
* incorrect packed and unpacked sizes would be returned */
if (first_file_check) {
if (entry->Flags & 0x01)
continue;
else
first_file_check = FALSE;
}
}
/* The wide file name may result from conversion from the
* non-wide filename and this conversion may fail. In that
* case, we can have entries of different files with the
* the same wide file name. For this reason, we use the
* non-wide file name to check if we have a new file and
* don't trust the wide file name. */
ended_file = has_last_entry && (!read_entry ||
(strncmp(strict_last_name, strict_current_name, 1024) != 0));
commit_file = ended_file && (index != NULL || file == NULL ||
(file != NULL && wcsncmp(last_name, file, 1024) == 0));
if (commit_file) { //this entry corresponds to a new file
zval *entry_obj,
*rararch_obj;
/* guaranteed by commit_file = ended_file &&...
* with ended_file = has_last_entry && ...
* with has_last_entry = (last_name != NULL)
* and last_entry is set when last_name is set */
assert(last_entry != NULL);
any_commit = TRUE; //at least one commit done
//take care of last entry
/* if target_is_obj, assume target is a zval that will hold the
* entry, otherwise assume it is a numerical array */
if (!target_is_obj) {
MAKE_STD_ZVAL(entry_obj);
}
else
entry_obj = target;
//create RarEntry object:
object_init_ex(entry_obj, rar_class_entry_ptr);
//rararch property:
MAKE_STD_ZVAL(rararch_obj);
Z_TYPE_P(rararch_obj) = IS_OBJECT;
Z_OBJ_HANDLE_P(rararch_obj) = rar->id;
Z_OBJ_HT_P(rararch_obj) = &rararch_object_handlers;
zend_update_property(rar_class_entry_ptr, entry_obj, "rarfile",
sizeof("rararch") - 1, rararch_obj TSRMLS_CC);
/* zend_update_property calls write_property handler, which
* increments the refcount. We must decrease it here */
zval_ptr_dtor(&rararch_obj); //restore refcount to 1
/* to avoid destruction of the object due to refcount hitting
* 0 when this new object zval we created is destroyed */
zend_objects_store_add_ref_by_handle(rar->id TSRMLS_CC);
//remaining properties:
_rar_entry_to_zval(last_entry, entry_obj, packed_size TSRMLS_CC);
if (!target_is_obj) //target is an array, add to it
add_next_index_zval(target, entry_obj);
else
break; //we're done
}
if (ended_file) {
packed_size = 0UL; //reset counter
}
if (read_entry) { //sum packed size of current entry
//we would exceed size of ulong. cap at ulong_max
if (ULONG_MAX - packed_size < entry->PackSize)
packed_size = ULONG_MAX;
else {
packed_size += entry->PackSize;
if (entry->UnpSizeHigh != 0) {
if (sizeof(unsigned long) >= 8) {
packed_size += ((unsigned long) entry->UnpSizeHigh) << 32;
}
else {
packed_size = ULONG_MAX; //cap
}
}
}
//prepare for next entry
last_entry = entry;
wcsncpy(last_name, current_name, 1024);
strncpy(strict_last_name, strict_current_name, 1024);
}
}
if (index != NULL)
*index = i;
return any_commit;
}
/* }}} */
static zend_object_value rararch_ce_create_object(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
zend_object_value zov;
ze_rararch_object *zobj;
zval *tmp;
zobj = emalloc(sizeof *zobj);
zend_object_std_init((zend_object*) zobj, class_type TSRMLS_CC);
zend_hash_copy(((zend_object*)zobj)->properties,
&(class_type->default_properties),
(copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
zov.handle = zend_objects_store_put(zobj,
(zend_objects_store_dtor_t) rararch_ce_destroy_object,
(zend_objects_free_object_storage_t) rararch_ce_free_object_storage,
NULL TSRMLS_CC);
zov.handlers = &rararch_object_handlers;
return zov;
}
/* }}} */
static void rararch_ce_destroy_object(ze_rararch_object *object,
zend_object_handle handle TSRMLS_DC) /* {{{ */
{
rar_file_t *rar = object->rar_file;
//not really relevant, calls destr. zend func. ce->destructor if it exists
zend_objects_destroy_object((zend_object*) object, handle TSRMLS_CC);
if (rar->arch_handle != NULL) {
RARCloseArchive(rar->arch_handle);
}
}
/* }}} */
static void rararch_ce_free_object_storage(ze_rararch_object *object TSRMLS_DC) /* {{{ */
{
rar_file_t *rar = object->rar_file;
int i;
if (rar->password != NULL) {
efree(rar->password);
}
if ((rar->entries != NULL) && (rar->entry_count > 0)) {
for (i = 0; i < rar->entry_count; i++) {
efree(rar->entries[i]);
}
efree(rar->entries);
rar->entry_count = 0;
}
efree(rar->list_open_data->ArcName);
efree(rar->list_open_data->CmtBuf);
efree(rar->list_open_data);
efree(rar->extract_open_data->ArcName);
efree(rar->extract_open_data);
efree(rar);
/* could call zend_objects_free_object_storage here (not before!), but
* instead I'll mimic its behaviour */
zend_object_std_dtor((zend_object*) object TSRMLS_CC);
efree(object);
}
/* }}} */
/* Missing function in VC6 */
#if !HAVE_STRNLEN
static size_t strnlen(const char *s, size_t maxlen) /* {{{ */
{
char *r = memchr(s, '\0', maxlen);
return r ? r-s : maxlen;
}
/* }}} */
#endif
/* }}} */
/* module functions */
/* {{{ proto RarArchive rar_open(string filename [, string password])
Open RAR archive and return RarArchive object */
PHP_FUNCTION(rar_open)
{
char *filename;
char *password = NULL;
char resolved_path[MAXPATHLEN];
int filename_len;
int password_len = 0;
rar_file_t *rar = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &filename,
&filename_len, &password, &password_len) == FAILURE) {
return;
}
if (OPENBASEDIR_CHECKPATH(filename)) {
RETURN_FALSE;
}
if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
RETURN_FALSE;
}
rar = emalloc(sizeof *rar);
rar->list_open_data = ecalloc(1, sizeof *rar->list_open_data);
rar->list_open_data->ArcName = estrndup(resolved_path,
strnlen(resolved_path, MAXPATHLEN));
rar->list_open_data->OpenMode = RAR_OM_LIST_INCSPLIT;
rar->list_open_data->CmtBuf = ecalloc(RAR_MAX_COMMENT_SIZE, 1);
rar->list_open_data->CmtBufSize = RAR_MAX_COMMENT_SIZE;
rar->extract_open_data = ecalloc(1, sizeof *rar->extract_open_data);
rar->extract_open_data->ArcName = estrndup(resolved_path,
strnlen(resolved_path, MAXPATHLEN));
rar->extract_open_data->OpenMode = RAR_OM_EXTRACT;
rar->extract_open_data->CmtBuf = NULL; //not interested in it again
rar->password = NULL;
rar->entries = NULL;
rar->entry_count = 0;
rar->arch_handle = RAROpenArchiveEx(rar->list_open_data);
if (rar->arch_handle != NULL && rar->list_open_data->OpenResult == 0) {
if (password_len > 0) {
rar->password = estrndup(password, password_len);
}
//rar->id = ZEND_REGISTER_RESOURCE(return_value, rar, le_rar_file);
object_init_ex(return_value, rararch_ce_ptr);
{
ze_rararch_object *zobj =
zend_object_store_get_object(return_value TSRMLS_CC);
zobj->rar_file = rar;
}
rar->id = Z_OBJ_HANDLE_P(return_value);
} else {
const char *err_str = _rar_error_to_string(rar->list_open_data->OpenResult);
if (err_str == NULL)
_rar_handle_ext_error("%s" TSRMLS_CC, "Archive opened failed "
"(returned NULL handle), but did not return an error. "
"Should not happen.");
else {
char *preamble;
spprintf(&preamble, 0, "Failed to open %s: ", filename);
_rar_handle_error_ex(preamble,
rar->list_open_data->OpenResult TSRMLS_CC);
efree(preamble);
}
efree(rar->list_open_data->ArcName);
efree(rar->list_open_data->CmtBuf);
efree(rar->list_open_data);
efree(rar->extract_open_data->ArcName);
efree(rar->extract_open_data);
efree(rar);
RETURN_FALSE;
}
RARSetCallback(rar->arch_handle, _rar_unrar_callback, (LPARAM) rar->password);
}
/* }}} */
/* {{{ proto array rar_list(RarArchive rarfile)
Return entries from the rar archive */
PHP_FUNCTION(rar_list)
{
zval *file = getThis();
rar_file_t *rar = NULL;
int result;
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
&file, rararch_ce_ptr) == FAILURE) {
return;
}
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
array_init(return_value);
_rar_raw_entries_to_files(rar, NULL, NULL, return_value TSRMLS_CC);
}
/* }}} */
/* {{{ proto object rar_entry_get(RarArchive rarfile, string filename)
Return entry from the rar archive */
PHP_FUNCTION(rar_entry_get)
{
zval *file = getThis();
char *filename;
rar_file_t *rar = NULL;
int result;
int found;
int filename_len;
wchar_t *filename_c = NULL;
if (file == NULL) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os",
&file, rararch_ce_ptr, &filename, &filename_len) == FAILURE) {
return;
}
}
else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&filename, &filename_len) == FAILURE) {
return;
}
}
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
filename_c = ecalloc(filename_len + 1, sizeof *filename_c);
_rar_utf_to_wide(filename, filename_c, filename_len + 1);
found = _rar_raw_entries_to_files(rar, filename_c, NULL, return_value
TSRMLS_CC);
if (!found) {
_rar_handle_ext_error(
"cannot find file \"%s\" in Rar archive \"%s\"."
TSRMLS_CC, filename, rar->list_open_data->ArcName);
RETVAL_FALSE;
}
efree(filename_c);
}
/* }}} */
/* {{{ proto string rar_solid_is(RarArchive rarfile)
Return whether RAR archive is solid */
PHP_FUNCTION(rar_solid_is)
{
zval *file = getThis();
rar_file_t *rar = NULL;
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
&file, rararch_ce_ptr) == FAILURE) {
return;
}
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
RETURN_FALSE;
}
RETURN_BOOL((rar->list_open_data->Flags & 0x0008) != 0);
}
/* }}} */
/* {{{ proto string rar_comment_get(RarArchive rarfile)
Return comment of the rar archive */
PHP_FUNCTION(rar_comment_get)
{
zval *file = getThis();
rar_file_t *rar = NULL;
unsigned cmt_state;
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
&file, rararch_ce_ptr) == FAILURE) {
return;
}
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
RETURN_FALSE;
}
cmt_state = rar->list_open_data->CmtState;
if (_rar_handle_error(cmt_state TSRMLS_CC) == FAILURE)
RETURN_FALSE;
if (cmt_state == 0) //comment not present
RETURN_NULL(); //oddly, requires ()
if (cmt_state == 1) { //comment read completely
//CmtSize - 1 because we don't need the null terminator
RETURN_STRINGL(rar->list_open_data->CmtBuf,
rar->list_open_data->CmtSize - 1, 1);
}
}
/* }}} */
/* {{{ proto bool rar_close(RarArchive rarfile)
Close Rar archive and free all resources */
PHP_FUNCTION(rar_close)
{
zval *file = getThis();
rar_file_t *rar = NULL;
if (file == NULL && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
&file, rararch_ce_ptr) == FAILURE) {
return;
}
if (!_rar_get_file_resource(file, &rar TSRMLS_CC)) {
RETURN_FALSE;
}
//zend_hash_index_del(&EG(regular_list), Z_RESVAL_P(file));
/* When changed from resource to custom object, instead of fiddling
* with the refcount to force object destruction, an indication that
* the file is already closed is given by setting rar->arch_handle
* to NULL. This is checked by _rar_get_file_resource. */
RARCloseArchive(rar->arch_handle);
rar->arch_handle = NULL;
RETURN_TRUE;
}
/* }}} */
/* {{{ proto string RarEntry::__toString()
Return string representation for entry */
PHP_METHOD(rararch, __toString)
{
zval *arch_obj = getThis();
rar_file_t *rar = NULL;
const char format[] = "RAR Archive \"%s\"%s",
closed[] = " (closed)";
char *restring;
int restring_len,
is_closed;
if (!_rar_get_file_resource_ex(arch_obj, &rar, TRUE TSRMLS_CC)) {
RETURN_FALSE;
}
is_closed = (rar->arch_handle == NULL);
//2 is size of %s, 1 is terminating 0
restring_len = (sizeof(format) - 1) - 2 * 2 + 1;
restring_len += strlen(rar->list_open_data->ArcName);
if (is_closed)
restring_len += sizeof(closed) - 1;
restring = emalloc(restring_len);
snprintf(restring, restring_len, format, rar->list_open_data->ArcName,
is_closed?closed:"");
restring[restring_len - 1] = '\0'; //just to be safe
RETURN_STRING(restring, 0);
}
/* }}} */
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_rararchive_open, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_rararchive_getentry, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_rararchive_void, 0)
ZEND_END_ARG_INFO()
/* }}} */
static zend_function_entry php_rararch_class_functions[] = {
PHP_ME_MAPPING(open, rar_open, arginfo_rararchive_open, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC)
PHP_ME_MAPPING(getEntries, rar_list, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
PHP_ME_MAPPING(getEntry, rar_entry_get, arginfo_rararchive_getentry, ZEND_ACC_PUBLIC)
#ifdef RAR_ARCHIVE_LIST_ALIAS
PHP_ME_MAPPING(list, rar_list, arginfo_rararchive_void, ZEND_ACC_PUBLIC | ZEND_ACC_DEPRECATED)
#endif
PHP_ME_MAPPING(isSolid, rar_solid_is, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
PHP_ME_MAPPING(getComment, rar_comment_get, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
PHP_ME_MAPPING(close, rar_close, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
PHP_ME(rararch, __toString, arginfo_rararchive_void, ZEND_ACC_PUBLIC)
PHP_ME_MAPPING(__construct, rar_bogus_ctor, arginfo_rararchive_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
{NULL, NULL, NULL}
};
/* {{{ Iteration. Very boring stuff indeed. */
/* {{{ Iteration Prototypes */
static zend_object_iterator *rararch_it_get_iterator(zend_class_entry *ce,
zval *object,
int by_ref TSRMLS_DC);
static void rararch_it_delete_cache(zend_object_iterator *iter TSRMLS_DC);
static void rararch_it_dtor(zend_object_iterator *iter TSRMLS_DC);
static void rararch_it_fetch(rararch_iterator *it TSRMLS_DC);
static int rararch_it_valid(zend_object_iterator *iter TSRMLS_DC);
static void rararch_it_current_data(zend_object_iterator *iter,
zval ***data TSRMLS_DC);
static void rararch_it_move_forward(zend_object_iterator *iter TSRMLS_DC);
static void rararch_it_rewind(zend_object_iterator *iter TSRMLS_DC);
/* }}} */
/* {{{ rararch_it_get_iterator */
static zend_object_iterator *rararch_it_get_iterator(zend_class_entry *ce,
zval *object,
int by_ref TSRMLS_DC)
{
rararch_iterator *it;
rar_file_t *rar;
int res;
if (by_ref) {
zend_error(E_ERROR,
"An iterator cannot be used with foreach by reference");
}
it = emalloc(sizeof *it);
res = _rar_get_file_resource_ex(object, &rar, 1 TSRMLS_CC);
if (!res)
zend_error(E_ERROR, "Cannot fetch RarArchive object");
if (rar->arch_handle == NULL)
zend_error(E_ERROR, "The archive is already closed, "
"cannot give an iterator");
if (rar->entries == NULL) {
res = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(res TSRMLS_CC) == FAILURE) {
rar->entry_count = 0;
}
}
zval_add_ref(&object);
it->parent.data = object;
it->parent.funcs = ce->iterator_funcs.funcs;
it->index = 0;
it->value = NULL;
return (zend_object_iterator*) it;
}
/* }}} */
/* {{{ rararch_it_invalidate_current */
static void rararch_it_invalidate_current(zend_object_iterator *iter TSRMLS_DC)
{
rararch_iterator *it = (rararch_iterator *) iter;
if (it->value != NULL) {
zval_ptr_dtor(&it->value);
it->value = NULL;
}
}
/* }}} */
/* {{{ rararch_it_dtor */
static void rararch_it_dtor(zend_object_iterator *iter TSRMLS_DC)
{
rararch_iterator *it = (rararch_iterator *) iter;
rararch_it_invalidate_current((zend_object_iterator *) it TSRMLS_CC);
zval_ptr_dtor((zval**) &it->parent.data); /* decrease refcount on zval object */
efree(it);
}
/* }}} */
/* {{{ rararch_it_fetch - populates it->current */
static void rararch_it_fetch(rararch_iterator *it TSRMLS_DC)
{
rar_file_t *rar_file;
int res;
assert(it->value == NULL);
MAKE_STD_ZVAL(it->value);
res = _rar_get_file_resource_ex(it->parent.data, &rar_file, 1 TSRMLS_CC);
if (!res)
zend_error(E_ERROR, "Cannot fecth RarArchive object");
res = _rar_raw_entries_to_files(rar_file, NULL, &it->index, it->value
TSRMLS_CC);
if (!res)
ZVAL_FALSE(it->value);
}
/* }}} */
/* {{{ rararch_it_valid */
static int rararch_it_valid(zend_object_iterator *iter TSRMLS_DC)
{
zval *value = ((rararch_iterator *) iter)->value;
assert(value != NULL);
return (Z_TYPE_P(value) != IS_BOOL)?SUCCESS:FAILURE;
}
/* }}} */
/* {{{ rararch_it_current_data */
static void rararch_it_current_data(zend_object_iterator *iter,
zval ***data TSRMLS_DC)
{
zval **value = &(((rararch_iterator *) iter)->value);
assert(*value != NULL);
*data = value;
}
/* }}} */
/* {{{ rararch_it_move_forward */
static void rararch_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
{
rararch_iterator *it = (rararch_iterator *) iter;
rararch_it_invalidate_current((zend_object_iterator *) it TSRMLS_CC);
it->value = NULL;
rararch_it_fetch(it TSRMLS_CC);
}
/* }}} */
/* {{{ rararch_it_rewind */
static void rararch_it_rewind(zend_object_iterator *iter TSRMLS_DC)
{
rararch_iterator *it = (rararch_iterator *) iter;
rararch_it_invalidate_current((zend_object_iterator *) it TSRMLS_CC);
it->index = 0;
it->value = NULL;
rararch_it_fetch(it TSRMLS_CC);
}
/* }}} */
/* iterator handler table */
static zend_object_iterator_funcs rararch_it_funcs = {
rararch_it_dtor,
rararch_it_valid,
rararch_it_current_data,
NULL,
rararch_it_move_forward,
rararch_it_rewind,
rararch_it_invalidate_current
};
/* }}} */
void minit_rararch(TSRMLS_D)
{
zend_class_entry ce;
memcpy(&rararch_object_handlers, zend_get_std_object_handlers(),
sizeof rararch_object_handlers);
INIT_CLASS_ENTRY(ce, "RarArchive", php_rararch_class_functions);
rararch_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
rararch_ce_ptr->ce_flags |= ZEND_ACC_FINAL_CLASS;
rararch_ce_ptr->clone = NULL;
rararch_ce_ptr->create_object = &rararch_ce_create_object;
rararch_ce_ptr->get_iterator = rararch_it_get_iterator;
rararch_ce_ptr->iterator_funcs.funcs = &rararch_it_funcs;
zend_class_implements(rararch_ce_ptr TSRMLS_CC, 1, zend_ce_traversable);
}
#ifdef __cplusplus
}
#endif

649
rarentry.c Normal file
View File

@@ -0,0 +1,649 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef __cplusplus
extern "C" {
#endif
#include "php.h"
#include "php_rar.h"
/* {{{ Globals with external linkage */
zend_class_entry *rar_class_entry_ptr;
/* }}} */
/* {{{ Globals with internal linkage */
static zend_object_handlers rarentry_object_handlers;
/* }}} */
/* {{{ Function prototypes for functions with internal linkage */
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
int name_length, char *doc_comment,
int doc_comment_len TSRMLS_DC);
static zval **_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC);
static void _rar_dos_date_to_text(int dos_time, char *date_string);
static zend_object_value rarentry_ce_create_object(zend_class_entry *class_type TSRMLS_DC);
/* }}} */
/* {{{ Functions with external linkage */
/* should be passed the last entry that corresponds to a given file
* only that one has the correct CRC. Still, it may have a wrong packedSize */
void _rar_entry_to_zval(struct RARHeaderDataEx *entry, zval *object,
unsigned long packed_size TSRMLS_DC) /* {{{ */
{
char tmp_s [MAX_LENGTH_OF_LONG + 1];
char time[50];
char *filename;
long unp_size;
if (sizeof(long) >= 8)
unp_size = ((long) entry->UnpSize) + (((long) entry->UnpSizeHigh) << 32);
else {
//for 32-bit long, at least don't give negative values
if ((unsigned long) entry->UnpSize > (unsigned long) LONG_MAX
|| entry->UnpSizeHigh != 0)
unp_size = LONG_MAX;
else
unp_size = (long) entry->UnpSize;
}
/* 2 instead of sizeof(wchar_t) would suffice, I think. I doubt
* _rar_wide_to_utf handles characters not in UCS-2. But better be safe */
filename = (char*) emalloc(sizeof(entry->FileNameW) * sizeof(wchar_t));
if (packed_size > (unsigned long) LONG_MAX)
packed_size = LONG_MAX;
_rar_wide_to_utf(entry->FileNameW, filename,
sizeof(entry->FileNameW) * sizeof(wchar_t));
/* we're not in class scope, so we cannot change the class private
* properties from here with add_property_x
* zend_update_property_x updates the scope accordingly */
zend_update_property_string(rar_class_entry_ptr, object, "name",
sizeof("name") - 1, filename TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "unpacked_size",
sizeof("unpacked_size") - 1, unp_size TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "packed_size",
sizeof("packed_size") - 1, packed_size TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "host_os",
sizeof("host_os") - 1, entry->HostOS TSRMLS_CC);
_rar_dos_date_to_text(entry->FileTime, time);
zend_update_property_string(rar_class_entry_ptr, object, "file_time",
sizeof("file_time") - 1, time TSRMLS_CC);
sprintf(tmp_s, "%lx", entry->FileCRC);
zend_update_property_string(rar_class_entry_ptr, object, "crc",
sizeof("crc") - 1, tmp_s TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "attr",
sizeof("attr") - 1, entry->FileAttr TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "version",
sizeof("version") - 1, entry->UnpVer TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "method",
sizeof("method") - 1, entry->Method TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, object, "flags",
sizeof("flags") - 1, entry->Flags TSRMLS_CC);
efree(filename);
}
/* }}} */
/* }}} */
/* {{{ Helper functions and preprocessor definitions */
#define RAR_GET_PROPERTY(var, prop_name) \
if (!entry_obj) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "this method cannot be called statically"); \
RETURN_FALSE; \
} \
if ((var = _rar_entry_get_property(entry_obj, prop_name, sizeof(prop_name) TSRMLS_CC)) == NULL) { \
RETURN_FALSE; \
}
#define REG_RAR_CLASS_CONST_LONG(const_name, value) \
zend_declare_class_constant_long(rar_class_entry_ptr, const_name, \
sizeof(const_name) - 1, (long) value TSRMLS_CC)
#define REG_RAR_PROPERTY(name, comment) \
_rar_decl_priv_prop_null(rar_class_entry_ptr, name, sizeof(name) -1, \
comment, sizeof(comment) - 1 TSRMLS_CC)
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
int name_length, char *doc_comment,
int doc_comment_len TSRMLS_DC) /* {{{ */
{
zval *property;
ALLOC_PERMANENT_ZVAL(property);
INIT_ZVAL(*property);
return zend_declare_property_ex(ce, name, name_length, property,
ZEND_ACC_PRIVATE, doc_comment, doc_comment_len TSRMLS_CC);
}
/* }}} */
static zval **_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
{
zval **tmp;
char *mangled_name;
int mangled_name_len;
//perhaps cleaner alternative: use Z_OBJ_HANDLER_P(entry_obj, read_property)
//another way to avoid mem allocation would be to get the mangled name from
//ce->properties_info.name (properties_info hash table indexes by unmangled name)
//see also zend_read_property
zend_mangle_property_name(&mangled_name, &mangled_name_len, "RarEntry",
sizeof("RarEntry") - 1, name, namelen, 0);
if (zend_hash_find(Z_OBJPROP_P(entry_obj), mangled_name, mangled_name_len,
(void**) &tmp) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Bug: unable to find property '%s'. Please report.", name);
efree(mangled_name);
return NULL;
}
efree(mangled_name);
return tmp;
}
/* }}} */
static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
{
int second, minute, hour, day, month, year;
/* following lines were taken from timefn.cpp */
second = (dos_time & 0x1f)*2;
minute = (dos_time>>5) & 0x3f;
hour = (dos_time>>11) & 0x1f;
day = (dos_time>>16) & 0x1f;
month = (dos_time>>21) & 0x0f;
year = (dos_time>>25)+1980;
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
}
/* }}} */
static zend_object_value rarentry_ce_create_object(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
zend_object_value zov;
zend_object *zobj;
zval *tmp;
zobj = emalloc(sizeof *zobj);
zend_object_std_init(zobj, class_type TSRMLS_CC);
zend_hash_copy(zobj->properties, &(class_type->default_properties),
(copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
zov.handle = zend_objects_store_put(zobj,
(zend_objects_store_dtor_t) zend_objects_destroy_object,
(zend_objects_free_object_storage_t) zend_objects_free_object_storage,
NULL TSRMLS_CC);
zov.handlers = &rarentry_object_handlers;
return zov;
}
/* }}} */
/* }}} */
/* {{{ Methods */
/* {{{ proto bool RarEntry::extract(string dir [, string filepath [, string password ]])
Extract file from the archive */
PHP_METHOD(rarentry, extract)
{ //lots of variables, but no need to be intimidated
char *dir,
*filepath = NULL,
*password = NULL;
int dir_len,
filepath_len = 0,
password_len = 0;
char *considered_path;
char considered_path_res[MAXPATHLEN];
int with_second_arg;
zval **tmp,
**tmp_name;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
struct RARHeaderDataEx entry;
HANDLE extract_handle = NULL;
int result;
int found;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &dir, &dir_len,
&filepath, &filepath_len, &password, &password_len) == FAILURE ) {
return;
}
RAR_GET_PROPERTY(tmp, "rarfile");
if (!_rar_get_file_resource(*tmp, &rar TSRMLS_CC)) {
RETURN_FALSE;
}
/* Decide where to extract */
with_second_arg = (filepath_len != 0);
//the arguments are mutually exclusive. If the second is specified, must ignore the first
if (!with_second_arg) {
if (dir_len == 0) //both params empty
dir = ".";
considered_path = dir;
}
else {
considered_path = filepath;
}
if (OPENBASEDIR_CHECKPATH(considered_path)) {
RETURN_FALSE;
}
if (!expand_filepath(considered_path, considered_path_res TSRMLS_CC)) {
RETURN_FALSE;
}
/* Find file inside archive */
RAR_GET_PROPERTY(tmp_name, "name");
if (password == NULL)
password = rar->password; //use rar_open password by default
result = _rar_find_file(rar->extract_open_data, Z_STRVAL_PP(tmp_name),
password, &extract_handle, &found, &entry);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
goto cleanup;
}
if (!found) {
_rar_handle_ext_error("Can't find file %s in archive %s" TSRMLS_CC,
Z_STRVAL_PP(tmp_name),
rar->list_open_data->ArcName);
RETVAL_FALSE;
goto cleanup;
}
/* Do extraction */
if (!with_second_arg)
result = RARProcessFile(extract_handle, RAR_EXTRACT,
considered_path_res, NULL);
else
result = RARProcessFile(extract_handle, RAR_EXTRACT,
NULL, considered_path_res);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
}
else {
RETVAL_TRUE;
}
cleanup:
if (extract_handle != NULL)
RARCloseArchive(extract_handle);
}
/* }}} */
/* {{{ proto string RarEntry::getName()
Return entry name */
PHP_METHOD(rarentry, getName)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "name");
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto int RarEntry::getUnpackedSize()
Return unpacked size of the entry */
PHP_METHOD(rarentry, getUnpackedSize)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "unpacked_size");
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getPackedSize()
Return packed size of the entry */
PHP_METHOD(rarentry, getPackedSize)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "packed_size");
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getHostOs()
Return host OS of the entry */
PHP_METHOD(rarentry, getHostOs)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "host_os");
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto string RarEntry::getFileTime()
Return modification time of the entry */
PHP_METHOD(rarentry, getFileTime)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "file_time");
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto string RarEntry::getCrc()
Return CRC of the entry */
PHP_METHOD(rarentry, getCrc)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "crc");
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto int RarEntry::getAttr()
Return attributes of the entry */
PHP_METHOD(rarentry, getAttr)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "attr");
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getVersion()
Return version of the archiver, used to create this entry */
PHP_METHOD(rarentry, getVersion)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "version");
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getMethod()
Return packing method */
PHP_METHOD(rarentry, getMethod)
{
zval **tmp;
zval *entry_obj = getThis();
RAR_GET_PROPERTY(tmp, "method");
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto resource RarEntry::getStream([string password])
Return stream for current entry */
PHP_METHOD(rarentry, getStream)
{
zval **tmp, **name;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
php_stream *stream = NULL;
char *password = NULL;
int password_len; //ignored
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s",
&password, &password_len) == FAILURE ) {
return;
}
RAR_GET_PROPERTY(name, "name");
RAR_GET_PROPERTY(tmp, "rarfile");
if (!_rar_get_file_resource(*tmp, &rar TSRMLS_CC)) {
RETURN_FALSE;
}
if (password == NULL)
password = rar->password; //use rar_open password by default
stream = php_stream_rar_open(rar->extract_open_data->ArcName,
Z_STRVAL_PP(name), password, "r" STREAMS_CC TSRMLS_CC);
if (stream != NULL) {
php_stream_to_zval(stream, return_value);
}
else
RETVAL_FALSE;
}
/* }}} */
/* {{{ proto int RarEntry::isDirectory()
Return whether the entry represents a directory */
PHP_METHOD(rarentry, isDirectory)
{
zval **tmp;
zval *entry_obj = getThis();
long flags;
int is_dir;
RAR_GET_PROPERTY(tmp, "flags");
flags = Z_LVAL_PP(tmp);
is_dir = ((flags & 0xE0) == 0xE0);
RETURN_BOOL(is_dir);
}
/* }}} */
/* {{{ proto int RarEntry::isEncrypted()
Return whether the entry is encrypted and needs a password */
PHP_METHOD(rarentry, isEncrypted)
{
zval **tmp;
zval *entry_obj = getThis();
long flags;
int is_encrypted;
RAR_GET_PROPERTY(tmp, "flags");
flags = Z_LVAL_PP(tmp);
is_encrypted = (flags & 0x04);
RETURN_BOOL(is_encrypted);
}
/* }}} */
/* {{{ proto string RarEntry::__toString()
Return string representation for entry */
PHP_METHOD(rarentry, __toString)
{
zval **flags_zval,
**name_zval,
**crc_zval;
zval *entry_obj = getThis();
long flags;
int is_dir;
char *name,
*crc;
char *restring;
int restring_len;
const char format[] = "RarEntry for %s \"%s\" (%s)";
RAR_GET_PROPERTY(flags_zval, "flags");
flags = Z_LVAL_PP(flags_zval);
is_dir = ((flags & 0xE0) == 0xE0);
RAR_GET_PROPERTY(name_zval, "name");
name = Z_STRVAL_PP(name_zval);
RAR_GET_PROPERTY(crc_zval, "crc");
crc = Z_STRVAL_PP(crc_zval);
//2 is size of %s, 8 is size of crc
restring_len = (sizeof(format)-1) - 2 * 3 + (sizeof("directory")-1) +
strlen(name) + 8 + 1;
restring = emalloc(restring_len);
snprintf(restring, restring_len, format, is_dir?"directory":"file",
name, crc);
restring[restring_len - 1] = '\0'; //just to be safe
RETURN_STRING(restring, 0);
}
/* }}} */
/* }}} */
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_extract, 0, 0, 1)
ZEND_ARG_INFO(0, path)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_getstream, 0, 0, 0)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_rar_void, 0)
ZEND_END_ARG_INFO()
/* }}} */
static zend_function_entry php_rar_class_functions[] = {
PHP_ME(rarentry, extract, arginfo_rarentry_extract, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getName, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getUnpackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getPackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getHostOs, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getFileTime, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getCrc, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getAttr, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getVersion, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getMethod, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getStream, arginfo_rarentry_getstream, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, isDirectory, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, isEncrypted, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, __toString, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME_MAPPING(__construct, rar_bogus_ctor, arginfo_rar_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
{NULL, NULL, NULL}
};
void minit_rarentry(TSRMLS_D)
{
zend_class_entry ce;
memcpy(&rarentry_object_handlers, zend_get_std_object_handlers(),
sizeof rarentry_object_handlers);
INIT_CLASS_ENTRY(ce, "RarEntry", php_rar_class_functions);
rar_class_entry_ptr = zend_register_internal_class(&ce TSRMLS_CC);
rar_class_entry_ptr->ce_flags |= ZEND_ACC_FINAL_CLASS;
rar_class_entry_ptr->clone = NULL;
//Custom creation currently not really needed, but you never know...
rar_class_entry_ptr->create_object = &rarentry_ce_create_object;
REG_RAR_PROPERTY("rarfile", "Associated RAR archive");
REG_RAR_PROPERTY("name", "File or directory name with path");
REG_RAR_PROPERTY("unpacked_size", "Size of file when unpacked");
REG_RAR_PROPERTY("packed_size", "Size of the packed file inside the archive");
REG_RAR_PROPERTY("host_os", "OS used to pack the file");
REG_RAR_PROPERTY("file_time", "Entry's time of last modification");
REG_RAR_PROPERTY("crc", "CRC checksum for the unpacked file");
REG_RAR_PROPERTY("attr", "OS-dependent file attributes");
REG_RAR_PROPERTY("version", "RAR version needed to extract entry");
REG_RAR_PROPERTY("method", "Identifier for packing method");
REG_RAR_PROPERTY("flags", "Entry header flags");
REG_RAR_CLASS_CONST_LONG("HOST_MSDOS", HOST_MSDOS);
REG_RAR_CLASS_CONST_LONG("HOST_OS2", HOST_OS2);
REG_RAR_CLASS_CONST_LONG("HOST_WIN32", HOST_WIN32);
REG_RAR_CLASS_CONST_LONG("HOST_UNIX", HOST_UNIX);
REG_RAR_CLASS_CONST_LONG("HOST_MACOS", HOST_MACOS);
REG_RAR_CLASS_CONST_LONG("HOST_BEOS", HOST_BEOS);
//see WinNT.h
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_READONLY", 0x00001L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_HIDDEN", 0x00002L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SYSTEM", 0x00004L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DIRECTORY", 0x00010L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ARCHIVE", 0x00020L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DEVICE", 0x00040L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NORMAL", 0x00080L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_TEMPORARY", 0x00100L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SPARSE_FILE", 0x00200L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_REPARSE_POINT", 0x00400L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_COMPRESSED", 0x00800L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_OFFLINE", 0x01000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NOT_CONTENT_INDEXED", 0x02000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ENCRYPTED", 0x04000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_VIRTUAL", 0x10000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_EXECUTE", 0x00001L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_WRITE", 0x00002L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_READ", 0x00004L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_EXECUTE", 0x00008L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_WRITE", 0x00010L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_READ", 0x00020L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_EXECUTE", 0x00040L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_WRITE", 0x00080L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_READ", 0x00100L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_STICKY", 0x00200L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETGID", 0x00400L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETUID", 0x00800L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FINAL_QUARTET", 0x0F000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FIFO", 0x01000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_CHAR_DEV", 0x02000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_DIRECTORY", 0x04000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_BLOCK_DEV", 0x06000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_REGULAR_FILE", 0x08000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SYM_LINK", 0x0A000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SOCKET", 0x0C000L);
}
#ifdef __cplusplus
}
#endif

View File

@@ -11,8 +11,17 @@ var_dump($rar_file1);
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
var_dump($rar_file2);
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
var_dump($rar_file3);
echo "Done\n";
?>
--EXPECTF--
resource(%d) of type (Rar)
resource(%d) of type (Rar)
object(RarArchive)#%d (%d) {
}
object(RarArchive)#%d (%d) {
}
Warning: rar_open(): Failed to open %s/no_such_file.rar: ERAR_EOPEN (file open error) in %s on line %d
bool(false)
Done

View File

@@ -13,102 +13,124 @@ $rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$list2 = rar_list($rar_file2);
var_dump($list2);
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
$list3 = rar_list($rar_file3);
var_dump($list3);
echo "Done\n";
?>
--EXPECTF--
array(2) {
[0]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%s (%s) {
}
["name%sprivate%s=>
string(9) "plain.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(15)
["packed_size"]=>
["packed_size%sprivate%s=>
int(25)
["host_os"]=>
["host_os%sprivate%s=>
int(3)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 11:01:24"
["crc"]=>
["crc%sprivate%s=>
string(8) "7728b6fe"
["attr"]=>
["attr%sprivate%s=>
int(33188)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(32800)
}
[1]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (0) {
}
["name%sprivate%s=>
string(30) "test file with whitespaces.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(14)
["packed_size"]=>
["packed_size%sprivate%s=>
int(20)
["host_os"]=>
["host_os%sprivate%s=>
int(3)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 11:01:32"
["crc"]=>
["crc%sprivate%s=>
string(8) "21890dd9"
["attr"]=>
["attr%sprivate%s=>
int(33188)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(32800)
}
}
array(2) {
[0]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["name%sprivate%s=>
string(5) "1.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(5)
["packed_size"]=>
["packed_size%sprivate%s=>
int(17)
["host_os"]=>
["host_os%sprivate%s=>
int(2)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:18"
["crc"]=>
["crc%sprivate%s=>
string(8) "a0de71c0"
["attr"]=>
["attr%sprivate%s=>
int(32)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(36992)
}
[1]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["name%sprivate%s=>
string(5) "2.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(5)
["packed_size"]=>
["packed_size%sprivate%s=>
int(16)
["host_os"]=>
["host_os%sprivate%s=>
int(2)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:26"
["crc"]=>
["crc%sprivate%s=>
string(8) "45a918de"
["attr"]=>
["attr%sprivate%s=>
int(32)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(37008)
}
}
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
Warning: rar_list() expects parameter 1 to be RarArchive, boolean given in %s on line %d
NULL
Done

View File

@@ -13,52 +13,66 @@ $rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entry2 = rar_entry_get($rar_file2, '2.txt');
var_dump($entry2);
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
$entry3 = rar_entry_get($rar_file3, '2.txt');
var_dump($entry3);
echo "Done\n";
?>
--EXPECTF--
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["name%sprivate%s=>
string(30) "test file with whitespaces.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(14)
["packed_size"]=>
["packed_size%sprivate%s=>
int(20)
["host_os"]=>
["host_os%sprivate%s=>
int(3)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 11:01:32"
["crc"]=>
["crc%sprivate%s=>
string(8) "21890dd9"
["attr"]=>
["attr%sprivate%s=>
int(33188)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(32800)
}
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["name%sprivate%s=>
string(5) "2.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(5)
["packed_size"]=>
["packed_size%sprivate%s=>
int(16)
["host_os"]=>
["host_os%sprivate%s=>
int(2)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:26"
["crc"]=>
["crc%sprivate%s=>
string(8) "45a918de"
["attr"]=>
["attr%sprivate%s=>
int(32)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(37008)
}
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
Warning: rar_entry_get() expects parameter 1 to be RarArchive, boolean given in %s on line %d
NULL
Done

View File

@@ -11,10 +11,12 @@ $entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
$entry1->extract(dirname(__FILE__));
$contents11 = file_get_contents(dirname(__FILE__).'/test file with whitespaces.txt');
echo $contents11."\n";
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
$entry1->extract(false,dirname(__FILE__).'/1.txt');
$contents12 = file_get_contents(dirname(__FILE__).'/1.txt');
echo $contents12."\n";
@unlink(dirname(__FILE__).'/1.txt');
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entry2 = rar_entry_get($rar_file2, '2.txt');
@@ -22,19 +24,59 @@ $entry2 = rar_entry_get($rar_file2, '2.txt');
$entry2->extract(dirname(__FILE__));
$contents21 = file_get_contents(dirname(__FILE__).'/2.txt');
echo $contents21."\n";
@unlink(dirname(__FILE__).'/2.txt');
$entry2->extract(false,dirname(__FILE__).'/some.txt');
$contents22 = file_get_contents(dirname(__FILE__).'/some.txt');
echo $contents22."\n";
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
@unlink(dirname(__FILE__).'/1.txt');
@unlink(dirname(__FILE__).'/2.txt');
@unlink(dirname(__FILE__).'/some.txt');
$entry2->extract(dirname(__FILE__));
var_dump(file_get_contents(dirname(__FILE__).'/2.txt'));
@unlink(dirname(__FILE__).'/2.txt');
$oldcwd = getcwd();
chdir(dirname(__FILE__));
var_dump($entry2);
var_dump($entry2->extract("",""));
@unlink('2.txt');
chdir($oldcwd);
echo "Done\n";
?>
--EXPECTF--
blah-blah-blah
blah-blah-blah
22222
22222
string(5) "22222"
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#3 (0) {
}
["name%sprivate%s=>
string(5) "2.txt"
["unpacked_size%sprivate%s=>
int(5)
["packed_size%sprivate%s=>
int(16)
["host_os%sprivate%s=>
int(2)
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:26"
["crc%sprivate%s=>
string(8) "45a918de"
["attr%sprivate%s=>
int(32)
["version%sprivate%s=>
int(29)
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(37008)
}
bool(true)
Done

24
tests/005.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
rar_comment_get() function
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/commented.rar');
var_export(rar_comment_get($rar_file1));
echo "\n";
var_export(rar_comment_get($rar_file1));
echo "\n";
$rar_file2 = rar_open(dirname(__FILE__).'/linux_rar.rar');
var_export(rar_comment_get($rar_file2));
echo "\n";
echo "Done\n";
?>
--EXPECTF--
'This is the comment of the file commented.rar.'
'This is the comment of the file commented.rar.'
NULL
Done

22
tests/006.phpt Normal file
View File

@@ -0,0 +1,22 @@
--TEST--
RarEntry::getCrc() method in multi-volume archives (PECL bug #9470)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
$list = rar_list($rar_file1);
echo $list[0]->getCrc()."\n";
echo $list[1]->getCrc()."\n";
echo $list[2]->getCrc()."\n";
echo "\n";
echo "Done\n";
?>
--EXPECTF--
52b28202
f2c79881
bcbce32e
Done

18
tests/007.phpt Normal file
View File

@@ -0,0 +1,18 @@
--TEST--
rar_open() function with a non-RAR
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_notrar.rar');
var_dump($rar_file1);
echo "\n";
echo "Done\n";
?>
--EXPECTF--
Warning: rar_open(): Failed to open %s: ERAR_BAD_ARCHIVE in %s on line %d
bool(false)
Done

34
tests/008.phpt Normal file
View File

@@ -0,0 +1,34 @@
--TEST--
rar_entry_get() function
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
$entry = rar_entry_get($rar_file1, "file1.txt");
echo "$entry\n";
$entry = rar_entry_get($rar_file1, "nonexistent_file.txt");
var_dump($entry);
echo "\n";
$rar_file2 = rar_open(dirname(__FILE__).'/nonexistent.rar');
$entry = rar_entry_get($rar_file2, "file1.txt");
var_dump($entry);
echo "\n";
echo "Done\n";
?>
--EXPECTF--
RarEntry for file "file1.txt" (52b28202)
Warning: rar_entry_get(): cannot find file "nonexistent_file.txt" in Rar archive "%s". in %s on line %d
bool(false)
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
Warning: rar_entry_get() expects parameter 1 to be RarArchive, boolean given in %s on line %d
NULL
Done

19
tests/009.phpt Normal file
View File

@@ -0,0 +1,19 @@
--TEST--
RarEntry::getName() function with unicode filenames
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entries = rar_list($rar_file1);
$name = reset($entries)->getName();
var_dump($name);
echo "\n";
echo "Done\n";
?>
--EXPECTF--
string(13) "file1À۞.txt"
Done

32
tests/010.phpt Normal file
View File

@@ -0,0 +1,32 @@
--TEST--
RarEntry::getStream() function (good RAR file, one volume)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
foreach ($entries as $e) {
$stream = $e->getStream();
echo $e->getName().":\n";
while (!feof($stream)) {
echo fread($stream, 8192);
}
echo "\n\n";
}
echo "Done\n";
?>
--EXPECTF--
2 files:
1.txt:
11111
2.txt:
22222
Done

38
tests/011.phpt Normal file
View File

@@ -0,0 +1,38 @@
--TEST--
RarEntry::getStream() function (good RAR file, several volumes)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
foreach ($entries as $e) {
$stream = $e->getStream();
echo $e->getName().": ";
$a = "";
while (!feof($stream)) {
$a .= fread($stream, 8192);
}
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
}
echo "Done\n";
?>
--EXPECTF--
3 files:
file1.txt: 18 bytes, CRC 52B28202
file2.txt: 17704 bytes, CRC F2C79881
file3.txt: 18 bytes, CRC BCBCE32E
Done

42
tests/012.phpt Normal file
View File

@@ -0,0 +1,42 @@
--TEST--
RarEntry::getStream() function (bad RAR file)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files (will test only the first 4):\n\n";
//var_dump($entries);
$i = 0;
foreach ($entries as $e) {
if ($i++ >= 2)
break;
//$e->extract(false, dirname(__FILE__).'/temp.txt');
//echo "now stream\n";
$stream = $e->getStream();
echo $e->getName().": ";
if ($stream === false) {
echo "Could not get stream.\n\n";
continue;
}
while (!feof($stream)) {
echo fread($stream, 8192);
}
fclose($stream);
echo "\n";
}
echo "Done\n";
?>
--EXPECTF--
51 files (will test only the first 4):
test%s: The great battle of Gunprex versus Optiter!!!!!1
Gunprex, Fire!
So long, Optiter!
test%s: it,greIater!
%s
Done

20
tests/013.phpt Normal file
View File

@@ -0,0 +1,20 @@
--TEST--
rar_entry_get() and RarEntry::getName() coherence
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entries = rar_list($rar_file1);
$name = reset($entries)->getName();
$entryback = rar_entry_get($rar_file1, $name);
echo "$entryback\n";
echo "\n";
echo "Done\n";
?>
--EXPECTF--
RarEntry for file "file1À۞.txt" (52b28202)
Done

26
tests/014.phpt Normal file
View File

@@ -0,0 +1,26 @@
--TEST--
RarEntry::getStream() on unicode entry
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entry = rar_entry_get($rar_file1, "file1À۞.txt");
echo $entry."\n";
echo "\n";
$stream = $entry->getStream();
if ($stream !== false)
while (!feof($stream)) {
echo fread($stream, 8192);
}
echo "\n";
echo "Done\n";
?>
--EXPECTF--
RarEntry for file "file1À۞.txt" (52b28202)
contents of file 1
Done

30
tests/015.phpt Normal file
View File

@@ -0,0 +1,30 @@
--TEST--
rar_close() liberates resource (PECL bug #9649)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
copy(dirname(__FILE__).'/latest_winrar.rar', dirname(__FILE__).'/temp.rar');
$rar_file1 = rar_open(dirname(__FILE__).'/temp.rar');
echo $rar_file1."\n";
$entries = rar_list($rar_file1);
$entry1 = reset($entries);
unset($entries);
echo $entry1."\n";
echo "\n";
rar_close($rar_file1);
echo $rar_file1."\n";
$entry1->extract(".");
unlink(dirname(__FILE__).'/temp.rar');
echo "Done\n";
?>
--EXPECTF--
RAR Archive "%s"
RarEntry for file "1.txt" (a0de71c0)
RAR Archive "%s" (closed)
Warning: RarEntry::extract(): The archive is already closed. in %s on line %d
Done

50
tests/016.phpt Normal file
View File

@@ -0,0 +1,50 @@
--TEST--
RarEntry::extract() method (corrupt RAR file)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files (will test only the first 4):\n\n";
//var_dump($entries);
$i = 0;
foreach ($entries as $e) {
if ($i++ >= 4)
break;
echo "Extraction of file #$i:\n";
$ret = $e->extract(false, dirname(__FILE__).'/temp.txt');
if ($ret)
echo "\tSUCCESS\n";
else
echo "\tFAILED\n";
echo "\n";
}
@unlink(dirname(__FILE__).'/temp.txt');
echo "Done\n";
?>
--EXPECTF--
51 files (will test only the first 4):
Extraction of file #1:
SUCCESS
Extraction of file #2:
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
FAILED
Extraction of file #3:
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
FAILED
Extraction of file #4:
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
FAILED
Done

22
tests/017.phpt Normal file
View File

@@ -0,0 +1,22 @@
--TEST--
RarEntry::extract() with unicode files
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entries = rar_list($rar_file1);
$e = reset($entries);
$e->extract(false, dirname(__FILE__).'/temp.txt');
echo file_get_contents(dirname(__FILE__).'/temp.txt');
echo "\n";
@unlink(dirname(__FILE__).'/temp.txt');
echo "Done\n";
?>
--EXPECTF--
contents of file 1
Done

24
tests/018.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
rar_list()/rar_entry_get() with not first volume
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part2.rar');
$entries = rar_list($rar_file1);
echo "Number of entries: " . count($entries) . "\n";
echo reset($entries)."\n";
$e = rar_entry_get($rar_file1, "file2.txt");
var_dump($e);
$e = rar_entry_get($rar_file1, "file3.txt");
echo $e."\n";
echo "Done\n";
--EXPECTF--
Number of entries: 1
RarEntry for file "file3.txt" (bcbce32e)
Warning: rar_entry_get(): cannot find file "file2.txt" in Rar archive "%s. in %s on line %d
bool(false)
RarEntry for file "file3.txt" (bcbce32e)
Done

34
tests/019.phpt Normal file
View File

@@ -0,0 +1,34 @@
--TEST--
RarEntry::getStream() function (store method)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/store_method.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
foreach ($entries as $e) {
$stream = $e->getStream();
echo $e->getName().": ";
$a = "";
while (!feof($stream)) {
$a .= fread($stream, 512);
}
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
}
echo "Done\n";
?>
--EXPECTF--
1 files:
tese.txt: 787 bytes, CRC 23B93A7A
Done

36
tests/020.phpt Normal file
View File

@@ -0,0 +1,36 @@
--TEST--
RarEntry::getStream() function (solid archive)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/solid.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
foreach ($entries as $e) {
$stream = $e->getStream();
echo $e->getName().": ";
$a = "";
while (!feof($stream)) {
$a .= fread($stream, 8192);
}
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
}
echo "Done\n";
?>
--EXPECTF--
2 files:
tese.txt: 787 bytes, CRC 23B93A7A
unrardll.txt: 19192 bytes, CRC 2ED64B6E
Done

19
tests/021.phpt Normal file
View File

@@ -0,0 +1,19 @@
--TEST--
RarEntry::isDirectory() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
$entries = rar_list($rar_file1);
foreach ($entries as $e) {
echo "{$e->getName()} is ". ($e->isDirectory()?"":"not ") . "a directory.\n";
}
echo "Done\n";
--EXPECTF--
dirwithsth%cfileindir.txt is not a directory.
dirwithsth is a directory.
emptydir is a directory.
Done

40
tests/022.phpt Normal file
View File

@@ -0,0 +1,40 @@
--TEST--
RarEntry::extract() with directory
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
$e = rar_entry_get($rar_file1, "emptydir");
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydir";
$exists = is_dir($dir);
var_dump($exists);
$extrres = $e->extract(dirname(__FILE__));
var_dump($extrres);
$exists = is_dir($dir);
var_dump($exists);
@rmdir($dir);
echo "\n\n";
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydircust";
$exists = is_dir($dir);
var_dump($exists);
$extrres = $e->extract(false, $dir);
var_dump($extrres);
$exists = is_dir($dir);
var_dump($exists);
@rmdir($dir);
echo "Done\n";
--EXPECTF--
bool(false)
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
Done

21
tests/023.phpt Normal file
View File

@@ -0,0 +1,21 @@
--TEST--
RarEntry::getStream() with directory
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
$e = rar_entry_get($rar_file1, "emptydir");
$stream = $e->getStream();
var_dump($stream);
var_dump(feof($stream));
var_dump(fread($stream, 200));
var_dump(feof($stream));
echo "Done\n";
--EXPECTF--
resource(%d) of type (stream)
bool(false)
string(0) ""
bool(true)
Done

46
tests/024.phpt Normal file
View File

@@ -0,0 +1,46 @@
--TEST--
rar_open()/RarEntry::getStream() (headers level password)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
echo "--> should fail (no password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar');
$entries = rar_list($rar_file1);
echo "\n--> should fail (wrong password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'wrongpassword');
$entries = rar_list($rar_file1);
echo "\n--> should work:\n";
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
$entries = rar_list($rar_file2);
echo "Found " . count($entries) . " files.\n";
echo "Content of first one follows:\n";
//reset($entries)->extract(false, "./temp.txt");
$stream = reset($entries)->getStream();
var_dump($stream);
if ($stream !== FALSE) {
while (!feof($stream)) {
echo fread($stream, 128);
}
}
echo "\n";
echo "Done\n";
--EXPECTF--
--> should fail (no password):
Warning: rar_list(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
--> should fail (wrong password):
Warning: rar_list(): ERAR_BAD_DATA in %s on line %d
--> should work:
Found 2 files.
Content of first one follows:
resource(%d) of type (stream)
Encrypted file 1 contents.
Done

26
tests/025.phpt Normal file
View File

@@ -0,0 +1,26 @@
--TEST--
rar_open()/RarEntry::extract() (headers level password)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
$entries = rar_list($rar_file2);
echo "Found " . count($entries) . " files.\n";
$tempfile = dirname(__FILE__).'/temp.txt';
@unlink($tempfile);
var_dump(reset($entries)->extract(false, $tempfile));
echo "Content of first one follows:\n";
echo file_get_contents($tempfile);
$stream = reset($entries)->getStream();
@unlink($tempfile);
echo "\n";
echo "Done\n";
--EXPECTF--
Found 2 files.
bool(true)
Content of first one follows:
Encrypted file 1 contents.
Done

45
tests/026.phpt Normal file
View File

@@ -0,0 +1,45 @@
--TEST--
RarEntry::getStream() (file level password)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
echo "--> should fail (no password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
$entries = rar_list($rar_file1);
var_dump(count($entries));
var_dump($entries[0]->getStream());
echo "\n";
echo "--> success (password is the same as the one given on rar_open):\n";
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar', 'samplepassword');
$entries = rar_list($rar_file2);
echo stream_get_contents($entries[0]->getStream());
echo "\n\n";
echo "--> should give incorrect data (password of 2nd file different from the one given on rar_open):\n";
echo rawurlencode(stream_get_contents($entries[1]->getStream()));
echo "\n\n";
echo "--> should give correct data (password of 2nd file is specified):\n";
echo stream_get_contents($entries[1]->getStream('samplepassword2'));
echo "\n\n";
echo "Done\n";
--EXPECTF--
--> should fail (no password):
int(2)
Warning: RarEntry::getStream(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
bool(false)
--> success (password is the same as the one given on rar_open):
Encrypted file 1 contents.
--> should give incorrect data (password of 2nd file different from the one given on rar_open):
t%09%A6%2B%0D%1B%F6%815%5E%E7%EC%C0%0BF%5EH%3A%C0%0D%815%5E%E7%EC%C0
--> should give correct data (password of 2nd file is specified):
Encrypted file 1 contents.
Done

54
tests/027.phpt Normal file
View File

@@ -0,0 +1,54 @@
--TEST--
RarEntry::getStream() with Linux directories and links
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar = rar_open(dirname(__FILE__) . "/dirlink_unix.rar");
echo "\nDirectory\n";
$e = rar_entry_get($rar, "nopermdir");
echo $e."\n";
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n"; //no read/write/execute perms
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n";
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
$stream = $e->getStream();
$cont = stream_get_contents($stream);
echo "$cont (strlen() " . strlen($cont) . ")\n";
echo "\nLink\n";
$e = rar_entry_get($rar, "link");
echo $e."\n";
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n";
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n"; //coincidence
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
$stream = $e->getStream();
$cont = stream_get_contents($stream);
echo "$cont (strlen() " . strlen($cont) . ")\n"; //varies on windows and linux
echo "Done\n";
--EXPECTF--
Directory
RarEntry for directory "nopermdir" (0)
perms: 0
win directory bit:
unix directory attr: 1
unix symlink attr:
(strlen() 0)
Link
RarEntry for file "link" (43e55b49)
perms: 777
win directory bit: 1
unix directory attr:
unix symlink attr: 1
%s
Done

14
tests/028.phpt Normal file
View File

@@ -0,0 +1,14 @@
--TEST--
RarArchive::open() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
var_dump(get_class($arch));
echo "Done\n";
--EXPECTF--
string(10) "RarArchive"
Done

21
tests/029.phpt Normal file
View File

@@ -0,0 +1,21 @@
--TEST--
RarArchive::getEntries() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
foreach ($arch->getEntries() as $e) {
echo $e . "\n";
}
echo "Done\n";
--EXPECTF--
RarEntry for file "emptydir%clink" (36ac99f1)
RarEntry for file "file" (b95e8411)
RarEntry for file "link" (43e55b49)
RarEntry for directory "emptydir" (0)
RarEntry for directory "nopermdir" (0)
RarEntry for directory "setuiddir" (0)
RarEntry for directory "stickydir" (0)
Done

14
tests/030.phpt Normal file
View File

@@ -0,0 +1,14 @@
--TEST--
RarArchive::getEntry() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_arch = RarArchive::open(dirname(__FILE__) . '/solid.rar');
$rar_entry = $rar_arch->getEntry('tese.txt');
echo $rar_entry;
echo "\n";
echo "Done\n";
--EXPECTF--
RarEntry for file "tese.txt" (23b93a7a)
Done

13
tests/031.phpt Normal file
View File

@@ -0,0 +1,13 @@
--TEST--
RarArchive::getComment() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_arch = RarArchive::open(dirname(__FILE__) . '/commented.rar');
echo $rar_arch->getComment();
echo "\n";
echo "Done\n";
--EXPECTF--
This is the comment of the file commented.rar.
Done

16
tests/032.phpt Normal file
View File

@@ -0,0 +1,16 @@
--TEST--
RarArchive traversal with multi-part archive
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rarF = RarArchive::open(dirname(__FILE__) . '/multi.part1.rar');
foreach ($rarF as $k => $rarE) {
echo "$k. $rarE\n";
}
echo "Done\n";
--EXPECTF--
0. RarEntry for file "file1.txt" (52b28202)
1. RarEntry for file "file2.txt" (f2c79881)
2. RarEntry for file "file3.txt" (bcbce32e)
Done

15
tests/033.phpt Normal file
View File

@@ -0,0 +1,15 @@
--TEST--
rar_solid_is() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$arch1 = RarArchive::open(dirname(__FILE__) . "/store_method.rar");
$arch2 = RarArchive::open(dirname(__FILE__) . "/solid.rar");
echo "$arch1: " . ($arch1->isSolid()?'yes':'no') ."\n";
echo "$arch2: " . (rar_solid_is($arch2)?'yes':'no') . "\n";
echo "Done.\n";
--EXPECTF--
RAR Archive "%sstore_method.rar": no
RAR Archive "%ssolid.rar": yes
Done.

16
tests/034.phpt Normal file
View File

@@ -0,0 +1,16 @@
--TEST--
RarException::(set/is)UsingExceptions() test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
echo "Initial state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
RarException::setUsingExceptions(true);
echo "State change done.\n";
echo "Final state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
echo "Done.\n";
--EXPECTF--
Initial state: no.
State change done.
Final state: yes.
Done.

19
tests/035.phpt Normal file
View File

@@ -0,0 +1,19 @@
--TEST--
rar_entry_get() non-existent file with exceptions
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
RarException::setUsingExceptions(true);
$arch = RarArchive::open(dirname(__FILE__) . "/latest_winrar.rar");
try {
$arch->getEntry('nonexistentfile.txt');
} catch (RarException $re) {
echo "Message: " . $re->getMessage()."\n";
echo "Code: " . $re->getCode() ."\n";
}
echo "Done.\n";
--EXPECTF--
Message: cannot find file "nonexistentfile.txt" in Rar archive "%slatest_winrar.rar".
Code: -1
Done.

18
tests/036.phpt Normal file
View File

@@ -0,0 +1,18 @@
--TEST--
rar_open() non-existent archive with exceptions
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
RarException::setUsingExceptions(true);
try {
$arch = RarArchive::open(dirname(__FILE__) . "/nonexistentarchive.rar");
} catch (RarException $re) {
echo "Message: " . $re->getMessage()."\n";
echo "Code: " . $re->getCode() ."\n";
}
echo "Done.\n";
--EXPECTF--
Message: unRAR internal error: Failed to open %snonexistentarchive.rar: ERAR_EOPEN (file open error)
Code: 15
Done.

24
tests/037.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
RarEntry::getStream(), password not given, with exceptions
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
RarException::setUsingExceptions(true);
echo "--> should fail (no password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
$entries = rar_list($rar_file1);
var_dump(count($entries));
try {
var_dump($entries[0]->getStream());
} catch (RarException $re) {
echo "Message: " . $re->getMessage()."\n";
echo "Code: " . $re->getCode() ."\n";
}
echo "Done.\n";
--EXPECTF--
--> should fail (no password):
int(2)
Message: unRAR internal error: ERAR_MISSING_PASSWORD (password needed but not specified)
Code: 22
Done.

15
tests/038.phpt Normal file
View File

@@ -0,0 +1,15 @@
--TEST--
RarArchive get iterator on closed file
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rarF = RarArchive::open(dirname(__FILE__) . '/latest_winrar.rar');
$rarF->close();
foreach ($rarF as $k => $rarE) {
echo "$k. $rarE\n";
unset($rarE);
}
echo "Done.\n";
--EXPECTF--
Fatal error: The archive is already closed, cannot give an iterator in %s on line %d

15
tests/039.phpt Normal file
View File

@@ -0,0 +1,15 @@
--TEST--
Access RAR archive with missing volumes
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rarF = RarArchive::open(dirname(__FILE__) . '/multi_broken.part1.rar');
var_dump(rar_list($rarF));
echo "Done.\n";
--EXPECTF--
Warning: rar_list(): Volume %smulti_broken.part2.rar was not found. in %s on line %d
Warning: rar_list(): ERAR_EOPEN (file open error) in %s on line %d
bool(false)
Done.

BIN
tests/commented.rar Normal file

Binary file not shown.

BIN
tests/corrupted.rar Normal file

Binary file not shown.

BIN
tests/directories.rar Normal file

Binary file not shown.

BIN
tests/dirlink_unix.rar Normal file

Binary file not shown.

BIN
tests/encrypted_headers.rar Normal file

Binary file not shown.

Binary file not shown.

BIN
tests/multi.part1.rar Normal file

Binary file not shown.

BIN
tests/multi.part2.rar Normal file

Binary file not shown.

BIN
tests/multi.part3.rar Normal file

Binary file not shown.

Binary file not shown.

9
tests/rar_notrar.rar Normal file
View File

@@ -0,0 +1,9 @@
6TGStcOyuEWU8uIuUALyOj7+iCAgQNcpGomfIg1QBpnXaiT93Ie8RbflCUO8u/1Z4hKNrieUqfoz
R8hO/foBjEosLYUxjjMMqg7JYNd//Mp8UNqcI/0Ao8tXUfAdpKzNu2N3gYV99xRG3yUOWeAXI1Gx
CaTj0uHuyzUQbskZdxInMqzajd9f9GVjpgrrz3sJNYMAT1qnFbCfXvRynv+Aby3TAiZKgnPVxuLs
VpaieK8VmL0fNzIqoPSUqyMn+9t8fd/fuJmvkXSl/et7YSsE/4hmSGf1XPLw0khH7jmnyTMxh7BF
VLjAt0bypII0tWZsQG7tHFtUb4UG2Np5Wt8ejCowkIHrBsUdZ4ALnySQmmqtakkqeFr73YPrhKGr
y7ZeQb2sCAPv/NbDMj3q6JeeiIbBNx0OS2oIf1UVbU8fzvbDdZnd579K/b0YP3B7wKK5P54fd9eg
kiapUkMAcFv7rSFBDGpszDhQFWpWJBY2OJCrAz0B+ZLymTYxiiirT4wTrTerAExTVHlHJF2r66m7
VvXnJ+f6VnqIkSSFhAiHfT1ckCyGcTHBU7wy5ODDDsvUy7dZ2/eq1OhhnPS0lpvZLUiDtAAnBMcq
axoA18HW9yccAh8BAnbQ/H7fIXqc4P3zA5CnxjAal25HE+3IVT4DCqOpT27aZvb/fJIkZDeXxwYv

BIN
tests/rar_unicode.rar Normal file

Binary file not shown.

BIN
tests/solid.rar Normal file

Binary file not shown.

BIN
tests/store_method.rar Normal file

Binary file not shown.

View File

@@ -1,41 +1,40 @@
****** ***** ****** unRAR - free utility for RAR archives
****** ***** ****** 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:
The source code of UnRAR utility is freeware. This means:
1. All copyrights to RAR and the utility unRAR are exclusively
owned by the author - Eugene Roshal.
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
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
Distribution of modified UnRAR sources in separate form or as a
part of other software is permitted, provided that it is clearly
stated in the documentation and source comments that the code may
not be used to develop a RAR (WinRAR) compatible archiver.
3. The unRAR utility may be freely distributed. No person or company
may charge a fee for the distribution of unRAR without written
permission from the copyright holder.
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".
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
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
UnRAR files from your storage devices and cease to use the
utility.
Thank you for your interest in RAR and unRAR.
Thank you for your interest in RAR and UnRAR.
Eugene Roshal
Alexander L. Roshal

View File

@@ -15,20 +15,18 @@
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
in rartypes.hpp.
It is important to provide 1 byte alignment for structures
in model.hpp. Now it contains '#pragma pack(1)' directive,
but your compiler may require something else. Though Unrar
should work with other model.hpp alignments, its memory
requirements may increase significantly. Alignment in other
modules is not important.
if computer architecture does not allow not aligned data access,
you need to undefine ALLOW_NOT_ALIGNED_INT and define
STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory
requirements.
If you use Borland C++ makefile (makefile.bcc), you need to define
BASEPATHCC environment (or makefile) variable containing
the path to Borland C++ installation.
Makefile.unix contains both Linux and IRIX compiler option sets.
Linux is selected by default. If you need to compile Unrar for IRIX,
just uncomment corresponding lines.
Makefile.unix contains numerous compiler option sets.
GCC Linux is selected by default. If you need to compile Unrar
for other platforms, uncomment corresponding lines.
2. Unrar binaries
@@ -42,13 +40,14 @@
This source includes parts of code written by the following authors:
Dmitry Shkarin PPMII text compression
Dmitry Shkarin PPMII v.H text compression
Dmitry Subbotin Carryless rangecoder
Szymon Stefanek AES encryption
Brian Gladman AES encryption
Steve Reid SHA-1 hash function
Marcus Herbert makefile.unix file
Tomasz Klim fixes for libunrar.so
Robert Riebisch makefile.dj and patches for DJGPP
4. Legal stuff

View File

@@ -1,15 +1,16 @@
bool Archive::GetComment(Array<byte> &CmtData)
bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
{
if (!MainComment)
return(false);
SaveFilePos SavePos(*this);
ushort CmtLength;
#ifndef SFX_MODULE
ushort CmtLength;
if (OldFormat)
{
Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET);
CmtLength=GetByte()+(GetByte()<<8);
CmtLength=GetByte();
CmtLength+=(GetByte()<<8);
}
else
#endif
@@ -22,7 +23,7 @@ bool Archive::GetComment(Array<byte> &CmtData)
else
{
Seek(SFXSize+SIZEOF_MARKHEAD+NewMhd.HeadSize,SEEK_SET);
return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData)!=0);
return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData,CmtDataW)!=0);
}
#ifndef SFX_MODULE
if (CommHead.HeadCRC!=HeaderCRC)
@@ -46,9 +47,14 @@ bool Archive::GetComment(Array<byte> &CmtData)
uint UnpCmtLength;
if (OldFormat)
{
UnpCmtLength=GetByte()+(GetByte()<<8);
#ifdef NOCRYPT
return(false);
#else
UnpCmtLength=GetByte();
UnpCmtLength+=(GetByte()<<8);
CmtLength-=2;
DataIO.SetCmt13Encryption();
#endif
}
else
UnpCmtLength=CommHead.UnpSize;
@@ -66,52 +72,80 @@ bool Archive::GetComment(Array<byte> &CmtData)
}
else
{
unsigned char *UnpData;
uint UnpDataSize;
byte *UnpData;
size_t UnpDataSize;
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
CmtData.Alloc(UnpDataSize);
memcpy(&CmtData[0],UnpData,UnpDataSize);
CmtData->Alloc(UnpDataSize);
memcpy(&((*CmtData)[0]),UnpData,UnpDataSize);
}
}
else
{
CmtData.Alloc(CmtLength);
CmtData->Alloc(CmtLength);
Read(&CmtData[0],CmtLength);
if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&CmtData[0],CmtLength)&0xffff))
Read(&((*CmtData)[0]),CmtLength);
if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&((*CmtData)[0]),CmtLength)&0xffff))
{
Log(FileName,St(MLogCommBrk));
Alarm();
CmtData.Reset();
CmtData->Reset();
return(false);
}
}
#endif
#if defined(_WIN_32) && !defined(_WIN_CE)
if (CmtData.Size()>0)
OemToCharBuff((char*)&CmtData[0],(char*)&CmtData[0],CmtData.Size());
if (CmtData->Size()>0)
{
size_t CmtSize=CmtData->Size();
OemToCharBuff((char *)CmtData->Addr(),(char *)CmtData->Addr(),(DWORD)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);
return(CmtData->Size()>0);
}
int Archive::ReadCommentData(Array<byte> &CmtData)
size_t Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
{
bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
if (!ReadSubData(&CmtData,NULL))
if (!ReadSubData(CmtData,NULL))
return(0);
int CmtSize=CmtData.Size();
size_t CmtSize=CmtData->Size();
if (Unicode)
{
CmtSize/=2;
Array<wchar> CmtDataW(CmtSize+1);
RawToWide(&CmtData[0],&CmtDataW[0],CmtSize);
CmtDataW[CmtSize]=0;
CmtData.Alloc(CmtSize*2);
WideToChar(&CmtDataW[0],(char *)&CmtData[0]);
CmtSize=strlen((char *)&CmtData[0]);
CmtData.Alloc(CmtSize);
Array<wchar> DataW(CmtSize+1);
RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
DataW[CmtSize]=0;
size_t 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);
}
@@ -122,9 +156,9 @@ void Archive::ViewComment()
if (Cmd->DisableComment)
return;
Array<byte> CmtBuf;
if (GetComment(CmtBuf))
if (GetComment(&CmtBuf,NULL))
{
int CmtSize=CmtBuf.Size();
size_t CmtSize=CmtBuf.Size();
char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize);
if (ChPtr!=NULL)
CmtSize=ChPtr-(char *)&CmtBuf[0];
@@ -138,47 +172,46 @@ void Archive::ViewComment()
#ifndef SFX_MODULE
void Archive::ViewFileComment()
{
if (!(NewLhd.Flags & LHD_COMMENT) || Cmd->DisableComment)
if (!(NewLhd.Flags & LHD_COMMENT) || Cmd->DisableComment || OldFormat)
return;
#ifndef GUI
mprintf(St(MFileComment));
#endif
Array<char> CmtBuf(0x8000);
const int MaxSize=0x8000;
Array<char> CmtBuf(MaxSize);
SaveFilePos SavePos(*this);
if (OldFormat)
Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
int64 SaveCurBlockPos=CurBlockPos;
int64 SaveNextBlockPos=NextBlockPos;
size_t Size=ReadHeader();
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
if (Size<7 || CommHead.HeadType!=COMM_HEAD)
return;
if (CommHead.HeadCRC!=HeaderCRC)
{
uint CmtLength=GetByte()+(GetByte()<<8);
Read(&CmtBuf[0],CmtLength);
OutComment(&CmtBuf[0],CmtLength);
#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
}
else
{
if (ReadHeader()<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)
return;
Read(&CmtBuf[0],CommHead.UnpSize);
if (CommHead.CommCRC!=CRC(0xffffffff,&CmtBuf[0],CommHead.UnpSize))
{
Log(FileName,St(MLogBrokFCmt));
}
else
{
OutComment(&CmtBuf[0],CommHead.UnpSize);
#ifndef GUI
mprintf("\n");
#endif
}
}
}
#endif

View File

@@ -47,6 +47,7 @@ Archive::Archive(RAROptions *InitCmd)
NewArchive=false;
SilentOpen=false;
}
@@ -56,7 +57,7 @@ void Archive::CheckArc(bool EnableBroken)
if (!IsArchive(EnableBroken))
{
Log(FileName,St(MBadArc),FileName);
ErrHandler.Exit(RAR_FATAL_ERROR);
ErrHandler.Exit(FATAL_ERROR);
}
}
#endif
@@ -130,12 +131,18 @@ bool Archive::IsArchive(bool EnableBroken)
}
else
{
Array<char> Buffer(0x40000);
long CurPos=int64to32(Tell());
Array<char> Buffer(MAXSFXSIZE);
long CurPos=(long)Tell();
int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
for (int I=0;I<ReadSize;I++)
if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I]))
{
if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
{
char *D=&Buffer[28-CurPos];
if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
continue;
}
SFXSize=CurPos+I;
Seek(SFXSize,SEEK_SET);
if (!OldFormat)
@@ -174,16 +181,33 @@ bool Archive::IsArchive(bool EnableBroken)
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;
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
NotFirstVolume=false;
while (ReadHeader())
while (ReadHeader()!=0)
{
int HeaderType=GetHeaderType();
if (HeaderType==NEWSUB_HEAD)
@@ -206,6 +230,12 @@ bool Archive::IsArchive(bool EnableBroken)
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
}
if (!Volume || !NotFirstVolume)
{
strcpy(FirstVolumeName,FileName);
strcpyw(FirstVolumeNameW,FileNameW);
}
return(true);
}
@@ -233,3 +263,5 @@ int Archive::GetRecoverySize(bool Required)
#endif

View File

@@ -10,13 +10,11 @@ class Archive:public File
private:
bool IsSignature(byte *D);
void UpdateLatestTime(FileHeader *CurBlock);
void Protect(int RecSectors);
void ConvertNameCase(char *Name);
void ConvertNameCase(wchar *Name);
void ConvertUnknownHeader();
bool AddArcComment(char *NameToShow);
int ReadOldHeader();
void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array<byte> &TimeData);
size_t ReadOldHeader();
void UnexpEndArcMsg();
#if !defined(SHELL_EXT) && !defined(NOCRYPT)
CryptData HeadersCrypt;
@@ -32,7 +30,7 @@ class Archive:public File
OldMainHeader OldMhd;
int RecoverySectors;
Int64 RecoveryPos;
int64 RecoveryPos;
RarTime LatestTime;
int LastReadBlock;
@@ -42,13 +40,13 @@ class Archive:public File
public:
Archive(RAROptions *InitCmd=NULL);
bool IsArchive(bool EnableBroken);
int SearchBlock(int BlockType);
int SearchSubBlock(const char *Type);
size_t SearchBlock(int BlockType);
size_t 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();
size_t ReadHeader();
void CheckArc(bool EnableBroken);
void CheckOpen(char *Name,wchar *NameW=NULL);
bool WCheckOpen(char *Name,wchar *NameW=NULL);
@@ -62,7 +60,7 @@ class Archive:public File
void WriteEndBlock(bool CloseVolume);
void CopyFileRecord(Archive &Src);
void CopyArchiveData(Archive &Src);
bool GetComment(Array<byte> &CmtData);
bool GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW);
void ViewComment();
void ViewFileComment();
void SetLatestTime(RarTime *NewTime);
@@ -71,15 +69,13 @@ class Archive:public File
bool IsArcDir();
bool IsArcLabel();
void ConvertAttributes();
int LhdSize();
int LhdExtraSize();
int GetRecoverySize(bool Required);
void VolSubtractHeaderSize(int SubSize);
void AddSubData(byte *SrcData,int DataSize,File *SrcFile,char *Name,bool AllowSplit);
void VolSubtractHeaderSize(size_t SubSize);
void AddSubData(byte *SrcData,size_t DataSize,File *SrcFile,const char *Name,bool AllowSplit);
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
int GetHeaderType() {return(CurHeaderType);};
int ReadCommentData(Array<byte> &CmtData);
void WriteCommentData(byte *Data,int DataSize,bool FileComment);
size_t ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW);
void WriteCommentData(byte *Data,size_t DataSize,bool FileComment);
RAROptions* GetRAROptions() {return(Cmd);}
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
@@ -98,8 +94,8 @@ class Archive:public File
EAHeader EAHead;
StreamHeader StreamHead;
Int64 CurBlockPos;
Int64 NextBlockPos;
int64 CurBlockPos;
int64 NextBlockPos;
bool OldFormat;
bool Solid;
@@ -110,16 +106,16 @@ class Archive:public File
bool NotFirstVolume;
bool Protected;
bool Encrypted;
unsigned int SFXSize;
size_t SFXSize;
bool BrokenFileHeader;
bool Splitting;
ushort HeaderCRC;
Int64 VolWrite;
Int64 AddingFilesSize;
uint AddingHeadersSize;
int64 VolWrite;
int64 AddingFilesSize;
size_t AddingHeadersSize;
bool NewArchive;

View File

@@ -1,8 +1,8 @@
#include "rar.hpp"
int Archive::SearchBlock(int BlockType)
size_t Archive::SearchBlock(int BlockType)
{
int Size,Count=0;
size_t Size,Count=0;
while ((Size=ReadHeader())!=0 &&
(BlockType==ENDARC_HEAD || GetHeaderType()!=ENDARC_HEAD))
{
@@ -16,10 +16,10 @@ int Archive::SearchBlock(int BlockType)
}
int Archive::SearchSubBlock(const char *Type)
size_t Archive::SearchSubBlock(const char *Type)
{
int Size;
while ((Size=ReadHeader())!=0)
size_t Size;
while ((Size=ReadHeader())!=0 && GetHeaderType()!=ENDARC_HEAD)
{
if (GetHeaderType()==NEWSUB_HEAD && SubHead.CmpName(Type))
return(Size);
@@ -29,7 +29,20 @@ int Archive::SearchSubBlock(const char *Type)
}
int Archive::ReadHeader()
void Archive::UnexpEndArcMsg()
{
int64 ArcSize=FileLength();
if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
{
#ifndef SHELL_EXT
Log(FileName,St(MLogUnexpEOF));
#endif
ErrHandler.SetErrorCode(WARNING);
}
}
size_t Archive::ReadHeader()
{
CurBlockPos=Tell();
@@ -40,7 +53,7 @@ int Archive::ReadHeader()
RawRead Raw(this);
bool Decrypt=Encrypted && CurBlockPos>=SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;
bool Decrypt=Encrypted && CurBlockPos>=(int64)SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;
if (Decrypt)
{
@@ -48,24 +61,28 @@ int Archive::ReadHeader()
return(0);
#else
if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
{
UnexpEndArcMsg();
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)
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,sizeof(Cmd->Password))==-1)
{
Close();
ErrHandler.Exit(RAR_USER_BREAK);
//ErrHandler.Exit(USER_BREAK); original
ErrHandler.Exit(NO_PASSWORD_ERROR);
}
#else
if (!GetPassword(PASSWORD_ARCHIVE,FileName,Cmd->Password,sizeof(Cmd->Password)))
{
Close();
ErrHandler.Exit(RAR_USER_BREAK);
ErrHandler.Exit(USER_BREAK);
}
#endif
HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false);
HeadersCrypt.SetCryptKeys(Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
Raw.SetCrypt(&HeadersCrypt);
#endif
}
@@ -73,14 +90,7 @@ int Archive::ReadHeader()
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(RAR_WARNING);
}
UnexpEndArcMsg();
return(0);
}
@@ -96,7 +106,7 @@ int Archive::ReadHeader()
Log(FileName,St(MLogFileHead),"???");
#endif
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
return(0);
}
@@ -116,11 +126,15 @@ int Archive::ReadHeader()
*(BaseBlock *)&NewMhd=ShortBlock;
Raw.Get(NewMhd.HighPosAV);
Raw.Get(NewMhd.PosAV);
if (NewMhd.Flags & MHD_ENCRYPTVER)
Raw.Get(NewMhd.EncryptVer);
break;
case ENDARC_HEAD:
*(BaseBlock *)&EndArcHead=ShortBlock;
if (EndArcHead.Flags & EARC_DATACRC)
Raw.Get(EndArcHead.ArcDataCRC);
if (EndArcHead.Flags & EARC_VOLNUMBER)
Raw.Get(EndArcHead.VolNumber);
break;
case FILE_HEAD:
case NEWSUB_HEAD:
@@ -142,25 +156,37 @@ int Archive::ReadHeader()
Raw.Get(hd->HighUnpSize);
}
else
{
hd->HighPackSize=hd->HighUnpSize=0;
hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize);
hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize);
if (hd->UnpSize==0xffffffff)
{
// UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
// that we do not know the unpacked file size and must unpack it
// until we find the end of file marker in compressed data.
hd->UnpSize=(uint)(INT64NDF);
hd->HighUnpSize=(uint)(INT64NDF>>32);
}
}
hd->FullPackSize=INT32TO64(hd->HighPackSize,hd->PackSize);
hd->FullUnpSize=INT32TO64(hd->HighUnpSize,hd->UnpSize);
char FileName[NM*4];
int NameSize=Min(hd->NameSize,sizeof(FileName)-1);
Raw.Get((byte *)FileName,NameSize);
FileName[NameSize]=0;
strncpy(hd->FileName,FileName,sizeof(hd->FileName));
hd->FileName[sizeof(hd->FileName)-1]=0;
strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));
if (hd->HeadType==NEWSUB_HEAD)
{
// Let's calculate the size of optional data.
int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
if (hd->Flags & LHD_SALT)
DataSize-=SALT_SIZE;
if (DataSize>0)
{
// Here we read optional additional fields for subheaders.
// They are stored after the file name and before salt.
hd->SubData.Alloc(DataSize);
Raw.Get(&hd->SubData[0],DataSize);
if (hd->CmpName(SUBHEAD_TYPE_RR))
@@ -176,10 +202,20 @@ int Archive::ReadHeader()
if (hd->Flags & LHD_UNICODE)
{
EncodeFileName NameCoder;
int Length=strlen(FileName)+1;
NameCoder.Decode(FileName,(byte *)FileName+Length,
hd->NameSize-Length,hd->FileNameW,
sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
size_t 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;
}
@@ -241,7 +277,7 @@ int Archive::ReadHeader()
if (hd->HeadType==NEWSUB_HEAD)
strcat(hd->FileName,"- ???");
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
#ifndef SHELL_EXT
Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
Alarm();
@@ -350,8 +386,10 @@ int Archive::ReadHeader()
bool Recovered=false;
if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0)
{
// Last 7 bytes of recovered volume can contain zeroes, because
// REV files store its own information (volume number, etc.) here.
SaveFilePos SavePos(*this);
Int64 Length=Tell();
int64 Length=Tell();
Seek(Length-7,SEEK_SET);
Recovered=true;
for (int J=0;J<7;J++)
@@ -366,9 +404,9 @@ int Archive::ReadHeader()
Close();
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
return(0);
// ErrHandler.Exit(RAR_CRC_ERROR);
// ErrHandler.Exit(CRC_ERROR);
}
}
}
@@ -379,7 +417,7 @@ int Archive::ReadHeader()
Log(FileName,St(MLogFileHead),"???");
#endif
BrokenFileHeader=true;
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
return(0);
}
return(Raw.Size());
@@ -387,10 +425,10 @@ int Archive::ReadHeader()
#ifndef SFX_MODULE
int Archive::ReadOldHeader()
size_t Archive::ReadOldHeader()
{
RawRead Raw(this);
if (CurBlockPos<=SFXSize)
if (CurBlockPos<=(int64)SFXSize)
{
Raw.Read(SIZEOF_OLDMHD);
Raw.Get(OldMhd.Mark,4);
@@ -424,6 +462,11 @@ int Archive::ReadOldHeader()
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;
@@ -434,7 +477,7 @@ int Archive::ReadOldHeader()
NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize;
CurHeaderType=FILE_HEAD;
}
return(Raw.Size());
return(NextBlockPos>CurBlockPos ? Raw.Size():0);
}
#endif
@@ -504,25 +547,46 @@ void Archive::ConvertAttributes()
}
#endif
#ifdef _UNIX
// umask defines which permission bits must not be set by default
// when creating a file or directory.
static mode_t mask = (mode_t) -1;
if (mask == (mode_t) -1)
{
// umask call returns the current umask value. Argument (022) is not
// important here.
mask = umask(022);
// Restore the original umask value, which was changed to 022 above.
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;
{
// Mapping MSDOS, OS/2 and Windows file attributes to Unix.
if (NewLhd.FileAttr & 0x10) // FILE_ATTRIBUTE_DIRECTORY
{
// For directories we use 0777 mask.
NewLhd.FileAttr=0777 & ~mask;
}
else
NewLhd.FileAttr=0x81b6 & ~mask;
if (NewLhd.FileAttr & 1) // FILE_ATTRIBUTE_READONLY
{
// For read only files we use 0444 mask with 'w' bits turned off.
NewLhd.FileAttr=0444 & ~mask;
}
else
{
// umask does not set +x for regular files, so we use 0666
// instead of 0777 as for directories.
NewLhd.FileAttr=0666 & ~mask;
}
}
break;
case HOST_UNIX:
case HOST_BEOS:
@@ -557,22 +621,34 @@ void Archive::ConvertUnknownHeader()
if ((byte)*s<32 || (byte)*s>127)
*s='_';
#endif
#if defined(_WIN_32) || defined(_EMX)
// ':' in file names is allowed in Unix, but not in Windows.
// Even worse, file data will be written to NTFS stream on NTFS,
// so automatic name correction on file create error in extraction
// routine does not work. In Windows and DOS versions we better
// replace ':' now.
if (*s==':')
*s='_';
#endif
}
for (wchar *s=NewLhd.FileNameW;*s!=0;s++)
{
if (*s=='/' || *s=='\\')
*s=CPATHDIVIDER;
}
int Archive::LhdSize()
{
return((NewLhd.Flags & LHD_LARGE) ? SIZEOF_NEWLHD+8:SIZEOF_NEWLHD);
}
int Archive::LhdExtraSize()
{
return(NewLhd.HeadSize-NewLhd.NameSize-LhdSize());
#if defined(_WIN_32) || defined(_EMX)
// ':' in file names is allowed in Unix, but not in Windows.
// Even worse, file data will be written to NTFS stream on NTFS,
// so automatic name correction on file create error in extraction
// routine does not work. In Windows and DOS versions we better
// replace ':' now.
if (*s==':')
*s='_';
#endif
}
}
@@ -584,10 +660,10 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
#ifndef SHELL_EXT
Log(FileName,St(MSubHeadCorrupt));
#endif
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
return(false);
}
if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>PACK_VER)
if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>/*PACK_VER*/36)
{
#ifndef SHELL_EXT
Log(FileName,St(MSubHeadUnknown));
@@ -610,13 +686,14 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
if (SubHead.Flags & LHD_PASSWORD)
if (*Cmd->Password)
SubDataIO.SetEncryption(SubHead.UnpVer,Cmd->Password,
(SubHead.Flags & LHD_SALT) ? SubHead.Salt:NULL,false);
(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.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER)!=0;
SubDataIO.SetSubHeader(&SubHead,NULL);
Unpack.SetDestSize(SubHead.UnpSize);
if (SubHead.Method==0x30)
@@ -629,7 +706,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
#ifndef SHELL_EXT
Log(FileName,St(MSubHeadDataCRC),SubHead.FileName);
#endif
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
if (UnpData!=NULL)
UnpData->Reset();
return(false);

View File

@@ -7,20 +7,21 @@ template <class T> class Array
{
private:
T *Buffer;
int BufSize;
int AllocSize;
size_t BufSize;
size_t AllocSize;
public:
Array();
Array(int Size);
Array(size_t Size);
~Array();
inline void CleanData();
inline T& operator [](int Item);
inline int Size();
void Add(int Items);
void Alloc(int Items);
inline T& operator [](size_t Item);
inline size_t Size();
void Add(size_t Items);
void Alloc(size_t Items);
void Reset();
void operator = (Array<T> &Src);
void Push(T Item);
T* Addr() {return(Buffer);}
};
template <class T> void Array<T>::CleanData()
@@ -37,7 +38,7 @@ template <class T> Array<T>::Array()
}
template <class T> Array<T>::Array(int Size)
template <class T> Array<T>::Array(size_t Size)
{
Buffer=(T *)rarmalloc(sizeof(T)*Size);
if (Buffer==NULL && Size!=0)
@@ -54,25 +55,25 @@ template <class T> Array<T>::~Array()
}
template <class T> inline T& Array<T>::operator [](int Item)
template <class T> inline T& Array<T>::operator [](size_t Item)
{
return(Buffer[Item]);
}
template <class T> inline int Array<T>::Size()
template <class T> inline size_t Array<T>::Size()
{
return(BufSize);
}
template <class T> void Array<T>::Add(int Items)
template <class T> void Array<T>::Add(size_t Items)
{
BufSize+=Items;
if (BufSize>AllocSize)
{
int Suggested=AllocSize+AllocSize/4+32;
int NewSize=Max(BufSize,Suggested);
size_t Suggested=AllocSize+AllocSize/4+32;
size_t NewSize=Max(BufSize,Suggested);
Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T));
if (Buffer==NULL)
@@ -82,7 +83,7 @@ template <class T> void Array<T>::Add(int Items)
}
template <class T> void Array<T>::Alloc(int Items)
template <class T> void Array<T>::Alloc(size_t Items)
{
if (Items>AllocSize)
Add(Items-BufSize);

View File

@@ -5,7 +5,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
if (Arc.HeaderCRC!=Arc.EAHead.HeadCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
return;
}
if (Arc.EAHead.Method<0x31 || Arc.EAHead.Method>0x35 || Arc.EAHead.UnpVer>PACK_VER)
@@ -29,14 +29,14 @@ void ExtractBeEA(Archive &Arc,char *FileName)
if (Arc.EAHead.EACRC!=~DataIO.UnpFileCRC)
{
Log(Arc.FileName,St(MEABroken),FileName);
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
return;
}
int fd = open(FileName,O_WRONLY);
if (fd==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
return;
}
@@ -51,7 +51,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
if (NameSize>=sizeof(Name))
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
break;
}
memcpy(Name,CurItem+10,NameSize);
@@ -59,7 +59,7 @@ void ExtractBeEA(Archive &Arc,char *FileName)
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
break;
}
AttrPos+=10+NameSize+Size;
@@ -79,7 +79,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
if (fd==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
return;
}
@@ -94,7 +94,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
if (NameSize>=sizeof(Name))
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
break;
}
memcpy(Name,CurItem+10,NameSize);
@@ -102,7 +102,7 @@ void ExtractBeEANew(Archive &Arc,char *FileName)
if (fs_write_attr(fd,Name,Type,0,CurItem+10+NameSize,Size)==-1)
{
Log(Arc.FileName,St(MCannotSetEA),FileName);
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
break;
}
AttrPos+=10+NameSize+Size;

View File

@@ -2,7 +2,7 @@
CommandData::CommandData()
{
FileArgs=ExclArgs=StoreArgs=ArcNames=NULL;
FileArgs=ExclArgs=InclArgs=StoreArgs=ArcNames=NULL;
Init();
}
@@ -22,10 +22,10 @@ void CommandData::Init()
*ArcNameW=0;
FileLists=false;
NoMoreSwitches=false;
TimeConverted=false;
FileArgs=new StringList;
ExclArgs=new StringList;
InclArgs=new StringList;
StoreArgs=new StringList;
ArcNames=new StringList;
}
@@ -35,37 +35,38 @@ void CommandData::Close()
{
delete FileArgs;
delete ExclArgs;
delete InclArgs;
delete StoreArgs;
delete ArcNames;
FileArgs=ExclArgs=StoreArgs=ArcNames=NULL;
FileArgs=ExclArgs=InclArgs=StoreArgs=ArcNames=NULL;
NextVolSizes.Reset();
}
#if !defined(SFX_MODULE) && !defined(_WIN_CE)
#if !defined(SFX_MODULE)
void CommandData::ParseArg(char *Arg,wchar *ArgW)
{
if (IsSwitch(*Arg) && !NoMoreSwitches)
if (Arg[1]=='-')
NoMoreSwitches=true;
else
ProcessSwitch(&Arg[1]);
ProcessSwitch(&Arg[1],(ArgW!=NULL && *ArgW!=0 ? &ArgW[1]:NULL));
else
if (*Command==0)
{
strncpy(Command,Arg,sizeof(Command));
strncpyz(Command,Arg,ASIZE(Command));
if (ArgW!=NULL)
strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0]));
if (toupper(*Command)=='S')
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);
GetConfigName(SFXName,SFXModule,true);
}
#ifndef GUI
*Command=toupper(*Command);
*Command=etoupper(*Command);
if (*Command!='I' && *Command!='S')
strupper(Command);
#endif
@@ -73,19 +74,23 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
else
if (*ArcName==0)
{
strncpy(ArcName,Arg,sizeof(ArcName));
strncpyz(ArcName,Arg,ASIZE(ArcName));
if (ArgW!=NULL)
strncpyw(ArcNameW,ArgW,sizeof(ArcNameW)/sizeof(ArcNameW[0]));
strncpyzw(ArcNameW,ArgW,ASIZE(ArcNameW));
}
else
{
int Length=strlen(Arg);
char EndChar=Arg[Length-1];
char CmdChar=toupper(*Command);
size_t Length=strlen(Arg);
char EndChar=Length==0 ? 0: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)
strcpy(ExtrPath,Arg);
{
strncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
if (ArgW!=NULL)
strncpyzw(ExtrPathW,ArgW,ASIZE(ExtrPathW));
}
else
if ((Add || CmdChar=='T') && *Arg!='@')
FileArgs->AddString(Arg);
@@ -95,8 +100,19 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
bool Found=FindFile::FastFind(Arg,NULL,&FileData);
if (!Found && *Arg=='@' && !IsWildcard(Arg))
{
ReadTextFile(Arg+1,FileArgs,false,true,true,true,true);
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,true);
}
else
if (Found && FileData.IsDir && Extract && *ExtrPath==0)
@@ -116,10 +132,10 @@ void CommandData::ParseDone()
{
if (FileArgs->ItemsCount()==0 && !FileLists)
FileArgs->AddString(MASKALL);
char CmdChar=toupper(*Command);
bool Extract=CmdChar=='X' || CmdChar=='E';
char CmdChar=etoupper(*Command);
bool Extract=CmdChar=='X' || CmdChar=='E' || CmdChar=='P';
if (Test && Extract)
Test=false;
Test=false; // Switch '-t' is senseless for 'X', 'E', 'P' commands.
BareOutput=(CmdChar=='L' || CmdChar=='V') && Command[1]=='B';
}
@@ -134,13 +150,37 @@ void CommandData::ParseEnvVar()
#endif
#if !defined(GUI) && !defined(SFX_MODULE)
// return 'false' if -cfg- is present and preprocess switches
// which must be processed before the rest of command line
#ifndef SFX_MODULE
bool CommandData::IsConfigEnabled(int argc,char *argv[])
{
bool ConfigEnabled=true;
for (int I=1;I<argc;I++)
if (IsSwitch(*argv[I]) && stricomp(&argv[I][1],"cfg-")==0)
return(false);
return(true);
if (IsSwitch(*argv[I]))
{
if (stricomp(&argv[I][1],"-")==0)
break;
if (stricomp(&argv[I][1],"cfg-")==0)
ConfigEnabled=false;
#ifndef GUI
if (strnicomp(&argv[I][1],"ilog",4)==0)
{
// ensure that correct log file name is already set
// if we need to report an error when processing the command line
ProcessSwitch(&argv[I][1]);
InitLogOptions(LogName);
}
#endif
if (strnicomp(&argv[I][1],"sc",2)==0)
{
// Process -sc before reading any file lists.
ProcessSwitch(&argv[I][1]);
}
}
return(ConfigEnabled);
}
#endif
@@ -153,8 +193,12 @@ void CommandData::ReadConfig(int argc,char *argv[])
{
char *Str;
while ((Str=List.GetString())!=NULL)
{
while (IsSpace(*Str))
Str++;
if (strnicomp(Str,"switches=",9)==0)
ProcessSwitchesString(Str+9);
}
}
}
#endif
@@ -182,16 +226,16 @@ void CommandData::ProcessSwitchesString(char *Str)
#endif
#if !defined(SFX_MODULE) && !defined(_WIN_CE)
void CommandData::ProcessSwitch(char *Switch)
#if !defined(SFX_MODULE)
void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW)
{
switch(toupper(Switch[0]))
switch(etoupper(Switch[0]))
{
case 'I':
if (strnicomp(&Switch[1],"LOG",3)==0)
{
strncpy(LogName,Switch[4] ? Switch+4:DefLogName,sizeof(LogName));
strncpyz(LogName,Switch[4] ? Switch+4:DefLogName,ASIZE(LogName));
break;
}
if (stricomp(&Switch[1],"SND")==0)
@@ -206,7 +250,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
if (strnicomp(&Switch[1],"EML",3)==0)
{
strncpy(EmailTo,Switch[4] ? Switch+4:"@",sizeof(EmailTo));
strncpyz(EmailTo,Switch[4] ? Switch+4:"@",ASIZE(EmailTo));
EmailTo[sizeof(EmailTo)-1]=0;
break;
}
@@ -215,9 +259,24 @@ void CommandData::ProcessSwitch(char *Switch)
MsgStream=MSG_NULL;
break;
}
if (stricomp(&Switch[1],"DP")==0)
if (etoupper(Switch[1])=='D')
{
DisablePercentage=true;
for (int I=2;Switch[I]!=0;I++)
switch(etoupper(Switch[I]))
{
case 'Q':
MsgStream=MSG_ERRONLY;
break;
case 'C':
DisableCopyright=true;
break;
case 'D':
DisableDone=true;
break;
case 'P':
DisablePercentage=true;
break;
}
break;
}
if (stricomp(&Switch[1],"OFF")==0)
@@ -227,7 +286,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'T':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'K':
ArcTime=ARCTIME_KEEP;
@@ -263,7 +322,7 @@ void CommandData::ProcessSwitch(char *Switch)
Mode=(EXTTIME_MODE)(Switch[3]-'0');
if (Switch[3]=='-')
Mode=EXTTIME_NONE;
switch(toupper(Switch[2]))
switch(etoupper(Switch[2]))
{
case 'M':
xmtime=Mode;
@@ -293,7 +352,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'A':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'C':
ClearArc=true;
@@ -307,9 +366,12 @@ void CommandData::ProcessSwitch(char *Switch)
else
{
GenerateArcName=true;
strncpy(GenerateMask,Switch+2,sizeof(GenerateMask));
strncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
}
break;
case 'I':
IgnoreGeneralAttr=true;
break;
case 'N': //reserved for archive name
break;
case 'O':
@@ -317,15 +379,20 @@ void CommandData::ProcessSwitch(char *Switch)
break;
case 'P':
strcpy(ArcPath,Switch+2);
if (SwitchW!=NULL && *SwitchW!=0)
strcpyw(ArcPathW,SwitchW+2);
break;
case 'S':
SyncFiles=true;
break;
default:
BadSwitch(Switch);
break;
}
break;
case 'D':
if (Switch[2]==0)
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'S':
DisableSortSolid=true;
@@ -339,7 +406,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'O':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case '+':
Overwrite=OVERWRITE_ALL;
@@ -347,6 +414,12 @@ void CommandData::ProcessSwitch(char *Switch)
case '-':
Overwrite=OVERWRITE_NONE;
break;
case 0:
Overwrite=OVERWRITE_FORCE_ASK;
break;
case 'R':
Overwrite=OVERWRITE_AUTORENAME;
break;
case 'W':
ProcessOwners=true;
break;
@@ -359,6 +432,9 @@ void CommandData::ProcessSwitch(char *Switch)
case 'S':
SaveStreams=true;
break;
case 'C':
SetCompressedAttr=true;
break;
#endif
default :
BadSwitch(Switch);
@@ -366,40 +442,61 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'R':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 0:
Recurse=RECURSE_ALWAYS;
break;
case '-':
Recurse=0;
Recurse=RECURSE_DISABLE;
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))
ReadTextFile(Switch+2,ExclArgs,false,true,true,true,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(Switch+2,Args,false,true,Charset,true,true,true);
}
else
ExclArgs->AddString(Switch+1);
Args->AddString(Switch+1);
}
break;
case 'E':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'P':
switch(Switch[2])
@@ -413,11 +510,11 @@ void CommandData::ProcessSwitch(char *Switch)
case '2':
ExclPath=EXCL_SAVEFULLPATH;
break;
case '3':
ExclPath=EXCL_ABSPATH;
break;
}
break;
case 'D':
ExclEmptyDir=true;
break;
case 'E':
ProcessEA=false;
break;
@@ -425,7 +522,13 @@ void CommandData::ProcessSwitch(char *Switch)
NoEndBlock=true;
break;
default:
ExclFileAttr=GetExclAttr(&Switch[1]);
if (Switch[1]=='+')
{
InclFileAttr=GetExclAttr(&Switch[2]);
InclAttrSet=true;
}
else
ExclFileAttr=GetExclAttr(&Switch[1]);
break;
}
break;
@@ -436,14 +539,14 @@ void CommandData::ProcessSwitch(char *Switch)
eprintf("\n");
}
else
strncpy(Password,Switch+1,sizeof(Password));
strncpyz(Password,Switch+1,ASIZE(Password));
break;
case 'H':
if (toupper(Switch[1])=='P')
if (etoupper(Switch[1])=='P')
{
EncryptHeaders=true;
if (Switch[2]!=0)
strncpy(Password,Switch+2,sizeof(Password));
strncpyz(Password,Switch+2,ASIZE(Password));
else
if (*Password==0)
{
@@ -453,10 +556,10 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'Z':
strncpy(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",sizeof(CommentFile));
strncpyz(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",ASIZE(CommentFile));
break;
case 'M':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'C':
{
@@ -470,19 +573,19 @@ void CommandData::ProcessSwitch(char *Switch)
int Param1=0,Param2=0;
FilterState State=FILTER_AUTO;
FilterType Type=FILTER_NONE;
if (isdigit(*Str))
if (IsDigit(*Str))
{
Param1=atoi(Str);
while (isdigit(*Str))
while (IsDigit(*Str))
Str++;
}
if (*Str==':' && isdigit(Str[1]))
if (*Str==':' && IsDigit(Str[1]))
{
Param2=atoi(++Str);
while (isdigit(*Str))
while (IsDigit(*Str))
Str++;
}
switch(toupper(*(Str++)))
switch(etoupper(*(Str++)))
{
case 'T': Type=FILTER_PPM; break;
case 'E': Type=FILTER_E8; break;
@@ -505,7 +608,7 @@ void CommandData::ProcessSwitch(char *Switch)
case 'D':
{
if ((WinSize=atoi(&Switch[2]))==0)
WinSize=0x10000<<(toupper(Switch[2])-'A');
WinSize=0x10000<<(etoupper(Switch[2])-'A');
else
WinSize*=1024;
if (!CheckWinSize())
@@ -539,6 +642,16 @@ void CommandData::ProcessSwitch(char *Switch)
}
}
break;
#ifdef PACK_SMP
case 'T':
Threads=atoi(Switch+2);
if (Threads>16)
BadSwitch(Switch);
else
{
}
break;
#endif
default:
Method=Switch[1]-'0';
if (Method>5 || Method<0)
@@ -547,7 +660,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'V':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
#ifdef _WIN_32
case 'D':
@@ -561,7 +674,7 @@ void CommandData::ProcessSwitch(char *Switch)
VolumePause=true;
break;
case 'E':
if (toupper(Switch[2])=='R')
if (etoupper(Switch[2])=='R')
VersionControl=atoi(Switch+3)+1;
break;
case '-':
@@ -569,16 +682,16 @@ void CommandData::ProcessSwitch(char *Switch)
break;
default:
{
Int64 NewVolSize=atoil(&Switch[1]);
int64 NewVolSize=atoil(&Switch[1]);
if (NewVolSize==0)
NewVolSize=INT64ERR;
NewVolSize=INT64NDF; // Autodetecting volume size.
else
switch (Switch[strlen(Switch)-1])
{
case 'f':
case 'F':
switch(int64to32(NewVolSize))
switch(NewVolSize)
{
case 360:
NewVolSize=362496;
@@ -632,13 +745,17 @@ void CommandData::ProcessSwitch(char *Switch)
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':
strncpy(TempPath,&Switch[1],sizeof(TempPath)-1);
strncpyz(TempPath,&Switch[1],ASIZE(TempPath));
AddEndSlash(TempPath);
break;
case 'S':
@@ -648,15 +765,15 @@ void CommandData::ProcessSwitch(char *Switch)
if (PointToName(SFXName)!=SFXName || FileExist(SFXName))
strcpy(SFXModule,SFXName);
else
GetConfigName(SFXName,SFXModule);
GetConfigName(SFXName,SFXModule,true);
}
if (isdigit(Switch[1]))
if (IsDigit(Switch[1]))
{
Solid|=SOLID_COUNT;
SolidCount=atoi(&Switch[1]);
}
else
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 0:
Solid|=SOLID_NORMAL;
@@ -673,11 +790,62 @@ void CommandData::ProcessSwitch(char *Switch)
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':
{
// Switch is already found bad, avoid reporting it several times.
bool AlreadyBad=false;
RAR_CHARSET rch=RCH_DEFAULT;
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);
AlreadyBad=true;
break;
};
if (!AlreadyBad)
if (Switch[3]==0)
CommentCharset=FilelistCharset=rch;
else
for (int I=3;Switch[I]!=0 && !AlreadyBad;I++)
switch(etoupper(Switch[I]))
{
case 'C':
CommentCharset=rch;
break;
case 'L':
FilelistCharset=rch;
break;
default:
BadSwitch(Switch);
AlreadyBad=true;
break;
}
}
break;
}
break;
case 'C':
if (Switch[2]==0)
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case '-':
DisableComment=true;
@@ -691,7 +859,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'K':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'B':
KeepBroken=true;
@@ -714,11 +882,11 @@ void CommandData::ProcessSwitch(char *Switch)
#endif
#if !defined(SFX_MODULE) && !defined(_WIN_CE)
#ifndef SFX_MODULE
void CommandData::BadSwitch(char *Switch)
{
mprintf(St(MUnknownOption),Switch);
ErrHandler.Exit(RAR_USER_ERROR);
ErrHandler.Exit(USER_ERROR);
}
#endif
@@ -726,7 +894,7 @@ void CommandData::BadSwitch(char *Switch)
#ifndef GUI
void CommandData::OutTitle()
{
if (BareOutput)
if (BareOutput || DisableCopyright)
return;
#if defined(__GNUC__) && defined(SFX_MODULE)
mprintf(St(MCopyrightS));
@@ -752,40 +920,41 @@ void CommandData::OutTitle()
#endif
inline bool CmpMSGID(MSGID i1,MSGID i2)
{
#ifdef MSGID_INT
return(i1==i2);
#else
// If MSGID is const char*, we cannot compare pointers only.
// Pointers to different instances of same strings can differ,
// so we need to compare complete strings.
return(strcmp(i1,i2)==0);
#endif
}
void CommandData::OutHelp()
{
#if !defined(GUI) && !defined(SILENT)
OutTitle();
static MSGID Help[]={
#ifdef SFX_MODULE
// Console SFX switches definition.
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,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,MCHelpSwINUL,
MCHelpSwIOFF,MCHelpSwKB,MCHelpSwOp,MCHelpSwOm,MCHelpSwOW,MCHelpSwP,
MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,
MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,
MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY
// UnRAR switches definition.
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,
MCHelpSwm,MCHelpSwAC,MCHelpSwAD,MCHelpSwAI,MCHelpSwAP,
MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,
MCHelpSwO,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,
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,MCHelpSwF,MCHelpSwHP,MCHelpSwIDP,MCHelpSwIEML,MCHelpSwIERR,
MCHelpSwILOG,MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwISND,MCHelpSwK,MCHelpSwKB,
MCHelpSwMn,MCHelpSwMC,MCHelpSwMD,MCHelpSwMS,MCHelpSwOp,MCHelpSwOm,
MCHelpSwOL,MCHelpSwOS,MCHelpSwOW,MCHelpSwP,MCHelpSwPm,MCHelpSwR,
MCHelpSwR0,MCHelpSwRI,MCHelpSwRR,MCHelpSwRV,MCHelpSwS,MCHelpSwSm,
MCHelpSwSFX,MCHelpSwSI,MCHelpSwT,MCHelpSwTA,MCHelpSwTB,MCHelpSwTK,
MCHelpSwTL,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwV,
MCHelpSwVn,MCHelpSwVD,MCHelpSwVER,MCHelpSwVN,MCHelpSwVP,MCHelpSwW,
MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY,MCHelpSwZ
// RAR switches definition.
//removed in 3.9.7
#endif
};
@@ -797,24 +966,38 @@ void CommandData::OutHelp()
continue;
#endif
#ifndef _WIN_32
if (Help[I]==MCHelpSwIEML || Help[I]==MCHelpSwVD || Help[I]==MCHelpSwAC ||
Help[I]==MCHelpSwAO || Help[I]==MCHelpSwOS || Help[I]==MCHelpSwIOFF)
static MSGID Win32Only[]={
MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
MCHelpSwEP2,MCHelpSwOC,MCHelpSwDR,MCHelpSwRI
};
bool Found=false;
for (int J=0;J<sizeof(Win32Only)/sizeof(Win32Only[0]);J++)
if (CmpMSGID(Help[I],Win32Only[J]))
{
Found=true;
break;
}
if (Found)
continue;
#endif
#if !defined(_UNIX) && !defined(_WIN_32)
if (Help[I]==MCHelpSwOW)
if (CmpMSGID(Help[I],MCHelpSwOW))
continue;
#endif
#if !defined(_WIN_32) && !defined(_EMX)
if (CmpMSGID(Help[I],MCHelpSwAC))
continue;
#endif
#ifndef SAVE_LINKS
if (Help[I]==MCHelpSwOL)
if (CmpMSGID(Help[I],MCHelpSwOL))
continue;
#endif
#if defined(_WIN_32) && !defined(_WIN_CE)
if (Help[I]==MCHelpSwRI)
#ifndef PACK_SMP
if (CmpMSGID(Help[I],MCHelpSwMT))
continue;
#endif
#if !defined(_BEOS)
if (Help[I]==MCHelpSwEE)
#ifndef _BEOS
if (CmpMSGID(Help[I],MCHelpSwEE))
{
#if defined(_EMX) && !defined(_DJGPP)
if (_osmode != OS2_MODE)
@@ -828,75 +1011,92 @@ void CommandData::OutHelp()
mprintf(St(Help[I]));
}
mprintf("\n");
ErrHandler.Exit(0);
ErrHandler.Exit(USER_ERROR);
#endif
}
bool CommandData::ExclCheck(char *CheckName,bool CheckFullPath)
bool CommandData::ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode)
{
char *Name=ConvertPath(CheckName,NULL);
char FullName[NM],*ExclName;
char FullName[NM],*CurName;
*FullName=0;
ExclArgs->Rewind();
while ((ExclName=ExclArgs->GetString())!=NULL)
Args->Rewind();
while ((CurName=Args->GetString())!=NULL)
#ifndef SFX_MODULE
if (CheckFullPath && IsFullPath(ExclName))
if (CheckFullPath && IsFullPath(CurName))
{
if (*FullName==0)
ConvertNameToFull(CheckName,FullName);
if (CmpName(ExclName,FullName,MATCH_WILDSUBPATH))
if (CmpName(CurName,FullName,MatchMode))
return(true);
}
else
#endif
if (CmpName(ConvertPath(ExclName,NULL),Name,MATCH_WILDSUBPATH))
if (CmpName(ConvertPath(CurName,NULL),Name,MatchMode))
return(true);
return(false);
}
// Return 'true' if we need to exclude the file from processing as result
// of -x switch. If CheckInclList is true, we also check the file against
// the include list created with -n switch.
bool CommandData::ExclCheck(char *CheckName,bool CheckFullPath,bool CheckInclList)
{
if (ExclCheckArgs(ExclArgs,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
return(true);
if (!CheckInclList || InclArgs->ItemsCount()==0)
return(false);
if (ExclCheckArgs(InclArgs,CheckName,false,MATCH_WILDSUBPATH))
return(false);
return(true);
}
#ifndef SFX_MODULE
// Return 'true' if we need to exclude the file from processing.
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
// Return 'true' if we need to exclude the file from processing.
bool CommandData::SizeCheck(int64 Size)
{
if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
return(true);
if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
return(true);
return(false);
}
#endif
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))
if (ExclCheck(NewLhd.FileName,false,true))
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;
@@ -908,14 +1108,17 @@ int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType
if (Unicode)
{
wchar NameW[NM],ArgW[NM],*NamePtr=NewLhd.FileNameW;
bool CorrectUnicode=true;
if (ArgNameW==NULL)
{
CharToWide(ArgName,ArgW);
if (!CharToWide(ArgName,ArgW) || *ArgW==0)
CorrectUnicode=false;
ArgNameW=ArgW;
}
if ((NewLhd.Flags & LHD_UNICODE)==0)
{
CharToWide(NewLhd.FileName,NameW);
if (!CharToWide(NewLhd.FileName,NameW) || *NameW==0)
CorrectUnicode=false;
NamePtr=NameW;
}
if (CmpName(ArgNameW,NamePtr,MatchType))
@@ -924,6 +1127,8 @@ int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType
*ExactMatch=stricompcw(ArgNameW,NamePtr)==0;
return(StringCount);
}
if (CorrectUnicode)
continue;
}
#endif
if (CmpName(ArgName,NewLhd.FileName,MatchType))
@@ -937,11 +1142,13 @@ int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType
}
#ifndef _WIN_CE
#ifndef GUI
void CommandData::ProcessCommand()
{
#ifndef SFX_MODULE
if (Command[1] && strchr("FUADPXETK",*Command)!=NULL || *ArcName==0)
const char *SingleCharCommands="FUADPXETK";
if (Command[1] && strchr(SingleCharCommands,*Command)!=NULL || *ArcName==0)
OutHelp();
#ifdef _UNIX
@@ -977,7 +1184,7 @@ void CommandData::ProcessCommand()
Extract.DoExtract(this);
}
break;
#if !defined(GUI) && !defined(SILENT)
#ifndef SILENT
case 'V':
case 'L':
ListArchive(this);
@@ -986,10 +1193,8 @@ void CommandData::ProcessCommand()
OutHelp();
#endif
}
#ifndef GUI
if (!BareOutput)
mprintf("\n");
#endif
}
#endif
@@ -1021,18 +1226,22 @@ bool CommandData::IsSwitch(int Ch)
#ifndef SFX_MODULE
uint CommandData::GetExclAttr(char *Str)
{
#ifdef _UNIX
return(strtol(Str,NULL,0));
#endif
#if defined(_WIN_32) || defined(_EMX)
uint Attr;
if (isdigit(*Str))
if (IsDigit(*Str))
return(strtol(Str,NULL,0));
else
{
uint Attr;
for (Attr=0;*Str;Str++)
switch(toupper(*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;
@@ -1048,10 +1257,10 @@ uint CommandData::GetExclAttr(char *Str)
case 'A':
Attr|=0x20;
break;
#endif
}
return(Attr);
}
#endif
}
#endif

View File

@@ -1,19 +1,19 @@
#ifndef _RAR_CMDDATA_
#define _RAR_CMDDATA_
#define DefaultStoreList "ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;zip;taz;tgz;z"
#define DefaultStoreList "7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lzh;mp3;rar;taz;tgz;z;zip"
class CommandData:public RAROptions
{
private:
void ProcessSwitchesString(char *Str);
void ProcessSwitch(char *Switch);
void ProcessSwitch(char *Switch,wchar *SwitchW=NULL);
void BadSwitch(char *Switch);
bool ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode);
uint GetExclAttr(char *Str);
bool FileLists;
bool NoMoreSwitches;
bool TimeConverted;
bool BareOutput;
public:
CommandData();
@@ -28,9 +28,11 @@ class CommandData:public RAROptions
void OutTitle();
void OutHelp();
bool IsSwitch(int Ch);
bool ExclCheck(char *CheckName,bool CheckFullPath);
bool ExclCheck(char *CheckName,bool CheckFullPath,bool CheckInclList);
bool StoreCheck(char *CheckName);
bool TimeCheck(RarTime &ft);
bool SizeCheck(int64 Size);
bool AnyFiltersActive();
int IsProcessFile(FileHeader &NewLhd,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH);
void ProcessCommand();
void AddArcName(char *Name,wchar *NameW);
@@ -47,6 +49,7 @@ class CommandData:public RAROptions
StringList *FileArgs;
StringList *ExclArgs;
StringList *InclArgs;
StringList *ArcNames;
StringList *StoreArgs;
};

View File

@@ -17,9 +17,10 @@ void RangeCoder::InitDecoder(Unpack *UnpackRead)
}
// (int) cast before "low" added only to suppress compiler warnings.
#define ARI_DEC_NORMALIZE(code,low,range,read) \
{ \
while ((low^(low+range))<TOP || range<BOT && ((range=-low&(BOT-1)),1)) \
while ((low^(low+range))<TOP || range<BOT && ((range=-(int)low&(BOT-1)),1)) \
{ \
code=(code << 8) | read->GetChar(); \
range <<= 8; \

View File

@@ -29,7 +29,7 @@ enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
enum FilterType {
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
FILTER_ITANIUM, FILTER_E8E9V2
};

View File

@@ -4,7 +4,12 @@
#include "log.cpp"
#endif
static int KbdAnsi(char *Addr,int Size);
#if !defined(GUI) && !defined(SILENT)
static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
static uint GetKey();
#endif
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
static bool Sound=false;
@@ -19,7 +24,7 @@ void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound)
#if !defined(GUI) && !defined(SILENT)
void mprintf(const char *fmt,...)
{
if (MsgStream==MSG_NULL)
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
return;
safebuf char Msg[MaxMsgSize];
va_list argptr;
@@ -56,6 +61,7 @@ void RawPrint(char *Msg,MESSAGE_TYPE MessageType)
OutFile.SetHandleType(FILE_HANDLESTD);
break;
case MSG_STDERR:
case MSG_ERRONLY:
OutFile.SetHandleType(FILE_HANDLEERR);
break;
default:
@@ -118,45 +124,25 @@ void GetPasswordText(char *Str,int MaxLength)
OemToChar(Str,Str);
SetConsoleMode(hConIn,ConInMode);
SetConsoleMode(hConOut,ConOutMode);
#elif defined(_EMX) || defined(_BEOS)
#elif defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
fgets(Str,MaxLength-1,stdin);
#else
strncpy(Str,getpass(""),MaxLength-1);
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[256];
char PromptStr[NM+256];
#if defined(_EMX) || defined(_BEOS)
strcpy(PromptStr,St(MAskPswEcho));
#else
@@ -165,7 +151,9 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
if (Type!=PASSWORD_GLOBAL)
{
strcat(PromptStr,St(MFor));
strcat(PromptStr,PointToName(FileName));
char *NameOnly=PointToName(FileName);
if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
strcat(PromptStr,NameOnly);
}
eprintf("\n%s: ",PromptStr);
GetPasswordText(Password,MaxLength);
@@ -173,19 +161,12 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
return(false);
if (Type==PASSWORD_GLOBAL)
{
strcpy(PromptStr,St(MReAskPsw));
eprintf(PromptStr);
char CmpStr[256];
GetPasswordText(CmpStr,sizeof(CmpStr));
eprintf(St(MReAskPsw));
char CmpStr[MAXPASSWORD];
GetPasswordText(CmpStr,ASIZE(CmpStr));
if (*CmpStr==0 || strcmp(Password,CmpStr)!=0)
{
strcpy(PromptStr,St(MNotMatchPsw));
/*
#ifdef _WIN_32
CharToOem(PromptStr,PromptStr);
#endif
*/
eprintf(PromptStr);
eprintf(St(MNotMatchPsw));
memset(Password,0,MaxLength);
memset(CmpStr,0,sizeof(CmpStr));
continue;
@@ -199,6 +180,29 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
#endif
#if !defined(GUI) && !defined(SILENT)
uint GetKey()
{
char Str[80];
bool EndOfFile;
#if defined(__GNUC__) || defined(sun)
EndOfFile=(fgets(Str,sizeof(Str),stdin)==NULL);
#else
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
EndOfFile=(SrcFile.Read(Str,sizeof(Str))==0);
#endif
if (EndOfFile)
{
// Looks like stdin is a null device. We can enter to infinite loop
// calling Ask(), so let's better exit.
ErrHandler.Exit(USER_BREAK);
}
return(Str[0]);
}
#endif
#if !defined(GUI) && !defined(SILENT)
int Ask(const char *AskStr)
{
@@ -209,7 +213,7 @@ int Ask(const char *AskStr)
for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
{
char *CurItem=Item[NumItems];
strncpy(CurItem,NextItem+1,sizeof(Item[0]));
strncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
char *EndItem=strchr(CurItem,'_');
if (EndItem!=NULL)
*EndItem=0;
@@ -250,18 +254,18 @@ int Ask(const char *AskStr)
#endif
int KbdAnsi(char *Addr,int Size)
int KbdAnsi(char *Addr,size_t Size)
{
int RetCode=0;
#ifndef GUI
for (int I=0;I<Size;I++)
for (size_t I=0;I<Size;I++)
if (Addr[I]==27 && Addr[I+1]=='[')
{
for (int J=I+2;J<Size;J++)
for (size_t J=I+2;J<Size;J++)
{
if (Addr[J]=='\"')
return(2);
if (!isdigit(Addr[J]) && Addr[J]!=';')
if (!IsDigit(Addr[J]) && Addr[J]!=';')
break;
}
RetCode=1;
@@ -271,16 +275,16 @@ int KbdAnsi(char *Addr,int Size)
}
void OutComment(char *Comment,int Size)
void OutComment(char *Comment,size_t Size)
{
#ifndef GUI
if (KbdAnsi(Comment,Size)==2)
return;
const int MaxOutSize=0x400;
for (int I=0;I<Size;I+=MaxOutSize)
const size_t MaxOutSize=0x400;
for (size_t I=0;I<Size;I+=MaxOutSize)
{
char Msg[MaxOutSize+1];
int CopySize=Min(MaxOutSize,Size-I);
size_t CopySize=Min(MaxOutSize,Size-I);
strncpy(Msg,Comment+I,CopySize);
Msg[CopySize]=0;
mprintf("%s",Msg);

View File

@@ -1,7 +1,9 @@
#ifndef _RAR_CONSIO_
#define _RAR_CONSIO_
enum {ALARM_SOUND,ERROR_SOUND,QUESTION_SOUND};
#if !defined(SILENT) && !defined(SFX_MODULE)
enum {SOUND_OK,SOUND_ALARM,SOUND_ERROR,SOUND_QUESTION};
#endif
enum PASSWORD_TYPE {PASSWORD_GLOBAL,PASSWORD_FILE,PASSWORD_ARCHIVE};
@@ -12,21 +14,28 @@ void mprintf(const char *fmt,...);
void eprintf(const char *fmt,...);
void Alarm();
void GetPasswordText(char *Str,int MaxLength);
unsigned int GetKey();
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength);
int Ask(const char *AskStr);
#endif
int KbdAnsi(char *Addr,int Size);
void OutComment(char *Comment,int Size);
void OutComment(char *Comment,size_t Size);
#ifdef SILENT
inline void mprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
inline void eprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
inline void mprintf(const char *fmt,int b) {}
inline void eprintf(const char *fmt,int b) {}
inline void mprintf(const char *fmt,const char *a,int b) {}
inline void eprintf(const char *fmt,const char *a,int b) {}
#ifdef __GNUC__
#define mprintf(args...)
#define eprintf(args...)
#else
#ifdef _MSC_VER
inline void mprintf(const char *fmt,...) {}
#else
inline void mprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
#endif
inline void eprintf(const char *fmt,const char *a=NULL,const char *b=NULL) {}
inline void mprintf(const char *fmt,int b) {}
inline void eprintf(const char *fmt,int b) {}
inline void mprintf(const char *fmt,const char *a,int b) {}
inline void eprintf(const char *fmt,const char *a,int b) {}
#endif
inline void Alarm() {}
inline void GetPasswordText(char *Str,int MaxLength) {}
inline unsigned int GetKey() {return(0);}

View File

@@ -14,13 +14,14 @@ void InitCRC()
}
uint CRC(uint StartCRC,void *Addr,uint Size)
uint CRC(uint StartCRC,const void *Addr,size_t Size)
{
if (CRCTab[1]==0)
InitCRC();
byte *Data=(byte *)Addr;
#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32)
while (Size>0 && ((int)Data & 7))
#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--;
@@ -42,16 +43,17 @@ uint CRC(uint StartCRC,void *Addr,uint Size)
Size-=8;
}
#endif
for (int I=0;I<Size;I++)
for (size_t I=0;I<Size;I++)
StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
return(StartCRC);
}
#ifndef SFX_MODULE
ushort OldCRC(ushort StartCRC,void *Addr,uint Size)
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
{
byte *Data=(byte *)Addr;
for (int I=0;I<Size;I++)
for (size_t I=0;I<Size;I++)
{
StartCRC=(StartCRC+Data[I])&0xffff;
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;

View File

@@ -4,7 +4,7 @@
extern uint CRCTab[256];
void InitCRC();
uint CRC(uint StartCRC,void *Addr,uint Size);
ushort OldCRC(ushort StartCRC,void *Addr,uint Size);
uint CRC(uint StartCRC,const void *Addr,size_t Size);
ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size);
#endif

View File

@@ -39,14 +39,9 @@ static byte InitSubstTable[256]={
};
#endif
CryptData::CryptData()
{
}
void CryptData::DecryptBlock(byte *Buf,int Size)
void CryptData::DecryptBlock(byte *Buf,size_t Size)
{
rin.blockDecrypt(Buf,Size,Buf);
}
@@ -190,7 +185,7 @@ void CryptData::Swap(byte *Ch1,byte *Ch2)
#endif
void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly)
void CryptData::SetCryptKeys(const char *Password,const byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash)
{
if (*Password==0)
return;
@@ -207,31 +202,32 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
Key[3]=0xA4E7F123L;
memset(Psw,0,sizeof(Psw));
#if defined(_WIN_32) && !defined(GUI)
CharToOemBuff(Password,(char*)Psw,strlen(Password));
CharToOemBuff(Password,(char*)Psw,(DWORD)strlen(Password));
#else
strncpy((char *)Psw,Password,MAXPASSWORD-1);
strncpyz((char *)Psw,Password,ASIZE(Psw));
#endif
int PswLength=strlen(Password);
size_t PswLength=strlen(Password);
memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
for (int J=0;J<256;J++)
for (int I=0;I<PswLength;I+=2)
for (size_t I=0;I<PswLength;I+=2)
{
uint N1=(byte)CRCTab[(Psw[I]-J)&0xff];
uint N2=(byte)CRCTab[(Psw[I+1]+J)&0xff];
for (int K=1;N1!=N2;N1=(N1+1)&0xff,K++)
Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xff]);
}
for (int I=0;I<PswLength;I+=16)
for (size_t I=0;I<PswLength;I+=16)
EncryptBlock20(&Psw[I]);
#endif
return;
}
bool Cached=false;
for (int I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++)
for (int I=0;I<ASIZE(Cache);I++)
if (strcmp(Cache[I].Password,Password)==0 &&
(Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0))
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&
Cache[I].HandsOffHash==HandsOffHash)
{
memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey));
memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit));
@@ -246,7 +242,7 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
PswW[MAXPASSWORD-1]=0;
byte RawPsw[2*MAXPASSWORD+SALT_SIZE];
WideToRaw(PswW,RawPsw);
int RawLength=2*strlenw(PswW);
size_t RawLength=2*strlenw(PswW);
if (Salt!=NULL)
{
memcpy(RawPsw+RawLength,Salt,SALT_SIZE);
@@ -258,22 +254,22 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
const int HashRounds=0x40000;
for (int I=0;I<HashRounds;I++)
{
hash_process( &c, RawPsw, RawLength);
hash_process( &c, RawPsw, RawLength, HandsOffHash);
byte PswNum[3];
PswNum[0]=(byte)I;
PswNum[1]=(byte)(I>>8);
PswNum[2]=(byte)(I>>16);
hash_process( &c, PswNum, 3);
hash_process( &c, PswNum, 3, HandsOffHash);
if (I%(HashRounds/16)==0)
{
hash_context tempc=c;
uint32 digest[5];
hash_final( &tempc, digest);
hash_final( &tempc, digest, HandsOffHash);
AESInit[I/(HashRounds/16)]=(byte)digest[4];
}
}
uint32 digest[5];
hash_final( &c, digest);
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));
@@ -281,6 +277,7 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
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]));
@@ -290,7 +287,7 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
#ifndef SFX_MODULE
void CryptData::SetOldKeys(char *Password)
void CryptData::SetOldKeys(const char *Password)
{
uint PswCRC=CRC(0xffffffff,Password,strlen(Password));
OldKey[0]=PswCRC&0xffff;

View File

@@ -3,6 +3,7 @@
enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
struct CryptKeyCacheItem
{
#ifndef _SFX_RTL_
@@ -22,6 +23,7 @@ struct CryptKeyCacheItem
char Password[MAXPASSWORD];
bool SaltPresent;
byte Salt[SALT_SIZE];
bool HandsOffHash;
};
class CryptData
@@ -32,7 +34,7 @@ class CryptData
void Crypt15(byte *Data,uint Count);
void UpdKeys(byte *Buf);
void Swap(byte *Ch1,byte *Ch2);
void SetOldKeys(char *Password);
void SetOldKeys(const char *Password);
Rijndael rin;
@@ -46,14 +48,13 @@ class CryptData
static CryptKeyCacheItem Cache[4];
static int CachePos;
public:
CryptData();
void SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly=false);
void SetCryptKeys(const char *Password,const 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 EncryptBlock(byte *Buf,size_t Size);
void DecryptBlock(byte *Buf,size_t Size);
void Crypt(byte *Data,uint Count,int Method);
static void SetSalt(byte *Salt,int SaltSize);
};

View File

@@ -37,6 +37,7 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
{
r->OpenResult=0;
DataSet *Data=new DataSet;
Data->Cmd.DllError=0;
Data->OpenMode=r->OpenMode;
Data->Cmd.FileArgs->AddString("*");
@@ -52,24 +53,24 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
Data->Cmd.VersionControl=1;
if (!Data->Arc.Open(r->ArcName,r->ArcNameW))
{
delete Data;
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;
r->OpenResult=ERAR_BAD_ARCHIVE;
return(NULL);
}
r->Flags=Data->Arc.NewMhd.Flags;
Array<byte> CmtData;
if (r->CmtBufSize!=0 && Data->Arc.GetComment(CmtData))
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
{
r->Flags|=2;
int Size=CmtData.Size()+1;
size_t Size=CmtData.Size()+1;
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
r->CmtSize=Min(Size,r->CmtBufSize);
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
if (Size<=r->CmtBufSize)
r->CmtBuf[r->CmtSize-1]=0;
@@ -103,12 +104,13 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
DataSet *Data=(DataSet *)hArcData;
try
{
if ((Data->HeaderSize=Data->Arc.SearchBlock(FILE_HEAD))<=0)
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
{
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Extract.SignatureFound=false;
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return(RARReadHeader(hArcData,D));
}
@@ -118,11 +120,14 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
}
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
{
if (RARProcessFile(hArcData,RAR_SKIP,NULL,NULL)==0)
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
if (Code==0)
return(RARReadHeader(hArcData,D));
else
return(Code);
}
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(D->FileName));
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;
@@ -148,12 +153,13 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
DataSet *Data=(DataSet *)hArcData;
try
{
if ((Data->HeaderSize=Data->Arc.SearchBlock(FILE_HEAD))<=0)
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
{
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Extract.SignatureFound=false;
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return(RARReadHeaderEx(hArcData,D));
}
@@ -163,26 +169,35 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
}
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
{
if (RARProcessFile(hArcData,RAR_SKIP,NULL,NULL)==0)
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
if (Code==0)
return(RARReadHeaderEx(hArcData,D));
else
return(Code);
}
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
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);
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(D->FileName));
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
{
bool result;
#ifdef _WIN_32
char AnsiName[NM];
OemToChar(Data->Arc.NewLhd.FileName,AnsiName);
CharToWide(AnsiName,D->FileNameW);
//The way to handle CharToWide failed calls differs to the method
//unrar 3.9.7 introduced. 3.9.7 only returns an empty string, while I
//call UtfToWide, which merely discarts invalid characters
result = CharToWide(AnsiName,D->FileNameW);
#else
CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW);
result = CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW);
#endif
if (!result)
UtfToWide(Data->Arc.NewLhd.FileName, D->FileNameW, NM);
}
D->Flags=Data->Arc.NewLhd.Flags;
D->PackSize=Data->Arc.NewLhd.PackSize;
@@ -206,19 +221,38 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
}
int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
int PASCAL ProcessFile(HANDLE hArcData, int Operation, char *DestPath,
char *DestName, wchar *DestPathW, wchar *DestNameW,
void *Buffer, size_t BufferSize, size_t *ReadSize,
bool InitDataIO, int *finished)
{
DataSet *Data=(DataSet *)hArcData;
/* if not extracting chunks, we want to init IO all the time
* (that was the behaviour before adding RAR_EXTRACT_CHUNK, which thus
* remains unaltered) */
if (Operation != RAR_EXTRACT_CHUNK)
InitDataIO = TRUE;
/* we must set these here because the function may return before executing the
* code that updates the variables. */
if (ReadSize != NULL)
*ReadSize = 0;
if (finished != NULL)
*finished = TRUE;
try
{
Data->Cmd.DllError=0;
if (Data->OpenMode==RAR_OM_LIST || Operation==RAR_SKIP && !Data->Arc.Solid)
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
Operation==RAR_SKIP && !Data->Arc.Solid)
{
if (/*Data->OpenMode==RAR_OM_LIST && */Data->Arc.Volume &&
if (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);
}
@@ -255,6 +289,9 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
strncpyw(Data->Cmd.ExtrPathW,NullToEmpty(DestPathW),NM-2);
AddEndSlash(Data->Cmd.ExtrPathW);
strncpyw(Data->Cmd.DllDestNameW,NullToEmpty(DestNameW),NM-1);
if (*Data->Cmd.DllDestNameW!=0 && *Data->Cmd.DllDestName==0)
WideToChar(Data->Cmd.DllDestNameW,Data->Cmd.DllDestName);
}
else
{
@@ -264,15 +301,51 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
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)
if (Operation == RAR_EXTRACT_CHUNK)
{
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
Data->Arc.SeekToNext();
//disabled completion percentage calculation/printing?
Data->Cmd.DisablePercentage = true;
//doesn't seem to be read except for inactive preproc. blocks anyway:
Data->Cmd.DisableDone = true;
Data->Extract.Buffer = Buffer;
Data->Extract.BufferSize = BufferSize;
}
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
bool Repeat=false;
if (Operation != RAR_EXTRACT_CHUNK)
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,
Data->HeaderSize,Repeat);
else
{
if (InitDataIO) //chunk, init
{
bool res;
res = Data->Extract.ExtractCurrentFileChunkInit(&Data->Cmd, Data->Arc,
Data->HeaderSize, Repeat);
if (!res && Data->Cmd.DllError == 0)
Data->Cmd.DllError = ERAR_UNKNOWN;
return Data->Cmd.DllError;
}
else //chunk, no init
//returns always true
//changes *ReadSize and *finished
Data->Extract.ExtractCurrentFileChunk(&Data->Cmd, Data->Arc,
ReadSize, finished);
}
/* if extracting by chunks, do move to next block, not even if we've read
* the whole file. The only purpose of this code seems to be applying
* permissions and other metadata to files, so we're not interested if
* extracting chunks */
if (Operation != RAR_EXTRACT_CHUNK) {
while (Data->Arc.ReadHeader()!=0 && Data->Arc.GetHeaderType()==NEWSUB_HEAD)
{
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
Data->Arc.SeekToNext();
}
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
}
}
}
catch (int ErrCode)
@@ -285,15 +358,32 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
{
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL));
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL,NULL,0,
NULL,false,NULL));
}
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
{
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName));
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName,NULL,0,
NULL,false,NULL));
}
int PASCAL RARProcessFileChunkInit(HANDLE hArcData)
{
return ProcessFile(hArcData, RAR_EXTRACT_CHUNK, NULL, NULL, NULL, NULL,
NULL, 0, NULL, true, NULL);
}
int PASCAL RARProcessFileChunk(HANDLE hArcData,
void *Buffer,
size_t BufferSize,
size_t *ReadSize,
int *finished)
{
return ProcessFile(hArcData, RAR_EXTRACT_CHUNK, NULL, NULL, NULL, NULL,
Buffer, BufferSize, ReadSize, false, finished);
}
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
{
@@ -302,7 +392,7 @@ void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
}
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData)
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
{
DataSet *Data=(DataSet *)hArcData;
Data->Cmd.Callback=Callback;
@@ -316,12 +406,13 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro
Data->Cmd.ProcessDataProc=ProcessDataProc;
}
#ifndef NOCRYPT
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
{
DataSet *Data=(DataSet *)hArcData;
strncpy(Data->Cmd.Password,Password,sizeof(Data->Cmd.Password));
strncpyz(Data->Cmd.Password,Password,ASIZE(Data->Cmd.Password));
}
#endif
int PASCAL RARGetDllVersion()
@@ -334,19 +425,21 @@ static int RarErrorToDll(int ErrCode)
{
switch(ErrCode)
{
case RAR_FATAL_ERROR:
case FATAL_ERROR:
return(ERAR_EREAD);
case RAR_CRC_ERROR:
case CRC_ERROR:
return(ERAR_BAD_DATA);
case RAR_WRITE_ERROR:
case WRITE_ERROR:
return(ERAR_EWRITE);
case RAR_OPEN_ERROR:
case OPEN_ERROR:
return(ERAR_EOPEN);
case RAR_CREATE_ERROR:
case CREATE_ERROR:
return(ERAR_ECREATE);
case RAR_MEMORY_ERROR:
case MEMORY_ERROR:
return(ERAR_NO_MEMORY);
case RAR_SUCCESS:
case NO_PASSWORD_ERROR: //not in original
return(ERAR_MISSING_PASSWORD);
case SUCCESS:
return(0);
default:
return(ERAR_UNKNOWN);

View File

@@ -1,12 +0,0 @@
EXPORTS
RAROpenArchive
RAROpenArchiveEx
RARCloseArchive
RARReadHeader
RARReadHeaderEx
RARProcessFile
RARSetCallback
RARSetChangeVolProc
RARSetProcessDataProc
RARSetPassword
RARGetDllVersion

View File

@@ -1,36 +1,44 @@
#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_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_OM_LIST 0
#define RAR_OM_EXTRACT 1
#define RAR_OM_LIST_INCSPLIT 2
#define RAR_SKIP 0
#define RAR_TEST 1
#define RAR_EXTRACT 2
#define RAR_EXTRACT_CHUNK 3
#define RAR_VOL_ASK 0
#define RAR_VOL_NOTIFY 1
#define RAR_DLL_VERSION 4
//Must be the same as MAXWINSIZE
//not in original
#define RAR_CHUNK_BUFFER_SIZE 0x400000
#ifdef _UNIX
#define CALLBACK
#define PASCAL
#define LONG long
#define HANDLE void *
#define LPARAM long
#define UINT unsigned int
#endif
@@ -108,7 +116,7 @@ enum UNRARCALLBACK_MESSAGES {
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD
};
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LONG UserData,LONG P1,LONG P2);
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
@@ -124,7 +132,9 @@ 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);
int PASCAL RARProcessFileChunkInit(HANDLE hArcData);
int PASCAL RARProcessFileChunk(HANDLE hArcData, void *Buffer, size_t BufferSize, size_t *ReadSize, int *finished);
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
void PASCAL RARSetPassword(HANDLE hArcData,char *Password);

View File

@@ -11,10 +11,10 @@ EncodeFileName::EncodeFileName()
void EncodeFileName::Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,
int MaxDecSize)
void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,
size_t MaxDecSize)
{
int EncPos=0,DecPos=0;
size_t EncPos=0,DecPos=0;
byte HighByte=EncName[EncPos++];
while (EncPos<EncSize && DecPos<MaxDecSize)
{

View File

@@ -8,13 +8,13 @@ class EncodeFileName
byte *EncName;
byte Flags;
int FlagBits;
int FlagsPos;
int DestSize;
uint FlagBits;
size_t FlagsPos;
size_t DestSize;
public:
EncodeFileName();
int Encode(char *Name,wchar *NameW,byte *EncName);
void Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,int MaxDecSize);
size_t Encode(char *Name,wchar *NameW,byte *EncName);
void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize);
};
#endif

View File

@@ -11,7 +11,7 @@ ErrorHandler::ErrorHandler()
void ErrorHandler::Clean()
{
ExitCode=RAR_SUCCESS;
ExitCode=SUCCESS;
ErrCount=0;
EnableBreak=true;
Silent=false;
@@ -22,7 +22,7 @@ void ErrorHandler::Clean()
void ErrorHandler::MemoryError()
{
MemoryErrorMsg();
Throw(RAR_MEMORY_ERROR);
Throw(MEMORY_ERROR);
}
@@ -30,7 +30,7 @@ void ErrorHandler::OpenError(const char *FileName)
{
#ifndef SILENT
OpenErrorMsg(FileName);
Throw(RAR_OPEN_ERROR);
Throw(OPEN_ERROR);
#endif
}
@@ -45,7 +45,7 @@ void ErrorHandler::CloseError(const char *FileName)
}
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RAR_FATAL_ERROR);
Throw(FATAL_ERROR);
#endif
}
@@ -56,7 +56,7 @@ void ErrorHandler::ReadError(const char *FileName)
ReadErrorMsg(NULL,FileName);
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RAR_FATAL_ERROR);
Throw(FATAL_ERROR);
#endif
}
@@ -66,6 +66,7 @@ bool ErrorHandler::AskRepeatRead(const char *FileName)
#if !defined(SILENT) && !defined(SFX_MODULE) && !defined(_WIN_CE)
if (!Silent)
{
SysErrMsg();
mprintf("\n");
Log(NULL,St(MErrRead),FileName);
return(Ask(St(MRetryAbort))==1);
@@ -81,7 +82,7 @@ void ErrorHandler::WriteError(const char *ArcName,const char *FileName)
WriteErrorMsg(ArcName,FileName);
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RAR_WRITE_ERROR);
Throw(WRITE_ERROR);
#endif
}
@@ -94,19 +95,20 @@ void ErrorHandler::WriteErrorFAT(const char *FileName)
ErrMsg(NULL,St(MNTFSRequired),FileName);
#endif
#if !defined(SILENT) && !defined(SFX_MODULE) || defined(RARDLL)
Throw(RAR_WRITE_ERROR);
Throw(WRITE_ERROR);
#endif
}
#endif
bool ErrorHandler::AskRepeatWrite(const char *FileName)
bool ErrorHandler::AskRepeatWrite(const char *FileName,bool DiskFull)
{
#if !defined(SILENT) && !defined(_WIN_CE)
if (!Silent)
{
SysErrMsg();
mprintf("\n");
Log(NULL,St(MErrWrite),FileName);
Log(NULL,St(DiskFull ? MNotEnoughDisk:MErrWrite),FileName);
return(Ask(St(MRetryAbort))==1);
}
#endif
@@ -124,7 +126,16 @@ void ErrorHandler::SeekError(const char *FileName)
}
#endif
#if !defined(SILENT) || defined(RARDLL)
Throw(RAR_FATAL_ERROR);
Throw(FATAL_ERROR);
#endif
}
void ErrorHandler::GeneralErrMsg(const char *Msg)
{
#ifndef SILENT
Log(NULL,"%s",Msg);
SysErrMsg();
#endif
}
@@ -164,19 +175,19 @@ void ErrorHandler::CreateErrorMsg(const char *ArcName,const char *FileName)
#ifndef SILENT
Log(ArcName && *ArcName ? ArcName:NULL,St(MCannotCreate),FileName);
Alarm();
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAXPATH)
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && defined(MAX_PATH)
if (GetLastError()==ERROR_PATH_NOT_FOUND)
{
int NameLength=strlen(FileName);
size_t NameLength=strlen(FileName);
if (!IsFullPath(FileName))
{
char CurDir[NM];
GetCurrentDirectory(sizeof(CurDir),CurDir);
NameLength+=strlen(CurDir)+1;
}
if (NameLength>MAXPATH)
if (NameLength>MAX_PATH)
{
Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAXPATH);
Log(ArcName && *ArcName ? ArcName:NULL,St(MMaxPathLimit),MAX_PATH);
}
}
#endif
@@ -238,14 +249,14 @@ void ErrorHandler::SetErrorCode(int Code)
{
switch(Code)
{
case RAR_WARNING:
case RAR_USER_BREAK:
if (ExitCode==RAR_SUCCESS)
case WARNING:
case USER_BREAK:
if (ExitCode==SUCCESS)
ExitCode=Code;
break;
case RAR_FATAL_ERROR:
if (ExitCode==RAR_SUCCESS || ExitCode==RAR_WARNING)
ExitCode=RAR_FATAL_ERROR;
case FATAL_ERROR:
if (ExitCode==SUCCESS || ExitCode==WARNING)
ExitCode=FATAL_ERROR;
break;
default:
ExitCode=Code;
@@ -280,8 +291,9 @@ void _stdfunction ProcessSignal(int SigType)
#if defined(USE_RC) && !defined(SFX_MODULE) && !defined(_WIN_CE)
ExtRes.UnloadDLL();
#endif
exit(RAR_USER_BREAK);
#ifdef _WIN_32
exit(USER_BREAK);
#if defined(_WIN_32) && !defined(_MSC_VER)
// never reached, just to avoid a compiler warning
return(TRUE);
#endif
}
@@ -305,7 +317,7 @@ void ErrorHandler::SetSignalHandlers(bool Enable)
void ErrorHandler::Throw(int Code)
{
if (Code==RAR_USER_BREAK && !EnableBreak)
if (Code==USER_BREAK && !EnableBreak)
return;
ErrHandler.SetErrorCode(Code);
#ifdef ALLOW_EXCEPTIONS
@@ -319,7 +331,8 @@ void ErrorHandler::Throw(int Code)
void ErrorHandler::SysErrMsg()
{
#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SILENT)
#if !defined(SFX_MODULE) && !defined(SILENT)
#ifdef _WIN_32
#define STRCHR strchr
#define ERRCHAR char
ERRCHAR *lpMsgBuf=NULL;
@@ -349,4 +362,16 @@ void ErrorHandler::SysErrMsg()
}
LocalFree( lpMsgBuf );
#endif
#if defined(_UNIX) || defined(_EMX)
char *err=strerror(errno);
if (err!=NULL)
Log(NULL,"\n%s",err);
#endif
#endif
}

View File

@@ -12,11 +12,13 @@
#define rarrealloc realloc
#define rarfree free
#define rarstrdup strdup
#define rarstrdupw strdupw
enum { RAR_SUCCESS,RAR_WARNING,RAR_FATAL_ERROR,RAR_CRC_ERROR,RAR_LOCK_ERROR,RAR_WRITE_ERROR,
RAR_OPEN_ERROR,RAR_USER_ERROR,RAR_MEMORY_ERROR,RAR_CREATE_ERROR,RAR_USER_BREAK=255};
//NO_PASSWORD_ERROR not in original. Maps to ERAR_MISSING_PASSWORD DLL error
enum { SUCCESS,WARNING,FATAL_ERROR,CRC_ERROR,LOCK_ERROR,WRITE_ERROR,
OPEN_ERROR,USER_ERROR,MEMORY_ERROR,CREATE_ERROR,NO_PASSWORD_ERROR,
USER_BREAK=255};
class ErrorHandler
{
@@ -38,8 +40,9 @@ class ErrorHandler
bool AskRepeatRead(const char *FileName);
void WriteError(const char *ArcName,const char *FileName);
void WriteErrorFAT(const char *FileName);
bool AskRepeatWrite(const char *FileName);
bool AskRepeatWrite(const char *FileName,bool DiskFull);
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);

View File

@@ -4,6 +4,9 @@ CmdExtract::CmdExtract()
{
TotalFileCount=0;
*Password=0;
//next two lines added by me
Buffer = NULL;
BufferSize = 0;
Unp=new Unpack(&DataIO);
Unp->Init(NULL);
}
@@ -18,35 +21,53 @@ CmdExtract::~CmdExtract()
void CmdExtract::DoExtract(CommandData *Cmd)
{
PasswordCancelled=false;
DataIO.SetCurrentCommand(*Cmd->Command);
struct FindData FD;
while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
if (FindFile::FastFind(ArcName,ArcNameW,&FD))
DataIO.TotalArcSize+=FD.Size;
Cmd->ArcNames->Rewind();
while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
{
while (ExtractArchive(Cmd)==EXTRACT_ARC_REPEAT)
;
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')
{
mprintf(St(MExtrNoFiles));
ErrHandler.SetErrorCode(RAR_WARNING);
if (!PasswordCancelled)
{
mprintf(St(MExtrNoFiles));
}
ErrHandler.SetErrorCode(WARNING);
}
#ifndef GUI
else
if (*Cmd->Command=='I')
mprintf(St(MDone));
else
if (ErrHandler.GetErrorCount()==0)
mprintf(St(MExtrAllOk));
if (!Cmd->DisableDone)
if (*Cmd->Command=='I')
mprintf(St(MDone));
else
mprintf(St(MExtrTotalErr),ErrHandler.GetErrorCount());
if (ErrHandler.GetErrorCount()==0)
mprintf(St(MExtrAllOk));
else
mprintf(St(MExtrTotalErr),ErrHandler.GetErrorCount());
#endif
}
@@ -71,6 +92,8 @@ void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc)
SignatureFound=false;
AllMatchesExact=true;
ReconstructDone=false;
StartTime.SetCurrentTime();
}
@@ -79,7 +102,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
Archive Arc(Cmd);
if (!Arc.WOpen(ArcName,ArcNameW))
{
ErrHandler.SetErrorCode(RAR_OPEN_ERROR);
ErrHandler.SetErrorCode(OPEN_ERROR);
return(EXTRACT_ARC_NEXT);
}
@@ -89,10 +112,11 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
mprintf(St(MNotRAR),ArcName);
#endif
if (CmpExt(ArcName,"rar"))
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
return(EXTRACT_ARC_NEXT);
}
// archive with corrupt encrypted header can be closed in IsArchive() call
if (!Arc.IsOpened())
return(EXTRACT_ARC_NEXT);
@@ -100,13 +124,45 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
if (Arc.Volume && Arc.NotFirstVolume)
{
char FirstVolName[NM];
VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING));
// If several volume names from same volume set are specified
// and current volume is not first in set and first volume is present
// and specified too, let's skip the current volume.
if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
Cmd->ArcNames->Search(FirstVolName,NULL,false))
return(EXTRACT_ARC_NEXT);
}
#endif
int64 VolumeSetSize=0; // Total size of volumes after the current volume.
if (Arc.Volume)
{
// Calculate the total size of all accessible volumes.
// This size is necessary to display the correct total progress indicator.
char NextName[NM];
wchar NextNameW[NM];
strcpy(NextName,Arc.FileName);
strcpyw(NextNameW,Arc.FileNameW);
while (true)
{
// First volume is already added to DataIO.TotalArcSize
// in initial TotalArcSize calculation in DoExtract.
// So we skip it and start from second volume.
NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
struct FindData FD;
if (FindFile::FastFind(NextName,NextNameW,&FD))
VolumeSetSize+=FD.Size;
else
break;
}
DataIO.TotalArcSize+=VolumeSetSize;
}
ExtractArchiveInit(Cmd,Arc);
if (*Cmd->Command=='T' || *Cmd->Command=='I')
@@ -124,34 +180,49 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
Arc.ViewComment();
// RAR can close a corrupt encrypted archive
if (!Arc.IsOpened())
return(EXTRACT_ARC_NEXT);
while (1)
{
int Size=Arc.ReadHeader();
size_t Size=Arc.ReadHeader();
bool Repeat=false;
if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
if (Repeat)
{
// If we started extraction from not first volume and need to
// restart it from first, we must correct DataIO.TotalArcSize
// for correct total progress display. We subtract the size
// of current volume and all volumes after it and add the size
// of new (first) volume.
struct FindData OldArc,NewArc;
if (FindFile::FastFind(Arc.FileName,Arc.FileNameW,&OldArc) &&
FindFile::FastFind(ArcName,ArcNameW,&NewArc))
DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
return(EXTRACT_ARC_REPEAT);
}
else
break;
}
return(EXTRACT_ARC_NEXT);
}
bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,bool &Repeat)
bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,bool &Repeat)
{
char Command=*Cmd->Command;
if (HeaderSize<=0)
if (HeaderSize==0)
if (DataIO.UnpVolume)
{
#ifdef NOVOLUME
return(false);
#else
if (!MergeArchive(Arc,NULL,false,Command))
if (!MergeArchive(Arc,&DataIO,false,Command))
{
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
return(false);
}
SignatureFound=false;
@@ -181,9 +252,9 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)
{
#ifndef NOVOLUME
if (!MergeArchive(Arc,NULL,false,Command))
if (!MergeArchive(Arc,&DataIO,false,Command))
{
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
return(false);
}
SignatureFound=false;
@@ -210,8 +281,10 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
wchar ArcFileNameW[NM];
*ArcFileNameW=0;
int MatchType=MATCH_WILDSUBPATH;
bool EqualNames=false;
int MatchNumber=Cmd->IsProcessFile(Arc.NewLhd,&EqualNames);
int MatchNumber=Cmd->IsProcessFile(Arc.NewLhd,&EqualNames,MatchType);
bool ExactMatch=MatchNumber!=0;
#if !defined(SFX_MODULE) && !defined(_WIN_CE)
if (Cmd->ExclPath==EXCL_BASEPATH)
@@ -229,7 +302,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
AllMatchesExact=false;
#ifdef UNICODE_SUPPORTED
bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE);
bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
#else
bool WideName=false;
#endif
@@ -249,8 +322,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
{
ConvertPath(Arc.NewLhd.FileNameW,ArcFileNameW);
char Name[NM];
WideToChar(ArcFileNameW,Name);
if (IsNameUsable(Name))
if (WideToChar(ArcFileNameW,Name) && IsNameUsable(Name))
strcpy(ArcFileName,Name);
}
#endif
@@ -283,9 +355,18 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
{
char CurVolName[NM];
/* Added the line below. The library was crashing without it, because
* ArcName wouldn't be initialized. this code path is executed when
* you open a volume, ask to unpack a file and that file doesn't start
* in the opened volume. This function now changes this->ArcName into
* the name of the first volume, sets the parameter Repeat to true and
* returns false.
* Possibly ArcName was supposed to be set from another method before.
* Would need further investigation. */
strncpy(ArcName, Arc.FileName, NM);
strcpy(CurVolName,ArcName);
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING));
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
{
*ArcNameW=0;
@@ -308,7 +389,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
strcpy(ArcName,CurVolName);
}
#endif
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER);
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0;
DataIO.NextVolumeMissing=false;
Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
@@ -326,6 +407,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#ifdef RARDLL
Cmd->DllError=ERAR_BAD_DATA;
#endif
ErrHandler.SetErrorCode(OPEN_ERROR);
}
ExactMatch=false;
}
@@ -335,21 +417,27 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
{
if (Arc.NewLhd.Flags & LHD_PASSWORD)
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);
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,sizeof(Cmd->Password))==-1)
{
Cmd->DllError = ERAR_MISSING_PASSWORD; //added by me
return false;
}
}
strcpy(Password,Cmd->Password);
#else
if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password)))
{
PasswordCancelled=true;
return(false);
}
#endif
@@ -362,7 +450,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll)))
{
case -1:
ErrHandler.Exit(RAR_USER_BREAK);
ErrHandler.Exit(USER_BREAK);
case 2:
if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password)))
{
@@ -387,7 +475,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#ifndef SFX_MODULE
if (Cmd->AppendArcNameToPath)
{
strcat(DestFileName,PointToName(Arc.FileName));
strcat(DestFileName,PointToName(Arc.FirstVolumeName));
SetExt(DestFileName,NULL);
AddEndSlash(DestFileName);
}
@@ -395,21 +483,37 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
char *ExtrName=ArcFileName;
bool EmptyName=false;
#ifndef SFX_MODULE
int Length=strlen(Cmd->ArcPath);
size_t 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)
{
@@ -430,10 +534,10 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if (Cmd->AppendArcNameToPath)
{
wchar FileNameW[NM];
if (*Arc.FileNameW!=0)
strcpyw(FileNameW,Arc.FileNameW);
if (*Arc.FirstVolumeNameW!=0)
strcpyw(FileNameW,Arc.FirstVolumeNameW);
else
CharToWide(Arc.FileName,FileNameW);
CharToWide(Arc.FirstVolumeName,FileNameW);
strcatw(DestFileNameW,PointToName(FileNameW));
SetExt(DestFileNameW,NULL);
AddEndSlash(DestFileNameW);
@@ -444,7 +548,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if (Length>0)
{
wchar ArcPathW[NM];
CharToWide(Cmd->ArcPath,ArcPathW);
GetWideName(Cmd->ArcPath,Cmd->ArcPathW,ArcPathW);
Length=strlenw(ArcPathW);
}
ExtrNameW+=Length;
@@ -452,39 +556,65 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
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/* && *ExtrName*/;
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;
{
// If directory already exists and its modification time is newer
// than start of extraction, it is likely it was created
// when creating a path to one of already extracted items.
// In such case we'll better update its time even if archived
// directory is older.
if (!FD.IsDir || FD.mtime<StartTime)
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)
{
strncpy(DestFileName,Cmd->DllDestName,sizeof(DestFileName));
strncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
*DestFileNameW=0;
if (Cmd->DllOpMode!=RAR_EXTRACT)
ExtrFile=false;
}
if (*Cmd->DllDestNameW)
{
strncpyw(DestFileNameW,Cmd->DllDestNameW,sizeof(DestFileNameW)/sizeof(DestFileNameW[0]));
strncpyzw(DestFileNameW,Cmd->DllDestNameW,ASIZE(DestFileNameW));
DestNameW=DestFileNameW;
if (Cmd->DllOpMode!=RAR_EXTRACT)
ExtrFile=false;
@@ -492,7 +622,8 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#endif
#ifdef SFX_MODULE
if (Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.Method!=0x30)
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
@@ -504,7 +635,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#endif
#endif
ExtrFile=false;
ErrHandler.SetErrorCode(RAR_WARNING);
ErrHandler.SetErrorCode(WARNING);
#ifdef RARDLL
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
#endif
@@ -533,7 +664,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#endif
return(true);
}
MKDIR_CODE MDCode=MakeDir(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
MKDIR_CODE MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
bool DirExist=false;
if (MDCode!=MKDIR_SUCCESS)
{
@@ -541,11 +672,11 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if (DirExist && !IsDir(GetFileAttr(DestFileName,DestNameW)))
{
bool UserReject;
FileCreate(Cmd,NULL,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.UnpSize,Arc.NewLhd.FileTime);
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);
MDCode=MakeDir(DestFileName,DestNameW,!Cmd->IgnoreGeneralAttr,Arc.NewLhd.FileAttr);
}
if (MDCode==MKDIR_SUCCESS)
{
@@ -558,7 +689,8 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
else
if (DirExist)
{
SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
if (!Cmd->IgnoreGeneralAttr)
SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
PrevExtracted=true;
}
else
@@ -568,13 +700,20 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#ifdef RARDLL
Cmd->DllError=ERAR_ECREATE;
#endif
ErrHandler.SetErrorCode(RAR_CREATE_ERROR);
ErrHandler.SetErrorCode(CREATE_ERROR);
}
if (PrevExtracted)
SetDirTime(DestFileName,
{
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
if (Cmd->SetCompressedAttr &&
(Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
SetFileCompression(DestFileName,DestNameW,true);
#endif
SetDirTime(DestFileName,DestNameW,
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
@@ -588,23 +727,31 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if ((Command=='E' || Command=='X') && ExtrFile && !Cmd->Test)
{
bool UserReject;
if (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.UnpSize,Arc.NewLhd.FileTime))
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(RAR_CREATE_ERROR);
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);
}
@@ -618,6 +765,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
SkipSolid=true;
TestMode=true;
ExtrFile=true;
}
if (ExtrFile)
{
@@ -660,7 +808,8 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
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.Flags & LHD_SALT) ? Arc.NewLhd.Salt:NULL,false,
Arc.NewLhd.UnpVer>=36);
DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
DataIO.SetFiles(&Arc,&CurFile);
DataIO.SetTestMode(TestMode);
@@ -674,20 +823,23 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
CurFile.SetAllowDelete(!Cmd->KeepBroken);
if (!ExtractLink(DataIO,Arc,DestFileName,DataIO.UnpFileCRC,Command=='X' || Command=='E') &&
(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);
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);
}
Unp->DoUnpack(Arc.NewLhd.UnpVer,(Arc.NewLhd.Flags & LHD_SOLID)!=0);
}
if (Arc.IsOpened())
Arc.SeekToNext();
@@ -705,7 +857,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
}
else
{
char *BadArcName=(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE) ? NULL:Arc.FileName;
char *BadArcName=/*(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE) ? NULL:*/Arc.FileName;
if (Arc.NewLhd.Flags & LHD_PASSWORD)
{
Log(BadArcName,St(MEncrBadCRC),ArcFileName);
@@ -715,7 +867,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
Log(BadArcName,St(MCRCFailed),ArcFileName);
}
BrokenFile=true;
ErrHandler.SetErrorCode(RAR_CRC_ERROR);
ErrHandler.SetErrorCode(CRC_ERROR);
#ifdef RARDLL
Cmd->DllError=ERAR_BAD_DATA;
#endif
@@ -733,20 +885,30 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#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(
CurFile.SetOpenFileTime(
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();
CurFile.SetCloseFileStat(
#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.SetCloseFileTime(
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime,
Arc.NewLhd.FileAttr);
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
if (!Cmd->IgnoreGeneralAttr)
SetFileAttr(CurFile.FileName,CurFile.FileNameW,Arc.NewLhd.FileAttr);
PrevExtracted=true;
}
}
@@ -765,18 +927,29 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
return(true);
}
//added by me
#if !defined(MIN)
#define MIN(a, b) (((a)<(b))?(a):(b))
#endif
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize)
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize)
{
Array<byte> Buffer(0x10000);
while (1)
{
unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
//uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
/* With that original code, the whole file would necessarily be read on the
* first call to this method */
uint Code=DataIO.UnpRead(&Buffer[0], MIN(Buffer.Size(), (size_t) DestUnpSize));
if (Code==0 || (int)Code==-1)
break;
Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
//Code=Code<DestUnpSize ? Code:(uint)DestUnpSize;
/* original code (basically Code = MIN(Code, (uint) DestUnpSize))
* discards extra data.
* It should not be necessary anymore (see change above) */
DataIO.UnpWrite(&Buffer[0],Code);
if (DestUnpSize>=0)
DestUnpSize-=Code;
}
}

View File

@@ -6,12 +6,15 @@ enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
class CmdExtract
{
private:
EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
RarTime StartTime; // time when extraction started
ComprDataIO DataIO;
Unpack *Unp;
long TotalFileCount;
unsigned long TotalFileCount;
long FileCount;
long MatchedArgs;
unsigned long FileCount;
unsigned long MatchedArgs;
bool FirstFile;
bool AllMatchesExact;
bool ReconstructDone;
@@ -22,18 +25,26 @@ class CmdExtract
char Password[MAXPASSWORD];
bool PasswordAll;
bool PrevExtracted;
bool SignatureFound;
char DestFileName[NM];
wchar DestFileNameW[NM];
bool PasswordCancelled;
public:
CmdExtract();
~CmdExtract();
void DoExtract(CommandData *Cmd);
void ExtractArchiveInit(CommandData *Cmd,Archive &Arc);
EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd);
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,
bool &Repeat);
static void UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize);
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,size_t HeaderSize,
bool &Repeat);
bool ExtractCurrentFileChunkInit(CommandData *Cmd, Archive &Arc,
size_t HeaderSize, bool &Repeat);
bool ExtractCurrentFileChunk(CommandData *Cmd, Archive &Arc,
size_t *ReadSize, int *finished);
static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize);
bool SignatureFound;
//next two lines added by me
void *Buffer;
size_t BufferSize;
};
#endif

155
unrar/extractchunk.cpp Normal file
View File

@@ -0,0 +1,155 @@
#include "rar.hpp"
bool CmdExtract::ExtractCurrentFileChunkInit(CommandData *Cmd,
Archive &Arc,
size_t HeaderSize,
bool &Repeat)
{
char Command = 'T';
Cmd->DllError=0;
Repeat = false;
//turn on checks reserved for the first files extracted from an archive?
FirstFile = true;
if (HeaderSize==0) {
if (DataIO.UnpVolume)
{
#ifdef NOVOLUME
return(false);
#else
if (!MergeArchive(Arc,&DataIO,false,Command)) //command irrelevant
{
ErrHandler.SetErrorCode(WARNING);
return false;
}
SignatureFound=false;
#endif
}
else
return false;
}
int HeadType=Arc.GetHeaderType();
if (HeadType!=FILE_HEAD)
return false;
DataIO.SetUnpackToMemory((byte*) this->Buffer, this->BufferSize);
DataIO.SetSkipUnpCRC(true);
DataIO.SetCurrentCommand(Command);
//will still write to mem, as we've told it, but if I've screwed up the
//there'll be no operations in the filesystem
DataIO.SetTestMode(true);
if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
{
char CurVolName[NM];
strncpy(ArcName, Arc.FileName, NM);
strcpy(CurVolName, ArcName);
VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)!=0);
if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
{
*ArcNameW=0;
Repeat=true;
ErrHandler.SetErrorCode(WARNING);
/* Actually known. The problem is that the file doesn't start on this volume. */
Cmd->DllError = ERAR_UNKNOWN;
return false;
}
strcpy(ArcName,CurVolName);
}
DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0;
DataIO.NextVolumeMissing=false;
Arc.Seek(Arc.NextBlockPos - Arc.NewLhd.FullPackSize, SEEK_SET);
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
{
if (*Cmd->Password==0)
if (Cmd->Callback==NULL ||
Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,
(LPARAM)sizeof(Cmd->Password))==-1)
{
ErrHandler.SetErrorCode(WARNING);
Cmd->DllError = ERAR_MISSING_PASSWORD;
return false;
}
strcpy(Password,Cmd->Password);
}
if ((Arc.NewLhd.Flags & LHD_PASSWORD) != 0) {
if (*Cmd->Password == '\0') {
if (Cmd->Callback == NULL ||
Cmd->Callback(UCM_NEEDPASSWORD, Cmd->UserData, (LPARAM) Cmd->Password,
(LPARAM) sizeof(Cmd->Password)) == -1) {
Cmd->DllError = ERAR_MISSING_PASSWORD;
return false;
}
}
strncpy(Password, Cmd->Password, sizeof Password);
}
if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
{
ErrHandler.SetErrorCode(WARNING);
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
return false;
}
if (IsLink(Arc.NewLhd.FileAttr))
return true;
if (Arc.IsArcDir())
return true;
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.SetSkipUnpCRC(true);
DataIO.SetFiles(&Arc, NULL);
return true;
}
bool CmdExtract::ExtractCurrentFileChunk(CommandData *Cmd, Archive &Arc,
size_t *ReadSize,
int *finished)
{
if (IsLink(Arc.NewLhd.FileAttr) || Arc.IsArcDir()) {
*ReadSize = 0;
*finished = TRUE;
return true;
}
DataIO.SetUnpackToMemory((byte*) this->Buffer, this->BufferSize);
if (Arc.NewLhd.Method==0x30) {
UnstoreFile(DataIO, this->BufferSize);
/* not very sophisticated and may result in a subsequent
* unnecessary call to this function (and probably will if
* the buffer size is chosen so that it just fits for small
* files) */
*finished = (DataIO.GetUnpackToMemorySizeLeft() > 0);
}
else
{
Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
if (Arc.NewLhd.UnpVer<=15)
Unp->DoUnpack(15,FileCount>1 && Arc.Solid, this->Buffer != NULL);
else
Unp->DoUnpack(Arc.NewLhd.UnpVer,
(Arc.NewLhd.Flags & LHD_SOLID)!=0, this->Buffer != NULL);
*finished = Unp->IsFileExtracted();
}
*ReadSize = this->BufferSize - DataIO.GetUnpackToMemorySizeLeft();
return true;
}

View File

@@ -1,13 +1,24 @@
#include "rar.hpp"
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize,
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)
@@ -19,7 +30,7 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
#endif
if (Cmd->AllYes || Mode==OVERWRITE_ALL)
break;
if (Mode==OVERWRITE_ASK)
if (Mode==OVERWRITE_DEFAULT || Mode==OVERWRITE_FORCE_ASK)
{
eprintf(St(MFileExists),Name);
int Choice=Ask(St(MYesNoAllRenQ));
@@ -51,11 +62,17 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
#ifdef _WIN_32
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
int Size=SrcFile.Read(NewName,NM);
int Size=SrcFile.Read(NewName,sizeof(NewName)-1);
NewName[Size]=0;
OemToChar(NewName,NewName);
#else
fgets(NewName,sizeof(NewName),stdin);
if (fgets(NewName,sizeof(NewName),stdin)==NULL)
{
// Process fgets failure as if user answered 'No'.
if (UserReject!=NULL)
*UserReject=true;
return(false);
}
#endif
RemoveLF(NewName);
if (PointToName(NewName)==NewName)
@@ -67,7 +84,18 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
continue;
}
if (Choice==6)
ErrHandler.Exit(RAR_USER_BREAK);
ErrHandler.Exit(USER_BREAK);
}
if (Mode==OVERWRITE_AUTORENAME)
{
if (GetAutoRenamedName(Name))
{
if (NameW!=NULL)
*NameW=0;
}
else
Mode=OVERWRITE_DEFAULT;
continue;
}
}
if (NewFile!=NULL && NewFile->Create(Name,NameW))
@@ -76,3 +104,142 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *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",int(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

View File

@@ -2,7 +2,12 @@
#define _RAR_FILECREATE_
bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW,
OVERWRITE_MODE Mode,bool *UserReject,Int64 FileSize=INT64ERR,
OVERWRITE_MODE Mode,bool *UserReject,int64 FileSize=INT64NDF,
uint FileTime=0);
bool GetAutoRenamedName(char *Name);
#if defined(_WIN_32) && !defined(_WIN_CE)
bool UpdateExistingShortName(char *Name,wchar *NameW);
#endif
#endif

View File

@@ -1,6 +1,6 @@
#include "rar.hpp"
static File *CreatedFiles[32];
static File *CreatedFiles[256];
static int RemoveCreatedActive=0;
File::File()
@@ -18,6 +18,9 @@ File::File()
AllowDelete=true;
CloseCount=0;
AllowExceptions=true;
#ifdef _WIN_32
NoSequentialRead=false;
#endif
}
@@ -55,12 +58,11 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
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,
FILE_FLAG_SEQUENTIAL_SCAN,NULL);
hNewFile=CreateFileW(NameW,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
else
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,NULL);
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
if (hNewFile==BAD_HANDLE && GetLastError()==ERROR_FILE_NOT_FOUND)
ErrorType=FILE_NOTFOUND;
@@ -78,6 +80,11 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
#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);
@@ -114,7 +121,7 @@ bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
void File::TOpen(const char *Name,const wchar *NameW)
{
if (!WOpen(Name,NameW))
ErrHandler.Exit(RAR_OPEN_ERROR);
ErrHandler.Exit(OPEN_ERROR);
}
#endif
@@ -128,14 +135,15 @@ bool File::WOpen(const char *Name,const wchar *NameW)
}
bool File::Create(const char *Name,const wchar *NameW)
bool File::Create(const char *Name,const wchar *NameW,bool ShareRead)
{
#ifdef _WIN_32
DWORD ShareMode=(ShareRead || File::OpenShared) ? FILE_SHARE_READ:0;
if (WinNT() && NameW!=NULL && *NameW!=0)
hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
CREATE_ALWAYS,0,NULL);
else
hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL,
CREATE_ALWAYS,0,NULL);
#else
hFile=fopen(Name,CREATEBINARY);
@@ -169,19 +177,19 @@ void File::AddFileToList(FileHandle hFile)
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
void File::TCreate(const char *Name,const wchar *NameW)
void File::TCreate(const char *Name,const wchar *NameW,bool ShareRead)
{
if (!WCreate(Name,NameW))
ErrHandler.Exit(RAR_FATAL_ERROR);
if (!WCreate(Name,NameW,ShareRead))
ErrHandler.Exit(FATAL_ERROR);
}
#endif
bool File::WCreate(const char *Name,const wchar *NameW)
bool File::WCreate(const char *Name,const wchar *NameW,bool ShareRead)
{
if (Create(Name,NameW))
if (Create(Name,NameW,ShareRead))
return(true);
ErrHandler.SetErrorCode(RAR_CREATE_ERROR);
ErrHandler.SetErrorCode(CREATE_ERROR);
ErrHandler.CreateErrorMsg(Name);
return(false);
}
@@ -198,7 +206,7 @@ bool File::Close()
if (!SkipClose)
{
#ifdef _WIN_32
Success=CloseHandle(hFile);
Success=CloseHandle(hFile)==TRUE;
#else
Success=fclose(hFile)!=EOF;
#endif
@@ -231,29 +239,37 @@ void File::Flush()
bool File::Delete()
{
if (HandleType!=FILE_HANDLENORMAL || !AllowDelete)
if (HandleType!=FILE_HANDLENORMAL)
return(false);
if (hFile!=BAD_HANDLE)
Close();
if (!AllowDelete)
return(false);
return(DelFile(FileName,FileNameW));
}
bool File::Rename(const char *NewName)
bool File::Rename(const char *NewName,const wchar *NewNameW)
{
// we do not need to rename if names are already same
bool Success=strcmp(FileName,NewName)==0;
if (Success && *FileNameW!=0 && *NullToEmpty(NewNameW)!=0)
Success=strcmpw(FileNameW,NewNameW)==0;
if (!Success)
Success=rename(FileName,NewName)==0;
Success=RenameFile(FileName,FileNameW,NewName,NewNameW);
if (Success)
{
// renamed successfully, storing the new name
strcpy(FileName,NewName);
*FileNameW=0;
strcpyw(FileNameW,NullToEmpty(NewNameW));
}
return(Success);
}
void File::Write(const void *Data,int Size)
void File::Write(const void *Data,size_t Size)
{
if (Size==0)
return;
@@ -279,36 +295,43 @@ void File::Write(const void *Data,int Size)
#endif
while (1)
{
bool Success;
bool Success=false;
#ifdef _WIN_32
DWORD Written;
DWORD Written=0;
if (HandleType!=FILE_HANDLENORMAL)
{
const int MaxSize=0x4000;
for (int I=0;I<Size;I+=MaxSize)
if (!(Success=WriteFile(hFile,(byte *)Data+I,Min(Size-I,MaxSize),&Written,NULL)))
// writing to stdout can fail in old Windows if data block is too large
const size_t MaxSize=0x4000;
for (size_t I=0;I<Size;I+=MaxSize)
{
Success=WriteFile(hFile,(byte *)Data+I,(DWORD)Min(Size-I,MaxSize),&Written,NULL)==TRUE;
if (!Success)
break;
}
}
else
Success=WriteFile(hFile,Data,Size,&Written,NULL);
Success=WriteFile(hFile,Data,(DWORD)Size,&Written,NULL)==TRUE;
#else
Success=fwrite(Data,1,Size,hFile)==Size && !ferror(hFile);
int Written=fwrite(Data,1,Size,hFile);
Success=Written==Size && !ferror(hFile);
#endif
if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
{
#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(RARDLL)
int ErrCode=GetLastError();
Int64 FilePos=Tell();
Int64 FreeSize=GetFreeDisk(FileName);
int64 FilePos=Tell();
uint64 FreeSize=GetFreeDisk(FileName);
SetLastError(ErrCode);
if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
ErrHandler.WriteErrorFAT(FileName);
#endif
if (ErrHandler.AskRepeatWrite(FileName))
if (ErrHandler.AskRepeatWrite(FileName,false))
{
#ifndef _WIN_32
clearerr(hFile);
#endif
if (Written<Size && Written>0)
Seek(Tell()-Written,SEEK_SET);
continue;
}
ErrHandler.WriteError(NULL,FileName);
@@ -319,9 +342,10 @@ void File::Write(const void *Data,int Size)
}
int File::Read(void *Data,int Size)
int File::Read(void *Data,size_t Size)
{
Int64 FilePos;
int64 FilePos=0; //initialized only to suppress some compilers warning
if (IgnoreReadErrors)
FilePos=Tell();
int ReadSize;
@@ -335,10 +359,10 @@ int File::Read(void *Data,int Size)
if (IgnoreReadErrors)
{
ReadSize=0;
for (int I=0;I<Size;I+=512)
for (size_t I=0;I<Size;I+=512)
{
Seek(FilePos+I,SEEK_SET);
int SizeToRead=Min(Size-I,512);
size_t SizeToRead=Min(Size-I,512);
int ReadCode=DirectRead(Data,SizeToRead);
ReadSize+=(ReadCode==-1) ? 512:ReadCode;
}
@@ -356,10 +380,11 @@ int File::Read(void *Data,int Size)
}
int File::DirectRead(void *Data,int Size)
// Returns -1 in case of error.
int File::DirectRead(void *Data,size_t Size)
{
#ifdef _WIN_32
const int MaxDeviceRead=20000;
const size_t MaxDeviceRead=20000;
#endif
#ifndef _WIN_CE
if (HandleType==FILE_HANDLESTD)
@@ -375,7 +400,7 @@ int File::DirectRead(void *Data,int Size)
#endif
#ifdef _WIN_32
DWORD Read;
if (!ReadFile(hFile,Data,Size,&Read,NULL))
if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
{
if (IsDevice() && Size>MaxDeviceRead)
return(DirectRead(Data,MaxDeviceRead));
@@ -391,41 +416,41 @@ int File::DirectRead(void *Data,int Size)
LastWrite=false;
}
clearerr(hFile);
int ReadSize=fread(Data,1,Size,hFile);
size_t ReadSize=fread(Data,1,Size,hFile);
if (ferror(hFile))
return(-1);
return(ReadSize);
return((int)ReadSize);
#endif
}
void File::Seek(Int64 Offset,int Method)
void File::Seek(int64 Offset,int Method)
{
if (!RawSeek(Offset,Method) && AllowExceptions)
ErrHandler.SeekError(FileName);
}
bool File::RawSeek(Int64 Offset,int Method)
bool File::RawSeek(int64 Offset,int Method)
{
if (hFile==BAD_HANDLE)
return(true);
if (!is64plus(Offset) && Method!=SEEK_SET)
if (Offset<0 && 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 &&
LONG HighDist=(LONG)(Offset>>32);
if (SetFilePointer(hFile,(LONG)Offset,&HighDist,Method)==0xffffffff &&
GetLastError()!=NO_ERROR)
return(false);
#else
LastWrite=false;
#ifdef _LARGEFILE_SOURCE
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
if (fseeko(hFile,Offset,Method)!=0)
#else
if (fseek(hFile,int64to32(Offset),Method)!=0)
if (fseek(hFile,(long)Offset,Method)!=0)
#endif
return(false);
#endif
@@ -433,7 +458,7 @@ bool File::RawSeek(Int64 Offset,int Method)
}
Int64 File::Tell()
int64 File::Tell()
{
#ifdef _WIN_32
LONG HighDist=0;
@@ -443,9 +468,9 @@ Int64 File::Tell()
ErrHandler.SeekError(FileName);
else
return(-1);
return(int32to64(HighDist,LowDist));
return(INT32TO64(HighDist,LowDist));
#else
#ifdef _LARGEFILE_SOURCE
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
return(ftello(hFile));
#else
return(ftell(hFile));
@@ -454,7 +479,7 @@ Int64 File::Tell()
}
void File::Prealloc(Int64 Size)
void File::Prealloc(int64 Size)
{
#ifdef _WIN_32
if (RawSeek(Size,SEEK_SET))
@@ -483,7 +508,7 @@ void File::PutByte(byte Byte)
bool File::Truncate()
{
#ifdef _WIN_32
return(SetEndOfFile(hFile));
return(SetEndOfFile(hFile)==TRUE);
#else
return(false);
#endif
@@ -553,31 +578,7 @@ void File::GetOpenFileTime(RarTime *ft)
}
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()
int64 File::FileLength()
{
SaveFilePos SavePos(*this);
Seek(0,SEEK_END);
@@ -654,16 +655,16 @@ bool File::RemoveCreated()
#ifndef SFX_MODULE
long File::Copy(File &Dest,Int64 Length)
int64 File::Copy(File &Dest,int64 Length)
{
Array<char> Buffer(0x10000);
long CopySize=0;
bool CopyAll=(Length==INT64ERR);
int64 CopySize=0;
bool CopyAll=(Length==INT64NDF);
while (CopyAll || Length>0)
{
Wait();
int SizeToRead=(!CopyAll && Length<Buffer.Size()) ? int64to32(Length):Buffer.Size();
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
int ReadSize=Read(&Buffer[0],SizeToRead);
if (ReadSize==0)
break;

View File

@@ -19,7 +19,7 @@ struct FileStat
{
uint FileAttr;
uint FileTime;
Int64 FileSize;
int64 FileSize;
bool IsDir;
};
@@ -37,6 +37,9 @@ class File
bool NewFile;
bool AllowDelete;
bool AllowExceptions;
#ifdef _WIN_32
bool NoSequentialRead;
#endif
protected:
bool OpenShared;
public:
@@ -53,31 +56,29 @@ class File
bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false);
void TOpen(const char *Name,const wchar *NameW=NULL);
bool WOpen(const char *Name,const wchar *NameW=NULL);
bool Create(const char *Name,const wchar *NameW=NULL);
void TCreate(const char *Name,const wchar *NameW=NULL);
bool WCreate(const char *Name,const wchar *NameW=NULL);
bool Create(const char *Name,const wchar *NameW=NULL,bool ShareRead=true);
void TCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true);
bool WCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true);
bool Close();
void Flush();
bool Delete();
bool Rename(const char *NewName);
void Write(const void *Data,int Size);
int Read(void *Data,int Size);
int DirectRead(void *Data,int Size);
void Seek(Int64 Offset,int Method);
bool RawSeek(Int64 Offset,int Method);
Int64 Tell();
void Prealloc(Int64 Size);
bool Rename(const char *NewName,const wchar *NewNameW=NULL);
void Write(const void *Data,size_t Size);
int Read(void *Data,size_t Size);
int DirectRead(void *Data,size_t Size);
void Seek(int64 Offset,int Method);
bool RawSeek(int64 Offset,int Method);
int64 Tell();
void Prealloc(int64 Size);
byte GetByte();
void PutByte(byte Byte);
bool Truncate();
void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
static void SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta);
void SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta);
void SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr);
void GetOpenFileTime(RarTime *ft);
bool IsOpened() {return(hFile!=BAD_HANDLE);};
Int64 FileLength();
int64 FileLength();
void SetHandleType(FILE_HANDLETYPE Type);
FILE_HANDLETYPE GetHandleType() {return(HandleType);};
bool IsDevice();
@@ -86,9 +87,12 @@ class File
FileHandle GetHandle() {return(hFile);};
void SetIgnoreReadErrors(bool Mode) {IgnoreReadErrors=Mode;};
char *GetName() {return(FileName);}
long Copy(File &Dest,Int64 Length=INT64ERR);
int64 Copy(File &Dest,int64 Length=INT64NDF);
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
#ifdef _WIN_32
void RemoveSequentialFlag() {NoSequentialRead=true;}
#endif
};
#endif

View File

@@ -1,6 +1,6 @@
#include "rar.hpp"
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr)
{
#ifdef _WIN_32
int Success;
@@ -10,7 +10,8 @@ MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
Success=CreateDirectory(Name,NULL);
if (Success)
{
SetFileAttr(Name,NameW,Attr);
if (SetAttr)
SetFileAttr(Name,NameW,Attr);
return(MKDIR_SUCCESS);
}
int ErrCode=GetLastError();
@@ -25,15 +26,15 @@ MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
if (__mkdir(Name)==0)
#endif
{
SetFileAttr(Name,NameW,Attr);
if (SetAttr)
SetFileAttr(Name,NameW,Attr);
return(MKDIR_SUCCESS);
}
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
#endif
#ifdef _UNIX
int prevmask=umask(0);
int ErrCode=Name==NULL ? -1:mkdir(Name,(mode_t)Attr);
umask(prevmask);
mode_t uattr=SetAttr ? (mode_t)Attr:0777;
int ErrCode=Name==NULL ? -1:mkdir(Name,uattr);
if (ErrCode==-1)
return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
return(MKDIR_SUCCESS);
@@ -41,19 +42,20 @@ MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
}
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
{
#ifdef _WIN_32
#if defined(_WIN_32) || defined(_EMX)
uint DirAttr=0;
#else
uint DirAttr=0777;
#endif
#ifdef UNICODE_SUPPORTED
bool Wide=PathW!=NULL && *PathW!=0;
bool Wide=PathW!=NULL && *PathW!=0 && UnicodeEnabled();
#else
bool Wide=false;
#endif
bool IgnoreAscii=false;
bool Success=true;
const char *s=Path;
for (int PosW=0;;PosW++)
@@ -76,34 +78,56 @@ void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
WideToChar(DirPtrW,DirName);
else
{
#ifndef DBCS_SUPPORTED
if (*s!=CPATHDIVIDER)
for (const char *n=s;*n!=0 && n-Path<NM;n++)
if (*n==CPATHDIVIDER)
{
s=n;
break;
}
#endif
strncpy(DirName,Path,s-Path);
DirName[s-Path]=0;
}
if (MakeDir(DirName,DirPtrW,DirAttr)==MKDIR_SUCCESS)
if (MakeDir(DirName,DirPtrW,true,DirAttr)==MKDIR_SUCCESS)
{
#ifndef GUI
mprintf(St(MCreatDir),DirName);
mprintf(" %s",St(MOk));
#endif
}
else
Success=false;
}
if (!IgnoreAscii)
s=charnext(s);
}
if (!SkipLastName)
MakeDir(Path,PathW,DirAttr);
if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
if (MakeDir(Path,PathW,true,DirAttr)!=MKDIR_SUCCESS)
Success=false;
return(Success);
}
void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta)
{
bool sm=ftm!=NULL && ftm->IsSet();
bool sc=ftc!=NULL && ftc->IsSet();
bool sa=ftc!=NULL && fta->IsSet();
#ifdef _WIN_32
if (!WinNT())
return;
HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
bool sm=ftm!=NULL && ftm->IsSet();
bool sc=ftc!=NULL && ftc->IsSet();
bool sa=fta!=NULL && fta->IsSet();
unsigned int DirAttr=GetFileAttr(Name,NameW);
bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0);
if (ResetAttr)
SetFileAttr(Name,NameW,0);
wchar DirNameW[NM];
GetWideName(Name,NameW,DirNameW);
HANDLE hFile=CreateFileW(DirNameW,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
if (hFile==INVALID_HANDLE_VALUE)
return;
@@ -116,6 +140,8 @@ void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
fta->GetWin32(&fa);
SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
CloseHandle(hFile);
if (ResetAttr)
SetFileAttr(Name,NameW,DirAttr);
#endif
#if defined(_UNIX) || defined(_EMX)
File::SetCloseFileTimeByName(Name,ftm,fta);
@@ -131,7 +157,7 @@ bool IsRemovable(const char *Name)
int Type=GetDriveType(*Root ? Root:NULL);
return(Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM);
#elif defined(_EMX)
char Drive=toupper(Name[0]);
char Drive=etoupper(Name[0]);
return((Drive=='A' || Drive=='B') && Name[1]==':');
#else
return(false);
@@ -140,7 +166,7 @@ bool IsRemovable(const char *Name)
#ifndef SFX_MODULE
Int64 GetFreeDisk(const char *Name)
int64 GetFreeDisk(const char *Name)
{
#ifdef _WIN_32
char Root[NM];
@@ -153,61 +179,68 @@ Int64 GetFreeDisk(const char *Name)
if (pGetDiskFreeSpaceEx==NULL)
{
HMODULE hKernel=GetModuleHandle("kernel32.dll");
HMODULE hKernel=GetModuleHandle("kernel32.dll");
if (hKernel!=NULL)
pGetDiskFreeSpaceEx=(GETDISKFREESPACEEX)GetProcAddress(hKernel,"GetDiskFreeSpaceExA");
}
if (pGetDiskFreeSpaceEx!=NULL)
{
GetFilePath(Name,Root);
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));
return(INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart));
}
// We are here if we failed to load GetDiskFreeSpaceExA.
DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters;
if (!GetDiskFreeSpace(*Root ? Root:NULL,&SectorsPerCluster,&BytesPerSector,&FreeClusters,&TotalClusters))
return(1457664);
Int64 FreeSize=SectorsPerCluster*BytesPerSector;
int64 FreeSize=SectorsPerCluster*BytesPerSector;
FreeSize=FreeSize*FreeClusters;
return(FreeSize);
#elif defined(_BEOS)
char Root[NM];
GetFilePath(Name,Root);
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;
int64 FreeSize=Info.block_size;
FreeSize=FreeSize*Info.free_blocks;
return(FreeSize);
#elif defined(_UNIX)
return(1457664);
#elif defined(_EMX)
int Drive=(!isalpha(Name[0]) || Name[1]!=':') ? 0:toupper(Name[0])-'A'+1;
int Drive=IsDiskLetter(Name) ? etoupper(Name[0])-'A'+1:0;
#ifndef _DJGPP
if (_osmode == OS2_MODE)
{
FSALLOCATE fsa;
if (DosQueryFSInfo(Drive,1,&fsa,sizeof(fsa))!=0)
return(1457664);
Int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
FreeSize=FreeSize*fsa.cUnitAvail;
return(FreeSize);
}
else
#endif
{
union REGS regs,outregs;
memset(&regs,0,sizeof(regs));
regs.h.ah=0x36;
regs.h.dl=Drive;
#ifdef _DJGPP
int86 (0x21,&regs,&outregs);
#else
_int86 (0x21,&regs,&outregs);
#endif
if (outregs.x.ax==0xffff)
return(1457664);
Int64 FreeSize=outregs.x.ax*outregs.x.cx;
int64 FreeSize=outregs.x.ax*outregs.x.cx;
FreeSize=FreeSize*outregs.x.bx;
return(FreeSize);
}
@@ -283,8 +316,9 @@ bool IsLink(uint Attr)
{
#ifdef _UNIX
return((Attr & 0xF000)==0xA000);
#endif
#else
return(false);
#endif
}
@@ -373,8 +407,10 @@ void ConvertNameToFull(const char *Src,char *Dest)
strcpy(FullName,Src);
else
{
getcwd(FullName,sizeof(FullName));
AddEndSlash(FullName);
if (getcwd(FullName,sizeof(FullName))==NULL)
*FullName=0;
else
AddEndSlash(FullName);
strcat(FullName,Src);
}
strcpy(Dest,FullName);
@@ -426,13 +462,13 @@ void ConvertNameToFull(const wchar *Src,wchar *Dest)
#ifndef SFX_MODULE
char *MkTemp(char *Name)
{
int Length=strlen(Name);
size_t Length=strlen(Name);
if (Length<=6)
return(NULL);
int Random=clock();
for (int Attempt=0;;Attempt++)
{
sprintf(Name+Length-6,"%06u",Random+Attempt);
sprintf(Name+Length-6,"%06u",(Random+Attempt)%1000000);
Name[Length-4]='.';
if (!FileExist(Name))
break;
@@ -447,27 +483,53 @@ char *MkTemp(char *Name)
#ifndef SFX_MODULE
uint CalcFileCRC(File *SrcFile,Int64 Size)
uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)
{
SaveFilePos SavePos(*SrcFile);
const int BufSize=0x10000;
const size_t BufSize=0x10000;
Array<byte> Data(BufSize);
Int64 BlockCount=0;
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)
while (true)
{
if ((++BlockCount & 15)==0)
size_t SizeToRead;
if (Size==INT64NDF) // If we process the entire file.
SizeToRead=BufSize; // Then always attempt to read the entire buffer.
else
SizeToRead=(size_t)Min((int64)BufSize,Size);
int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
if (ReadSize==0)
break;
++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)
if (Size!=INT64NDF)
Size-=ReadSize;
}
#if !defined(SILENT) && !defined(_WIN_CE)
if (ShowMode==CALCCRC_SHOWALL)
mprintf("\b\b\b\b ");
#endif
return(DataCRC^0xffffffff);
}
#endif
@@ -491,13 +553,33 @@ bool DelFile(const char *Name,const wchar *NameW)
}
bool DelDir(const char *Name)
{
return(DelDir(Name,NULL));
}
bool DelDir(const char *Name,const wchar *NameW)
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
bool SetFileCompression(char *Name,wchar *NameW,bool State)
{
return(rmdir(Name)==0);
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

View File

@@ -3,11 +3,11 @@
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr);
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr);
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta);
bool IsRemovable(const char *Name);
Int64 GetFreeDisk(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);
@@ -25,11 +25,20 @@ void ConvertNameToFull(const wchar *Src,wchar *Dest);
char* MkTemp(char *Name);
uint CalcFileCRC(File *SrcFile,Int64 Size=INT64ERR);
enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL};
uint CalcFileCRC(File *SrcFile,int64 Size=INT64NDF,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

View File

@@ -2,12 +2,13 @@
static bool IsUnicode(byte *Data,int Size);
bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
bool ConvertToAnsi,bool Unquote,bool SkipComments)
bool ReadTextFile(const char *Name,StringList *List,bool Config,
bool AbortOnError,RAR_CHARSET SrcCharset,bool Unquote,
bool SkipComments,bool ExpandEnvStr)
{
char FileName[NM];
if (Config)
GetConfigName(Name,FileName);
GetConfigName(Name,FileName,true);
else
strcpy(FileName,Name);
@@ -19,7 +20,7 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
if (!OpenCode)
{
if (AbortOnError)
ErrHandler.Exit(RAR_OPEN_ERROR);
ErrHandler.Exit(OPEN_ERROR);
return(false);
}
}
@@ -37,9 +38,19 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
memset(&Data[DataSize],0,5);
if (IsUnicode((byte *)&Data[0],DataSize))
if (SrcCharset==RCH_UNICODE ||
SrcCharset==RCH_DEFAULT && IsUnicode((byte *)&Data[0],DataSize))
{
wchar *CurStr=(wchar *)&Data[2];
// Unicode in native system format, can be more than 2 bytes per character.
Array<wchar> DataW(Data.Size()/2+1);
for (size_t I=2;I<Data.Size()-1;I+=2)
{
// Need to convert Data to (byte) first to prevent the sign extension
// to higher bytes.
DataW[(I-2)/2]=(wchar)((byte)Data[I])+(wchar)((byte)Data[I+1])*256;
}
wchar *CurStr=&DataW[0];
Array<char> AnsiName;
while (*CurStr!=0)
@@ -63,8 +74,11 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
}
if (*CurStr)
{
int Length=strlenw(CurStr);
int AddSize=Length-AnsiName.Size()+1;
// Length and AddSize must be defined as signed, because AddSize
// can be negative.
int Length=(int)strlenw(CurStr);
int AddSize=4*(Length-(int)AnsiName.Size()+1);
if (AddSize>0)
AnsiName.Add(AddSize);
if (Unquote && *CurStr=='\"' && CurStr[Length-1]=='\"')
@@ -72,8 +86,29 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
CurStr[Length-1]=0;
CurStr++;
}
WideToChar(CurStr,&AnsiName[0]);
List->AddString(&AnsiName[0],CurStr);
WideToChar(CurStr,&AnsiName[0],AnsiName.Size());
bool Expanded=false;
#if defined(_WIN_32) && !defined(_WIN_CE)
if (ExpandEnvStr && *CurStr=='%')
{
// expanding environment variables in Windows version
char ExpName[NM];
wchar ExpNameW[NM];
*ExpNameW=0;
int ret,retw=1;
ret=ExpandEnvironmentStrings(&AnsiName[0],ExpName,ASIZE(ExpName));
if (ret!=0 && WinNT())
retw=ExpandEnvironmentStringsW(CurStr,ExpNameW,ASIZE(ExpNameW));
Expanded=ret!=0 && ret<ASIZE(ExpName) &&
retw!=0 && retw<ASIZE(ExpNameW);
if (Expanded)
List->AddString(ExpName,ExpNameW);
}
#endif
if (!Expanded)
List->AddString(&AnsiName[0],CurStr);
}
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
@@ -106,7 +141,7 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
{
if (Unquote && *CurStr=='\"')
{
int Length=strlen(CurStr);
size_t Length=strlen(CurStr);
if (CurStr[Length-1]=='\"')
{
CurStr[Length-1]=0;
@@ -114,10 +149,25 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
}
}
#if defined(_WIN_32)
if (ConvertToAnsi)
if (SrcCharset==RCH_OEM)
OemToChar(CurStr,CurStr);
#endif
List->AddString(CurStr);
bool Expanded=false;
#if defined(_WIN_32) && !defined(_WIN_CE)
if (ExpandEnvStr && *CurStr=='%')
{
// expanding environment variables in Windows version
char ExpName[NM];
int ret=ExpandEnvironmentStrings(CurStr,ExpName,ASIZE(ExpName));
Expanded=ret!=0 && ret<ASIZE(ExpName);
if (Expanded)
List->AddString(ExpName);
}
#endif
if (!Expanded)
List->AddString(CurStr);
}
CurStr=NextStr+1;
while (*CurStr=='\r' || *CurStr=='\n')
@@ -133,7 +183,7 @@ bool IsUnicode(byte *Data,int Size)
if (Size<4 || Data[0]!=0xff || Data[1]!=0xfe)
return(false);
for (int I=2;I<Size;I++)
if (Data[I]<32)
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
return(true);
return(false);
}

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