mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
GwR work in progress DRM metadata edits, fix for timestamp
This commit is contained in:
commit
d6de6a564c
@ -12,6 +12,7 @@ __docformat__ = 'restructuredtext en'
|
||||
from struct import pack, unpack
|
||||
from cStringIO import StringIO
|
||||
|
||||
from calibre import prints
|
||||
from calibre.ebooks.mobi import MobiError
|
||||
from calibre.ebooks.mobi.writer import rescale_image, MAX_THUMB_DIMEN
|
||||
from calibre.ebooks.mobi.langcodes import iana2mobi
|
||||
@ -85,6 +86,8 @@ class StreamSlicer(object):
|
||||
self._stream.truncate(value)
|
||||
|
||||
class MetadataUpdater(object):
|
||||
DRM_KEY_SIZE = 48
|
||||
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
data = self.data = StreamSlicer(stream)
|
||||
@ -104,6 +107,7 @@ class MetadataUpdater(object):
|
||||
self.cover_record = self.thumbnail_record = None
|
||||
self.timestamp = None
|
||||
self.pdbrecords = self.get_pdbrecords()
|
||||
self.drm_block = self.fetchDRMdata()
|
||||
|
||||
self.original_exth_records = {}
|
||||
if not have_exth:
|
||||
@ -112,6 +116,40 @@ class MetadataUpdater(object):
|
||||
# Fetch timestamp, cover_record, thumbnail_record
|
||||
self.fetchEXTHFields()
|
||||
|
||||
def fetchDRMdata(self):
|
||||
''' Grab everything between end of EXTH and title '''
|
||||
'''
|
||||
if False and self.have_exth:
|
||||
print "incoming file has EXTH header"
|
||||
# 20:24 = mobiHeaderLength, 16=PDBHeader size, 4 = len('EXTH')
|
||||
exth_off = int(unpack('>I', self.record0[20:24])[0] + 16)
|
||||
print "exth_off = 0x%x" % exth_off
|
||||
exth_len_offset = exth_off + 4
|
||||
print "exth_len_offset = 0x%x" % exth_len_offset
|
||||
exth_len = int(unpack('>I', self.record0[exth_len_offset:exth_len_offset+4])[0])
|
||||
print "len(EXTH) = 0x%x" % exth_len
|
||||
title_offset = int(unpack('>I', self.record0[0x54:0x58])[0])
|
||||
print "offset of full title = 0x%x" % title_offset
|
||||
drm_off = exth_off + exth_len
|
||||
print "DRM data begins at 0x%x" % drm_off
|
||||
print "DRM len is 0x%x bytes" % (title_offset - drm_off)
|
||||
return self.record0[drm_off:drm_off + (title_offset - drm_off)]
|
||||
else:
|
||||
'''
|
||||
if True:
|
||||
drm_offset = int(unpack('>I', self.record0[0xa8:0xac])[0])
|
||||
self.drm_key_count = int(unpack('>I', self.record0[0xac:0xb0])[0])
|
||||
drm_string = ''
|
||||
for x in range(self.drm_key_count):
|
||||
base_addr = drm_offset + (x * self.DRM_KEY_SIZE)
|
||||
drm_string += self.record0[base_addr:base_addr + self.DRM_KEY_SIZE]
|
||||
return drm_string
|
||||
else:
|
||||
drm_offset = int(unpack('>I', self.record0[0xa8:0xac])[0])
|
||||
title_offset = int(unpack('>I', self.record0[0x54:0x58])[0])
|
||||
drm_blocklen = title_offset - drm_offset
|
||||
return self.record0[drm_offset:drm_offset + drm_blocklen]
|
||||
|
||||
def fetchEXTHFields(self):
|
||||
stream = self.stream
|
||||
record0 = self.record0
|
||||
@ -210,8 +248,13 @@ class MetadataUpdater(object):
|
||||
exth = ['EXTH', pack('>II', 12, 0), pad]
|
||||
exth = ''.join(exth)
|
||||
|
||||
# Update title_offset, title_len if new_title
|
||||
self.record0[0x54:0x58] = pack('>L', 0x10 + mobi_header_length + len(exth))
|
||||
# Update drm_offset
|
||||
self.record0[0xa8:0xac] = pack('>L', 0x10 + mobi_header_length + len(exth))
|
||||
if True:
|
||||
self.record0[0xb0:0xb4] = pack('>L', len(self.drm_block))
|
||||
# Update title_offset
|
||||
self.record0[0x54:0x58] = pack('>L', 0x10 + mobi_header_length + len(exth) + len(self.drm_block))
|
||||
|
||||
if new_title:
|
||||
self.record0[0x58:0x5c] = pack('>L', len(new_title))
|
||||
|
||||
@ -219,6 +262,7 @@ class MetadataUpdater(object):
|
||||
new_record0 = StringIO()
|
||||
new_record0.write(self.record0[:0x10 + mobi_header_length])
|
||||
new_record0.write(exth)
|
||||
new_record0.write(self.drm_block)
|
||||
if new_title:
|
||||
#new_record0.write(new_title.encode(self.codec, 'replace'))
|
||||
new_title = (new_title or _('Unknown')).encode(self.codec, 'replace')
|
||||
@ -343,7 +387,8 @@ class MetadataUpdater(object):
|
||||
pop_exth_record(202)
|
||||
|
||||
if getattr(self, 'encryption_type', -1) != 0:
|
||||
raise MobiError('Setting metadata in DRMed MOBI files is not supported.')
|
||||
prints(u"Setting metadata for '%s' (DRM)" % mi.title)
|
||||
# raise MobiError('Setting metadata in DRMed MOBI files is not supported.')
|
||||
|
||||
# Restore any original EXTH fields that weren't modified/updated
|
||||
for id in sorted(self.original_exth_records):
|
||||
|
@ -310,6 +310,7 @@ class Serializer(object):
|
||||
text = text.replace('&', '&')
|
||||
text = text.replace('<', '<')
|
||||
text = text.replace('>', '>')
|
||||
text = text.replace(u'\u00AD', '') # Soft-hyphen
|
||||
if quot:
|
||||
text = text.replace('"', '"')
|
||||
self.buffer.write(encode(text))
|
||||
|
@ -357,6 +357,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
||||
self.pubdate.setDate(QDate(pubdate.year, pubdate.month,
|
||||
pubdate.day))
|
||||
timestamp = db.timestamp(self.id, index_is_id=True)
|
||||
self.orig_timestamp = timestamp
|
||||
self.date.setDate(QDate(timestamp.year, timestamp.month,
|
||||
timestamp.day))
|
||||
|
||||
@ -656,6 +657,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
||||
self.db.set_pubdate(self.id, d)
|
||||
d = self.date.date()
|
||||
d = qt_to_dt(d)
|
||||
if d.date() != self.orig_timestamp.date():
|
||||
self.db.set_timestamp(self.id, d)
|
||||
|
||||
if self.cover_changed:
|
||||
|
@ -1751,7 +1751,7 @@ class EPUB_MOBI(CatalogPlugin):
|
||||
|
||||
today = datetime.datetime.now()
|
||||
date_range_list = []
|
||||
today_time = datetime.datetime(today.year, today.month, today.day)
|
||||
today_time = datetime.datetime(today.year, today.month, today.day, 23, 59, 59)
|
||||
books_added_in_date_range = False
|
||||
for (i, date) in enumerate(self.DATE_RANGE):
|
||||
date_range_limit = self.DATE_RANGE[i]
|
||||
@ -1759,14 +1759,20 @@ class EPUB_MOBI(CatalogPlugin):
|
||||
date_range = '%d to %d days ago' % (self.DATE_RANGE[i-1], self.DATE_RANGE[i])
|
||||
else:
|
||||
date_range = 'Last %d days' % (self.DATE_RANGE[i])
|
||||
|
||||
for book in self.booksByDateRange:
|
||||
book_time = datetime.datetime(book['timestamp'].year, book['timestamp'].month, book['timestamp'].day)
|
||||
if (today_time-book_time).days <= date_range_limit:
|
||||
#print "generateHTMLByDateAdded: %s added %d days ago" % (book['title'], (today_time-book_time).days)
|
||||
book_time = datetime.datetime(book['timestamp'].year,
|
||||
book['timestamp'].month,
|
||||
book['timestamp'].day,
|
||||
book['timestamp'].hour,
|
||||
book['timestamp'].minute)
|
||||
delta = today_time-book_time
|
||||
if delta.days <= date_range_limit:
|
||||
date_range_list.append(book)
|
||||
books_added_in_date_range = True
|
||||
else:
|
||||
break
|
||||
|
||||
dtc = add_books_to_HTML_by_date_range(date_range_list, date_range, dtc)
|
||||
date_range_list = [book]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user