2010-12-31 04:41:07 +06:00
#!/usr/bin/env python
2012-12-19 19:48:11 +06:00
# -*- coding: utf-8 -*-
2010-12-31 04:41:07 +06:00
2013-03-26 22:38:18 +06:00
# topazextract.py
2012-12-19 19:48:11 +06:00
# Mostly written by some_updates based on code from many others
2013-03-26 22:38:18 +06:00
# Changelog
# 4.9 - moved unicode_argv call inside main for Windows DeDRM compatibility
2013-04-10 16:50:10 +06:00
# 5.0 - Fixed potential unicode problem with command line interface
2013-03-26 22:38:18 +06:00
2013-04-10 16:50:10 +06:00
__version__ = ' 5.0 '
2012-12-19 19:48:11 +06:00
import sys
import os , csv , getopt
import zlib , zipfile , tempfile , shutil
import traceback
from struct import pack
from struct import unpack
from alfcrypto import Topaz_Cipher
class SafeUnbuffered :
2010-12-31 04:41:07 +06:00
def __init__ ( self , stream ) :
self . stream = stream
2012-12-19 19:48:11 +06:00
self . encoding = stream . encoding
if self . encoding == None :
self . encoding = " utf-8 "
2010-12-31 04:41:07 +06:00
def write ( self , data ) :
2012-12-19 19:48:11 +06:00
if isinstance ( data , unicode ) :
data = data . encode ( self . encoding , " replace " )
2010-12-31 04:41:07 +06:00
self . stream . write ( data )
self . stream . flush ( )
def __getattr__ ( self , attr ) :
return getattr ( self . stream , attr )
2012-12-19 19:48:11 +06:00
iswindows = sys . platform . startswith ( ' win ' )
isosx = sys . platform . startswith ( ' darwin ' )
def unicode_argv ( ) :
if iswindows :
# Uses shell32.GetCommandLineArgvW to get sys.argv as a list of Unicode
# strings.
# Versions 2.x of Python don't support Unicode in sys.argv on
# Windows, with the underlying Windows API instead replacing multi-byte
# characters with '?'.
from ctypes import POINTER , byref , cdll , c_int , windll
from ctypes . wintypes import LPCWSTR , LPWSTR
GetCommandLineW = cdll . kernel32 . GetCommandLineW
GetCommandLineW . argtypes = [ ]
GetCommandLineW . restype = LPCWSTR
CommandLineToArgvW = windll . shell32 . CommandLineToArgvW
CommandLineToArgvW . argtypes = [ LPCWSTR , POINTER ( c_int ) ]
CommandLineToArgvW . restype = POINTER ( LPWSTR )
cmd = GetCommandLineW ( )
argc = c_int ( 0 )
argv = CommandLineToArgvW ( cmd , byref ( argc ) )
if argc . value > 0 :
# Remove Python executable and commands if present
start = argc . value - len ( sys . argv )
return [ argv [ i ] for i in
xrange ( start , argc . value ) ]
# if we don't have any arguments at all, just pass back script name
# this should never happen
return [ u " mobidedrm.py " ]
else :
argvencoding = sys . stdin . encoding
if argvencoding == None :
argvencoding = ' utf-8 '
2013-06-12 00:41:21 +06:00
return [ arg if ( type ( arg ) == unicode ) else unicode ( arg , argvencoding ) for arg in sys . argv ]
2011-06-16 11:59:20 +06:00
2012-12-27 05:17:56 +06:00
#global switch
debug = False
2011-06-16 11:59:20 +06:00
if ' calibre ' in sys . modules :
inCalibre = True
2013-03-20 16:23:54 +06:00
from calibre_plugins . dedrm import kgenpids
2011-06-16 11:59:20 +06:00
else :
inCalibre = False
2012-12-19 19:48:11 +06:00
import kgenpids
2011-06-16 11:59:20 +06:00
2012-05-16 22:15:43 +06:00
2012-12-19 19:48:11 +06:00
class DrmException ( Exception ) :
2010-12-31 04:41:07 +06:00
pass
2011-06-16 11:59:20 +06:00
2012-03-07 00:24:28 +06:00
2011-06-16 11:59:20 +06:00
# recursive zip creation support routine
def zipUpDir ( myzip , tdir , localname ) :
currentdir = tdir
2012-12-19 19:48:11 +06:00
if localname != u " " :
2013-06-12 00:41:21 +06:00
currentdir = os . path . join ( currentdir , localname )
2011-06-16 11:59:20 +06:00
list = os . listdir ( currentdir )
for file in list :
afilename = file
localfilePath = os . path . join ( localname , afilename )
2013-06-12 00:41:21 +06:00
realfilePath = os . path . join ( currentdir , file )
2011-06-16 11:59:20 +06:00
if os . path . isfile ( realfilePath ) :
myzip . write ( realfilePath , localfilePath )
elif os . path . isdir ( realfilePath ) :
zipUpDir ( myzip , tdir , localfilePath )
2010-12-31 04:41:07 +06:00
#
# Utility routines
#
# Get a 7 bit encoded number from file
def bookReadEncodedNumber ( fo ) :
flag = False
data = ord ( fo . read ( 1 ) )
if data == 0xFF :
2012-03-07 00:24:28 +06:00
flag = True
data = ord ( fo . read ( 1 ) )
2010-12-31 04:41:07 +06:00
if data > = 0x80 :
datax = ( data & 0x7F )
2013-06-12 00:41:21 +06:00
while data > = 0x80 :
2010-12-31 04:41:07 +06:00
data = ord ( fo . read ( 1 ) )
datax = ( datax << 7 ) + ( data & 0x7F )
2012-03-07 00:24:28 +06:00
data = datax
2010-12-31 04:41:07 +06:00
if flag :
2012-03-07 00:24:28 +06:00
data = - data
2010-12-31 04:41:07 +06:00
return data
2012-03-07 00:24:28 +06:00
# Get a length prefixed string from file
2010-12-31 04:41:07 +06:00
def bookReadString ( fo ) :
stringLength = bookReadEncodedNumber ( fo )
2012-12-19 19:48:11 +06:00
return unpack ( str ( stringLength ) + ' s ' , fo . read ( stringLength ) ) [ 0 ]
2010-12-31 04:41:07 +06:00
#
# crypto routines
#
# Context initialisation for the Topaz Crypto
def topazCryptoInit ( key ) :
2012-03-07 00:24:28 +06:00
return Topaz_Cipher ( ) . ctx_init ( key )
# ctx1 = 0x0CAFFE19E
# for keyChar in key:
# keyByte = ord(keyChar)
# ctx2 = ctx1
# ctx1 = ((((ctx1 >>2) * (ctx1 >>7))&0xFFFFFFFF) ^ (keyByte * keyByte * 0x0F902007)& 0xFFFFFFFF )
# return [ctx1,ctx2]
2010-12-31 04:41:07 +06:00
# decrypt data with the context prepared by topazCryptoInit()
def topazCryptoDecrypt ( data , ctx ) :
2012-03-07 00:24:28 +06:00
return Topaz_Cipher ( ) . decrypt ( data , ctx )
# ctx1 = ctx[0]
# ctx2 = ctx[1]
# plainText = ""
# for dataChar in data:
# dataByte = ord(dataChar)
# m = (dataByte ^ ((ctx1 >> 3) &0xFF) ^ ((ctx2<<3) & 0xFF)) &0xFF
# ctx2 = ctx1
# ctx1 = (((ctx1 >> 2) * (ctx1 >> 7)) &0xFFFFFFFF) ^((m * m * 0x0F902007) &0xFFFFFFFF)
# plainText += chr(m)
# return plainText
2010-12-31 04:41:07 +06:00
# Decrypt data with the PID
def decryptRecord ( data , PID ) :
ctx = topazCryptoInit ( PID )
return topazCryptoDecrypt ( data , ctx )
# Try to decrypt a dkey record (contains the bookPID)
def decryptDkeyRecord ( data , PID ) :
record = decryptRecord ( data , PID )
2012-12-19 19:48:11 +06:00
fields = unpack ( ' 3sB8sB8s3s ' , record )
if fields [ 0 ] != ' PID ' or fields [ 5 ] != ' pid ' :
raise DrmException ( u " Didn ' t find PID magic numbers in record " )
2010-12-31 04:41:07 +06:00
elif fields [ 1 ] != 8 or fields [ 3 ] != 8 :
2012-12-19 19:48:11 +06:00
raise DrmException ( u " Record didn ' t contain correct length fields " )
2010-12-31 04:41:07 +06:00
elif fields [ 2 ] != PID :
2012-12-19 19:48:11 +06:00
raise DrmException ( u " Record didn ' t contain PID " )
2010-12-31 04:41:07 +06:00
return fields [ 4 ]
# Decrypt all dkey records (contain the book PID)
def decryptDkeyRecords ( data , PID ) :
nbKeyRecords = ord ( data [ 0 ] )
records = [ ]
data = data [ 1 : ]
for i in range ( 0 , nbKeyRecords ) :
length = ord ( data [ 0 ] )
try :
key = decryptDkeyRecord ( data [ 1 : length + 1 ] , PID )
records . append ( key )
2012-12-19 19:48:11 +06:00
except DrmException :
2010-12-31 04:41:07 +06:00
pass
data = data [ 1 + length : ]
if len ( records ) == 0 :
2012-12-19 19:48:11 +06:00
raise DrmException ( u " BookKey Not Found " )
2010-12-31 04:41:07 +06:00
return records
class TopazBook :
2011-06-16 11:59:20 +06:00
def __init__ ( self , filename ) :
2010-12-31 04:41:07 +06:00
self . fo = file ( filename , ' rb ' )
2011-06-16 11:59:20 +06:00
self . outdir = tempfile . mkdtemp ( )
2011-10-28 12:24:15 +06:00
# self.outdir = 'rawdat'
2010-12-31 04:41:07 +06:00
self . bookPayloadOffset = 0
self . bookHeaderRecords = { }
self . bookMetadata = { }
self . bookKey = None
2012-12-19 19:48:11 +06:00
magic = unpack ( ' 4s ' , self . fo . read ( 4 ) ) [ 0 ]
2010-12-31 04:41:07 +06:00
if magic != ' TPZ0 ' :
2012-12-19 19:48:11 +06:00
raise DrmException ( u " Parse Error : Invalid Header, not a Topaz file " )
2010-12-31 04:41:07 +06:00
self . parseTopazHeaders ( )
self . parseMetadata ( )
def parseTopazHeaders ( self ) :
def bookReadHeaderRecordData ( ) :
2012-03-07 00:24:28 +06:00
# Read and return the data of one header record at the current book file position
2010-12-31 04:41:07 +06:00
# [[offset,decompressedLength,compressedLength],...]
nbValues = bookReadEncodedNumber ( self . fo )
2012-12-27 05:17:56 +06:00
if debug : print " %d records in header " % nbValues ,
2010-12-31 04:41:07 +06:00
values = [ ]
for i in range ( 0 , nbValues ) :
values . append ( [ bookReadEncodedNumber ( self . fo ) , bookReadEncodedNumber ( self . fo ) , bookReadEncodedNumber ( self . fo ) ] )
return values
def parseTopazHeaderRecord ( ) :
# Read and parse one header record at the current book file position and return the associated data
# [[offset,decompressedLength,compressedLength],...]
if ord ( self . fo . read ( 1 ) ) != 0x63 :
2012-12-19 19:48:11 +06:00
raise DrmException ( u " Parse Error : Invalid Header " )
2010-12-31 04:41:07 +06:00
tag = bookReadString ( self . fo )
record = bookReadHeaderRecordData ( )
return [ tag , record ]
nbRecords = bookReadEncodedNumber ( self . fo )
2012-12-27 05:17:56 +06:00
if debug : print " Headers: %d " % nbRecords
2010-12-31 04:41:07 +06:00
for i in range ( 0 , nbRecords ) :
result = parseTopazHeaderRecord ( )
2012-12-27 05:17:56 +06:00
if debug : print result [ 0 ] , " : " , result [ 1 ]
2010-12-31 04:41:07 +06:00
self . bookHeaderRecords [ result [ 0 ] ] = result [ 1 ]
if ord ( self . fo . read ( 1 ) ) != 0x64 :
2012-12-19 19:48:11 +06:00
raise DrmException ( u " Parse Error : Invalid Header " )
2010-12-31 04:41:07 +06:00
self . bookPayloadOffset = self . fo . tell ( )
def parseMetadata ( self ) :
# Parse the metadata record from the book payload and return a list of [key,values]
2012-12-19 19:48:11 +06:00
self . fo . seek ( self . bookPayloadOffset + self . bookHeaderRecords [ ' metadata ' ] [ 0 ] [ 0 ] )
2010-12-31 04:41:07 +06:00
tag = bookReadString ( self . fo )
2012-12-19 19:48:11 +06:00
if tag != ' metadata ' :
raise DrmException ( u " Parse Error : Record Names Don ' t Match " )
2010-12-31 04:41:07 +06:00
flags = ord ( self . fo . read ( 1 ) )
nbRecords = ord ( self . fo . read ( 1 ) )
2012-12-27 05:17:56 +06:00
if debug : print " Metadata Records: %d " % nbRecords
2010-12-31 04:41:07 +06:00
for i in range ( 0 , nbRecords ) :
2011-02-18 17:37:27 +06:00
keyval = bookReadString ( self . fo )
content = bookReadString ( self . fo )
2012-12-27 05:17:56 +06:00
if debug : print keyval
if debug : print content
2011-02-18 17:37:27 +06:00
self . bookMetadata [ keyval ] = content
2010-12-31 04:41:07 +06:00
return self . bookMetadata
def getPIDMetaInfo ( self ) :
2011-02-18 17:37:27 +06:00
keysRecord = self . bookMetadata . get ( ' keys ' , ' ' )
keysRecordRecord = ' '
if keysRecord != ' ' :
keylst = keysRecord . split ( ' , ' )
for keyval in keylst :
keysRecordRecord + = self . bookMetadata . get ( keyval , ' ' )
2010-12-31 04:41:07 +06:00
return keysRecord , keysRecordRecord
def getBookTitle ( self ) :
title = ' '
if ' Title ' in self . bookMetadata :
title = self . bookMetadata [ ' Title ' ]
2012-12-19 19:48:11 +06:00
return title . decode ( ' utf-8 ' )
2010-12-31 04:41:07 +06:00
def setBookKey ( self , key ) :
self . bookKey = key
def getBookPayloadRecord ( self , name , index ) :
2012-03-07 00:24:28 +06:00
# Get a record in the book payload, given its name and index.
# decrypted and decompressed if necessary
2010-12-31 04:41:07 +06:00
encrypted = False
compressed = False
2012-03-07 00:24:28 +06:00
try :
2010-12-31 04:41:07 +06:00
recordOffset = self . bookHeaderRecords [ name ] [ index ] [ 0 ]
except :
2012-12-19 19:48:11 +06:00
raise DrmException ( " Parse Error : Invalid Record, record not found " )
2010-12-31 04:41:07 +06:00
self . fo . seek ( self . bookPayloadOffset + recordOffset )
tag = bookReadString ( self . fo )
if tag != name :
2012-12-19 19:48:11 +06:00
raise DrmException ( " Parse Error : Invalid Record, record name doesn ' t match " )
2010-12-31 04:41:07 +06:00
recordIndex = bookReadEncodedNumber ( self . fo )
if recordIndex < 0 :
encrypted = True
recordIndex = - recordIndex - 1
if recordIndex != index :
2012-12-19 19:48:11 +06:00
raise DrmException ( " Parse Error : Invalid Record, index doesn ' t match " )
2010-12-31 04:41:07 +06:00
if ( self . bookHeaderRecords [ name ] [ index ] [ 2 ] > 0 ) :
compressed = True
record = self . fo . read ( self . bookHeaderRecords [ name ] [ index ] [ 2 ] )
else :
record = self . fo . read ( self . bookHeaderRecords [ name ] [ index ] [ 1 ] )
if encrypted :
if self . bookKey :
ctx = topazCryptoInit ( self . bookKey )
record = topazCryptoDecrypt ( record , ctx )
else :
2012-12-19 19:48:11 +06:00
raise DrmException ( " Error: Attempt to decrypt without bookKey " )
2010-12-31 04:41:07 +06:00
if compressed :
record = zlib . decompress ( record )
return record
def processBook ( self , pidlst ) :
raw = 0
fixedimage = True
try :
keydata = self . getBookPayloadRecord ( ' dkey ' , 0 )
2012-12-19 19:48:11 +06:00
except DrmException , e :
print u " no dkey record found, book may not be encrypted "
print u " attempting to extrct files without a book key "
2010-12-31 04:41:07 +06:00
self . createBookDirectory ( )
self . extractFiles ( )
2012-12-19 19:48:11 +06:00
print u " Successfully Extracted Topaz contents "
2012-09-09 06:45:24 +06:00
if inCalibre :
2013-03-20 16:23:54 +06:00
from calibre_plugins . dedrm import genbook
2012-09-09 06:45:24 +06:00
else :
import genbook
2012-11-20 19:28:12 +06:00
2010-12-31 04:41:07 +06:00
rv = genbook . generateBook ( self . outdir , raw , fixedimage )
if rv == 0 :
2012-12-19 19:48:11 +06:00
print u " Book Successfully generated. "
2012-03-07 00:24:28 +06:00
return rv
2010-12-31 04:41:07 +06:00
# try each pid to decode the file
bookKey = None
for pid in pidlst :
# use 8 digit pids here
pid = pid [ 0 : 8 ]
2012-12-19 19:48:11 +06:00
print u " Trying: {0} " . format ( pid )
2010-12-31 04:41:07 +06:00
bookKeys = [ ]
data = keydata
try :
bookKeys + = decryptDkeyRecords ( data , pid )
2012-12-19 19:48:11 +06:00
except DrmException , e :
2010-12-31 04:41:07 +06:00
pass
else :
bookKey = bookKeys [ 0 ]
2012-12-19 19:48:11 +06:00
print u " Book Key Found! ( {0} ) " . format ( bookKey . encode ( ' hex ' ) )
2010-12-31 04:41:07 +06:00
break
if not bookKey :
2016-09-29 12:00:11 +06:00
raise DrmException ( u " No key found in {0:d} keys tried. Read the FAQs at Harper ' s repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md " . format ( len ( pidlst ) ) )
2010-12-31 04:41:07 +06:00
self . setBookKey ( bookKey )
self . createBookDirectory ( )
2013-10-03 00:59:40 +06:00
self . extractFiles ( )
2012-12-19 19:48:11 +06:00
print u " Successfully Extracted Topaz contents "
2012-09-09 06:45:24 +06:00
if inCalibre :
2013-03-20 16:23:54 +06:00
from calibre_plugins . dedrm import genbook
2012-09-09 06:45:24 +06:00
else :
import genbook
2012-11-20 19:28:12 +06:00
2010-12-31 04:41:07 +06:00
rv = genbook . generateBook ( self . outdir , raw , fixedimage )
if rv == 0 :
2012-12-19 19:48:11 +06:00
print u " Book Successfully generated "
2012-03-07 00:24:28 +06:00
return rv
2010-12-31 04:41:07 +06:00
def createBookDirectory ( self ) :
outdir = self . outdir
# create output directory structure
if not os . path . exists ( outdir ) :
os . makedirs ( outdir )
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " img " )
2010-12-31 04:41:07 +06:00
if not os . path . exists ( destdir ) :
os . makedirs ( destdir )
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " color_img " )
2010-12-31 04:41:07 +06:00
if not os . path . exists ( destdir ) :
os . makedirs ( destdir )
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " page " )
2010-12-31 04:41:07 +06:00
if not os . path . exists ( destdir ) :
os . makedirs ( destdir )
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " glyphs " )
2010-12-31 04:41:07 +06:00
if not os . path . exists ( destdir ) :
os . makedirs ( destdir )
def extractFiles ( self ) :
outdir = self . outdir
for headerRecord in self . bookHeaderRecords :
name = headerRecord
2012-12-19 19:48:11 +06:00
if name != ' dkey ' :
ext = u " .dat "
if name == ' img ' : ext = u " .jpg "
if name == ' color ' : ext = u " .jpg "
print u " Processing Section: {0} \n . . . " . format ( name ) ,
2010-12-31 04:41:07 +06:00
for index in range ( 0 , len ( self . bookHeaderRecords [ name ] ) ) :
2012-12-19 19:48:11 +06:00
fname = u " {0} {1:04d} {2} " . format ( name , index , ext )
2010-12-31 04:41:07 +06:00
destdir = outdir
if name == ' img ' :
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " img " )
2010-12-31 04:41:07 +06:00
if name == ' color ' :
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " color_img " )
2010-12-31 04:41:07 +06:00
if name == ' page ' :
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " page " )
2010-12-31 04:41:07 +06:00
if name == ' glyphs ' :
2012-12-19 19:48:11 +06:00
destdir = os . path . join ( outdir , u " glyphs " )
2010-12-31 04:41:07 +06:00
outputFile = os . path . join ( destdir , fname )
2012-12-19 19:48:11 +06:00
print u " . " ,
2010-12-31 04:41:07 +06:00
record = self . getBookPayloadRecord ( name , index )
if record != ' ' :
file ( outputFile , ' wb ' ) . write ( record )
2012-12-19 19:48:11 +06:00
print u " "
2010-12-31 04:41:07 +06:00
2012-12-19 19:48:11 +06:00
def getFile ( self , zipname ) :
2011-06-16 11:59:20 +06:00
htmlzip = zipfile . ZipFile ( zipname , ' w ' , zipfile . ZIP_DEFLATED , False )
2012-12-19 19:48:11 +06:00
htmlzip . write ( os . path . join ( self . outdir , u " book.html " ) , u " book.html " )
htmlzip . write ( os . path . join ( self . outdir , u " book.opf " ) , u " book.opf " )
if os . path . isfile ( os . path . join ( self . outdir , u " cover.jpg " ) ) :
htmlzip . write ( os . path . join ( self . outdir , u " cover.jpg " ) , u " cover.jpg " )
htmlzip . write ( os . path . join ( self . outdir , u " style.css " ) , u " style.css " )
zipUpDir ( htmlzip , self . outdir , u " img " )
2011-06-16 11:59:20 +06:00
htmlzip . close ( )
2012-12-19 19:48:11 +06:00
def getBookType ( self ) :
return u " Topaz "
def getBookExtension ( self ) :
return u " .htmlz "
2011-06-16 11:59:20 +06:00
def getSVGZip ( self , zipname ) :
svgzip = zipfile . ZipFile ( zipname , ' w ' , zipfile . ZIP_DEFLATED , False )
2012-12-19 19:48:11 +06:00
svgzip . write ( os . path . join ( self . outdir , u " index_svg.xhtml " ) , u " index_svg.xhtml " )
zipUpDir ( svgzip , self . outdir , u " svg " )
zipUpDir ( svgzip , self . outdir , u " img " )
2011-06-16 11:59:20 +06:00
svgzip . close ( )
2012-11-20 19:28:12 +06:00
2011-06-16 11:59:20 +06:00
def cleanup ( self ) :
if os . path . isdir ( self . outdir ) :
2012-05-16 22:15:43 +06:00
shutil . rmtree ( self . outdir , True )
2010-12-31 04:41:07 +06:00
def usage ( progname ) :
2012-12-19 19:48:11 +06:00
print u " Removes DRM protection from Topaz ebooks and extracts the contents "
print u " Usage: "
2013-03-20 16:23:54 +06:00
print u " {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] <infile> <outdir> " . format ( progname )
2010-12-31 04:41:07 +06:00
# Main
2013-03-26 22:38:18 +06:00
def cli_main ( ) :
argv = unicode_argv ( )
2010-12-31 04:41:07 +06:00
progname = os . path . basename ( argv [ 0 ] )
2012-12-19 19:48:11 +06:00
print u " TopazExtract v {0} . " . format ( __version__ )
2012-03-07 00:24:28 +06:00
2010-12-31 04:41:07 +06:00
try :
2013-04-10 16:50:10 +06:00
opts , args = getopt . getopt ( argv [ 1 : ] , " k:p:s:x " )
2010-12-31 04:41:07 +06:00
except getopt . GetoptError , err :
2012-12-19 19:48:11 +06:00
print u " Error in options or arguments: {0} " . format ( err . args [ 0 ] )
2010-12-31 04:41:07 +06:00
usage ( progname )
return 1
if len ( args ) < 2 :
usage ( progname )
return 1
2012-03-07 00:24:28 +06:00
2012-12-19 19:48:11 +06:00
infile = args [ 0 ]
outdir = args [ 1 ]
if not os . path . isfile ( infile ) :
print u " Input File {0} Does Not Exist. " . format ( infile )
return 1
if not os . path . exists ( outdir ) :
print u " Output Directory {0} Does Not Exist. " . format ( outdir )
return 1
2013-03-20 16:23:54 +06:00
kDatabaseFiles = [ ]
2012-12-19 19:48:11 +06:00
serials = [ ]
pids = [ ]
2010-12-31 04:41:07 +06:00
for o , a in opts :
2012-12-19 19:48:11 +06:00
if o == ' -k ' :
2010-12-31 04:41:07 +06:00
if a == None :
2012-12-19 19:48:11 +06:00
raise DrmException ( " Invalid parameter for -k " )
2013-03-20 16:23:54 +06:00
kDatabaseFiles . append ( a )
2012-12-19 19:48:11 +06:00
if o == ' -p ' :
2010-12-31 04:41:07 +06:00
if a == None :
2012-12-19 19:48:11 +06:00
raise DrmException ( " Invalid parameter for -p " )
2010-12-31 04:41:07 +06:00
pids = a . split ( ' , ' )
2012-12-19 19:48:11 +06:00
if o == ' -s ' :
2010-12-31 04:41:07 +06:00
if a == None :
2012-12-19 19:48:11 +06:00
raise DrmException ( " Invalid parameter for -s " )
serials = [ serial . replace ( " " , " " ) for serial in a . split ( ' , ' ) ]
2010-12-31 04:41:07 +06:00
bookname = os . path . splitext ( os . path . basename ( infile ) ) [ 0 ]
2011-06-16 11:59:20 +06:00
tb = TopazBook ( infile )
2010-12-31 04:41:07 +06:00
title = tb . getBookTitle ( )
2012-12-19 19:48:11 +06:00
print u " Processing Book: {0} " . format ( title )
md1 , md2 = tb . getPIDMetaInfo ( )
2013-03-20 16:23:54 +06:00
pids . extend ( kgenpids . getPidList ( md1 , md2 , serials , kDatabaseFiles ) )
2010-12-31 04:41:07 +06:00
try :
2012-12-19 19:48:11 +06:00
print u " Decrypting Book "
2012-11-20 19:28:12 +06:00
tb . processBook ( pids )
2011-06-16 11:59:20 +06:00
2012-12-19 19:48:11 +06:00
print u " Creating HTML ZIP Archive "
zipname = os . path . join ( outdir , bookname + u " _nodrm.htmlz " )
tb . getFile ( zipname )
2011-06-16 11:59:20 +06:00
2012-12-19 19:48:11 +06:00
print u " Creating SVG ZIP Archive "
zipname = os . path . join ( outdir , bookname + u " _SVG.zip " )
2011-06-16 11:59:20 +06:00
tb . getSVGZip ( zipname )
# removing internal temporary directory of pieces
tb . cleanup ( )
2012-12-19 19:48:11 +06:00
except DrmException , e :
print u " Decryption failed \n {0} " . format ( traceback . format_exc ( ) )
try :
tb . cleanup ( )
except :
pass
2010-12-31 04:41:07 +06:00
return 1
2011-06-16 11:59:20 +06:00
except Exception , e :
2012-12-19 19:48:11 +06:00
print u " Decryption failed \ m {0} " . format ( traceback . format_exc ( ) )
try :
tb . cleanup ( )
except :
pass
2011-06-16 11:59:20 +06:00
return 1
2010-12-31 04:41:07 +06:00
return 0
2012-03-07 00:24:28 +06:00
2010-12-31 04:41:07 +06:00
if __name__ == ' __main__ ' :
2012-12-19 19:48:11 +06:00
sys . stdout = SafeUnbuffered ( sys . stdout )
sys . stderr = SafeUnbuffered ( sys . stderr )
sys . exit ( cli_main ( ) )