diff --git a/lib/unrar2/.hgignore b/lib/unrar2/.hgignore new file mode 100644 index 00000000..28998a5c --- /dev/null +++ b/lib/unrar2/.hgignore @@ -0,0 +1,4 @@ +syntax: glob + +*.pyc +build/* \ No newline at end of file diff --git a/lib/unrar2/.hgtags b/lib/unrar2/.hgtags new file mode 100644 index 00000000..9f0fd548 --- /dev/null +++ b/lib/unrar2/.hgtags @@ -0,0 +1,4 @@ +f2570b5f7205f1433661a9508f464f691cf63389 0.97 +d3595b2c9a1aec510f8ae1dcfef1eb8562a77fc0 0.99.1 +d23822f936c663784c5edda09cd5a6effe1e882d 0.99.2 +855a137f51581bd6d7a79264856020aa52fd0b66 0.99.3 diff --git a/lib/unrar2/MANIFEST.in b/lib/unrar2/MANIFEST.in new file mode 100644 index 00000000..e7ce0a66 --- /dev/null +++ b/lib/unrar2/MANIFEST.in @@ -0,0 +1,2 @@ +recursive-include UnRARDLL *.* +include test.rar UnRAR2.html license.txt diff --git a/lib/unrar2/PKG-INFO b/lib/unrar2/PKG-INFO new file mode 100644 index 00000000..4d0117f1 --- /dev/null +++ b/lib/unrar2/PKG-INFO @@ -0,0 +1,27 @@ +Metadata-Version: 1.1 +Name: pyUnRAR2 +Version: 0.99.3 +Summary: Improved Python wrapper around the free UnRAR.dll +Home-page: http://code.google.com/py-unrar2 +Author: Konstantin Yegupov +Author-email: yk4ever@gmail.com +License: MIT +Description: pyUnRAR2 is a ctypes based wrapper around the free UnRAR.dll. + + It is an modified version of Jimmy Retzlaff's pyUnRAR - more simple, + stable and foolproof. + Notice that it has INCOMPATIBLE interface. + + It enables reading and unpacking of archives created with the + RAR/WinRAR archivers. There is a low-level interface which is very + similar to the C interface provided by UnRAR. There is also a + higher level interface which makes some common operations easier. +Platform: Windows +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Win32 (MS Windows) +Classifier: License :: OSI Approved :: MIT License +Classifier: Natural Language :: English +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Archiving :: Compression diff --git a/lib/unrar2/UnRAR2.html b/lib/unrar2/UnRAR2.html new file mode 100644 index 00000000..fa4d2057 --- /dev/null +++ b/lib/unrar2/UnRAR2.html @@ -0,0 +1,194 @@ + + +Python: package UnRAR2 + + + + +
 
+ 
UnRAR2 (version 0.99.2)
index
/home/rainman/dev/py-unrar2/UnRAR2/__init__.py
+

pyUnRAR2 is a ctypes based wrapper around the free UnRAR.dll. 

+It is an modified version of Jimmy Retzlaff's pyUnRAR - more simple,
+stable and foolproof.
+Notice that it has INCOMPATIBLE interface.

+It enables reading and unpacking of archives created with the
+RAR/WinRAR archivers. There is a low-level interface which is very
+similar to the C interface provided by UnRAR. There is also a
+higher level interface which makes some common operations easier.

+

+ + + + + +
 
+Package Contents
       
UnRAR2 (package)
+rar_exceptions
+
setup
+test_UnRAR2
+
unix
+windows
+

+ + + + + +
 
+Classes
       
+
UnRAR2.unix.RarFileImplementation(__builtin__.object) +
+
+
RarFile +
+
+
__builtin__.object +
+
+
RarInfo +
+
+
+

+ + + + + +
 
+class RarFile(UnRAR2.unix.RarFileImplementation)
    
Method resolution order:
+
RarFile
+
UnRAR2.unix.RarFileImplementation
+
__builtin__.object
+
+
+Methods defined here:
+
__del__(self)
+ +
__init__(self, archiveName, password=None)
Instantiate the archive.

+archiveName is the name of the RAR file.
+password is used to decrypt the files in the archive.

+Properties:
+    comment - comment associated with the archive

+>>> print RarFile('test.rar').comment
+This is a test.
+ +
extract(self, condition='*', path='.', withSubpath=True, overwrite=True)
Extract specific files from archive to disk.

+If "condition" is a list of numbers, then extract files which have those positions in infolist.
+If "condition" is a string, then it is treated as a wildcard for names of files to extract.
+If "condition" is a function, it is treated as a callback function, which accepts a RarInfo object
+    and returns either boolean True (extract) or boolean False (skip).
+DEPRECATED: If "condition" callback returns string (only supported for Windows) - 
+    that string will be used as a new name to save the file under.
+If "condition" is omitted, all files are extracted.

+"path" is a directory to extract to
+"withSubpath" flag denotes whether files are extracted with their full path in the archive.
+"overwrite" flag denotes whether extracted files will overwrite old ones. Defaults to true.

+Returns list of RarInfos for extracted files.
+ +
infoiter(self)
Iterate over all the files in the archive, generating RarInfos.

+>>> import os
+>>> for fileInArchive in RarFile('test.rar').infoiter():
+...     print os.path.split(fileInArchive.filename)[-1],
+...     print fileInArchive.isdir,
+...     print fileInArchive.size,
+...     print fileInArchive.comment,
+...     print tuple(fileInArchive.datetime)[0:5],
+...     print time.strftime('%a, %d %b %Y %H:%M', fileInArchive.datetime)
+test True 0 None (2003, 6, 30, 1, 59) Mon, 30 Jun 2003 01:59
+test.txt False 20 None (2003, 6, 30, 2, 1) Mon, 30 Jun 2003 02:01
+this.py False 1030 None (2002, 2, 8, 16, 47) Fri, 08 Feb 2002 16:47
+ +
infolist(self)
Return a list of RarInfos, descripting the contents of the archive.
+ +
read_files(self, condition='*')
Read specific files from archive into memory.
+If "condition" is a list of numbers, then return files which have those positions in infolist.
+If "condition" is a string, then it is treated as a wildcard for names of files to extract.
+If "condition" is a function, it is treated as a callback function, which accepts a RarInfo object 
+    and returns boolean True (extract) or False (skip).
+If "condition" is omitted, all files are returned.

+Returns list of tuples (RarInfo info, str contents)
+ +
+Methods inherited from UnRAR2.unix.RarFileImplementation:
+
call(self, cmd, options=[], files=[])
+ +
destruct(self)
+ +
escaped_password(self)
+ +
init(self, password=None)
+ +
+Data descriptors inherited from UnRAR2.unix.RarFileImplementation:
+
__dict__
+
dictionary for instance variables (if defined)
+
+
__weakref__
+
list of weak references to the object (if defined)
+
+

+ + + + + + + +
 
+class RarInfo(__builtin__.object)
   Represents a file header in an archive. Don't instantiate directly.
+Use only to obtain information about file.
+YOU CANNOT EXTRACT FILE CONTENTS USING THIS OBJECT.
+USE METHODS OF RarFile CLASS INSTEAD.

+Properties:
+    index - index of file within the archive
+    filename - name of the file in the archive including path (if any)
+    datetime - file date/time as a struct_time suitable for time.strftime
+    isdir - True if the file is a directory
+    size - size in bytes of the uncompressed file
+    comment - comment associated with the file
+    
+Note - this is not currently intended to be a Python file-like object.
 
 Methods defined here:
+
__init__(self, rarfile, data)
+ +
__str__(self)
+ +
+Data descriptors defined here:
+
__dict__
+
dictionary for instance variables (if defined)
+
+
__weakref__
+
list of weak references to the object (if defined)
+
+

+ + + + + +
 
+Functions
       
condition2checker(condition)
Converts different condition types to callback
+

+ + + + + +
 
+Data
       __version__ = '0.99.2'
+in_windows = False
+ \ No newline at end of file diff --git a/lib/unrar2/UnRARDLL/license.txt b/lib/unrar2/UnRARDLL/license.txt new file mode 100644 index 00000000..0c1540e5 --- /dev/null +++ b/lib/unrar2/UnRARDLL/license.txt @@ -0,0 +1,18 @@ + The unrar.dll library is freeware. This means: + + 1. All copyrights to RAR and the unrar.dll are exclusively + owned by the author - Alexander Roshal. + + 2. The unrar.dll library may be used in any software to handle RAR + archives without limitations free of charge. + + 3. THE RAR ARCHIVER AND THE UNRAR.DLL LIBRARY 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. + + Thank you for your interest in RAR and unrar.dll. + + + Alexander L. Roshal \ No newline at end of file diff --git a/lib/unrar2/unrar.dll b/lib/unrar2/UnRARDLL/unrar.dll similarity index 100% rename from lib/unrar2/unrar.dll rename to lib/unrar2/UnRARDLL/unrar.dll diff --git a/lib/unrar2/unrar.h b/lib/unrar2/UnRARDLL/unrar.h similarity index 100% rename from lib/unrar2/unrar.h rename to lib/unrar2/UnRARDLL/unrar.h diff --git a/lib/unrar2/UnRARDLL/unrar.lib b/lib/unrar2/UnRARDLL/unrar.lib new file mode 100644 index 00000000..0f6b3146 Binary files /dev/null and b/lib/unrar2/UnRARDLL/unrar.lib differ diff --git a/lib/unrar2/UnRARDLL/unrardll.txt b/lib/unrar2/UnRARDLL/unrardll.txt new file mode 100644 index 00000000..c49dd5b4 --- /dev/null +++ b/lib/unrar2/UnRARDLL/unrardll.txt @@ -0,0 +1,606 @@ + + UnRAR.dll Manual + ~~~~~~~~~~~~~~~~ + + UnRAR.dll is a 32-bit Windows dynamic-link library which provides + file extraction from RAR archives. + + + Exported functions + +==================================================================== +HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData) +==================================================================== + +Description +~~~~~~~~~~~ + Open RAR archive and allocate memory structures + +Parameters +~~~~~~~~~~ +ArchiveData Points to RAROpenArchiveData structure + +struct RAROpenArchiveData +{ + char *ArcName; + UINT OpenMode; + UINT OpenResult; + char *CmtBuf; + UINT CmtBufSize; + UINT CmtSize; + UINT CmtState; +}; + +Structure fields: + +ArcName + Input parameter which should point to zero terminated string + containing the archive name. + +OpenMode + Input parameter. + + Possible values + + RAR_OM_LIST + Open archive for reading file headers only. + + RAR_OM_EXTRACT + Open archive for testing and extracting files. + + RAR_OM_LIST_INCSPLIT + Open archive for reading file headers only. If you open an archive + in such mode, RARReadHeader[Ex] will return all file headers, + including those with "file continued from previous volume" flag. + In case of RAR_OM_LIST such headers are automatically skipped. + So if you process RAR volumes in RAR_OM_LIST_INCSPLIT mode, you will + get several file header records for same file if file is split between + volumes. For such files only the last file header record will contain + the correct file CRC and if you wish to get the correct packed size, + you need to sum up packed sizes of all parts. + +OpenResult + Output parameter. + + Possible values + + 0 Success + ERAR_NO_MEMORY Not enough memory to initialize data structures + ERAR_BAD_DATA Archive header broken + ERAR_BAD_ARCHIVE File is not valid RAR archive + ERAR_UNKNOWN_FORMAT Unknown encryption used for archive headers + ERAR_EOPEN File open error + +CmtBuf + Input parameter which should point to the buffer for archive + comments. Maximum comment size is limited to 64Kb. Comment text is + zero terminated. If the comment text is larger than the buffer + size, the comment text will be truncated. If CmtBuf is set to + NULL, comments will not be read. + +CmtBufSize + Input parameter which should contain size of buffer for archive + comments. + +CmtSize + Output parameter containing size of comments actually read into the + buffer, cannot exceed CmtBufSize. + +CmtState + Output parameter. + + Possible values + + 0 comments not present + 1 Comments read completely + ERAR_NO_MEMORY Not enough memory to extract comments + ERAR_BAD_DATA Broken comment + ERAR_UNKNOWN_FORMAT Unknown comment format + ERAR_SMALL_BUF Buffer too small, comments not completely read + +Return values +~~~~~~~~~~~~~ + Archive handle or NULL in case of error + + +======================================================================== +HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData) +======================================================================== + +Description +~~~~~~~~~~~ + Similar to RAROpenArchive, but uses RAROpenArchiveDataEx structure + allowing to specify Unicode archive name and returning information + about archive flags. + +Parameters +~~~~~~~~~~ +ArchiveData Points to RAROpenArchiveDataEx structure + +struct RAROpenArchiveDataEx +{ + char *ArcName; + wchar_t *ArcNameW; + unsigned int OpenMode; + unsigned int OpenResult; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; + unsigned int Flags; + unsigned int Reserved[32]; +}; + +Structure fields: + +ArcNameW + Input parameter which should point to zero terminated Unicode string + containing the archive name or NULL if Unicode name is not specified. + +Flags + Output parameter. Combination of bit flags. + + Possible values + + 0x0001 - Volume attribute (archive volume) + 0x0002 - Archive comment present + 0x0004 - Archive lock attribute + 0x0008 - Solid attribute (solid archive) + 0x0010 - New volume naming scheme ('volname.partN.rar') + 0x0020 - Authenticity information present + 0x0040 - Recovery record present + 0x0080 - Block headers are encrypted + 0x0100 - First volume (set only by RAR 3.0 and later) + +Reserved[32] + Reserved for future use. Must be zero. + +Information on other structure fields and function return values +is available above, in RAROpenArchive function description. + + +==================================================================== +int PASCAL RARCloseArchive(HANDLE hArcData) +==================================================================== + +Description +~~~~~~~~~~~ + Close RAR archive and release allocated memory. It must be called when + archive processing is finished, even if the archive processing was stopped + due to an error. + +Parameters +~~~~~~~~~~ +hArcData + This parameter should contain the archive handle obtained from the + RAROpenArchive function call. + +Return values +~~~~~~~~~~~~~ + 0 Success + ERAR_ECLOSE Archive close error + + +==================================================================== +int PASCAL RARReadHeader(HANDLE hArcData, + struct RARHeaderData *HeaderData) +==================================================================== + +Description +~~~~~~~~~~~ + Read header of file in archive. + +Parameters +~~~~~~~~~~ +hArcData + This parameter should contain the archive handle obtained from the + RAROpenArchive function call. + +HeaderData + It should point to RARHeaderData structure: + +struct RARHeaderData +{ + char ArcName[260]; + char FileName[260]; + UINT Flags; + UINT PackSize; + UINT UnpSize; + UINT HostOS; + UINT FileCRC; + UINT FileTime; + UINT UnpVer; + UINT Method; + UINT FileAttr; + char *CmtBuf; + UINT CmtBufSize; + UINT CmtSize; + UINT CmtState; +}; + +Structure fields: + +ArcName + Output parameter which contains a zero terminated string of the + current archive name. May be used to determine the current volume + name. + +FileName + Output parameter which contains a zero terminated string of the + file name in OEM (DOS) encoding. + +Flags + Output parameter which contains file flags: + + 0x01 - file continued from previous volume + 0x02 - file continued on next volume + 0x04 - file encrypted with password + 0x08 - file comment present + 0x10 - compression of previous files is used (solid flag) + + bits 7 6 5 + + 0 0 0 - dictionary size 64 Kb + 0 0 1 - dictionary size 128 Kb + 0 1 0 - dictionary size 256 Kb + 0 1 1 - dictionary size 512 Kb + 1 0 0 - dictionary size 1024 Kb + 1 0 1 - dictionary size 2048 KB + 1 1 0 - dictionary size 4096 KB + 1 1 1 - file is directory + + Other bits are reserved. + +PackSize + Output parameter means packed file size or size of the + file part if file was split between volumes. + +UnpSize + Output parameter - unpacked file size. + +HostOS + Output parameter - operating system used for archiving: + + 0 - MS DOS; + 1 - OS/2. + 2 - Win32 + 3 - Unix + +FileCRC + Output parameter which contains unpacked file CRC. In case of file parts + split between volumes only the last part contains the correct CRC + and it is accessible only in RAR_OM_LIST_INCSPLIT listing mode. + +FileTime + Output parameter - contains date and time in standard MS DOS format. + +UnpVer + Output parameter - RAR version needed to extract file. + It is encoded as 10 * Major version + minor version. + +Method + Output parameter - packing method. + +FileAttr + Output parameter - file attributes. + +CmtBuf + File comments support is not implemented in the new DLL version yet. + Now CmtState is always 0. + +/* + * Input parameter which should point to the buffer for file + * comments. Maximum comment size is limited to 64Kb. Comment text is + * a zero terminated string in OEM encoding. If the comment text is + * larger than the buffer size, the comment text will be truncated. + * If CmtBuf is set to NULL, comments will not be read. + */ + +CmtBufSize + Input parameter which should contain size of buffer for archive + comments. + +CmtSize + Output parameter containing size of comments actually read into the + buffer, should not exceed CmtBufSize. + +CmtState + Output parameter. + + Possible values + + 0 Absent comments + 1 Comments read completely + ERAR_NO_MEMORY Not enough memory to extract comments + ERAR_BAD_DATA Broken comment + ERAR_UNKNOWN_FORMAT Unknown comment format + ERAR_SMALL_BUF Buffer too small, comments not completely read + +Return values +~~~~~~~~~~~~~ + + 0 Success + ERAR_END_ARCHIVE End of archive + ERAR_BAD_DATA File header broken + + +==================================================================== +int PASCAL RARReadHeaderEx(HANDLE hArcData, + struct RARHeaderDataEx *HeaderData) +==================================================================== + +Description +~~~~~~~~~~~ + Similar to RARReadHeader, but uses RARHeaderDataEx structure, +containing information about Unicode file names and 64 bit file sizes. + +struct RARHeaderDataEx +{ + char ArcName[1024]; + wchar_t ArcNameW[1024]; + char FileName[1024]; + wchar_t FileNameW[1024]; + unsigned int Flags; + unsigned int PackSize; + unsigned int PackSizeHigh; + unsigned int UnpSize; + unsigned int UnpSizeHigh; + unsigned int HostOS; + unsigned int FileCRC; + unsigned int FileTime; + unsigned int UnpVer; + unsigned int Method; + unsigned int FileAttr; + char *CmtBuf; + unsigned int CmtBufSize; + unsigned int CmtSize; + unsigned int CmtState; + unsigned int Reserved[1024]; +}; + + +==================================================================== +int PASCAL RARProcessFile(HANDLE hArcData, + int Operation, + char *DestPath, + char *DestName) +==================================================================== + +Description +~~~~~~~~~~~ + Performs action and moves the current position in the archive to + the next file. Extract or test the current file from the archive + opened in RAR_OM_EXTRACT mode. If the mode RAR_OM_LIST is set, + then a call to this function will simply skip the archive position + to the next file. + +Parameters +~~~~~~~~~~ +hArcData + This parameter should contain the archive handle obtained from the + RAROpenArchive function call. + +Operation + File operation. + + Possible values + + RAR_SKIP Move to the next file in the archive. If the + archive is solid and RAR_OM_EXTRACT mode was set + when the archive was opened, the current file will + be processed - the operation will be performed + slower than a simple seek. + + RAR_TEST Test the current file and move to the next file in + the archive. If the archive was opened with + RAR_OM_LIST mode, the operation is equal to + RAR_SKIP. + + RAR_EXTRACT Extract the current file and move to the next file. + If the archive was opened with RAR_OM_LIST mode, + the operation is equal to RAR_SKIP. + + +DestPath + This parameter should point to a zero terminated string containing the + destination directory to which to extract files to. If DestPath is equal + to NULL, it means extract to the current directory. This parameter has + meaning only if DestName is NULL. + +DestName + This parameter should point to a string containing the full path and name + to assign to extracted file or it can be NULL to use the default name. + If DestName is defined (not NULL), it overrides both the original file + name saved in the archive and path specigied in DestPath setting. + + Both DestPath and DestName must be in OEM encoding. If necessary, + use CharToOem to convert text to OEM before passing to this function. + +Return values +~~~~~~~~~~~~~ + 0 Success + ERAR_BAD_DATA File CRC error + ERAR_BAD_ARCHIVE Volume is not valid RAR archive + ERAR_UNKNOWN_FORMAT Unknown archive format + ERAR_EOPEN Volume open error + ERAR_ECREATE File create error + ERAR_ECLOSE File close error + ERAR_EREAD Read error + ERAR_EWRITE Write error + + +Note: if you wish to cancel extraction, return -1 when processing + UCM_PROCESSDATA callback message. + + +==================================================================== +int PASCAL RARProcessFileW(HANDLE hArcData, + int Operation, + wchar_t *DestPath, + wchar_t *DestName) +==================================================================== + +Description +~~~~~~~~~~~ + Unicode version of RARProcessFile. It uses Unicode DestPath + and DestName parameters, other parameters and return values + are the same as in RARProcessFile. + + +==================================================================== +void PASCAL RARSetCallback(HANDLE hArcData, + int PASCAL (*CallbackProc)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2), + LPARAM UserData); +==================================================================== + +Description +~~~~~~~~~~~ + Set a user-defined callback function to process Unrar events. + +Parameters +~~~~~~~~~~ +hArcData + This parameter should contain the archive handle obtained from the + RAROpenArchive function call. + +CallbackProc + It should point to a user-defined callback function. + + The function will be passed four parameters: + + + msg Type of event. Described below. + + UserData User defined value passed to RARSetCallback. + + P1 and P2 Event dependent parameters. Described below. + + + Possible events + + UCM_CHANGEVOLUME Process volume change. + + P1 Points to the zero terminated name + of the next volume. + + P2 The function call mode: + + RAR_VOL_ASK Required volume is absent. The function should + prompt user and return a positive value + to retry or return -1 value to terminate + operation. The function may also specify a new + volume name, placing it to the address specified + by P1 parameter. + + RAR_VOL_NOTIFY Required volume is successfully opened. + This is a notification call and volume name + modification is not allowed. The function should + return a positive value to continue or -1 + to terminate operation. + + UCM_PROCESSDATA Process unpacked data. It may be used to read + a file while it is being extracted or tested + without actual extracting file to disk. + Return a positive value to continue process + or -1 to cancel the archive operation + + P1 Address pointing to the unpacked data. + Function may refer to the data but must not + change it. + + P2 Size of the unpacked data. It is guaranteed + only that the size will not exceed the maximum + dictionary size (4 Mb in RAR 3.0). + + UCM_NEEDPASSWORD DLL needs a password to process archive. + This message must be processed if you wish + to be able to handle archives with encrypted + file names. It can be also used as replacement + of RARSetPassword function even for usual + encrypted files with non-encrypted names. + + P1 Address pointing to the buffer for a password. + You need to copy a password here. + + P2 Size of the password buffer. + + +UserData + User data passed to callback function. + + Other functions of UnRAR.dll should not be called from the callback + function. + +Return values +~~~~~~~~~~~~~ + None + + + +==================================================================== +void PASCAL RARSetChangeVolProc(HANDLE hArcData, + int PASCAL (*ChangeVolProc)(char *ArcName,int Mode)); +==================================================================== + +Obsoleted, use RARSetCallback instead. + + + +==================================================================== +void PASCAL RARSetProcessDataProc(HANDLE hArcData, + int PASCAL (*ProcessDataProc)(unsigned char *Addr,int Size)) +==================================================================== + +Obsoleted, use RARSetCallback instead. + + +==================================================================== +void PASCAL RARSetPassword(HANDLE hArcData, + char *Password); +==================================================================== + +Description +~~~~~~~~~~~ + Set a password to decrypt files. + +Parameters +~~~~~~~~~~ +hArcData + This parameter should contain the archive handle obtained from the + RAROpenArchive function call. + +Password + It should point to a string containing a zero terminated password. + +Return values +~~~~~~~~~~~~~ + None + + +==================================================================== +void PASCAL RARGetDllVersion(); +==================================================================== + +Description +~~~~~~~~~~~ + Returns API version. + +Parameters +~~~~~~~~~~ + None. + +Return values +~~~~~~~~~~~~~ + Returns an integer value denoting UnRAR.dll API version, which is also +defined in unrar.h as RAR_DLL_VERSION. API version number is incremented +only in case of noticeable changes in UnRAR.dll API. Do not confuse it +with version of UnRAR.dll stored in DLL resources, which is incremented +with every DLL rebuild. + + If RARGetDllVersion() returns a value lower than UnRAR.dll which your +application was designed for, it may indicate that DLL version is too old +and it will fail to provide all necessary functions to your application. + + This function is absent in old versions of UnRAR.dll, so it is safer +to use LoadLibrary and GetProcAddress to access this function. + diff --git a/lib/unrar2/UnRARDLL/whatsnew.txt b/lib/unrar2/UnRARDLL/whatsnew.txt new file mode 100644 index 00000000..874d19b1 --- /dev/null +++ b/lib/unrar2/UnRARDLL/whatsnew.txt @@ -0,0 +1,80 @@ +List of unrar.dll API changes. We do not include performance and reliability +improvements into this list, but this library and RAR/UnRAR tools share +the same source code. So the latest version of unrar.dll usually contains +same decompression algorithm changes as the latest UnRAR version. +============================================================================ + +-- 18 January 2008 + +all LONG parameters of CallbackProc function were changed +to LPARAM type for 64 bit mode compatibility. + + +-- 12 December 2007 + +Added new RAR_OM_LIST_INCSPLIT open mode for function RAROpenArchive. + + +-- 14 August 2007 + +Added NoCrypt\unrar_nocrypt.dll without decryption code for those +applications where presence of encryption or decryption code is not +allowed because of legal restrictions. + + +-- 14 December 2006 + +Added ERAR_MISSING_PASSWORD error type. This error is returned +if empty password is specified for encrypted file. + + +-- 12 June 2003 + +Added RARProcessFileW function, Unicode version of RARProcessFile + + +-- 9 August 2002 + +Added RAROpenArchiveEx function allowing to specify Unicode archive +name and get archive flags. + + +-- 24 January 2002 + +Added RARReadHeaderEx function allowing to read Unicode file names +and 64 bit file sizes. + + +-- 23 January 2002 + +Added ERAR_UNKNOWN error type (it is used for all errors which +do not have special ERAR code yet) and UCM_NEEDPASSWORD callback +message. + +Unrar.dll automatically opens all next volumes not only when extracting, +but also in RAR_OM_LIST mode. + + +-- 27 November 2001 + +RARSetChangeVolProc and RARSetProcessDataProc are replaced by +the single callback function installed with RARSetCallback. +Unlike old style callbacks, the new function accepts the user defined +parameter. Unrar.dll still supports RARSetChangeVolProc and +RARSetProcessDataProc for compatibility purposes, but if you write +a new application, better use RARSetCallback. + +File comments support is not implemented in the new DLL version yet. +Now CmtState is always 0. + + +-- 13 August 2001 + +Added RARGetDllVersion function, so you may distinguish old unrar.dll, +which used C style callback functions and the new one with PASCAL callbacks. + + +-- 10 May 2001 + +Callback functions in RARSetChangeVolProc and RARSetProcessDataProc +use PASCAL style call convention now. diff --git a/lib/unrar2/UnRARDLL/x64/readme.txt b/lib/unrar2/UnRARDLL/x64/readme.txt new file mode 100644 index 00000000..bbfb340d --- /dev/null +++ b/lib/unrar2/UnRARDLL/x64/readme.txt @@ -0,0 +1 @@ +This is x64 version of unrar.dll. diff --git a/lib/unrar2/unrar64.dll b/lib/unrar2/UnRARDLL/x64/unrar64.dll similarity index 100% rename from lib/unrar2/unrar64.dll rename to lib/unrar2/UnRARDLL/x64/unrar64.dll diff --git a/lib/unrar2/UnRARDLL/x64/unrar64.lib b/lib/unrar2/UnRARDLL/x64/unrar64.lib new file mode 100644 index 00000000..fd037919 Binary files /dev/null and b/lib/unrar2/UnRARDLL/x64/unrar64.lib differ diff --git a/lib/unrar2/__init__.py b/lib/unrar2/__init__.py index b5c9a4d3..fe27cfe1 100644 --- a/lib/unrar2/__init__.py +++ b/lib/unrar2/__init__.py @@ -33,7 +33,7 @@ similar to the C interface provided by UnRAR. There is also a higher level interface which makes some common operations easier. """ -__version__ = '0.99.2' +__version__ = '0.99.3' try: WindowsError diff --git a/lib/unrar2/license.txt b/lib/unrar2/license.txt new file mode 100644 index 00000000..a395801b --- /dev/null +++ b/lib/unrar2/license.txt @@ -0,0 +1,21 @@ +Copyright (c) 2003-2005 Jimmy Retzlaff, 2008 Konstantin Yegupov + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/unrar2/setup.py b/lib/unrar2/setup.py new file mode 100644 index 00000000..7fab60fe --- /dev/null +++ b/lib/unrar2/setup.py @@ -0,0 +1,54 @@ +# setup.py, config file for distutils + +import __init__ + +from distutils.core import setup +from distutils.command.install_data import install_data +import os + + +class smart_install_data(install_data): + def run(self): + #need to change self.install_dir to the actual library dir + install_cmd = self.get_finalized_command('install') + self.install_dir = getattr(install_cmd, 'install_lib') + return install_data.run(self) + + +data_files = [] +for dirpath, dirnames, filenames in os.walk(r'.'): + for dirname in ['.svn','build', 'dist', '_sgbak', '.hg']: + try: + dirnames.remove(dirname) + except ValueError: + pass + for filename in [fn for fn in filenames if os.path.splitext(fn)[-1].lower() in ('.pyc', '.pyo', '.scc')]: + filenames.remove(filename) + parts = ['UnRAR2']+dirpath.split(os.sep)[1:] + + data_files.append((os.path.join(*parts), [os.path.join(dirpath, fn) for fn in filenames])) + +setup(name='pyUnRAR2', + version=__init__.__version__, + description='Improved Python wrapper around the free UnRAR.dll', + long_description=__init__.__doc__.strip(), + author='Konstantin Yegupov', + author_email='yk4ever@gmail.com', + url='http://code.google.com/py-unrar2', + license='MIT', + platforms='Windows', + classifiers=[ + 'Development Status :: 4 - Beta', + 'Environment :: Win32 (MS Windows)', + 'License :: OSI Approved :: MIT License', + 'Natural Language :: English', + 'Operating System :: Microsoft :: Windows', + 'Programming Language :: Python', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: System :: Archiving :: Compression', + ], + packages=['UnRAR2'], + package_dir={'UnRAR2' : ''}, + data_files=data_files, + cmdclass = {'install_data': smart_install_data}, + ) diff --git a/lib/unrar2/test.rar b/lib/unrar2/test.rar new file mode 100644 index 00000000..c1ee72b9 Binary files /dev/null and b/lib/unrar2/test.rar differ diff --git a/lib/unrar2/test_UnRAR2.py b/lib/unrar2/test_UnRAR2.py new file mode 100644 index 00000000..13c092b6 --- /dev/null +++ b/lib/unrar2/test_UnRAR2.py @@ -0,0 +1,138 @@ +import os, sys + +import UnRAR2 +from UnRAR2.rar_exceptions import * + + +def cleanup(dir='test'): + for path, dirs, files in os.walk(dir): + for fn in files: + os.remove(os.path.join(path, fn)) + for dir in dirs: + os.removedirs(os.path.join(path, dir)) + + +# basic test +cleanup() +rarc = UnRAR2.RarFile('test.rar') +rarc.infolist() +assert rarc.comment == "This is a test." +for info in rarc.infoiter(): + saveinfo = info + assert (str(info)=="""""") + break +rarc.extract() +assert os.path.exists('test'+os.sep+'test.txt') +assert os.path.exists('test'+os.sep+'this.py') +del rarc +assert (str(saveinfo)=="""""") +cleanup() + +# extract all the files in test.rar +cleanup() +UnRAR2.RarFile('test.rar').extract() +assert os.path.exists('test'+os.sep+'test.txt') +assert os.path.exists('test'+os.sep+'this.py') +cleanup() + +# extract all the files in test.rar matching the wildcard *.txt +cleanup() +UnRAR2.RarFile('test.rar').extract('*.txt') +assert os.path.exists('test'+os.sep+'test.txt') +assert not os.path.exists('test'+os.sep+'this.py') +cleanup() + + +# check the name and size of each file, extracting small ones +cleanup() +archive = UnRAR2.RarFile('test.rar') +assert archive.comment == 'This is a test.' +archive.extract(lambda rarinfo: rarinfo.size <= 1024) +for rarinfo in archive.infoiter(): + if rarinfo.size <= 1024 and not rarinfo.isdir: + assert rarinfo.size == os.stat(rarinfo.filename).st_size +assert file('test'+os.sep+'test.txt', 'rt').read() == 'This is only a test.' +assert not os.path.exists('test'+os.sep+'this.py') +cleanup() + + +# extract this.py, overriding it's destination +cleanup('test2') +archive = UnRAR2.RarFile('test.rar') +archive.extract('*.py', 'test2', False) +assert os.path.exists('test2'+os.sep+'this.py') +cleanup('test2') + + +# extract test.txt to memory +cleanup() +archive = UnRAR2.RarFile('test.rar') +entries = UnRAR2.RarFile('test.rar').read_files('*test.txt') +assert len(entries)==1 +assert entries[0][0].filename.endswith('test.txt') +assert entries[0][1]=='This is only a test.' + + +# extract all the files in test.rar with overwriting +cleanup() +fo = open('test'+os.sep+'test.txt',"wt") +fo.write("blah") +fo.close() +UnRAR2.RarFile('test.rar').extract('*.txt') +assert open('test'+os.sep+'test.txt',"rt").read()!="blah" +cleanup() + +# extract all the files in test.rar without overwriting +cleanup() +fo = open('test'+os.sep+'test.txt',"wt") +fo.write("blahblah") +fo.close() +UnRAR2.RarFile('test.rar').extract('*.txt', overwrite = False) +assert open('test'+os.sep+'test.txt',"rt").read()=="blahblah" +cleanup() + +# list big file in an archive +list(UnRAR2.RarFile('test_nulls.rar').infoiter()) + +# extract files from an archive with protected files +cleanup() +rarc = UnRAR2.RarFile('test_protected_files.rar', password="protected") +rarc.extract() +assert os.path.exists('test'+os.sep+'top_secret_xxx_file.txt') +cleanup() +errored = False +try: + UnRAR2.RarFile('test_protected_files.rar', password="proteqted").extract() +except IncorrectRARPassword: + errored = True +assert not os.path.exists('test'+os.sep+'top_secret_xxx_file.txt') +assert errored +cleanup() + +# extract files from an archive with protected headers +cleanup() +UnRAR2.RarFile('test_protected_headers.rar', password="secret").extract() +assert os.path.exists('test'+os.sep+'top_secret_xxx_file.txt') +cleanup() +errored = False +try: + UnRAR2.RarFile('test_protected_headers.rar', password="seqret").extract() +except IncorrectRARPassword: + errored = True +assert not os.path.exists('test'+os.sep+'top_secret_xxx_file.txt') +assert errored +cleanup() + +# make sure docstring examples are working +import doctest +doctest.testmod(UnRAR2) + +# update documentation +import pydoc +pydoc.writedoc(UnRAR2) + +# cleanup +try: + os.remove('__init__.pyc') +except: + pass diff --git a/lib/unrar2/test_nulls.rar b/lib/unrar2/test_nulls.rar new file mode 100644 index 00000000..84352e26 Binary files /dev/null and b/lib/unrar2/test_nulls.rar differ diff --git a/lib/unrar2/test_protected_files.rar b/lib/unrar2/test_protected_files.rar new file mode 100644 index 00000000..8e55a6d3 Binary files /dev/null and b/lib/unrar2/test_protected_files.rar differ diff --git a/lib/unrar2/test_protected_headers.rar b/lib/unrar2/test_protected_headers.rar new file mode 100644 index 00000000..7fba0d2e Binary files /dev/null and b/lib/unrar2/test_protected_headers.rar differ diff --git a/lib/unrar2/unix.py b/lib/unrar2/unix.py index 21f384cf..bd9ee859 100644 --- a/lib/unrar2/unix.py +++ b/lib/unrar2/unix.py @@ -33,115 +33,158 @@ from rar_exceptions import * class UnpackerNotInstalled(Exception): pass rar_executable_cached = None +rar_executable_version = None def call_unrar(params): "Calls rar/unrar command line executable, returns stdout pipe" global rar_executable_cached if rar_executable_cached is None: - for command in ('unrar', 'rar', os.path.join(os.path.dirname(__file__), 'unrar')): + for command in ('unrar', 'rar'): try: - subprocess.Popen([command], stdout = subprocess.PIPE) + subprocess.Popen([command], stdout=subprocess.PIPE) rar_executable_cached = command break except OSError: pass if rar_executable_cached is None: raise UnpackerNotInstalled("No suitable RAR unpacker installed") - + assert type(params) == list, "params must be list" args = [rar_executable_cached] + params try: gc.disable() # See http://bugs.python.org/issue1336 - return subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.PIPE) + return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) finally: gc.enable() class RarFileImplementation(object): - def init(self, password = None): + def init(self, password=None): + global rar_executable_version self.password = password - - - + + stdoutdata, stderrdata = self.call('v', []).communicate() - + for line in stderrdata.splitlines(): if line.strip().startswith("Cannot open"): raise FileOpenError - if line.find("CRC failed") >= 0: - raise IncorrectRARPassword + if line.find("CRC failed")>=0: + raise IncorrectRARPassword accum = [] source = iter(stdoutdata.splitlines()) line = '' - while not (line.startswith('Comment:') or line.startswith('Pathname/Comment')): - if line.strip().endswith('is not RAR archive'): - raise InvalidRARArchive + while not (line.startswith('UNRAR')): line = source.next() - while not line.startswith('Pathname/Comment'): - accum.append(line.rstrip('\n')) + signature = line + # The code below is mighty flaky + # and will probably crash on localized versions of RAR + # but I see no safe way to rewrite it using a CLI tool + if signature.startswith("UNRAR 4"): + rar_executable_version = 4 + while not (line.startswith('Comment:') or line.startswith('Pathname/Comment')): + if line.strip().endswith('is not RAR archive'): + raise InvalidRARArchive + line = source.next() + while not line.startswith('Pathname/Comment'): + accum.append(line.rstrip('\n')) + line = source.next() + if len(accum): + accum[0] = accum[0][9:] # strip out "Comment:" part + self.comment = '\n'.join(accum[:-1]) + else: + self.comment = None + elif signature.startswith("UNRAR 5"): + rar_executable_version = 5 line = source.next() - if len(accum): - accum[0] = accum[0][9:] - self.comment = '\n'.join(accum[:-1]) + while not line.startswith('Archive:'): + if line.strip().endswith('is not RAR archive'): + raise InvalidRARArchive + accum.append(line.rstrip('\n')) + line = source.next() + if len(accum): + self.comment = '\n'.join(accum[:-1]).strip() + else: + self.comment = None else: - self.comment = None - + raise UnpackerNotInstalled("Unsupported RAR version, expected 4.x or 5.x, found: " + + signature.split(" ")[1]) + + def escaped_password(self): return '-' if self.password == None else self.password - - - def call(self, cmd, options = [], files = []): - options2 = options + ['p' + self.escaped_password()] - soptions = ['-' + x for x in options2] - return call_unrar([cmd] + soptions + ['--', self.archiveName] + files) + + + def call(self, cmd, options=[], files=[]): + options2 = options + ['p'+self.escaped_password()] + soptions = ['-'+x for x in options2] + return call_unrar([cmd]+soptions+['--',self.archiveName]+files) def infoiter(self): - - stdoutdata, stderrdata = self.call('v', ['c-']).communicate() - + + command = "v" if rar_executable_version == 4 else "l" + stdoutdata, stderrdata = self.call(command, ['c-']).communicate() + for line in stderrdata.splitlines(): if line.strip().startswith("Cannot open"): raise FileOpenError - + accum = [] source = iter(stdoutdata.splitlines()) line = '' - while not line.startswith('--------------'): + while not line.startswith('-----------'): if line.strip().endswith('is not RAR archive'): raise InvalidRARArchive - if line.find("CRC failed") >= 0: - raise IncorrectRARPassword + if line.startswith("CRC failed") or line.startswith("Checksum error"): + raise IncorrectRARPassword line = source.next() line = source.next() i = 0 re_spaces = re.compile(r"\s+") - while not line.startswith('--------------'): - accum.append(line) - if len(accum) == 2: + if rar_executable_version == 4: + while not line.startswith('-----------'): + accum.append(line) + if len(accum)==2: + data = {} + data['index'] = i + # asterisks mark password-encrypted files + data['filename'] = accum[0].strip().lstrip("*") # asterisks marks password-encrypted files + fields = re_spaces.split(accum[1].strip()) + data['size'] = int(fields[0]) + attr = fields[5] + data['isdir'] = 'd' in attr.lower() + data['datetime'] = time.strptime(fields[3]+" "+fields[4], '%d-%m-%y %H:%M') + data['comment'] = None + yield data + accum = [] + i += 1 + line = source.next() + elif rar_executable_version == 5: + while not line.startswith('-----------'): + fields = line.strip().lstrip("*").split() data = {} data['index'] = i - data['filename'] = accum[0].strip() - info = re_spaces.split(accum[1].strip()) - data['size'] = int(info[0]) - attr = info[5] + data['filename'] = " ".join(fields[4:]) + data['size'] = int(fields[1]) + attr = fields[0] data['isdir'] = 'd' in attr.lower() - data['datetime'] = time.strptime(info[3] + " " + info[4], '%d-%m-%y %H:%M') + data['datetime'] = time.strptime(fields[2]+" "+fields[3], '%d-%m-%y %H:%M') data['comment'] = None yield data - accum = [] i += 1 - line = source.next() + line = source.next() + def read_files(self, checker): res = [] for info in self.infoiter(): checkres = checker(info) - if checkres == True and not info.isdir: + if checkres==True and not info.isdir: pipe = self.call('p', ['inul'], [info.filename]).stdout res.append((info, pipe.read())) - return res - + return res + def extract(self, checker, path, withSubpath, overwrite): res = [] command = 'x' @@ -151,7 +194,7 @@ class RarFileImplementation(object): if overwrite: options.append('o+') else: - options.append('o-') + options.append('o-') if not path.endswith(os.sep): path += os.sep names = [] @@ -159,17 +202,17 @@ class RarFileImplementation(object): checkres = checker(info) if type(checkres) in [str, unicode]: raise NotImplementedError("Condition callbacks returning strings are deprecated and only supported in Windows") - if checkres == True and not info.isdir: + if checkres==True and not info.isdir: names.append(info.filename) res.append(info) names.append(path) proc = self.call(command, options, names) stdoutdata, stderrdata = proc.communicate() - if stderrdata.find("CRC failed") >= 0: - raise IncorrectRARPassword - return res - + if stderrdata.find("CRC failed")>=0 or stderrdata.find("Checksum error")>=0: + raise IncorrectRARPassword + return res + def destruct(self): pass - + diff --git a/lib/unrar2/unrar b/lib/unrar2/unrar deleted file mode 100644 index 3de16761..00000000 Binary files a/lib/unrar2/unrar and /dev/null differ diff --git a/lib/unrar2/windows.py b/lib/unrar2/windows.py index 4a0062a7..bb92481b 100644 --- a/lib/unrar2/windows.py +++ b/lib/unrar2/windows.py @@ -64,11 +64,11 @@ UCM_NEEDPASSWORD = 2 architecture_bits = ctypes.sizeof(ctypes.c_voidp)*8 dll_name = "unrar.dll" if architecture_bits == 64: - dll_name = "unrar64.dll" + dll_name = "x64\\unrar64.dll" try: - unrar = ctypes.WinDLL(os.path.join(os.path.split(__file__)[0], dll_name)) + unrar = ctypes.WinDLL(os.path.join(os.path.split(__file__)[0], 'UnRARDLL', dll_name)) except WindowsError: unrar = ctypes.WinDLL(dll_name) @@ -304,4 +304,6 @@ class RarFileImplementation(object): self.needskip = False res.append(info) - return res \ No newline at end of file + return res + + diff --git a/tests/xem_tests.py b/tests/xem_tests.py index e2045208..7e0c2326 100644 --- a/tests/xem_tests.py +++ b/tests/xem_tests.py @@ -22,6 +22,7 @@ from __future__ import with_statement import unittest import sys, os.path import datetime +import re sys.path.append(os.path.abspath('..')) sys.path.append(os.path.abspath('../lib')) @@ -64,11 +65,16 @@ class XEMBasicTests(test.SickbeardTestDBCase): print "There was an error creating the show" def test_formating(self): - release = "UFC.172.26th.April.2014.HDTV.x264.720p-Sir.Paul[rartv]" - # parse the name to break it into show name, season, and episode - np = NameParser(file) - parse_result = np.parse(release).convert() - airdate = parse_result.sports_event_date.toordinal() + name = "Game.of.Thrones.S03.720p.HDTV.x264-CtrlHD" + release = "Game of Thrones" + + escaped_name = re.sub('\\\\[\\s.-]', '\W+', re.escape(release)) + curRegex = '^' + escaped_name + '\W+(?:(?:S\d[\dE._ -])|(?:\d\d?x)|(?:\d{4}\W\d\d\W\d\d)|(?:(?:part|pt)[\._ -]?(\d|[ivx]))|Season\W+\d+\W+|E\d+\W+|(?:\d{1,3}.+\d{1,}[a-zA-Z]{2}\W+[a-zA-Z]{3,}\W+\d{4}.+))' + print(u"Checking if show " + name + " matches " + curRegex) + + match = re.search(curRegex, name, re.I) + if match: + print(u"Matched " + curRegex + " to " + name) print(parse_result)