Produce an output more similar to Mobi Unpack when dumping a MOBI header

This commit is contained in:
NiLuJe 2012-09-14 17:55:15 +02:00
parent 87fc87978b
commit 6c42c0ea6c

View File

@ -116,61 +116,85 @@ class Record(object): # {{{
# EXTH {{{ # EXTH {{{
class EXTHRecord(object): class EXTHRecord(object):
def __init__(self, type_, data): def __init__(self, type_, data, length):
self.type = type_ self.type = type_
self.data = data self.data = data
self.length = length
self.name = { self.name = {
1 : 'DRM Server id', 1 : 'Drm Server Id',
2 : 'DRM Commerce id', 2 : 'Drm Commerce Id',
3 : 'DRM ebookbase book id', 3 : 'Drm Ebookbase Book Id',
100 : 'author', 100 : 'Creator',
101 : 'publisher', 101 : 'Publisher',
102 : 'imprint', 102 : 'Imprint',
103 : 'description', 103 : 'Description',
104 : 'isbn', 104 : 'ISBN',
105 : 'subject', 105 : 'Subject',
106 : 'publishingdate', 106 : 'Published',
107 : 'review', 107 : 'Review',
108 : 'contributor', 108 : 'Contributor',
109 : 'rights', 109 : 'Rights',
110 : 'subjectcode', 110 : 'SubjectCode',
111 : 'type', 111 : 'Type',
112 : 'source', 112 : 'Source',
113 : 'asin', 113 : 'ASIN',
114 : 'versionnumber', 114 : 'versionNumber',
115 : 'sample', 115 : 'sample',
116 : 'startreading', 116 : 'StartOffset',
117 : 'adult', 117 : 'Adult',
118 : 'retailprice', 118 : 'Price',
119 : 'retailpricecurrency', 119 : 'Currency',
121 : 'KF8 header section index', 121 : 'KF8_Boundary_Section',
125 : 'KF8 resources (images/fonts) count', 122 : 'fixed-layout',
129 : 'KF8 cover URI', 123 : 'book-type',
131 : 'KF8 unknown count', 124 : 'orientation-lock',
201 : 'coveroffset', 125 : 'KF8_Count_of_Resources_Fonts_Images',
202 : 'thumboffset', 126 : 'original-resolution',
203 : 'hasfakecover', 127 : 'zero-gutter',
128 : 'zero-margin',
129 : 'KF8_Masthead/Cover_Image',
131 : 'KF8_Unidentified_Count',
132 : 'RegionMagnification',
200 : 'DictShortName',
201 : 'CoverOffset',
202 : 'ThumbOffset',
203 : 'Fake Cover',
204 : 'Creator Software', 204 : 'Creator Software',
205 : 'Creator Major Version', # '>I' 205 : 'Creator Major Version', # '>I'
206 : 'Creator Minor Version', # '>I' 206 : 'Creator Minor Version', # '>I'
207 : 'Creator Build Number', # '>I' 207 : 'Creator Build Number', # '>I'
208 : 'watermark', 208 : 'Watermark',
209 : 'tamper_proof_keys', 209 : 'Tamper Proof Keys [hex]',
300 : 'fontsignature', 300 : 'Font Signature [hex]',
301 : 'clippinglimit', # percentage '>B' 301 : 'Clipping Limit [3xx]', # percentage '>B'
402 : 'publisherlimit', 401 : 'Clipping Limit', # percentage '>B'
404 : 'TTS flag', # '>B' 1 - TTS disabled 0 - TTS enabled 402 : 'Publisher Limit',
501 : 'cdetype', # 4 chars (PDOC or EBOK) 404 : 'Text to Speech Disabled', # '>B' 1 - TTS disabled 0 - TTS enabled
502 : 'lastupdatetime', 501 : 'CDE Type', # 4 chars (PDOC, EBOK, MAGZ, ...)
503 : 'updatedtitle', 502 : 'last_update_time',
524 : 'language', 503 : 'Updated Title',
504 : 'ASIN [5xx]',
524 : 'Language',
525 : 'TextDirection',
528 : 'Unknown_Logical_Value',
535 : 'Kindlegen Build-Rev Number',
}.get(self.type, repr(self.type)) }.get(self.type, repr(self.type))
if (self.name in {'coveroffset', 'thumboffset', 'hasfakecover', if (self.name in {'sample', 'StartOffset', 'CoverOffset', 'ThumbOffset', 'Fake Cover',
'Creator Major Version', 'Creator Minor Version', 'Creator Software', 'Creator Major Version', 'Creator Minor Version',
'Creator Build Number', 'Creator Software', 'startreading'} or 'Creator Build Number', 'Clipping Limit (3xx)', 'Clipping Limit',
'Publisher Limit', 'Text to Speech Disabled'} or
self.type in {121, 125, 131}): self.type in {121, 125, 131}):
self.data, = struct.unpack(b'>I', self.data) if self.length == 9:
self.data, = struct.unpack(b'>B', self.data)
elif self.length == 10:
self.data, = struct.unpack(b'>H', self.data)
elif self.length == 12:
self.data, = struct.unpack(b'>L', self.data)
else:
self.data, = struct.unpack(b'>I', self.data) # Assume I for unknown sizes...
elif self.type in {209, 300}:
self.data = bytes(self.data.encode('hex'))
def __str__(self): def __str__(self):
return '%s (%d): %r'%(self.name, self.type, self.data) return '%s (%d): %r'%(self.name, self.type, self.data)
@ -181,8 +205,8 @@ class EXTHHeader(object):
self.raw = raw self.raw = raw
if not self.raw.startswith(b'EXTH'): if not self.raw.startswith(b'EXTH'):
raise ValueError('EXTH header does not start with EXTH') raise ValueError('EXTH header does not start with EXTH')
self.length, = struct.unpack(b'>I', self.raw[4:8]) self.length, = struct.unpack(b'>L', self.raw[4:8])
self.count, = struct.unpack(b'>I', self.raw[8:12]) self.count, = struct.unpack(b'>L', self.raw[8:12])
pos = 12 pos = 12
self.records = [] self.records = []
@ -199,9 +223,9 @@ class EXTHHeader(object):
return getattr(ans, 'data', default) return getattr(ans, 'data', default)
def read_record(self, pos): def read_record(self, pos):
type_, length = struct.unpack(b'>II', self.raw[pos:pos+8]) type_, length = struct.unpack(b'>LL', self.raw[pos:pos+8])
data = self.raw[(pos+8):(pos+length)] data = self.raw[(pos+8):(pos+length)]
self.records.append(EXTHRecord(type_, data)) self.records.append(EXTHRecord(type_, data, length))
return pos + length return pos + length
@property @property