wiki:RarSourceCodes

Version 4 (modified by guest, 15 years ago) (diff)

Removed Ruby-code and added more links

Programming Languages

  1. Python

These snippets should be useful to read RAR archives with store compression (which means none compression is used). Feel free to edit/add source-codes if you have faster/better/new language implementation.

Links:

Python

#(c)Kamil Dzióbek turbos11(at)gmail.com
#   BSD License

from struct import *

def getlastsplit(firsrarfile,x):
    if firsrarfile[-3:]=='001':
        return firsrarfile[:-3]+('%03d' %(x+1))
    if firsrarfile[-11:-6]=='.part':
        return firsrarfile[0:-6]+('%02d' % (x+1))+firsrarfile[-4:]
    if firsrarfile[-10:-5]=='.part':
        return firsrarfile[0:-5]+('%1d' % (x+1))+firsrarfile[-4:]
    return firsrarfile[0:-2]+('%02d' %(x-1) )

def addfilehash(name,hash,seek):
    f=open(name, 'rb')
    f.seek(seek)
    for i in range(8192):
        hash+=unpack('<q', f.read(8))[0]
        hash =hash & 0xffffffffffffffff
    return hash


def OpensubtitlesHashRar(firsrarfile):
    """Hash file in rar split archive. -> (size,hash)"""
    if not(firsrarfile.lower().endswith('.rar') | firsrarfile.endswith('.001')):
        raise Exception('Bad file suffix. Only .rar and .001 support.')
    if firsrarfile[-11:-6]=='.part':
        firsrarfile=firsrarfile[0:-6]+'01'+firsrarfile[-4:]
    f=open(firsrarfile, 'rb')
    a=f.read(4)
    if a!='Rar!':
        raise Exception('ERROR: This is not rar file.')
    seek=0
    for i in range(4):
        f.seek(seek)
        a=f.read(100)
        type,flag,size=unpack( '<BHH', a[2:2+5]) 
        if 0x74==type:
            if 0x30!=unpack( '<B', a[25:25+1])[0]:
                raise Exception('Bad compression method! Work only for "store".')            
            s_partiizebodystart=seek+size
            s_partiizebody,s_unpacksize=unpack( '<II', a[7:7+2*4])
            if (flag & 0x0100):
                s_unpacksize=(unpack( '<I', a[36:36+4])[0] <<32 )+s_unpacksize
                print 'Hash untested for files biger that 2gb. May work or may generate bad hash.'
            lastrarfile=getlastsplit(firsrarfile,(s_unpacksize-1)/s_partiizebody)
            hash=addfilehash(firsrarfile,s_unpacksize,s_partiizebodystart)
            hash=addfilehash(lastrarfile,hash,(s_unpacksize%s_partiizebody)+s_partiizebodystart-65536)
            return (s_unpacksize,"%016x" % hash )
        seek+=size
    raise Exception('ERROR: Not Body part in rar file.')

#example
firsrarsplitfile='I:\\test.rar'
size,hash=OpensubtitlesHashRar(firsrarsplitfile)
print 'use this valuse on opensubtiles.com\n\tsize is: %d\n\thash is: %s' % (size,hash)