Use print() function in both Python 2 and Python 3
Legacy __print__ statements are syntax errors in Python 3 but __print()__ function works as expected in both Python 2 and Python 3.
This commit is contained in:
parent
b71ed3887e
commit
5bb6b58bc1
|
@ -150,6 +150,7 @@
|
||||||
# after all.
|
# after all.
|
||||||
#
|
#
|
||||||
"""Manage all Kobo books, either encrypted or DRM-free."""
|
"""Manage all Kobo books, either encrypted or DRM-free."""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__version__ = '3.2.4'
|
__version__ = '3.2.4'
|
||||||
__about__ = u"Obok v{0}\nCopyright © 2012-2016 Physisticated et al.".format(__version__)
|
__about__ = u"Obok v{0}\nCopyright © 2012-2016 Physisticated et al.".format(__version__)
|
||||||
|
@ -291,7 +292,7 @@ class KoboLibrary(object):
|
||||||
of books, their titles, and the user's encryption key(s)."""
|
of books, their titles, and the user's encryption key(s)."""
|
||||||
|
|
||||||
def __init__ (self, serials = [], device_path = None):
|
def __init__ (self, serials = [], device_path = None):
|
||||||
print __about__
|
print(__about__)
|
||||||
self.kobodir = u""
|
self.kobodir = u""
|
||||||
kobodb = u""
|
kobodb = u""
|
||||||
|
|
||||||
|
@ -374,7 +375,7 @@ class KoboLibrary(object):
|
||||||
# make a copy of the database in a temporary file
|
# make a copy of the database in a temporary file
|
||||||
# so we can ensure it's not using WAL logging which sqlite3 can't do.
|
# so we can ensure it's not using WAL logging which sqlite3 can't do.
|
||||||
self.newdb = tempfile.NamedTemporaryFile(mode='wb', delete=False)
|
self.newdb = tempfile.NamedTemporaryFile(mode='wb', delete=False)
|
||||||
print self.newdb.name
|
print(self.newdb.name)
|
||||||
olddb = open(kobodb, 'rb')
|
olddb = open(kobodb, 'rb')
|
||||||
self.newdb.write(olddb.read(18))
|
self.newdb.write(olddb.read(18))
|
||||||
self.newdb.write('\x01\x01')
|
self.newdb.write('\x01\x01')
|
||||||
|
@ -595,32 +596,32 @@ class KoboFile(object):
|
||||||
# assume utf-8 with no BOM
|
# assume utf-8 with no BOM
|
||||||
textoffset = 0
|
textoffset = 0
|
||||||
stride = 1
|
stride = 1
|
||||||
print u"Checking text:{0}:".format(contents[:10])
|
print(u"Checking text:{0}:".format(contents[:10]))
|
||||||
# check for byte order mark
|
# check for byte order mark
|
||||||
if contents[:3]=="\xef\xbb\xbf":
|
if contents[:3]=="\xef\xbb\xbf":
|
||||||
# seems to be utf-8 with BOM
|
# seems to be utf-8 with BOM
|
||||||
print u"Could be utf-8 with BOM"
|
print(u"Could be utf-8 with BOM")
|
||||||
textoffset = 3
|
textoffset = 3
|
||||||
elif contents[:2]=="\xfe\xff":
|
elif contents[:2]=="\xfe\xff":
|
||||||
# seems to be utf-16BE
|
# seems to be utf-16BE
|
||||||
print u"Could be utf-16BE"
|
print(u"Could be utf-16BE")
|
||||||
textoffset = 3
|
textoffset = 3
|
||||||
stride = 2
|
stride = 2
|
||||||
elif contents[:2]=="\xff\xfe":
|
elif contents[:2]=="\xff\xfe":
|
||||||
# seems to be utf-16LE
|
# seems to be utf-16LE
|
||||||
print u"Could be utf-16LE"
|
print(u"Could be utf-16LE")
|
||||||
textoffset = 2
|
textoffset = 2
|
||||||
stride = 2
|
stride = 2
|
||||||
else:
|
else:
|
||||||
print u"Perhaps utf-8 without BOM"
|
print(u"Perhaps utf-8 without BOM")
|
||||||
|
|
||||||
# now check that the first few characters are in the ASCII range
|
# now check that the first few characters are in the ASCII range
|
||||||
for i in xrange(textoffset,textoffset+5*stride,stride):
|
for i in xrange(textoffset,textoffset+5*stride,stride):
|
||||||
if ord(contents[i])<32 or ord(contents[i])>127:
|
if ord(contents[i])<32 or ord(contents[i])>127:
|
||||||
# Non-ascii, so decryption probably failed
|
# Non-ascii, so decryption probably failed
|
||||||
print u"Bad character at {0}, value {1}".format(i,ord(contents[i]))
|
print(u"Bad character at {0}, value {1}".format(i,ord(contents[i])))
|
||||||
raise ValueError
|
raise ValueError
|
||||||
print u"Seems to be good text"
|
print(u"Seems to be good text")
|
||||||
return True
|
return True
|
||||||
if contents[:5]=="<?xml" or contents[:8]=="\xef\xbb\xbf<?xml":
|
if contents[:5]=="<?xml" or contents[:8]=="\xef\xbb\xbf<?xml":
|
||||||
# utf-8
|
# utf-8
|
||||||
|
@ -641,13 +642,13 @@ class KoboFile(object):
|
||||||
# utf-16LE of weird <!DOCTYPE start
|
# utf-16LE of weird <!DOCTYPE start
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print u"Bad XML: {0}".format(contents[:8])
|
print(u"Bad XML: {0}".format(contents[:8]))
|
||||||
raise ValueError
|
raise ValueError
|
||||||
elif self.mimetype == 'image/jpeg':
|
elif self.mimetype == 'image/jpeg':
|
||||||
if contents[:3] == '\xff\xd8\xff':
|
if contents[:3] == '\xff\xd8\xff':
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print u"Bad JPEG: {0}".format(contents[:3].encode('hex'))
|
print(u"Bad JPEG: {0}".format(contents[:3].encode('hex')))
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -670,18 +671,18 @@ class KoboFile(object):
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
def decrypt_book(book, lib):
|
def decrypt_book(book, lib):
|
||||||
print u"Converting {0}".format(book.title)
|
print(u"Converting {0}".format(book.title))
|
||||||
zin = zipfile.ZipFile(book.filename, "r")
|
zin = zipfile.ZipFile(book.filename, "r")
|
||||||
# make filename out of Unicode alphanumeric and whitespace equivalents from title
|
# make filename out of Unicode alphanumeric and whitespace equivalents from title
|
||||||
outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
|
outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
|
||||||
if (book.type == 'drm-free'):
|
if (book.type == 'drm-free'):
|
||||||
print u"DRM-free book, conversion is not needed"
|
print(u"DRM-free book, conversion is not needed")
|
||||||
shutil.copyfile(book.filename, outname)
|
shutil.copyfile(book.filename, outname)
|
||||||
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
|
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
|
||||||
return 0
|
return 0
|
||||||
result = 1
|
result = 1
|
||||||
for userkey in lib.userkeys:
|
for userkey in lib.userkeys:
|
||||||
print u"Trying key: {0}".format(userkey.encode('hex_codec'))
|
print(u"Trying key: {0}".format(userkey.encode('hex_codec')))
|
||||||
try:
|
try:
|
||||||
zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
|
zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
|
||||||
for filename in zin.namelist():
|
for filename in zin.namelist():
|
||||||
|
@ -693,12 +694,12 @@ def decrypt_book(book, lib):
|
||||||
file.check(contents)
|
file.check(contents)
|
||||||
zout.writestr(filename, contents)
|
zout.writestr(filename, contents)
|
||||||
zout.close()
|
zout.close()
|
||||||
print u"Decryption succeeded."
|
print(u"Decryption succeeded.")
|
||||||
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
|
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
|
||||||
result = 0
|
result = 0
|
||||||
break
|
break
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print u"Decryption failed."
|
print(u"Decryption failed.")
|
||||||
zout.close()
|
zout.close()
|
||||||
os.remove(outname)
|
os.remove(outname)
|
||||||
zin.close()
|
zin.close()
|
||||||
|
@ -723,8 +724,8 @@ def cli_main():
|
||||||
books = lib.books
|
books = lib.books
|
||||||
else:
|
else:
|
||||||
for i, book in enumerate(lib.books):
|
for i, book in enumerate(lib.books):
|
||||||
print u"{0}: {1}".format(i + 1, book.title)
|
print(u"{0}: {1}".format(i + 1, book.title))
|
||||||
print u"Or 'all'"
|
print(u"Or 'all'")
|
||||||
|
|
||||||
choice = raw_input(u"Convert book number... ")
|
choice = raw_input(u"Convert book number... ")
|
||||||
if choice == u'all':
|
if choice == u'all':
|
||||||
|
@ -734,14 +735,14 @@ def cli_main():
|
||||||
num = int(choice)
|
num = int(choice)
|
||||||
books = [lib.books[num - 1]]
|
books = [lib.books[num - 1]]
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
print u"Invalid choice. Exiting..."
|
print(u"Invalid choice. Exiting...")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
results = [decrypt_book(book, lib) for book in books]
|
results = [decrypt_book(book, lib) for book in books]
|
||||||
lib.close()
|
lib.close()
|
||||||
overall_result = all(result != 0 for result in results)
|
overall_result = all(result != 0 for result in results)
|
||||||
if overall_result != 0:
|
if overall_result != 0:
|
||||||
print u"Could not decrypt book with any of the keys found."
|
print(u"Could not decrypt book with any of the keys found.")
|
||||||
return overall_result
|
return overall_result
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
# __init__.py for DeDRM_plugin
|
# __init__.py for DeDRM_plugin
|
||||||
# Copyright © 2008-2019 Apprentice Harper et al.
|
# Copyright © 2008-2019 Apprentice Harper et al.
|
||||||
|
@ -164,7 +165,7 @@ class DeDRM(FileTypePlugin):
|
||||||
else:
|
else:
|
||||||
names = [u"libalfcrypto32.so",u"libalfcrypto64.so",u"kindlekey.py",u"adobekey.py",u"subasyncio.py"]
|
names = [u"libalfcrypto32.so",u"libalfcrypto64.so",u"kindlekey.py",u"adobekey.py",u"subasyncio.py"]
|
||||||
lib_dict = self.load_resources(names)
|
lib_dict = self.load_resources(names)
|
||||||
print u"{0} v{1}: Copying needed library files from plugin's zip".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Copying needed library files from plugin's zip".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
|
|
||||||
for entry, data in lib_dict.items():
|
for entry, data in lib_dict.items():
|
||||||
file_path = os.path.join(self.alfdir, entry)
|
file_path = os.path.join(self.alfdir, entry)
|
||||||
|
@ -176,7 +177,7 @@ class DeDRM(FileTypePlugin):
|
||||||
try:
|
try:
|
||||||
open(file_path,'wb').write(data)
|
open(file_path,'wb').write(data)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when copying needed library files".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Exception when copying needed library files".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -197,11 +198,11 @@ class DeDRM(FileTypePlugin):
|
||||||
|
|
||||||
inf = self.temporary_file(u".epub")
|
inf = self.temporary_file(u".epub")
|
||||||
try:
|
try:
|
||||||
print u"{0} v{1}: Verifying zip archive integrity".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Verifying zip archive integrity".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
fr = zipfix.fixZip(path_to_ebook, inf.name)
|
fr = zipfix.fixZip(path_to_ebook, inf.name)
|
||||||
fr.fix()
|
fr.fix()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print u"{0} v{1}: Error \'{2}\' when checking zip archive".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
|
print(u"{0} v{1}: Error \'{2}\' when checking zip archive".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]))
|
||||||
raise Exception(e)
|
raise Exception(e)
|
||||||
|
|
||||||
# import the decryption keys
|
# import the decryption keys
|
||||||
|
@ -214,19 +215,19 @@ class DeDRM(FileTypePlugin):
|
||||||
|
|
||||||
#check the book
|
#check the book
|
||||||
if ignobleepub.ignobleBook(inf.name):
|
if ignobleepub.ignobleBook(inf.name):
|
||||||
print u"{0} v{1}: “{2}” is a secure Barnes & Noble ePub".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook))
|
print(u"{0} v{1}: “{2}” is a secure Barnes & Noble ePub".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook)))
|
||||||
|
|
||||||
# Attempt to decrypt epub with each encryption key (generated or provided).
|
# Attempt to decrypt epub with each encryption key (generated or provided).
|
||||||
for keyname, userkey in dedrmprefs['bandnkeys'].items():
|
for keyname, userkey in dedrmprefs['bandnkeys'].items():
|
||||||
keyname_masked = u"".join((u'X' if (x.isdigit()) else x) for x in keyname)
|
keyname_masked = u"".join((u'X' if (x.isdigit()) else x) for x in keyname)
|
||||||
print u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname_masked)
|
print(u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname_masked))
|
||||||
of = self.temporary_file(u".epub")
|
of = self.temporary_file(u".epub")
|
||||||
|
|
||||||
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
||||||
try:
|
try:
|
||||||
result = ignobleepub.decryptBook(userkey, inf.name, of.name)
|
result = ignobleepub.decryptBook(userkey, inf.name, of.name)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when trying to decrypt after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when trying to decrypt after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
result = 1
|
result = 1
|
||||||
|
|
||||||
|
@ -237,10 +238,10 @@ class DeDRM(FileTypePlugin):
|
||||||
# Return the modified PersistentTemporary file to calibre.
|
# Return the modified PersistentTemporary file to calibre.
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime)
|
print(u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime))
|
||||||
|
|
||||||
# perhaps we should see if we can get a key from a log file
|
# perhaps we should see if we can get a key from a log file
|
||||||
print u"{0} v{1}: Looking for new NOOK Study Keys after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Looking for new NOOK Study Keys after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
# get the default NOOK Study keys
|
# get the default NOOK Study keys
|
||||||
defaultkeys = []
|
defaultkeys = []
|
||||||
|
@ -257,7 +258,7 @@ class DeDRM(FileTypePlugin):
|
||||||
defaultkeys = WineGetKeys(scriptpath, u".b64",dedrmprefs['adobewineprefix'])
|
defaultkeys = WineGetKeys(scriptpath, u".b64",dedrmprefs['adobewineprefix'])
|
||||||
|
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when getting default NOOK Study Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when getting default NOOK Study Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
newkeys = []
|
newkeys = []
|
||||||
|
@ -268,7 +269,7 @@ class DeDRM(FileTypePlugin):
|
||||||
if len(newkeys) > 0:
|
if len(newkeys) > 0:
|
||||||
try:
|
try:
|
||||||
for i,userkey in enumerate(newkeys):
|
for i,userkey in enumerate(newkeys):
|
||||||
print u"{0} v{1}: Trying a new default key".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Trying a new default key".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
|
|
||||||
of = self.temporary_file(u".epub")
|
of = self.temporary_file(u".epub")
|
||||||
|
|
||||||
|
@ -276,7 +277,7 @@ class DeDRM(FileTypePlugin):
|
||||||
try:
|
try:
|
||||||
result = ignobleepub.decryptBook(userkey, inf.name, of.name)
|
result = ignobleepub.decryptBook(userkey, inf.name, of.name)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when trying to decrypt after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when trying to decrypt after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
result = 1
|
result = 1
|
||||||
|
|
||||||
|
@ -285,59 +286,59 @@ class DeDRM(FileTypePlugin):
|
||||||
if result == 0:
|
if result == 0:
|
||||||
# Decryption was a success
|
# Decryption was a success
|
||||||
# Store the new successful key in the defaults
|
# Store the new successful key in the defaults
|
||||||
print u"{0} v{1}: Saving a new default key".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Saving a new default key".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
try:
|
try:
|
||||||
dedrmprefs.addnamedvaluetoprefs('bandnkeys','nook_Study_key',keyvalue)
|
dedrmprefs.addnamedvaluetoprefs('bandnkeys','nook_Study_key',keyvalue)
|
||||||
dedrmprefs.writeprefs()
|
dedrmprefs.writeprefs()
|
||||||
print u"{0} v{1}: Saved a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Saved a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
# Return the modified PersistentTemporary file to calibre.
|
# Return the modified PersistentTemporary file to calibre.
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
print u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
# import the Adobe Adept ePub handler
|
# import the Adobe Adept ePub handler
|
||||||
import calibre_plugins.dedrm.ineptepub as ineptepub
|
import calibre_plugins.dedrm.ineptepub as ineptepub
|
||||||
|
|
||||||
if ineptepub.adeptBook(inf.name):
|
if ineptepub.adeptBook(inf.name):
|
||||||
print u"{0} v{1}: {2} is a secure Adobe Adept ePub".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook))
|
print(u"{0} v{1}: {2} is a secure Adobe Adept ePub".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook)))
|
||||||
|
|
||||||
# Attempt to decrypt epub with each encryption key (generated or provided).
|
# Attempt to decrypt epub with each encryption key (generated or provided).
|
||||||
for keyname, userkeyhex in dedrmprefs['adeptkeys'].items():
|
for keyname, userkeyhex in dedrmprefs['adeptkeys'].items():
|
||||||
userkey = userkeyhex.decode('hex')
|
userkey = userkeyhex.decode('hex')
|
||||||
print u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname)
|
print(u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname))
|
||||||
of = self.temporary_file(u".epub")
|
of = self.temporary_file(u".epub")
|
||||||
|
|
||||||
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
||||||
try:
|
try:
|
||||||
result = ineptepub.decryptBook(userkey, inf.name, of.name)
|
result = ineptepub.decryptBook(userkey, inf.name, of.name)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
result = 1
|
result = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
of.close()
|
of.close()
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception closing temporary file after {2:.1f} seconds. Ignored.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception closing temporary file after {2:.1f} seconds. Ignored.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
if result == 0:
|
if result == 0:
|
||||||
# Decryption was successful.
|
# Decryption was successful.
|
||||||
# Return the modified PersistentTemporary file to calibre.
|
# Return the modified PersistentTemporary file to calibre.
|
||||||
print u"{0} v{1}: Decrypted with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
|
print(u"{0} v{1}: Decrypted with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime))
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
|
print(u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime))
|
||||||
|
|
||||||
# perhaps we need to get a new default ADE key
|
# perhaps we need to get a new default ADE key
|
||||||
print u"{0} v{1}: Looking for new default Adobe Digital Editions Keys after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Looking for new default Adobe Digital Editions Keys after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
# get the default Adobe keys
|
# get the default Adobe keys
|
||||||
defaultkeys = []
|
defaultkeys = []
|
||||||
|
@ -355,7 +356,7 @@ class DeDRM(FileTypePlugin):
|
||||||
|
|
||||||
self.default_key = defaultkeys[0]
|
self.default_key = defaultkeys[0]
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when getting default Adobe Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when getting default Adobe Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.default_key = u""
|
self.default_key = u""
|
||||||
|
|
||||||
|
@ -367,14 +368,14 @@ class DeDRM(FileTypePlugin):
|
||||||
if len(newkeys) > 0:
|
if len(newkeys) > 0:
|
||||||
try:
|
try:
|
||||||
for i,userkey in enumerate(newkeys):
|
for i,userkey in enumerate(newkeys):
|
||||||
print u"{0} v{1}: Trying a new default key".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Trying a new default key".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
of = self.temporary_file(u".epub")
|
of = self.temporary_file(u".epub")
|
||||||
|
|
||||||
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
||||||
try:
|
try:
|
||||||
result = ineptepub.decryptBook(userkey, inf.name, of.name)
|
result = ineptepub.decryptBook(userkey, inf.name, of.name)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
result = 1
|
result = 1
|
||||||
|
|
||||||
|
@ -383,31 +384,31 @@ class DeDRM(FileTypePlugin):
|
||||||
if result == 0:
|
if result == 0:
|
||||||
# Decryption was a success
|
# Decryption was a success
|
||||||
# Store the new successful key in the defaults
|
# Store the new successful key in the defaults
|
||||||
print u"{0} v{1}: Saving a new default key".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Saving a new default key".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
try:
|
try:
|
||||||
dedrmprefs.addnamedvaluetoprefs('adeptkeys','default_key',keyvalue.encode('hex'))
|
dedrmprefs.addnamedvaluetoprefs('adeptkeys','default_key',keyvalue.encode('hex'))
|
||||||
dedrmprefs.writeprefs()
|
dedrmprefs.writeprefs()
|
||||||
print u"{0} v{1}: Saved a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Saved a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print u"{0} v{1}: Decrypted with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Decrypted with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
# Return the modified PersistentTemporary file to calibre.
|
# Return the modified PersistentTemporary file to calibre.
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
print u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print u"{0} v{1}: Unexpected Exception trying a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Unexpected Exception trying a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Something went wrong with decryption.
|
# Something went wrong with decryption.
|
||||||
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
|
|
||||||
# Not a Barnes & Noble nor an Adobe Adept
|
# Not a Barnes & Noble nor an Adobe Adept
|
||||||
# Import the fixed epub.
|
# Import the fixed epub.
|
||||||
print u"{0} v{1}: “{2}” is neither an Adobe Adept nor a Barnes & Noble encrypted ePub".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook))
|
print(u"{0} v{1}: “{2}” is neither an Adobe Adept nor a Barnes & Noble encrypted ePub".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook)))
|
||||||
raise DeDRMError(u"{0} v{1}: Couldn't decrypt after {2:.1f} seconds. DRM free perhaps?".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
raise DeDRMError(u"{0} v{1}: Couldn't decrypt after {2:.1f} seconds. DRM free perhaps?".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
|
|
||||||
def PDFDecrypt(self,path_to_ebook):
|
def PDFDecrypt(self,path_to_ebook):
|
||||||
|
@ -416,17 +417,17 @@ class DeDRM(FileTypePlugin):
|
||||||
|
|
||||||
dedrmprefs = prefs.DeDRM_Prefs()
|
dedrmprefs = prefs.DeDRM_Prefs()
|
||||||
# Attempt to decrypt epub with each encryption key (generated or provided).
|
# Attempt to decrypt epub with each encryption key (generated or provided).
|
||||||
print u"{0} v{1}: {2} is a PDF ebook".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook))
|
print(u"{0} v{1}: {2} is a PDF ebook".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook)))
|
||||||
for keyname, userkeyhex in dedrmprefs['adeptkeys'].items():
|
for keyname, userkeyhex in dedrmprefs['adeptkeys'].items():
|
||||||
userkey = userkeyhex.decode('hex')
|
userkey = userkeyhex.decode('hex')
|
||||||
print u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname)
|
print(u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname))
|
||||||
of = self.temporary_file(u".pdf")
|
of = self.temporary_file(u".pdf")
|
||||||
|
|
||||||
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
||||||
try:
|
try:
|
||||||
result = ineptpdf.decryptBook(userkey, path_to_ebook, of.name)
|
result = ineptpdf.decryptBook(userkey, path_to_ebook, of.name)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
result = 1
|
result = 1
|
||||||
|
|
||||||
|
@ -437,10 +438,10 @@ class DeDRM(FileTypePlugin):
|
||||||
# Return the modified PersistentTemporary file to calibre.
|
# Return the modified PersistentTemporary file to calibre.
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
|
print(u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime))
|
||||||
|
|
||||||
# perhaps we need to get a new default ADE key
|
# perhaps we need to get a new default ADE key
|
||||||
print u"{0} v{1}: Looking for new default Adobe Digital Editions Keys after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Looking for new default Adobe Digital Editions Keys after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
# get the default Adobe keys
|
# get the default Adobe keys
|
||||||
defaultkeys = []
|
defaultkeys = []
|
||||||
|
@ -458,7 +459,7 @@ class DeDRM(FileTypePlugin):
|
||||||
|
|
||||||
self.default_key = defaultkeys[0]
|
self.default_key = defaultkeys[0]
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when getting default Adobe Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when getting default Adobe Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.default_key = u""
|
self.default_key = u""
|
||||||
|
|
||||||
|
@ -470,14 +471,14 @@ class DeDRM(FileTypePlugin):
|
||||||
if len(newkeys) > 0:
|
if len(newkeys) > 0:
|
||||||
try:
|
try:
|
||||||
for i,userkey in enumerate(newkeys):
|
for i,userkey in enumerate(newkeys):
|
||||||
print u"{0} v{1}: Trying a new default key".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Trying a new default key".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
of = self.temporary_file(u".pdf")
|
of = self.temporary_file(u".pdf")
|
||||||
|
|
||||||
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
|
||||||
try:
|
try:
|
||||||
result = ineptpdf.decryptBook(userkey, path_to_ebook, of.name)
|
result = ineptpdf.decryptBook(userkey, path_to_ebook, of.name)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when decrypting after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
result = 1
|
result = 1
|
||||||
|
|
||||||
|
@ -486,23 +487,23 @@ class DeDRM(FileTypePlugin):
|
||||||
if result == 0:
|
if result == 0:
|
||||||
# Decryption was a success
|
# Decryption was a success
|
||||||
# Store the new successful key in the defaults
|
# Store the new successful key in the defaults
|
||||||
print u"{0} v{1}: Saving a new default key".format(PLUGIN_NAME, PLUGIN_VERSION)
|
print(u"{0} v{1}: Saving a new default key".format(PLUGIN_NAME, PLUGIN_VERSION))
|
||||||
try:
|
try:
|
||||||
dedrmprefs.addnamedvaluetoprefs('adeptkeys','default_key',keyvalue.encode('hex'))
|
dedrmprefs.addnamedvaluetoprefs('adeptkeys','default_key',keyvalue.encode('hex'))
|
||||||
dedrmprefs.writeprefs()
|
dedrmprefs.writeprefs()
|
||||||
print u"{0} v{1}: Saved a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Saved a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
# Return the modified PersistentTemporary file to calibre.
|
# Return the modified PersistentTemporary file to calibre.
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
print u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Something went wrong with decryption.
|
# Something went wrong with decryption.
|
||||||
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
|
|
||||||
|
@ -533,8 +534,8 @@ class DeDRM(FileTypePlugin):
|
||||||
decoded = False
|
decoded = False
|
||||||
# perhaps we need to get a new default Kindle for Mac/PC key
|
# perhaps we need to get a new default Kindle for Mac/PC key
|
||||||
defaultkeys = []
|
defaultkeys = []
|
||||||
print u"{0} v{1}: Failed to decrypt with error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION,e.args[0])
|
print(u"{0} v{1}: Failed to decrypt with error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION,e.args[0]))
|
||||||
print u"{0} v{1}: Looking for new default Kindle Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Looking for new default Kindle Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if iswindows or isosx:
|
if iswindows or isosx:
|
||||||
|
@ -547,7 +548,7 @@ class DeDRM(FileTypePlugin):
|
||||||
scriptpath = os.path.join(self.alfdir,u"kindlekey.py")
|
scriptpath = os.path.join(self.alfdir,u"kindlekey.py")
|
||||||
defaultkeys = WineGetKeys(scriptpath, u".k4i",dedrmprefs['kindlewineprefix'])
|
defaultkeys = WineGetKeys(scriptpath, u".k4i",dedrmprefs['kindlewineprefix'])
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Exception when getting default Kindle Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
|
print(u"{0} v{1}: Exception when getting default Kindle Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -557,12 +558,12 @@ class DeDRM(FileTypePlugin):
|
||||||
if keyvalue not in dedrmprefs['kindlekeys'].values():
|
if keyvalue not in dedrmprefs['kindlekeys'].values():
|
||||||
newkeys[keyname] = keyvalue
|
newkeys[keyname] = keyvalue
|
||||||
if len(newkeys) > 0:
|
if len(newkeys) > 0:
|
||||||
print u"{0} v{1}: Found {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), u"key" if len(newkeys)==1 else u"keys")
|
print(u"{0} v{1}: Found {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), u"key" if len(newkeys)==1 else u"keys"))
|
||||||
try:
|
try:
|
||||||
book = k4mobidedrm.GetDecryptedBook(path_to_ebook,newkeys.items(),[],[],[],self.starttime)
|
book = k4mobidedrm.GetDecryptedBook(path_to_ebook,newkeys.items(),[],[],[],self.starttime)
|
||||||
decoded = True
|
decoded = True
|
||||||
# store the new successful keys in the defaults
|
# store the new successful keys in the defaults
|
||||||
print u"{0} v{1}: Saving {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), u"key" if len(newkeys)==1 else u"keys")
|
print(u"{0} v{1}: Saving {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), u"key" if len(newkeys)==1 else u"keys"))
|
||||||
for keyvalue in newkeys.values():
|
for keyvalue in newkeys.values():
|
||||||
dedrmprefs.addnamedvaluetoprefs('kindlekeys','default_key',keyvalue)
|
dedrmprefs.addnamedvaluetoprefs('kindlekeys','default_key',keyvalue)
|
||||||
dedrmprefs.writeprefs()
|
dedrmprefs.writeprefs()
|
||||||
|
@ -570,7 +571,7 @@ class DeDRM(FileTypePlugin):
|
||||||
pass
|
pass
|
||||||
if not decoded:
|
if not decoded:
|
||||||
#if you reached here then no luck raise and exception
|
#if you reached here then no luck raise and exception
|
||||||
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
|
|
||||||
of = self.temporary_file(book.getBookExtension())
|
of = self.temporary_file(book.getBookExtension())
|
||||||
|
@ -589,7 +590,7 @@ class DeDRM(FileTypePlugin):
|
||||||
# Attempt to decrypt epub with each encryption key (generated or provided).
|
# Attempt to decrypt epub with each encryption key (generated or provided).
|
||||||
for keyname, userkey in dedrmprefs['ereaderkeys'].items():
|
for keyname, userkey in dedrmprefs['ereaderkeys'].items():
|
||||||
keyname_masked = u"".join((u'X' if (x.isdigit()) else x) for x in keyname)
|
keyname_masked = u"".join((u'X' if (x.isdigit()) else x) for x in keyname)
|
||||||
print u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname_masked)
|
print(u"{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname_masked))
|
||||||
of = self.temporary_file(u".pmlz")
|
of = self.temporary_file(u".pmlz")
|
||||||
|
|
||||||
# Give the userkey, ebook and TemporaryPersistent file to the decryption function.
|
# Give the userkey, ebook and TemporaryPersistent file to the decryption function.
|
||||||
|
@ -600,12 +601,12 @@ class DeDRM(FileTypePlugin):
|
||||||
# Decryption was successful return the modified PersistentTemporary
|
# Decryption was successful return the modified PersistentTemporary
|
||||||
# file to Calibre's import process.
|
# file to Calibre's import process.
|
||||||
if result == 0:
|
if result == 0:
|
||||||
print u"{0} v{1}: Successfully decrypted with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime)
|
print(u"{0} v{1}: Successfully decrypted with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime))
|
||||||
return of.name
|
return of.name
|
||||||
|
|
||||||
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime)
|
print(u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime))
|
||||||
|
|
||||||
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||||
|
|
||||||
|
|
||||||
|
@ -615,7 +616,7 @@ class DeDRM(FileTypePlugin):
|
||||||
sys.stdout=SafeUnbuffered(sys.stdout)
|
sys.stdout=SafeUnbuffered(sys.stdout)
|
||||||
sys.stderr=SafeUnbuffered(sys.stderr)
|
sys.stderr=SafeUnbuffered(sys.stderr)
|
||||||
|
|
||||||
print u"{0} v{1}: Trying to decrypt {2}".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook))
|
print(u"{0} v{1}: Trying to decrypt {2}".format(PLUGIN_NAME, PLUGIN_VERSION, os.path.basename(path_to_ebook)))
|
||||||
self.starttime = time.time()
|
self.starttime = time.time()
|
||||||
|
|
||||||
booktype = os.path.splitext(path_to_ebook)[1].lower()[1:]
|
booktype = os.path.splitext(path_to_ebook)[1].lower()[1:]
|
||||||
|
@ -634,9 +635,9 @@ class DeDRM(FileTypePlugin):
|
||||||
# Adobe Adept or B&N ePub
|
# Adobe Adept or B&N ePub
|
||||||
decrypted_ebook = self.ePubDecrypt(path_to_ebook)
|
decrypted_ebook = self.ePubDecrypt(path_to_ebook)
|
||||||
else:
|
else:
|
||||||
print u"Unknown booktype {0}. Passing back to calibre unchanged".format(booktype)
|
print(u"Unknown booktype {0}. Passing back to calibre unchanged".format(booktype))
|
||||||
return path_to_ebook
|
return path_to_ebook
|
||||||
print u"{0} v{1}: Finished after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
|
print(u"{0} v{1}: Finished after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
|
||||||
return decrypted_ebook
|
return decrypted_ebook
|
||||||
|
|
||||||
def is_customizable(self):
|
def is_customizable(self):
|
||||||
|
|
|
@ -52,6 +52,7 @@ from __future__ import with_statement
|
||||||
"""
|
"""
|
||||||
Retrieve Adobe ADEPT user key.
|
Retrieve Adobe ADEPT user key.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = '6.0'
|
__version__ = '6.0'
|
||||||
|
@ -407,7 +408,7 @@ if iswindows:
|
||||||
keys.append(userkey)
|
keys.append(userkey)
|
||||||
if len(keys) == 0:
|
if len(keys) == 0:
|
||||||
raise ADEPTError('Could not locate privateLicenseKey')
|
raise ADEPTError('Could not locate privateLicenseKey')
|
||||||
print u"Found {0:d} keys".format(len(keys))
|
print(u"Found {0:d} keys".format(len(keys)))
|
||||||
return keys
|
return keys
|
||||||
|
|
||||||
|
|
||||||
|
@ -465,7 +466,7 @@ def getkey(outpath):
|
||||||
outfile = outpath
|
outfile = outpath
|
||||||
with file(outfile, 'wb') as keyfileout:
|
with file(outfile, 'wb') as keyfileout:
|
||||||
keyfileout.write(keys[0])
|
keyfileout.write(keys[0])
|
||||||
print u"Saved a key to {0}".format(outfile)
|
print(u"Saved a key to {0}".format(outfile))
|
||||||
else:
|
else:
|
||||||
keycount = 0
|
keycount = 0
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
@ -476,28 +477,28 @@ def getkey(outpath):
|
||||||
break
|
break
|
||||||
with file(outfile, 'wb') as keyfileout:
|
with file(outfile, 'wb') as keyfileout:
|
||||||
keyfileout.write(key)
|
keyfileout.write(key)
|
||||||
print u"Saved a key to {0}".format(outfile)
|
print(u"Saved a key to {0}".format(outfile))
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def usage(progname):
|
def usage(progname):
|
||||||
print u"Finds, decrypts and saves the default Adobe Adept encryption key(s)."
|
print(u"Finds, decrypts and saves the default Adobe Adept encryption key(s).")
|
||||||
print u"Keys are saved to the current directory, or a specified output directory."
|
print(u"Keys are saved to the current directory, or a specified output directory.")
|
||||||
print u"If a file name is passed instead of a directory, only the first key is saved, in that file."
|
print(u"If a file name is passed instead of a directory, only the first key is saved, in that file.")
|
||||||
print u"Usage:"
|
print(u"Usage:")
|
||||||
print u" {0:s} [-h] [<outpath>]".format(progname)
|
print(u" {0:s} [-h] [<outpath>]".format(progname))
|
||||||
|
|
||||||
def cli_main():
|
def cli_main():
|
||||||
sys.stdout=SafeUnbuffered(sys.stdout)
|
sys.stdout=SafeUnbuffered(sys.stdout)
|
||||||
sys.stderr=SafeUnbuffered(sys.stderr)
|
sys.stderr=SafeUnbuffered(sys.stderr)
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
print u"{0} v{1}\nCopyright © 2009-2013 i♥cabbages and Apprentice Alf".format(progname,__version__)
|
print(u"{0} v{1}\nCopyright © 2009-2013 i♥cabbages and Apprentice Alf".format(progname,__version__))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(argv[1:], "h")
|
opts, args = getopt.getopt(argv[1:], "h")
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print u"Error in options or arguments: {0}".format(err.args[0])
|
print(u"Error in options or arguments: {0}".format(err.args[0]))
|
||||||
usage(progname)
|
usage(progname)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
@ -528,7 +529,7 @@ def cli_main():
|
||||||
outfile = outpath
|
outfile = outpath
|
||||||
with file(outfile, 'wb') as keyfileout:
|
with file(outfile, 'wb') as keyfileout:
|
||||||
keyfileout.write(keys[0])
|
keyfileout.write(keys[0])
|
||||||
print u"Saved a key to {0}".format(outfile)
|
print(u"Saved a key to {0}".format(outfile))
|
||||||
else:
|
else:
|
||||||
keycount = 0
|
keycount = 0
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
@ -539,9 +540,9 @@ def cli_main():
|
||||||
break
|
break
|
||||||
with file(outfile, 'wb') as keyfileout:
|
with file(outfile, 'wb') as keyfileout:
|
||||||
keyfileout.write(key)
|
keyfileout.write(key)
|
||||||
print u"Saved a key to {0}".format(outfile)
|
print(u"Saved a key to {0}".format(outfile))
|
||||||
else:
|
else:
|
||||||
print u"Could not retrieve Adobe Adept key."
|
print(u"Could not retrieve Adobe Adept key.")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
# pbkdf2.py Copyright © 2009 Daniel Holth <dholth@fastmail.fm>
|
# pbkdf2.py Copyright © 2009 Daniel Holth <dholth@fastmail.fm>
|
||||||
# pbkdf2.py This code may be freely used and modified for any purpose.
|
# pbkdf2.py This code may be freely used and modified for any purpose.
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import sys, os
|
import sys, os
|
||||||
import hmac
|
import hmac
|
||||||
from struct import pack
|
from struct import pack
|
||||||
|
@ -158,7 +159,7 @@ def _load_libalfcrypto():
|
||||||
topazCryptoDecrypt(ctx, data, out, len(data))
|
topazCryptoDecrypt(ctx, data, out, len(data))
|
||||||
return out.raw
|
return out.raw
|
||||||
|
|
||||||
print u"Using Library AlfCrypto DLL/DYLIB/SO"
|
print(u"Using Library AlfCrypto DLL/DYLIB/SO")
|
||||||
return (AES_CBC, Pukall_Cipher, Topaz_Cipher)
|
return (AES_CBC, Pukall_Cipher, Topaz_Cipher)
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,7 +245,7 @@ def _load_python_alfcrypto():
|
||||||
cleartext = self.aes.decrypt(iv + data)
|
cleartext = self.aes.decrypt(iv + data)
|
||||||
return cleartext
|
return cleartext
|
||||||
|
|
||||||
print u"Using Library AlfCrypto Python"
|
print(u"Using Library AlfCrypto Python")
|
||||||
return (AES_CBC, Pukall_Cipher, Topaz_Cipher)
|
return (AES_CBC, Pukall_Cipher, Topaz_Cipher)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ from __future__ import with_statement
|
||||||
"""
|
"""
|
||||||
Retrieve Kindle for Android Serial Number.
|
Retrieve Kindle for Android Serial Number.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = '1.5'
|
__version__ = '1.5'
|
||||||
|
@ -228,7 +229,7 @@ def get_serials2(path=STORAGE2):
|
||||||
if len(userdata_utf8) > 0:
|
if len(userdata_utf8) > 0:
|
||||||
dsns.append(userdata_utf8)
|
dsns.append(userdata_utf8)
|
||||||
except:
|
except:
|
||||||
print "Error getting one of the device serial name keys"
|
print("Error getting one of the device serial name keys")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
dsns = list(set(dsns))
|
dsns = list(set(dsns))
|
||||||
|
@ -243,7 +244,7 @@ def get_serials2(path=STORAGE2):
|
||||||
if len(userdata_utf8) > 0:
|
if len(userdata_utf8) > 0:
|
||||||
tokens.append(userdata_utf8)
|
tokens.append(userdata_utf8)
|
||||||
except:
|
except:
|
||||||
print "Error getting one of the account token keys"
|
print("Error getting one of the account token keys")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
pass
|
pass
|
||||||
tokens = list(set(tokens))
|
tokens = list(set(tokens))
|
||||||
|
@ -321,13 +322,13 @@ def getkey(outfile, inpath):
|
||||||
|
|
||||||
|
|
||||||
def usage(progname):
|
def usage(progname):
|
||||||
print u"Decrypts the serial number(s) of Kindle For Android from Android backup or file"
|
print(u"Decrypts the serial number(s) of Kindle For Android from Android backup or file")
|
||||||
print u"Get backup.ab file using adb backup com.amazon.kindle for Android 4.0+."
|
print(u"Get backup.ab file using adb backup com.amazon.kindle for Android 4.0+.")
|
||||||
print u"Otherwise extract AmazonSecureStorage.xml from /data/data/com.amazon.kindle/shared_prefs/AmazonSecureStorage.xml"
|
print(u"Otherwise extract AmazonSecureStorage.xml from /data/data/com.amazon.kindle/shared_prefs/AmazonSecureStorage.xml")
|
||||||
print u"Or map_data_storage.db from /data/data/com.amazon.kindle/databases/map_data_storage.db"
|
print(u"Or map_data_storage.db from /data/data/com.amazon.kindle/databases/map_data_storage.db")
|
||||||
print u""
|
print(u"")
|
||||||
print u"Usage:"
|
print(u"Usage:")
|
||||||
print u" {0:s} [-h] [-b <backup.ab>] [<outfile.k4a>]".format(progname)
|
print(u" {0:s} [-h] [-b <backup.ab>] [<outfile.k4a>]".format(progname))
|
||||||
|
|
||||||
|
|
||||||
def cli_main():
|
def cli_main():
|
||||||
|
@ -335,13 +336,13 @@ def cli_main():
|
||||||
sys.stderr=SafeUnbuffered(sys.stderr)
|
sys.stderr=SafeUnbuffered(sys.stderr)
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
print u"{0} v{1}\nCopyright © 2010-2015 Thom, some_updates, Apprentice Alf and Apprentice Harper".format(progname,__version__)
|
print(u"{0} v{1}\nCopyright © 2010-2015 Thom, some_updates, Apprentice Alf and Apprentice Harper".format(progname,__version__))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(argv[1:], "hb:")
|
opts, args = getopt.getopt(argv[1:], "hb:")
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
usage(progname)
|
usage(progname)
|
||||||
print u"\nError in options or arguments: {0}".format(err.args[0])
|
print(u"\nError in options or arguments: {0}".format(err.args[0]))
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
inpath = ""
|
inpath = ""
|
||||||
|
@ -373,13 +374,13 @@ def cli_main():
|
||||||
|
|
||||||
if not os.path.isfile(inpath):
|
if not os.path.isfile(inpath):
|
||||||
usage(progname)
|
usage(progname)
|
||||||
print u"\n{0:s} file not found".format(inpath)
|
print(u"\n{0:s} file not found".format(inpath))
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
if getkey(outfile, inpath):
|
if getkey(outfile, inpath):
|
||||||
print u"\nSaved Kindle for Android key to {0}".format(outfile)
|
print(u"\nSaved Kindle for Android key to {0}".format(outfile))
|
||||||
else:
|
else:
|
||||||
print u"\nCould not retrieve Kindle for Android key."
|
print(u"\nCould not retrieve Kindle for Android key.")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -390,7 +391,7 @@ def gui_main():
|
||||||
import tkMessageBox
|
import tkMessageBox
|
||||||
import tkFileDialog
|
import tkFileDialog
|
||||||
except:
|
except:
|
||||||
print "Tkinter not installed"
|
print("Tkinter not installed")
|
||||||
return cli_main()
|
return cli_main()
|
||||||
|
|
||||||
class DecryptionDialog(Tkinter.Frame):
|
class DecryptionDialog(Tkinter.Frame):
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
|
@ -457,7 +458,7 @@ class ManageKeysDialog(QDialog):
|
||||||
|
|
||||||
class RenameKeyDialog(QDialog):
|
class RenameKeyDialog(QDialog):
|
||||||
def __init__(self, parent=None,):
|
def __init__(self, parent=None,):
|
||||||
print repr(self), repr(parent)
|
print(repr(self), repr(parent))
|
||||||
QDialog.__init__(self, parent)
|
QDialog.__init__(self, parent)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.setWindowTitle("{0} {1}: Rename {0}".format(PLUGIN_NAME, PLUGIN_VERSION, parent.key_type_name))
|
self.setWindowTitle("{0} {1}: Rename {0}".format(PLUGIN_NAME, PLUGIN_VERSION, parent.key_type_name))
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||||
# For use with Topaz Scripts Version 2.6
|
# For use with Topaz Scripts Version 2.6
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
class Unbuffered:
|
class Unbuffered:
|
||||||
def __init__(self, stream):
|
def __init__(self, stream):
|
||||||
self.stream = stream
|
self.stream = stream
|
||||||
|
@ -139,7 +140,7 @@ class Dictionary(object):
|
||||||
self.pos = val
|
self.pos = val
|
||||||
return self.stable[self.pos]
|
return self.stable[self.pos]
|
||||||
else:
|
else:
|
||||||
print "Error - %d outside of string table limits" % val
|
print("Error - %d outside of string table limits" % val)
|
||||||
raise TpzDRMError('outside of string table limits')
|
raise TpzDRMError('outside of string table limits')
|
||||||
# sys.exit(-1)
|
# sys.exit(-1)
|
||||||
|
|
||||||
|
@ -151,7 +152,7 @@ class Dictionary(object):
|
||||||
|
|
||||||
def dumpDict(self):
|
def dumpDict(self):
|
||||||
for i in xrange(self.size):
|
for i in xrange(self.size):
|
||||||
print "%d %s %s" % (i, convert(i), self.stable[i])
|
print("%d %s %s" % (i, convert(i), self.stable[i]))
|
||||||
return
|
return
|
||||||
|
|
||||||
# parses the xml snippets that are represented by each page*.dat file.
|
# parses the xml snippets that are represented by each page*.dat file.
|
||||||
|
@ -457,7 +458,7 @@ class PageParser(object):
|
||||||
elif (argtype == 'snippets') :
|
elif (argtype == 'snippets') :
|
||||||
result = arg
|
result = arg
|
||||||
else :
|
else :
|
||||||
print "Error Unknown argtype %s" % argtype
|
print("Error Unknown argtype %s" % argtype)
|
||||||
sys.exit(-2)
|
sys.exit(-2)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -469,7 +470,7 @@ class PageParser(object):
|
||||||
known_token = False
|
known_token = False
|
||||||
self.tag_push(token)
|
self.tag_push(token)
|
||||||
|
|
||||||
if self.debug : print 'Processing: ', self.get_tagpath(0)
|
if self.debug : print('Processing: ', self.get_tagpath(0))
|
||||||
cnt = self.tagpath_len()
|
cnt = self.tagpath_len()
|
||||||
for j in xrange(cnt):
|
for j in xrange(cnt):
|
||||||
tkn = self.get_tagpath(j)
|
tkn = self.get_tagpath(j)
|
||||||
|
@ -495,7 +496,7 @@ class PageParser(object):
|
||||||
|
|
||||||
if (subtags == 1):
|
if (subtags == 1):
|
||||||
ntags = readEncodedNumber(self.fo)
|
ntags = readEncodedNumber(self.fo)
|
||||||
if self.debug : print 'subtags: ' + token + ' has ' + str(ntags)
|
if self.debug : print('subtags: ' + token + ' has ' + str(ntags))
|
||||||
for j in xrange(ntags):
|
for j in xrange(ntags):
|
||||||
val = readEncodedNumber(self.fo)
|
val = readEncodedNumber(self.fo)
|
||||||
subtagres.append(self.procToken(self.dict.lookup(val)))
|
subtagres.append(self.procToken(self.dict.lookup(val)))
|
||||||
|
@ -529,7 +530,7 @@ class PageParser(object):
|
||||||
else:
|
else:
|
||||||
result = []
|
result = []
|
||||||
if (self.debug or self.first_unknown):
|
if (self.debug or self.first_unknown):
|
||||||
print 'Unknown Token:', token
|
print('Unknown Token:', token)
|
||||||
self.first_unknown = False
|
self.first_unknown = False
|
||||||
self.tag_pop()
|
self.tag_pop()
|
||||||
return result
|
return result
|
||||||
|
@ -544,9 +545,9 @@ class PageParser(object):
|
||||||
result = 'Set of '+ str(cnt) + ' xml snippets. The overall structure \n'
|
result = 'Set of '+ str(cnt) + ' xml snippets. The overall structure \n'
|
||||||
result += 'of the document is indicated by snippet number sets at the\n'
|
result += 'of the document is indicated by snippet number sets at the\n'
|
||||||
result += 'end of each snippet. \n'
|
result += 'end of each snippet. \n'
|
||||||
print result
|
print(result)
|
||||||
for i in xrange(cnt):
|
for i in xrange(cnt):
|
||||||
if self.debug: print 'Snippet:',str(i)
|
if self.debug: print('Snippet:',str(i))
|
||||||
snippet = []
|
snippet = []
|
||||||
snippet.append(i)
|
snippet.append(i)
|
||||||
val = readEncodedNumber(self.fo)
|
val = readEncodedNumber(self.fo)
|
||||||
|
@ -588,10 +589,10 @@ class PageParser(object):
|
||||||
cnt = readEncodedNumber(self.fo)
|
cnt = readEncodedNumber(self.fo)
|
||||||
mode = readEncodedNumber(self.fo)
|
mode = readEncodedNumber(self.fo)
|
||||||
|
|
||||||
if self.debug : print 'Loop for', cnt, 'with mode', mode, ': '
|
if self.debug : print('Loop for', cnt, 'with mode', mode, ': ')
|
||||||
return self.doLoop76Mode(argtype, cnt, mode)
|
return self.doLoop76Mode(argtype, cnt, mode)
|
||||||
|
|
||||||
if self.dbug: print "Unknown command", cmd
|
if self.dbug: print("Unknown command", cmd)
|
||||||
result = []
|
result = []
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -720,7 +721,7 @@ class PageParser(object):
|
||||||
else:
|
else:
|
||||||
rlst.append(self.formatTag(j))
|
rlst.append(self.formatTag(j))
|
||||||
result = "".join(rlst)
|
result = "".join(rlst)
|
||||||
if self.debug : print result
|
if self.debug : print(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -775,7 +776,7 @@ class PageParser(object):
|
||||||
self.doc.append(tag)
|
self.doc.append(tag)
|
||||||
else:
|
else:
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print "Main Loop: Unknown value: %x" % v
|
print("Main Loop: Unknown value: %x" % v)
|
||||||
if (v == 0):
|
if (v == 0):
|
||||||
if (self.peek(1) == 0x5f):
|
if (self.peek(1) == 0x5f):
|
||||||
skip = self.fo.read(1)
|
skip = self.fo.read(1)
|
||||||
|
@ -783,11 +784,11 @@ class PageParser(object):
|
||||||
|
|
||||||
# now do snippet injection
|
# now do snippet injection
|
||||||
if len(self.snippetList) > 0 :
|
if len(self.snippetList) > 0 :
|
||||||
if self.debug : print 'Injecting Snippets:'
|
if self.debug : print('Injecting Snippets:')
|
||||||
snippet = self.injectSnippets(self.snippetList[0])
|
snippet = self.injectSnippets(self.snippetList[0])
|
||||||
snipno = snippet[0]
|
snipno = snippet[0]
|
||||||
tag_add = snippet[1]
|
tag_add = snippet[1]
|
||||||
if self.debug : print self.formatTag(tag_add)
|
if self.debug : print(self.formatTag(tag_add))
|
||||||
if len(tag_add) > 0:
|
if len(tag_add) > 0:
|
||||||
self.doc.append(tag_add)
|
self.doc.append(tag_add)
|
||||||
|
|
||||||
|
@ -812,19 +813,19 @@ def getXML(dict, fname):
|
||||||
return xmlpage
|
return xmlpage
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print 'Usage: '
|
print('Usage: ')
|
||||||
print ' convert2xml.py dict0000.dat infile.dat '
|
print(' convert2xml.py dict0000.dat infile.dat ')
|
||||||
print ' '
|
print(' ')
|
||||||
print ' Options:'
|
print(' Options:')
|
||||||
print ' -h print this usage help message '
|
print(' -h print this usage help message ')
|
||||||
print ' -d turn on debug output to check for potential errors '
|
print(' -d turn on debug output to check for potential errors ')
|
||||||
print ' --flat-xml output the flattened xml page description only '
|
print(' --flat-xml output the flattened xml page description only ')
|
||||||
print ' '
|
print(' ')
|
||||||
print ' This program will attempt to convert a page*.dat file or '
|
print(' This program will attempt to convert a page*.dat file or ')
|
||||||
print ' glyphs*.dat file, using the dict0000.dat file, to its xml description. '
|
print(' glyphs*.dat file, using the dict0000.dat file, to its xml description. ')
|
||||||
print ' '
|
print(' ')
|
||||||
print ' Use "cmbtc_dump.py" first to unencrypt, uncompress, and dump '
|
print(' Use "cmbtc_dump.py" first to unencrypt, uncompress, and dump ')
|
||||||
print ' the *.dat files from a Topaz format e-book.'
|
print(' the *.dat files from a Topaz format e-book.')
|
||||||
|
|
||||||
#
|
#
|
||||||
# Main
|
# Main
|
||||||
|
@ -846,7 +847,7 @@ def main(argv):
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
|
|
||||||
# print help information and exit:
|
# print help information and exit:
|
||||||
print str(err) # will print something like "option -a not recognized"
|
print(str(err)) # will print something like "option -a not recognized"
|
||||||
usage()
|
usage()
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
@ -875,7 +876,7 @@ def main(argv):
|
||||||
xmlpage = pp.process()
|
xmlpage = pp.process()
|
||||||
|
|
||||||
if printOutput:
|
if printOutput:
|
||||||
print xmlpage
|
print(xmlpage)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
return xmlpage
|
return xmlpage
|
||||||
|
|
|
@ -15,6 +15,7 @@ Provide base64 encoding.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
|
@ -23,9 +24,9 @@ import os
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
def usage(progname):
|
def usage(progname):
|
||||||
print "Applies base64 encoding to the supplied file, sending to standard output"
|
print("Applies base64 encoding to the supplied file, sending to standard output")
|
||||||
print "Usage:"
|
print("Usage:")
|
||||||
print " %s <infile>" % progname
|
print(" %s <infile>" % progname)
|
||||||
|
|
||||||
def cli_main(argv=sys.argv):
|
def cli_main(argv=sys.argv):
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
|
@ -37,7 +38,7 @@ def cli_main(argv=sys.argv):
|
||||||
keypath = argv[1]
|
keypath = argv[1]
|
||||||
with open(keypath, 'rb') as f:
|
with open(keypath, 'rb') as f:
|
||||||
keyder = f.read()
|
keyder = f.read()
|
||||||
print keyder.encode('base64')
|
print(keyder.encode('base64'))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__version__ = '1.01'
|
__version__ = '1.01'
|
||||||
|
|
||||||
|
@ -199,7 +200,7 @@ def encryption(infile):
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
print encryption(argv[1])
|
print(encryption(argv[1]))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||||
# For use with Topaz Scripts Version 2.6
|
# For use with Topaz Scripts Version 2.6
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
|
@ -750,11 +751,11 @@ class DocParser(object):
|
||||||
hlst.append('<div class="graphic"><img src="img/img%04d.jpg" alt="" /></div>' % int(simgsrc))
|
hlst.append('<div class="graphic"><img src="img/img%04d.jpg" alt="" /></div>' % int(simgsrc))
|
||||||
|
|
||||||
else :
|
else :
|
||||||
print ' Making region type', regtype,
|
print(' Making region type', regtype, end=' ')
|
||||||
(pos, temp) = self.findinDoc('paragraph',start,end)
|
(pos, temp) = self.findinDoc('paragraph',start,end)
|
||||||
(pos2, temp) = self.findinDoc('span',start,end)
|
(pos2, temp) = self.findinDoc('span',start,end)
|
||||||
if pos != -1 or pos2 != -1:
|
if pos != -1 or pos2 != -1:
|
||||||
print ' a "text" region'
|
print(' a "text" region')
|
||||||
orig_regtype = regtype
|
orig_regtype = regtype
|
||||||
regtype = 'fixed'
|
regtype = 'fixed'
|
||||||
ptype = 'full'
|
ptype = 'full'
|
||||||
|
@ -779,7 +780,7 @@ class DocParser(object):
|
||||||
else :
|
else :
|
||||||
hlst.append(self.buildParagraph(pclass, pdesc, ptype, regtype))
|
hlst.append(self.buildParagraph(pclass, pdesc, ptype, regtype))
|
||||||
else :
|
else :
|
||||||
print ' a "graphic" region'
|
print(' a "graphic" region')
|
||||||
(pos, simgsrc) = self.findinDoc('img.src',start,end)
|
(pos, simgsrc) = self.findinDoc('img.src',start,end)
|
||||||
if simgsrc:
|
if simgsrc:
|
||||||
hlst.append('<div class="graphic"><img src="img/img%04d.jpg" alt="" /></div>' % int(simgsrc))
|
hlst.append('<div class="graphic"><img src="img/img%04d.jpg" alt="" /></div>' % int(simgsrc))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#! /usr/bin/python
|
#! /usr/bin/python
|
||||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
class Unbuffered:
|
class Unbuffered:
|
||||||
def __init__(self, stream):
|
def __init__(self, stream):
|
||||||
self.stream = stream
|
self.stream = stream
|
||||||
|
@ -117,7 +118,7 @@ class Dictionary(object):
|
||||||
self.pos = val
|
self.pos = val
|
||||||
return self.stable[self.pos]
|
return self.stable[self.pos]
|
||||||
else:
|
else:
|
||||||
print "Error: %d outside of string table limits" % val
|
print("Error: %d outside of string table limits" % val)
|
||||||
raise TpzDRMError('outside or string table limits')
|
raise TpzDRMError('outside or string table limits')
|
||||||
# sys.exit(-1)
|
# sys.exit(-1)
|
||||||
def getSize(self):
|
def getSize(self):
|
||||||
|
@ -268,32 +269,32 @@ class GlyphDict(object):
|
||||||
def generateBook(bookDir, raw, fixedimage):
|
def generateBook(bookDir, raw, fixedimage):
|
||||||
# sanity check Topaz file extraction
|
# sanity check Topaz file extraction
|
||||||
if not os.path.exists(bookDir) :
|
if not os.path.exists(bookDir) :
|
||||||
print "Can not find directory with unencrypted book"
|
print("Can not find directory with unencrypted book")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
dictFile = os.path.join(bookDir,'dict0000.dat')
|
dictFile = os.path.join(bookDir,'dict0000.dat')
|
||||||
if not os.path.exists(dictFile) :
|
if not os.path.exists(dictFile) :
|
||||||
print "Can not find dict0000.dat file"
|
print("Can not find dict0000.dat file")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
pageDir = os.path.join(bookDir,'page')
|
pageDir = os.path.join(bookDir,'page')
|
||||||
if not os.path.exists(pageDir) :
|
if not os.path.exists(pageDir) :
|
||||||
print "Can not find page directory in unencrypted book"
|
print("Can not find page directory in unencrypted book")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
imgDir = os.path.join(bookDir,'img')
|
imgDir = os.path.join(bookDir,'img')
|
||||||
if not os.path.exists(imgDir) :
|
if not os.path.exists(imgDir) :
|
||||||
print "Can not find image directory in unencrypted book"
|
print("Can not find image directory in unencrypted book")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
glyphsDir = os.path.join(bookDir,'glyphs')
|
glyphsDir = os.path.join(bookDir,'glyphs')
|
||||||
if not os.path.exists(glyphsDir) :
|
if not os.path.exists(glyphsDir) :
|
||||||
print "Can not find glyphs directory in unencrypted book"
|
print("Can not find glyphs directory in unencrypted book")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
metaFile = os.path.join(bookDir,'metadata0000.dat')
|
metaFile = os.path.join(bookDir,'metadata0000.dat')
|
||||||
if not os.path.exists(metaFile) :
|
if not os.path.exists(metaFile) :
|
||||||
print "Can not find metadata0000.dat in unencrypted book"
|
print("Can not find metadata0000.dat in unencrypted book")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
svgDir = os.path.join(bookDir,'svg')
|
svgDir = os.path.join(bookDir,'svg')
|
||||||
|
@ -307,10 +308,10 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
|
|
||||||
otherFile = os.path.join(bookDir,'other0000.dat')
|
otherFile = os.path.join(bookDir,'other0000.dat')
|
||||||
if not os.path.exists(otherFile) :
|
if not os.path.exists(otherFile) :
|
||||||
print "Can not find other0000.dat in unencrypted book"
|
print("Can not find other0000.dat in unencrypted book")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
print "Updating to color images if available"
|
print("Updating to color images if available")
|
||||||
spath = os.path.join(bookDir,'color_img')
|
spath = os.path.join(bookDir,'color_img')
|
||||||
dpath = os.path.join(bookDir,'img')
|
dpath = os.path.join(bookDir,'img')
|
||||||
filenames = os.listdir(spath)
|
filenames = os.listdir(spath)
|
||||||
|
@ -322,7 +323,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
imgdata = file(sfile,'rb').read()
|
imgdata = file(sfile,'rb').read()
|
||||||
file(dfile,'wb').write(imgdata)
|
file(dfile,'wb').write(imgdata)
|
||||||
|
|
||||||
print "Creating cover.jpg"
|
print("Creating cover.jpg")
|
||||||
isCover = False
|
isCover = False
|
||||||
cpath = os.path.join(bookDir,'img')
|
cpath = os.path.join(bookDir,'img')
|
||||||
cpath = os.path.join(cpath,'img0000.jpg')
|
cpath = os.path.join(cpath,'img0000.jpg')
|
||||||
|
@ -333,10 +334,10 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
isCover = True
|
isCover = True
|
||||||
|
|
||||||
|
|
||||||
print 'Processing Dictionary'
|
print('Processing Dictionary')
|
||||||
dict = Dictionary(dictFile)
|
dict = Dictionary(dictFile)
|
||||||
|
|
||||||
print 'Processing Meta Data and creating OPF'
|
print('Processing Meta Data and creating OPF')
|
||||||
meta_array = getMetaArray(metaFile)
|
meta_array = getMetaArray(metaFile)
|
||||||
|
|
||||||
# replace special chars in title and authors like & < >
|
# replace special chars in title and authors like & < >
|
||||||
|
@ -360,7 +361,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
mlst = None
|
mlst = None
|
||||||
file(xname, 'wb').write(metastr)
|
file(xname, 'wb').write(metastr)
|
||||||
|
|
||||||
print 'Processing StyleSheet'
|
print('Processing StyleSheet')
|
||||||
|
|
||||||
# get some scaling info from metadata to use while processing styles
|
# get some scaling info from metadata to use while processing styles
|
||||||
# and first page info
|
# and first page info
|
||||||
|
@ -426,7 +427,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
xname = os.path.join(xmlDir, 'other0000.xml')
|
xname = os.path.join(xmlDir, 'other0000.xml')
|
||||||
file(xname, 'wb').write(convert2xml.getXML(dict, otherFile))
|
file(xname, 'wb').write(convert2xml.getXML(dict, otherFile))
|
||||||
|
|
||||||
print 'Processing Glyphs'
|
print('Processing Glyphs')
|
||||||
gd = GlyphDict()
|
gd = GlyphDict()
|
||||||
filenames = os.listdir(glyphsDir)
|
filenames = os.listdir(glyphsDir)
|
||||||
filenames = sorted(filenames)
|
filenames = sorted(filenames)
|
||||||
|
@ -440,7 +441,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
counter = 0
|
counter = 0
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
# print ' ', filename
|
# print ' ', filename
|
||||||
print '.',
|
print('.', end=' ')
|
||||||
fname = os.path.join(glyphsDir,filename)
|
fname = os.path.join(glyphsDir,filename)
|
||||||
flat_xml = convert2xml.fromData(dict, fname)
|
flat_xml = convert2xml.fromData(dict, fname)
|
||||||
|
|
||||||
|
@ -459,7 +460,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
glyfile.write('</defs>\n')
|
glyfile.write('</defs>\n')
|
||||||
glyfile.write('</svg>\n')
|
glyfile.write('</svg>\n')
|
||||||
glyfile.close()
|
glyfile.close()
|
||||||
print " "
|
print(" ")
|
||||||
|
|
||||||
|
|
||||||
# start up the html
|
# start up the html
|
||||||
|
@ -481,7 +482,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
hlst.append('<link href="style.css" rel="stylesheet" type="text/css" />\n')
|
hlst.append('<link href="style.css" rel="stylesheet" type="text/css" />\n')
|
||||||
hlst.append('</head>\n<body>\n')
|
hlst.append('</head>\n<body>\n')
|
||||||
|
|
||||||
print 'Processing Pages'
|
print('Processing Pages')
|
||||||
# Books are at 1440 DPI. This is rendering at twice that size for
|
# Books are at 1440 DPI. This is rendering at twice that size for
|
||||||
# readability when rendering to the screen.
|
# readability when rendering to the screen.
|
||||||
scaledpi = 1440.0
|
scaledpi = 1440.0
|
||||||
|
@ -495,7 +496,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
|
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
# print ' ', filename
|
# print ' ', filename
|
||||||
print ".",
|
print(".", end=' ')
|
||||||
fname = os.path.join(pageDir,filename)
|
fname = os.path.join(pageDir,filename)
|
||||||
flat_xml = convert2xml.fromData(dict, fname)
|
flat_xml = convert2xml.fromData(dict, fname)
|
||||||
|
|
||||||
|
@ -517,8 +518,8 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
hlst = None
|
hlst = None
|
||||||
file(os.path.join(bookDir, htmlFileName), 'wb').write(htmlstr)
|
file(os.path.join(bookDir, htmlFileName), 'wb').write(htmlstr)
|
||||||
|
|
||||||
print " "
|
print(" ")
|
||||||
print 'Extracting Table of Contents from Amazon OCR'
|
print('Extracting Table of Contents from Amazon OCR')
|
||||||
|
|
||||||
# first create a table of contents file for the svg images
|
# first create a table of contents file for the svg images
|
||||||
tlst = []
|
tlst = []
|
||||||
|
@ -550,7 +551,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
toclst = tocentries.split('\n')
|
toclst = tocentries.split('\n')
|
||||||
toclst.pop()
|
toclst.pop()
|
||||||
for entry in toclst:
|
for entry in toclst:
|
||||||
print entry
|
print(entry)
|
||||||
title, pagenum = entry.split('|')
|
title, pagenum = entry.split('|')
|
||||||
id = pageidnums[int(pagenum)]
|
id = pageidnums[int(pagenum)]
|
||||||
if (raw):
|
if (raw):
|
||||||
|
@ -580,7 +581,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
slst.append('</head>\n')
|
slst.append('</head>\n')
|
||||||
slst.append('<body>\n')
|
slst.append('<body>\n')
|
||||||
|
|
||||||
print "Building svg images of each book page"
|
print("Building svg images of each book page")
|
||||||
slst.append('<h2>List of Pages</h2>\n')
|
slst.append('<h2>List of Pages</h2>\n')
|
||||||
slst.append('<div>\n')
|
slst.append('<div>\n')
|
||||||
idlst = sorted(pageIDMap.keys())
|
idlst = sorted(pageIDMap.keys())
|
||||||
|
@ -593,7 +594,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
nextid = idlst[j+1]
|
nextid = idlst[j+1]
|
||||||
else:
|
else:
|
||||||
nextid = None
|
nextid = None
|
||||||
print '.',
|
print('.', end=' ')
|
||||||
pagelst = pageIDMap[pageid]
|
pagelst = pageIDMap[pageid]
|
||||||
flst = []
|
flst = []
|
||||||
for page in pagelst:
|
for page in pagelst:
|
||||||
|
@ -618,7 +619,7 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
slst = None
|
slst = None
|
||||||
file(os.path.join(bookDir, 'index_svg.xhtml'), 'wb').write(svgindex)
|
file(os.path.join(bookDir, 'index_svg.xhtml'), 'wb').write(svgindex)
|
||||||
|
|
||||||
print " "
|
print(" ")
|
||||||
|
|
||||||
# build the opf file
|
# build the opf file
|
||||||
opfname = os.path.join(bookDir, 'book.opf')
|
opfname = os.path.join(bookDir, 'book.opf')
|
||||||
|
@ -667,20 +668,20 @@ def generateBook(bookDir, raw, fixedimage):
|
||||||
olst = None
|
olst = None
|
||||||
file(opfname, 'wb').write(opfstr)
|
file(opfname, 'wb').write(opfstr)
|
||||||
|
|
||||||
print 'Processing Complete'
|
print('Processing Complete')
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print "genbook.py generates a book from the extract Topaz Files"
|
print("genbook.py generates a book from the extract Topaz Files")
|
||||||
print "Usage:"
|
print("Usage:")
|
||||||
print " genbook.py [-r] [-h [--fixed-image] <bookDir> "
|
print(" genbook.py [-r] [-h [--fixed-image] <bookDir> ")
|
||||||
print " "
|
print(" ")
|
||||||
print "Options:"
|
print("Options:")
|
||||||
print " -h : help - print this usage message"
|
print(" -h : help - print this usage message")
|
||||||
print " -r : generate raw svg files (not wrapped in xhtml)"
|
print(" -r : generate raw svg files (not wrapped in xhtml)")
|
||||||
print " --fixed-image : genearate any Fixed Area as an svg image in the html"
|
print(" --fixed-image : genearate any Fixed Area as an svg image in the html")
|
||||||
print " "
|
print(" ")
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
|
@ -692,7 +693,7 @@ def main(argv):
|
||||||
opts, args = getopt.getopt(argv[1:], "rh:",["fixed-image"])
|
opts, args = getopt.getopt(argv[1:], "rh:",["fixed-image"])
|
||||||
|
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print str(err)
|
print(str(err))
|
||||||
usage()
|
usage()
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ from __future__ import with_statement
|
||||||
"""
|
"""
|
||||||
Decrypt Barnes & Noble encrypted ePub books.
|
Decrypt Barnes & Noble encrypted ePub books.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = "4.1"
|
__version__ = "4.1"
|
||||||
|
@ -262,7 +263,7 @@ def decryptBook(keyb64, inpath, outpath):
|
||||||
namelist = set(inf.namelist())
|
namelist = set(inf.namelist())
|
||||||
if 'META-INF/rights.xml' not in namelist or \
|
if 'META-INF/rights.xml' not in namelist or \
|
||||||
'META-INF/encryption.xml' not in namelist:
|
'META-INF/encryption.xml' not in namelist:
|
||||||
print u"{0:s} is DRM-free.".format(os.path.basename(inpath))
|
print(u"{0:s} is DRM-free.".format(os.path.basename(inpath)))
|
||||||
return 1
|
return 1
|
||||||
for name in META_NAMES:
|
for name in META_NAMES:
|
||||||
namelist.remove(name)
|
namelist.remove(name)
|
||||||
|
@ -272,7 +273,7 @@ def decryptBook(keyb64, inpath, outpath):
|
||||||
expr = './/%s' % (adept('encryptedKey'),)
|
expr = './/%s' % (adept('encryptedKey'),)
|
||||||
bookkey = ''.join(rights.findtext(expr))
|
bookkey = ''.join(rights.findtext(expr))
|
||||||
if len(bookkey) != 64:
|
if len(bookkey) != 64:
|
||||||
print u"{0:s} is not a secure Barnes & Noble ePub.".format(os.path.basename(inpath))
|
print(u"{0:s} is not a secure Barnes & Noble ePub.".format(os.path.basename(inpath)))
|
||||||
return 1
|
return 1
|
||||||
bookkey = aes.decrypt(bookkey.decode('base64'))
|
bookkey = aes.decrypt(bookkey.decode('base64'))
|
||||||
bookkey = bookkey[:-ord(bookkey[-1])]
|
bookkey = bookkey[:-ord(bookkey[-1])]
|
||||||
|
@ -315,7 +316,7 @@ def decryptBook(keyb64, inpath, outpath):
|
||||||
pass
|
pass
|
||||||
outf.writestr(zi, decryptor.decrypt(path, data))
|
outf.writestr(zi, decryptor.decrypt(path, data))
|
||||||
except:
|
except:
|
||||||
print u"Could not decrypt {0:s} because of an exception:\n{1:s}".format(os.path.basename(inpath), traceback.format_exc())
|
print(u"Could not decrypt {0:s} because of an exception:\n{1:s}".format(os.path.basename(inpath), traceback.format_exc()))
|
||||||
return 2
|
return 2
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ -326,13 +327,13 @@ def cli_main():
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
if len(argv) != 4:
|
if len(argv) != 4:
|
||||||
print u"usage: {0} <keyfile.b64> <inbook.epub> <outbook.epub>".format(progname)
|
print(u"usage: {0} <keyfile.b64> <inbook.epub> <outbook.epub>".format(progname))
|
||||||
return 1
|
return 1
|
||||||
keypath, inpath, outpath = argv[1:]
|
keypath, inpath, outpath = argv[1:]
|
||||||
userkey = open(keypath,'rb').read()
|
userkey = open(keypath,'rb').read()
|
||||||
result = decryptBook(userkey, inpath, outpath)
|
result = decryptBook(userkey, inpath, outpath)
|
||||||
if result == 0:
|
if result == 0:
|
||||||
print u"Successfully decrypted {0:s} as {1:s}".format(os.path.basename(inpath),os.path.basename(outpath))
|
print(u"Successfully decrypted {0:s} as {1:s}".format(os.path.basename(inpath),os.path.basename(outpath)))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def gui_main():
|
def gui_main():
|
||||||
|
|
|
@ -18,6 +18,7 @@ from __future__ import with_statement
|
||||||
"""
|
"""
|
||||||
Get Barnes & Noble EPUB user key from nook Studio log file
|
Get Barnes & Noble EPUB user key from nook Studio log file
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = "1.1"
|
__version__ = "1.1"
|
||||||
|
@ -198,7 +199,7 @@ def nookkeys(files = []):
|
||||||
for file in files:
|
for file in files:
|
||||||
fileKeys = getKeysFromLog(file)
|
fileKeys = getKeysFromLog(file)
|
||||||
if fileKeys:
|
if fileKeys:
|
||||||
print u"Found {0} keys in the Nook Study log files".format(len(fileKeys))
|
print(u"Found {0} keys in the Nook Study log files".format(len(fileKeys)))
|
||||||
keys.extend(fileKeys)
|
keys.extend(fileKeys)
|
||||||
return list(set(keys))
|
return list(set(keys))
|
||||||
|
|
||||||
|
@ -211,7 +212,7 @@ def getkey(outpath, files=[]):
|
||||||
outfile = outpath
|
outfile = outpath
|
||||||
with file(outfile, 'w') as keyfileout:
|
with file(outfile, 'w') as keyfileout:
|
||||||
keyfileout.write(keys[-1])
|
keyfileout.write(keys[-1])
|
||||||
print u"Saved a key to {0}".format(outfile)
|
print(u"Saved a key to {0}".format(outfile))
|
||||||
else:
|
else:
|
||||||
keycount = 0
|
keycount = 0
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
@ -222,16 +223,16 @@ def getkey(outpath, files=[]):
|
||||||
break
|
break
|
||||||
with file(outfile, 'w') as keyfileout:
|
with file(outfile, 'w') as keyfileout:
|
||||||
keyfileout.write(key)
|
keyfileout.write(key)
|
||||||
print u"Saved a key to {0}".format(outfile)
|
print(u"Saved a key to {0}".format(outfile))
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def usage(progname):
|
def usage(progname):
|
||||||
print u"Finds the nook Study encryption keys."
|
print(u"Finds the nook Study encryption keys.")
|
||||||
print u"Keys are saved to the current directory, or a specified output directory."
|
print(u"Keys are saved to the current directory, or a specified output directory.")
|
||||||
print u"If a file name is passed instead of a directory, only the first key is saved, in that file."
|
print(u"If a file name is passed instead of a directory, only the first key is saved, in that file.")
|
||||||
print u"Usage:"
|
print(u"Usage:")
|
||||||
print u" {0:s} [-h] [-k <logFile>] [<outpath>]".format(progname)
|
print(u" {0:s} [-h] [-k <logFile>] [<outpath>]".format(progname))
|
||||||
|
|
||||||
|
|
||||||
def cli_main():
|
def cli_main():
|
||||||
|
@ -239,12 +240,12 @@ def cli_main():
|
||||||
sys.stderr=SafeUnbuffered(sys.stderr)
|
sys.stderr=SafeUnbuffered(sys.stderr)
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
print u"{0} v{1}\nCopyright © 2015 Apprentice Alf".format(progname,__version__)
|
print(u"{0} v{1}\nCopyright © 2015 Apprentice Alf".format(progname,__version__))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(argv[1:], "hk:")
|
opts, args = getopt.getopt(argv[1:], "hk:")
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print u"Error in options or arguments: {0}".format(err.args[0])
|
print(u"Error in options or arguments: {0}".format(err.args[0]))
|
||||||
usage(progname)
|
usage(progname)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
@ -273,7 +274,7 @@ def cli_main():
|
||||||
outpath = os.path.realpath(os.path.normpath(outpath))
|
outpath = os.path.realpath(os.path.normpath(outpath))
|
||||||
|
|
||||||
if not getkey(outpath, files):
|
if not getkey(outpath, files):
|
||||||
print u"Could not retrieve nook Study key."
|
print(u"Could not retrieve nook Study key.")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,7 +308,7 @@ def gui_main():
|
||||||
keys = nookkeys()
|
keys = nookkeys()
|
||||||
keycount = 0
|
keycount = 0
|
||||||
for key in keys:
|
for key in keys:
|
||||||
print key
|
print(key)
|
||||||
while True:
|
while True:
|
||||||
keycount += 1
|
keycount += 1
|
||||||
outfile = os.path.join(progpath,u"nookkey{0:d}.b64".format(keycount))
|
outfile = os.path.join(progpath,u"nookkey{0:d}.b64".format(keycount))
|
||||||
|
|
|
@ -28,6 +28,7 @@ from __future__ import with_statement
|
||||||
"""
|
"""
|
||||||
Fetch Barnes & Noble EPUB user key from B&N servers using email and password
|
Fetch Barnes & Noble EPUB user key from B&N servers using email and password
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = "1.1"
|
__version__ = "1.1"
|
||||||
|
@ -155,14 +156,14 @@ def cli_main():
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
if len(argv) != 4:
|
if len(argv) != 4:
|
||||||
print u"usage: {0} <email> <password> <keyfileout.b64>".format(progname)
|
print(u"usage: {0} <email> <password> <keyfileout.b64>".format(progname))
|
||||||
return 1
|
return 1
|
||||||
email, password, keypath = argv[1:]
|
email, password, keypath = argv[1:]
|
||||||
userkey = fetch_key(email, password)
|
userkey = fetch_key(email, password)
|
||||||
if len(userkey) == 28:
|
if len(userkey) == 28:
|
||||||
open(keypath,'wb').write(userkey)
|
open(keypath,'wb').write(userkey)
|
||||||
return 0
|
return 0
|
||||||
print u"Failed to fetch key."
|
print(u"Failed to fetch key.")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ from __future__ import with_statement
|
||||||
"""
|
"""
|
||||||
Generate Barnes & Noble EPUB user key from name and credit card number.
|
Generate Barnes & Noble EPUB user key from name and credit card number.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = "2.8"
|
__version__ = "2.8"
|
||||||
|
@ -223,12 +224,12 @@ def cli_main():
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
if AES is None:
|
if AES is None:
|
||||||
print "%s: This script requires OpenSSL or PyCrypto, which must be installed " \
|
print("%s: This script requires OpenSSL or PyCrypto, which must be installed " \
|
||||||
"separately. Read the top-of-script comment for details." % \
|
"separately. Read the top-of-script comment for details." % \
|
||||||
(progname,)
|
(progname,))
|
||||||
return 1
|
return 1
|
||||||
if len(argv) != 4:
|
if len(argv) != 4:
|
||||||
print u"usage: {0} <Name> <CC#> <keyfileout.b64>".format(progname)
|
print(u"usage: {0} <Name> <CC#> <keyfileout.b64>".format(progname))
|
||||||
return 1
|
return 1
|
||||||
name, ccn, keypath = argv[1:]
|
name, ccn, keypath = argv[1:]
|
||||||
userkey = generate_key(name, ccn)
|
userkey = generate_key(name, ccn)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
# Engine to remove drm from Kindle KFX ebooks
|
# Engine to remove drm from Kindle KFX ebooks
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ class KFXZipBook:
|
||||||
data += fh.read()
|
data += fh.read()
|
||||||
if self.voucher is None:
|
if self.voucher is None:
|
||||||
self.decrypt_voucher(totalpids)
|
self.decrypt_voucher(totalpids)
|
||||||
print u'Decrypting KFX DRMION: {0}'.format(filename)
|
print(u'Decrypting KFX DRMION: {0}'.format(filename))
|
||||||
outfile = StringIO()
|
outfile = StringIO()
|
||||||
ion.DrmIon(StringIO(data[8:-8]), lambda name: self.voucher).parse(outfile)
|
ion.DrmIon(StringIO(data[8:-8]), lambda name: self.voucher).parse(outfile)
|
||||||
self.decrypted[filename] = outfile.getvalue()
|
self.decrypted[filename] = outfile.getvalue()
|
||||||
|
@ -65,7 +66,7 @@ class KFXZipBook:
|
||||||
else:
|
else:
|
||||||
raise Exception(u'The .kfx-zip archive contains an encrypted DRMION file without a DRM voucher')
|
raise Exception(u'The .kfx-zip archive contains an encrypted DRMION file without a DRM voucher')
|
||||||
|
|
||||||
print u'Decrypting KFX DRM voucher: {0}'.format(info.filename)
|
print(u'Decrypting KFX DRM voucher: {0}'.format(info.filename))
|
||||||
|
|
||||||
for pid in [''] + totalpids:
|
for pid in [''] + totalpids:
|
||||||
for dsn_len,secret_len in [(0,0), (16,0), (16,40), (32,40), (40,40)]:
|
for dsn_len,secret_len in [(0,0), (16,0), (16,40), (32,40), (40,40)]:
|
||||||
|
@ -84,7 +85,7 @@ class KFXZipBook:
|
||||||
else:
|
else:
|
||||||
raise Exception(u'Failed to decrypt KFX DRM voucher with any key')
|
raise Exception(u'Failed to decrypt KFX DRM voucher with any key')
|
||||||
|
|
||||||
print u'KFX DRM voucher successfully decrypted'
|
print(u'KFX DRM voucher successfully decrypted')
|
||||||
|
|
||||||
license_type = voucher.getlicensetype()
|
license_type = voucher.getlicensetype()
|
||||||
if license_type != "Purchase":
|
if license_type != "Purchase":
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
# kgenpids.py
|
# kgenpids.py
|
||||||
# Copyright © 2008-2017 Apprentice Harper et al.
|
# Copyright © 2008-2017 Apprentice Harper et al.
|
||||||
|
@ -214,7 +215,7 @@ def getK4Pids(rec209, token, kindleDatabase):
|
||||||
try:
|
try:
|
||||||
# Get the DSN token, if present
|
# Get the DSN token, if present
|
||||||
DSN = (kindleDatabase[1])['DSN'].decode('hex')
|
DSN = (kindleDatabase[1])['DSN'].decode('hex')
|
||||||
print u"Got DSN key from database {0}".format(kindleDatabase[0])
|
print(u"Got DSN key from database {0}".format(kindleDatabase[0]))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# See if we have the info to generate the DSN
|
# See if we have the info to generate the DSN
|
||||||
try:
|
try:
|
||||||
|
@ -225,7 +226,7 @@ def getK4Pids(rec209, token, kindleDatabase):
|
||||||
try:
|
try:
|
||||||
# Get the SerialNumber token, if present
|
# Get the SerialNumber token, if present
|
||||||
IDString = (kindleDatabase[1])['SerialNumber'].decode('hex')
|
IDString = (kindleDatabase[1])['SerialNumber'].decode('hex')
|
||||||
print u"Got SerialNumber from database {0}".format(kindleDatabase[0])
|
print(u"Got SerialNumber from database {0}".format(kindleDatabase[0]))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# Get the IDString we added
|
# Get the IDString we added
|
||||||
IDString = (kindleDatabase[1])['IDString'].decode('hex')
|
IDString = (kindleDatabase[1])['IDString'].decode('hex')
|
||||||
|
@ -233,7 +234,7 @@ def getK4Pids(rec209, token, kindleDatabase):
|
||||||
try:
|
try:
|
||||||
# Get the UsernameHash token, if present
|
# Get the UsernameHash token, if present
|
||||||
encodedUsername = (kindleDatabase[1])['UsernameHash'].decode('hex')
|
encodedUsername = (kindleDatabase[1])['UsernameHash'].decode('hex')
|
||||||
print u"Got UsernameHash from database {0}".format(kindleDatabase[0])
|
print(u"Got UsernameHash from database {0}".format(kindleDatabase[0]))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# Get the UserName we added
|
# Get the UserName we added
|
||||||
UserName = (kindleDatabase[1])['UserName'].decode('hex')
|
UserName = (kindleDatabase[1])['UserName'].decode('hex')
|
||||||
|
@ -241,7 +242,7 @@ def getK4Pids(rec209, token, kindleDatabase):
|
||||||
encodedUsername = encodeHash(UserName,charMap1)
|
encodedUsername = encodeHash(UserName,charMap1)
|
||||||
#print u"encodedUsername",encodedUsername.encode('hex')
|
#print u"encodedUsername",encodedUsername.encode('hex')
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print u"Keys not found in the database {0}.".format(kindleDatabase[0])
|
print(u"Keys not found in the database {0}.".format(kindleDatabase[0]))
|
||||||
return pids
|
return pids
|
||||||
|
|
||||||
# Get the ID string used
|
# Get the ID string used
|
||||||
|
@ -297,14 +298,14 @@ def getPidList(md1, md2, serials=[], kDatabases=[]):
|
||||||
try:
|
try:
|
||||||
pidlst.extend(getK4Pids(md1, md2, kDatabase))
|
pidlst.extend(getK4Pids(md1, md2, kDatabase))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print u"Error getting PIDs from database {0}: {1}".format(kDatabase[0],e.args[0])
|
print(u"Error getting PIDs from database {0}: {1}".format(kDatabase[0],e.args[0]))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
for serialnum in serials:
|
for serialnum in serials:
|
||||||
try:
|
try:
|
||||||
pidlst.extend(getKindlePids(md1, md2, serialnum))
|
pidlst.extend(getKindlePids(md1, md2, serialnum))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print u"Error getting PIDs from serial number {0}: {1}".format(serialnum ,e.args[0])
|
print(u"Error getting PIDs from serial number {0}: {1}".format(serialnum ,e.args[0]))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
return pidlst
|
return pidlst
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
# 0.4 Added support for serial numbers starting with '9', fixed unicode bugs.
|
# 0.4 Added support for serial numbers starting with '9', fixed unicode bugs.
|
||||||
# 0.5 moved unicode_argv call inside main for Windows DeDRM compatibility
|
# 0.5 moved unicode_argv call inside main for Windows DeDRM compatibility
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import binascii
|
import binascii
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ def unicode_argv():
|
||||||
return [arg if (type(arg) == unicode) else unicode(arg,argvencoding) for arg in sys.argv]
|
return [arg if (type(arg) == unicode) else unicode(arg,argvencoding) for arg in sys.argv]
|
||||||
|
|
||||||
if sys.hexversion >= 0x3000000:
|
if sys.hexversion >= 0x3000000:
|
||||||
print 'This script is incompatible with Python 3.x. Please install Python 2.7.x.'
|
print('This script is incompatible with Python 3.x. Please install Python 2.7.x.')
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
letters = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789'
|
letters = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789'
|
||||||
|
@ -113,28 +114,28 @@ def pidFromSerial(s, l):
|
||||||
return pid
|
return pid
|
||||||
|
|
||||||
def cli_main():
|
def cli_main():
|
||||||
print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky"
|
print(u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky")
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
if len(argv)==2:
|
if len(argv)==2:
|
||||||
serial = argv[1]
|
serial = argv[1]
|
||||||
else:
|
else:
|
||||||
print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>"
|
print(u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>")
|
||||||
return 1
|
return 1
|
||||||
if len(serial)==16:
|
if len(serial)==16:
|
||||||
if serial.startswith("B") or serial.startswith("9"):
|
if serial.startswith("B") or serial.startswith("9"):
|
||||||
print u"Kindle serial number detected"
|
print(u"Kindle serial number detected")
|
||||||
else:
|
else:
|
||||||
print u"Warning: unrecognized serial number. Please recheck input."
|
print(u"Warning: unrecognized serial number. Please recheck input.")
|
||||||
return 1
|
return 1
|
||||||
pid = pidFromSerial(serial.encode("utf-8"),7)+'*'
|
pid = pidFromSerial(serial.encode("utf-8"),7)+'*'
|
||||||
print u"Mobipocket PID for Kindle serial#{0} is {1}".format(serial,checksumPid(pid))
|
print(u"Mobipocket PID for Kindle serial#{0} is {1}".format(serial,checksumPid(pid)))
|
||||||
return 0
|
return 0
|
||||||
elif len(serial)==40:
|
elif len(serial)==40:
|
||||||
print u"iPhone serial number (UDID) detected"
|
print(u"iPhone serial number (UDID) detected")
|
||||||
pid = pidFromSerial(serial.encode("utf-8"),8)
|
pid = pidFromSerial(serial.encode("utf-8"),8)
|
||||||
print u"Mobipocket PID for iPhone serial#{0} is {1}".format(serial,checksumPid(pid))
|
print(u"Mobipocket PID for iPhone serial#{0} is {1}".format(serial,checksumPid(pid)))
|
||||||
return 0
|
return 0
|
||||||
print u"Warning: unrecognized serial number. Please recheck input."
|
print(u"Warning: unrecognized serial number. Please recheck input.")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
# Copyright © 2008 The Dark Reverser
|
# Copyright © 2008 The Dark Reverser
|
||||||
# Portions © 2008–2017 Apprentice Harper et al.
|
# Portions © 2008–2017 Apprentice Harper et al.
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = u"0.42"
|
__version__ = u"0.42"
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ import binascii
|
||||||
try:
|
try:
|
||||||
from alfcrypto import Pukall_Cipher
|
from alfcrypto import Pukall_Cipher
|
||||||
except:
|
except:
|
||||||
print u"AlfCrypto not found. Using python PC1 implementation."
|
print(u"AlfCrypto not found. Using python PC1 implementation.")
|
||||||
|
|
||||||
# Wrap a stream so that output gets flushed immediately
|
# Wrap a stream so that output gets flushed immediately
|
||||||
# and also make sure that any unicode strings get
|
# and also make sure that any unicode strings get
|
||||||
|
@ -244,12 +245,12 @@ class MobiBook:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __init__(self, infile):
|
def __init__(self, infile):
|
||||||
print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
|
print(u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from alfcrypto import Pukall_Cipher
|
from alfcrypto import Pukall_Cipher
|
||||||
except:
|
except:
|
||||||
print u"AlfCrypto not found. Using python PC1 implementation."
|
print(u"AlfCrypto not found. Using python PC1 implementation.")
|
||||||
|
|
||||||
# initial sanity check on file
|
# initial sanity check on file
|
||||||
self.data_file = file(infile, 'rb').read()
|
self.data_file = file(infile, 'rb').read()
|
||||||
|
@ -282,7 +283,7 @@ class MobiBook:
|
||||||
self.mobi_version = -1
|
self.mobi_version = -1
|
||||||
|
|
||||||
if self.magic == 'TEXtREAd':
|
if self.magic == 'TEXtREAd':
|
||||||
print u"PalmDoc format book detected."
|
print(u"PalmDoc format book detected.")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
|
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
|
||||||
|
@ -424,10 +425,10 @@ class MobiBook:
|
||||||
|
|
||||||
def processBook(self, pidlist):
|
def processBook(self, pidlist):
|
||||||
crypto_type, = struct.unpack('>H', self.sect[0xC:0xC+2])
|
crypto_type, = struct.unpack('>H', self.sect[0xC:0xC+2])
|
||||||
print u"Crypto Type is: {0:d}".format(crypto_type)
|
print(u"Crypto Type is: {0:d}".format(crypto_type))
|
||||||
self.crypto_type = crypto_type
|
self.crypto_type = crypto_type
|
||||||
if crypto_type == 0:
|
if crypto_type == 0:
|
||||||
print u"This book is not encrypted."
|
print(u"This book is not encrypted.")
|
||||||
# we must still check for Print Replica
|
# we must still check for Print Replica
|
||||||
self.print_replica = (self.loadSection(1)[0:4] == '%MOP')
|
self.print_replica = (self.loadSection(1)[0:4] == '%MOP')
|
||||||
self.mobi_data = self.data_file
|
self.mobi_data = self.data_file
|
||||||
|
@ -444,12 +445,12 @@ class MobiBook:
|
||||||
for pid in pidlist:
|
for pid in pidlist:
|
||||||
if len(pid)==10:
|
if len(pid)==10:
|
||||||
if checksumPid(pid[0:-2]) != pid:
|
if checksumPid(pid[0:-2]) != pid:
|
||||||
print u"Warning: PID {0} has incorrect checksum, should have been {1}".format(pid,checksumPid(pid[0:-2]))
|
print(u"Warning: PID {0} has incorrect checksum, should have been {1}".format(pid,checksumPid(pid[0:-2])))
|
||||||
goodpids.append(pid[0:-2])
|
goodpids.append(pid[0:-2])
|
||||||
elif len(pid)==8:
|
elif len(pid)==8:
|
||||||
goodpids.append(pid)
|
goodpids.append(pid)
|
||||||
else:
|
else:
|
||||||
print u"Warning: PID {0} has wrong number of digits".format(pid)
|
print(u"Warning: PID {0} has wrong number of digits".format(pid))
|
||||||
|
|
||||||
if self.crypto_type == 1:
|
if self.crypto_type == 1:
|
||||||
t1_keyvec = 'QDCVEPMU675RUBSZ'
|
t1_keyvec = 'QDCVEPMU675RUBSZ'
|
||||||
|
@ -475,22 +476,22 @@ class MobiBook:
|
||||||
self.patchSection(0, '\xff' * 4 + '\0' * 12, 0xA8)
|
self.patchSection(0, '\xff' * 4 + '\0' * 12, 0xA8)
|
||||||
|
|
||||||
if pid=='00000000':
|
if pid=='00000000':
|
||||||
print u"File has default encryption, no specific key needed."
|
print(u"File has default encryption, no specific key needed.")
|
||||||
else:
|
else:
|
||||||
print u"File is encoded with PID {0}.".format(checksumPid(pid))
|
print(u"File is encoded with PID {0}.".format(checksumPid(pid)))
|
||||||
|
|
||||||
# clear the crypto type
|
# clear the crypto type
|
||||||
self.patchSection(0, "\0" * 2, 0xC)
|
self.patchSection(0, "\0" * 2, 0xC)
|
||||||
|
|
||||||
# decrypt sections
|
# decrypt sections
|
||||||
print u"Decrypting. Please wait . . .",
|
print(u"Decrypting. Please wait . . .", end=' ')
|
||||||
mobidataList = []
|
mobidataList = []
|
||||||
mobidataList.append(self.data_file[:self.sections[1][0]])
|
mobidataList.append(self.data_file[:self.sections[1][0]])
|
||||||
for i in xrange(1, self.records+1):
|
for i in xrange(1, self.records+1):
|
||||||
data = self.loadSection(i)
|
data = self.loadSection(i)
|
||||||
extra_size = getSizeOfTrailingDataEntries(data, len(data), self.extra_data_flags)
|
extra_size = getSizeOfTrailingDataEntries(data, len(data), self.extra_data_flags)
|
||||||
if i%100 == 0:
|
if i%100 == 0:
|
||||||
print u".",
|
print(u".", end=' ')
|
||||||
# print "record %d, extra_size %d" %(i,extra_size)
|
# print "record %d, extra_size %d" %(i,extra_size)
|
||||||
decoded_data = PC1(found_key, data[0:len(data) - extra_size])
|
decoded_data = PC1(found_key, data[0:len(data) - extra_size])
|
||||||
if i==1:
|
if i==1:
|
||||||
|
@ -501,7 +502,7 @@ class MobiBook:
|
||||||
if self.num_sections > self.records+1:
|
if self.num_sections > self.records+1:
|
||||||
mobidataList.append(self.data_file[self.sections[self.records+1][0]:])
|
mobidataList.append(self.data_file[self.sections[self.records+1][0]:])
|
||||||
self.mobi_data = "".join(mobidataList)
|
self.mobi_data = "".join(mobidataList)
|
||||||
print u"done"
|
print(u"done")
|
||||||
return
|
return
|
||||||
|
|
||||||
def getUnencryptedBook(infile,pidlist):
|
def getUnencryptedBook(infile,pidlist):
|
||||||
|
@ -516,10 +517,10 @@ def cli_main():
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
if len(argv)<3 or len(argv)>4:
|
if len(argv)<3 or len(argv)>4:
|
||||||
print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
|
print(u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__))
|
||||||
print u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks"
|
print(u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks")
|
||||||
print u"Usage:"
|
print(u"Usage:")
|
||||||
print u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname)
|
print(u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname))
|
||||||
return 1
|
return 1
|
||||||
else:
|
else:
|
||||||
infile = argv[1]
|
infile = argv[1]
|
||||||
|
@ -532,7 +533,7 @@ def cli_main():
|
||||||
stripped_file = getUnencryptedBook(infile, pidlist)
|
stripped_file = getUnencryptedBook(infile, pidlist)
|
||||||
file(outfile, 'wb').write(stripped_file)
|
file(outfile, 'wb').write(stripped_file)
|
||||||
except DrmException, e:
|
except DrmException, e:
|
||||||
print u"MobiDeDRM v{0} Error: {1:s}".format(__version__,e.args[0])
|
print(u"MobiDeDRM v{0} Error: {1:s}".format(__version__,e.args[0]))
|
||||||
return 1
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -23,7 +24,7 @@ def decryptepub(infile, outdir, rscpath):
|
||||||
zippath = os.path.join(bpath,name + '_temp.zip')
|
zippath = os.path.join(bpath,name + '_temp.zip')
|
||||||
rv = zipfix.repairBook(infile, zippath)
|
rv = zipfix.repairBook(infile, zippath)
|
||||||
if rv != 0:
|
if rv != 0:
|
||||||
print "Error while trying to fix epub"
|
print("Error while trying to fix epub")
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
# determine a good name for the output file
|
# determine a good name for the output file
|
||||||
|
@ -43,7 +44,7 @@ def decryptepub(infile, outdir, rscpath):
|
||||||
try:
|
try:
|
||||||
rv = ineptepub.decryptBook(userkey, zippath, outfile)
|
rv = ineptepub.decryptBook(userkey, zippath, outfile)
|
||||||
if rv == 0:
|
if rv == 0:
|
||||||
print "Decrypted Adobe ePub with key file {0}".format(filename)
|
print("Decrypted Adobe ePub with key file {0}".format(filename))
|
||||||
break
|
break
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
errlog += traceback.format_exc()
|
errlog += traceback.format_exc()
|
||||||
|
@ -63,7 +64,7 @@ def decryptepub(infile, outdir, rscpath):
|
||||||
try:
|
try:
|
||||||
rv = ignobleepub.decryptBook(userkey, zippath, outfile)
|
rv = ignobleepub.decryptBook(userkey, zippath, outfile)
|
||||||
if rv == 0:
|
if rv == 0:
|
||||||
print "Decrypted B&N ePub with key file {0}".format(filename)
|
print("Decrypted B&N ePub with key file {0}".format(filename))
|
||||||
break
|
break
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
errlog += traceback.format_exc()
|
errlog += traceback.format_exc()
|
||||||
|
@ -72,14 +73,14 @@ def decryptepub(infile, outdir, rscpath):
|
||||||
else:
|
else:
|
||||||
encryption = epubtest.encryption(zippath)
|
encryption = epubtest.encryption(zippath)
|
||||||
if encryption == "Unencrypted":
|
if encryption == "Unencrypted":
|
||||||
print "{0} is not DRMed.".format(name)
|
print("{0} is not DRMed.".format(name))
|
||||||
rv = 0
|
rv = 0
|
||||||
else:
|
else:
|
||||||
print "{0} has an unknown encryption.".format(name)
|
print("{0} has an unknown encryption.".format(name))
|
||||||
|
|
||||||
os.remove(zippath)
|
os.remove(zippath)
|
||||||
if rv != 0:
|
if rv != 0:
|
||||||
print errlog
|
print(errlog)
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ def decryptpdf(infile, outdir, rscpath):
|
||||||
rv = 1
|
rv = 1
|
||||||
|
|
||||||
if rv != 0:
|
if rv != 0:
|
||||||
print errlog
|
print(errlog)
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,7 +127,7 @@ def decryptpdb(infile, outdir, rscpath):
|
||||||
try:
|
try:
|
||||||
name, cc8 = i.split(':')
|
name, cc8 = i.split(':')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print ' Error parsing user supplied social drm data.'
|
print(' Error parsing user supplied social drm data.')
|
||||||
return 1
|
return 1
|
||||||
try:
|
try:
|
||||||
rv = erdr2pml.decryptBook(infile, outpath, True, erdr2pml.getuser_key(name, cc8))
|
rv = erdr2pml.decryptBook(infile, outpath, True, erdr2pml.getuser_key(name, cc8))
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
|
||||||
# For use with Topaz Scripts Version 2.6
|
# For use with Topaz Scripts Version 2.6
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import csv
|
import csv
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
@ -114,9 +115,9 @@ class DocParser(object):
|
||||||
|
|
||||||
# process each style converting what you can
|
# process each style converting what you can
|
||||||
|
|
||||||
if debug: print ' ', 'Processing styles.'
|
if debug: print(' ', 'Processing styles.')
|
||||||
for j in xrange(stylecnt):
|
for j in xrange(stylecnt):
|
||||||
if debug: print ' ', 'Processing style %d' %(j)
|
if debug: print(' ', 'Processing style %d' %(j))
|
||||||
start = styleList[j]
|
start = styleList[j]
|
||||||
end = styleList[j+1]
|
end = styleList[j+1]
|
||||||
|
|
||||||
|
@ -135,7 +136,7 @@ class DocParser(object):
|
||||||
else :
|
else :
|
||||||
sclass = ''
|
sclass = ''
|
||||||
|
|
||||||
if debug: print 'sclass', sclass
|
if debug: print('sclass', sclass)
|
||||||
|
|
||||||
# check for any "after class" specifiers
|
# check for any "after class" specifiers
|
||||||
(pos, aftclass) = self.findinDoc('style._after_class',start,end)
|
(pos, aftclass) = self.findinDoc('style._after_class',start,end)
|
||||||
|
@ -145,7 +146,7 @@ class DocParser(object):
|
||||||
else :
|
else :
|
||||||
aftclass = ''
|
aftclass = ''
|
||||||
|
|
||||||
if debug: print 'aftclass', aftclass
|
if debug: print('aftclass', aftclass)
|
||||||
|
|
||||||
cssargs = {}
|
cssargs = {}
|
||||||
|
|
||||||
|
@ -154,8 +155,8 @@ class DocParser(object):
|
||||||
(pos1, attr) = self.findinDoc('style.rule.attr', start, end)
|
(pos1, attr) = self.findinDoc('style.rule.attr', start, end)
|
||||||
(pos2, val) = self.findinDoc('style.rule.value', start, end)
|
(pos2, val) = self.findinDoc('style.rule.value', start, end)
|
||||||
|
|
||||||
if debug: print 'attr', attr
|
if debug: print('attr', attr)
|
||||||
if debug: print 'val', val
|
if debug: print('val', val)
|
||||||
|
|
||||||
if attr == None : break
|
if attr == None : break
|
||||||
|
|
||||||
|
@ -182,7 +183,7 @@ class DocParser(object):
|
||||||
try:
|
try:
|
||||||
f = float(val)
|
f = float(val)
|
||||||
except:
|
except:
|
||||||
print "Warning: unrecognised val, ignoring"
|
print("Warning: unrecognised val, ignoring")
|
||||||
val = 0
|
val = 0
|
||||||
pv = float(val)/scale
|
pv = float(val)/scale
|
||||||
cssargs[attr] = (self.attr_val_map[attr], pv)
|
cssargs[attr] = (self.attr_val_map[attr], pv)
|
||||||
|
@ -194,7 +195,7 @@ class DocParser(object):
|
||||||
if aftclass != "" : keep = False
|
if aftclass != "" : keep = False
|
||||||
|
|
||||||
if keep :
|
if keep :
|
||||||
if debug: print 'keeping style'
|
if debug: print('keeping style')
|
||||||
# make sure line-space does not go below 100% or above 300% since
|
# make sure line-space does not go below 100% or above 300% since
|
||||||
# it can be wacky in some styles
|
# it can be wacky in some styles
|
||||||
if 'line-space' in cssargs:
|
if 'line-space' in cssargs:
|
||||||
|
@ -266,15 +267,15 @@ class DocParser(object):
|
||||||
|
|
||||||
def convert2CSS(flatxml, fontsize, ph, pw):
|
def convert2CSS(flatxml, fontsize, ph, pw):
|
||||||
|
|
||||||
print ' ', 'Using font size:',fontsize
|
print(' ', 'Using font size:',fontsize)
|
||||||
print ' ', 'Using page height:', ph
|
print(' ', 'Using page height:', ph)
|
||||||
print ' ', 'Using page width:', pw
|
print(' ', 'Using page width:', pw)
|
||||||
|
|
||||||
# create a document parser
|
# create a document parser
|
||||||
dp = DocParser(flatxml, fontsize, ph, pw)
|
dp = DocParser(flatxml, fontsize, ph, pw)
|
||||||
if debug: print ' ', 'Created DocParser.'
|
if debug: print(' ', 'Created DocParser.')
|
||||||
csspage = dp.process()
|
csspage = dp.process()
|
||||||
if debug: print ' ', 'Processed DocParser.'
|
if debug: print(' ', 'Processed DocParser.')
|
||||||
return csspage
|
return csspage
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
# 4.9 - moved unicode_argv call inside main for Windows DeDRM compatibility
|
# 4.9 - moved unicode_argv call inside main for Windows DeDRM compatibility
|
||||||
# 5.0 - Fixed potential unicode problem with command line interface
|
# 5.0 - Fixed potential unicode problem with command line interface
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
__version__ = '5.0'
|
__version__ = '5.0'
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
@ -213,7 +214,7 @@ class TopazBook:
|
||||||
# Read and return the data of one header record at the current book file position
|
# Read and return the data of one header record at the current book file position
|
||||||
# [[offset,decompressedLength,compressedLength],...]
|
# [[offset,decompressedLength,compressedLength],...]
|
||||||
nbValues = bookReadEncodedNumber(self.fo)
|
nbValues = bookReadEncodedNumber(self.fo)
|
||||||
if debug: print "%d records in header " % nbValues,
|
if debug: print("%d records in header " % nbValues, end=' ')
|
||||||
values = []
|
values = []
|
||||||
for i in range (0,nbValues):
|
for i in range (0,nbValues):
|
||||||
values.append([bookReadEncodedNumber(self.fo),bookReadEncodedNumber(self.fo),bookReadEncodedNumber(self.fo)])
|
values.append([bookReadEncodedNumber(self.fo),bookReadEncodedNumber(self.fo),bookReadEncodedNumber(self.fo)])
|
||||||
|
@ -227,10 +228,10 @@ class TopazBook:
|
||||||
record = bookReadHeaderRecordData()
|
record = bookReadHeaderRecordData()
|
||||||
return [tag,record]
|
return [tag,record]
|
||||||
nbRecords = bookReadEncodedNumber(self.fo)
|
nbRecords = bookReadEncodedNumber(self.fo)
|
||||||
if debug: print "Headers: %d" % nbRecords
|
if debug: print("Headers: %d" % nbRecords)
|
||||||
for i in range (0,nbRecords):
|
for i in range (0,nbRecords):
|
||||||
result = parseTopazHeaderRecord()
|
result = parseTopazHeaderRecord()
|
||||||
if debug: print result[0], ": ", result[1]
|
if debug: print(result[0], ": ", result[1])
|
||||||
self.bookHeaderRecords[result[0]] = result[1]
|
self.bookHeaderRecords[result[0]] = result[1]
|
||||||
if ord(self.fo.read(1)) != 0x64 :
|
if ord(self.fo.read(1)) != 0x64 :
|
||||||
raise DrmException(u"Parse Error : Invalid Header")
|
raise DrmException(u"Parse Error : Invalid Header")
|
||||||
|
@ -244,12 +245,12 @@ class TopazBook:
|
||||||
raise DrmException(u"Parse Error : Record Names Don't Match")
|
raise DrmException(u"Parse Error : Record Names Don't Match")
|
||||||
flags = ord(self.fo.read(1))
|
flags = ord(self.fo.read(1))
|
||||||
nbRecords = ord(self.fo.read(1))
|
nbRecords = ord(self.fo.read(1))
|
||||||
if debug: print "Metadata Records: %d" % nbRecords
|
if debug: print("Metadata Records: %d" % nbRecords)
|
||||||
for i in range (0,nbRecords) :
|
for i in range (0,nbRecords) :
|
||||||
keyval = bookReadString(self.fo)
|
keyval = bookReadString(self.fo)
|
||||||
content = bookReadString(self.fo)
|
content = bookReadString(self.fo)
|
||||||
if debug: print keyval
|
if debug: print(keyval)
|
||||||
if debug: print content
|
if debug: print(content)
|
||||||
self.bookMetadata[keyval] = content
|
self.bookMetadata[keyval] = content
|
||||||
return self.bookMetadata
|
return self.bookMetadata
|
||||||
|
|
||||||
|
@ -319,11 +320,11 @@ class TopazBook:
|
||||||
try:
|
try:
|
||||||
keydata = self.getBookPayloadRecord('dkey', 0)
|
keydata = self.getBookPayloadRecord('dkey', 0)
|
||||||
except DrmException, e:
|
except DrmException, e:
|
||||||
print u"no dkey record found, book may not be encrypted"
|
print(u"no dkey record found, book may not be encrypted")
|
||||||
print u"attempting to extrct files without a book key"
|
print(u"attempting to extrct files without a book key")
|
||||||
self.createBookDirectory()
|
self.createBookDirectory()
|
||||||
self.extractFiles()
|
self.extractFiles()
|
||||||
print u"Successfully Extracted Topaz contents"
|
print(u"Successfully Extracted Topaz contents")
|
||||||
if inCalibre:
|
if inCalibre:
|
||||||
from calibre_plugins.dedrm import genbook
|
from calibre_plugins.dedrm import genbook
|
||||||
else:
|
else:
|
||||||
|
@ -331,7 +332,7 @@ class TopazBook:
|
||||||
|
|
||||||
rv = genbook.generateBook(self.outdir, raw, fixedimage)
|
rv = genbook.generateBook(self.outdir, raw, fixedimage)
|
||||||
if rv == 0:
|
if rv == 0:
|
||||||
print u"Book Successfully generated."
|
print(u"Book Successfully generated.")
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
# try each pid to decode the file
|
# try each pid to decode the file
|
||||||
|
@ -339,7 +340,7 @@ class TopazBook:
|
||||||
for pid in pidlst:
|
for pid in pidlst:
|
||||||
# use 8 digit pids here
|
# use 8 digit pids here
|
||||||
pid = pid[0:8]
|
pid = pid[0:8]
|
||||||
print u"Trying: {0}".format(pid)
|
print(u"Trying: {0}".format(pid))
|
||||||
bookKeys = []
|
bookKeys = []
|
||||||
data = keydata
|
data = keydata
|
||||||
try:
|
try:
|
||||||
|
@ -348,7 +349,7 @@ class TopazBook:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
bookKey = bookKeys[0]
|
bookKey = bookKeys[0]
|
||||||
print u"Book Key Found! ({0})".format(bookKey.encode('hex'))
|
print(u"Book Key Found! ({0})".format(bookKey.encode('hex')))
|
||||||
break
|
break
|
||||||
|
|
||||||
if not bookKey:
|
if not bookKey:
|
||||||
|
@ -357,7 +358,7 @@ class TopazBook:
|
||||||
self.setBookKey(bookKey)
|
self.setBookKey(bookKey)
|
||||||
self.createBookDirectory()
|
self.createBookDirectory()
|
||||||
self.extractFiles()
|
self.extractFiles()
|
||||||
print u"Successfully Extracted Topaz contents"
|
print(u"Successfully Extracted Topaz contents")
|
||||||
if inCalibre:
|
if inCalibre:
|
||||||
from calibre_plugins.dedrm import genbook
|
from calibre_plugins.dedrm import genbook
|
||||||
else:
|
else:
|
||||||
|
@ -365,7 +366,7 @@ class TopazBook:
|
||||||
|
|
||||||
rv = genbook.generateBook(self.outdir, raw, fixedimage)
|
rv = genbook.generateBook(self.outdir, raw, fixedimage)
|
||||||
if rv == 0:
|
if rv == 0:
|
||||||
print u"Book Successfully generated"
|
print(u"Book Successfully generated")
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def createBookDirectory(self):
|
def createBookDirectory(self):
|
||||||
|
@ -394,7 +395,7 @@ class TopazBook:
|
||||||
ext = u".dat"
|
ext = u".dat"
|
||||||
if name == 'img': ext = u".jpg"
|
if name == 'img': ext = u".jpg"
|
||||||
if name == 'color' : ext = u".jpg"
|
if name == 'color' : ext = u".jpg"
|
||||||
print u"Processing Section: {0}\n. . .".format(name),
|
print(u"Processing Section: {0}\n. . .".format(name), end=' ')
|
||||||
for index in range (0,len(self.bookHeaderRecords[name])) :
|
for index in range (0,len(self.bookHeaderRecords[name])) :
|
||||||
fname = u"{0}{1:04d}{2}".format(name,index,ext)
|
fname = u"{0}{1:04d}{2}".format(name,index,ext)
|
||||||
destdir = outdir
|
destdir = outdir
|
||||||
|
@ -407,11 +408,11 @@ class TopazBook:
|
||||||
if name == 'glyphs':
|
if name == 'glyphs':
|
||||||
destdir = os.path.join(outdir,u"glyphs")
|
destdir = os.path.join(outdir,u"glyphs")
|
||||||
outputFile = os.path.join(destdir,fname)
|
outputFile = os.path.join(destdir,fname)
|
||||||
print u".",
|
print(u".", end=' ')
|
||||||
record = self.getBookPayloadRecord(name,index)
|
record = self.getBookPayloadRecord(name,index)
|
||||||
if record != '':
|
if record != '':
|
||||||
file(outputFile, 'wb').write(record)
|
file(outputFile, 'wb').write(record)
|
||||||
print u" "
|
print(u" ")
|
||||||
|
|
||||||
def getFile(self, zipname):
|
def getFile(self, zipname):
|
||||||
htmlzip = zipfile.ZipFile(zipname,'w',zipfile.ZIP_DEFLATED, False)
|
htmlzip = zipfile.ZipFile(zipname,'w',zipfile.ZIP_DEFLATED, False)
|
||||||
|
@ -441,20 +442,20 @@ class TopazBook:
|
||||||
shutil.rmtree(self.outdir, True)
|
shutil.rmtree(self.outdir, True)
|
||||||
|
|
||||||
def usage(progname):
|
def usage(progname):
|
||||||
print u"Removes DRM protection from Topaz ebooks and extracts the contents"
|
print(u"Removes DRM protection from Topaz ebooks and extracts the contents")
|
||||||
print u"Usage:"
|
print(u"Usage:")
|
||||||
print u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] <infile> <outdir>".format(progname)
|
print(u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] <infile> <outdir>".format(progname))
|
||||||
|
|
||||||
# Main
|
# Main
|
||||||
def cli_main():
|
def cli_main():
|
||||||
argv=unicode_argv()
|
argv=unicode_argv()
|
||||||
progname = os.path.basename(argv[0])
|
progname = os.path.basename(argv[0])
|
||||||
print u"TopazExtract v{0}.".format(__version__)
|
print(u"TopazExtract v{0}.".format(__version__))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(argv[1:], "k:p:s:x")
|
opts, args = getopt.getopt(argv[1:], "k:p:s:x")
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
print u"Error in options or arguments: {0}".format(err.args[0])
|
print(u"Error in options or arguments: {0}".format(err.args[0]))
|
||||||
usage(progname)
|
usage(progname)
|
||||||
return 1
|
return 1
|
||||||
if len(args)<2:
|
if len(args)<2:
|
||||||
|
@ -464,11 +465,11 @@ def cli_main():
|
||||||
infile = args[0]
|
infile = args[0]
|
||||||
outdir = args[1]
|
outdir = args[1]
|
||||||
if not os.path.isfile(infile):
|
if not os.path.isfile(infile):
|
||||||
print u"Input File {0} Does Not Exist.".format(infile)
|
print(u"Input File {0} Does Not Exist.".format(infile))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if not os.path.exists(outdir):
|
if not os.path.exists(outdir):
|
||||||
print u"Output Directory {0} Does Not Exist.".format(outdir)
|
print(u"Output Directory {0} Does Not Exist.".format(outdir))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
kDatabaseFiles = []
|
kDatabaseFiles = []
|
||||||
|
@ -493,19 +494,19 @@ def cli_main():
|
||||||
|
|
||||||
tb = TopazBook(infile)
|
tb = TopazBook(infile)
|
||||||
title = tb.getBookTitle()
|
title = tb.getBookTitle()
|
||||||
print u"Processing Book: {0}".format(title)
|
print(u"Processing Book: {0}".format(title))
|
||||||
md1, md2 = tb.getPIDMetaInfo()
|
md1, md2 = tb.getPIDMetaInfo()
|
||||||
pids.extend(kgenpids.getPidList(md1, md2, serials, kDatabaseFiles))
|
pids.extend(kgenpids.getPidList(md1, md2, serials, kDatabaseFiles))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print u"Decrypting Book"
|
print(u"Decrypting Book")
|
||||||
tb.processBook(pids)
|
tb.processBook(pids)
|
||||||
|
|
||||||
print u" Creating HTML ZIP Archive"
|
print(u" Creating HTML ZIP Archive")
|
||||||
zipname = os.path.join(outdir, bookname + u"_nodrm.htmlz")
|
zipname = os.path.join(outdir, bookname + u"_nodrm.htmlz")
|
||||||
tb.getFile(zipname)
|
tb.getFile(zipname)
|
||||||
|
|
||||||
print u" Creating SVG ZIP Archive"
|
print(u" Creating SVG ZIP Archive")
|
||||||
zipname = os.path.join(outdir, bookname + u"_SVG.zip")
|
zipname = os.path.join(outdir, bookname + u"_SVG.zip")
|
||||||
tb.getSVGZip(zipname)
|
tb.getSVGZip(zipname)
|
||||||
|
|
||||||
|
@ -513,7 +514,7 @@ def cli_main():
|
||||||
tb.cleanup()
|
tb.cleanup()
|
||||||
|
|
||||||
except DrmException, e:
|
except DrmException, e:
|
||||||
print u"Decryption failed\n{0}".format(traceback.format_exc())
|
print(u"Decryption failed\n{0}".format(traceback.format_exc()))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tb.cleanup()
|
tb.cleanup()
|
||||||
|
@ -522,7 +523,7 @@ def cli_main():
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print u"Decryption failed\m{0}".format(traceback.format_exc())
|
print(u"Decryption failed\m{0}".format(traceback.format_exc()))
|
||||||
try:
|
try:
|
||||||
tb.cleanup()
|
tb.cleanup()
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
|
||||||
import json
|
import json
|
||||||
|
|
||||||
basepath, script = os.path.split(scriptpath)
|
basepath, script = os.path.split(scriptpath)
|
||||||
print u"{0} v{1}: Running {2} under Wine".format(PLUGIN_NAME, PLUGIN_VERSION, script)
|
print(u"{0} v{1}: Running {2} under Wine".format(PLUGIN_NAME, PLUGIN_VERSION, script))
|
||||||
|
|
||||||
outdirpath = os.path.join(basepath, u"winekeysdir")
|
outdirpath = os.path.join(basepath, u"winekeysdir")
|
||||||
if not os.path.exists(outdirpath):
|
if not os.path.exists(outdirpath):
|
||||||
|
@ -31,26 +32,26 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
|
||||||
cmdline = u"WINEPREFIX=\"{2}\" wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
|
cmdline = u"WINEPREFIX=\"{2}\" wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
|
||||||
else:
|
else:
|
||||||
cmdline = u"wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
|
cmdline = u"wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
|
||||||
print u"{0} v{1}: Command line: '{2}'".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline)
|
print(u"{0} v{1}: Command line: '{2}'".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cmdline = cmdline.encode(sys.getfilesystemencoding())
|
cmdline = cmdline.encode(sys.getfilesystemencoding())
|
||||||
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
|
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
|
||||||
result = p2.wait("wait")
|
result = p2.wait("wait")
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
|
print(u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]))
|
||||||
if wineprefix != "" and os.path.exists(wineprefix):
|
if wineprefix != "" and os.path.exists(wineprefix):
|
||||||
cmdline = u"WINEPREFIX=\"{2}\" wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
|
cmdline = u"WINEPREFIX=\"{2}\" wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
|
||||||
else:
|
else:
|
||||||
cmdline = u"wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
|
cmdline = u"wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
|
||||||
print u"{0} v{1}: Command line: “{2}”".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline)
|
print(u"{0} v{1}: Command line: “{2}”".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cmdline = cmdline.encode(sys.getfilesystemencoding())
|
cmdline = cmdline.encode(sys.getfilesystemencoding())
|
||||||
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
|
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
|
||||||
result = p2.wait("wait")
|
result = p2.wait("wait")
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
|
print(u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]))
|
||||||
|
|
||||||
# try finding winekeys anyway, even if above code errored
|
# try finding winekeys anyway, even if above code errored
|
||||||
winekeys = []
|
winekeys = []
|
||||||
|
@ -66,8 +67,8 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
|
||||||
new_key_value = keyfile.read()
|
new_key_value = keyfile.read()
|
||||||
winekeys.append(new_key_value)
|
winekeys.append(new_key_value)
|
||||||
except:
|
except:
|
||||||
print u"{0} v{1}: Error loading file {2}".format(PLUGIN_NAME, PLUGIN_VERSION, filename)
|
print(u"{0} v{1}: Error loading file {2}".format(PLUGIN_NAME, PLUGIN_VERSION, filename))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
os.remove(fpath)
|
os.remove(fpath)
|
||||||
print u"{0} v{1}: Found and decrypted {2} {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(winekeys), u"key file" if len(winekeys) == 1 else u"key files")
|
print(u"{0} v{1}: Found and decrypted {2} {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(winekeys), u"key file" if len(winekeys) == 1 else u"key files"))
|
||||||
return winekeys
|
return winekeys
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"""
|
"""
|
||||||
Re-write zip (or ePub) fixing problems with file names (and mimetype entry).
|
Re-write zip (or ePub) fixing problems with file names (and mimetype entry).
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__version__ = "1.1"
|
__version__ = "1.1"
|
||||||
|
@ -156,22 +157,22 @@ class fixZip:
|
||||||
|
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print """usage: zipfix.py inputzip outputzip
|
print("""usage: zipfix.py inputzip outputzip
|
||||||
inputzip is the source zipfile to fix
|
inputzip is the source zipfile to fix
|
||||||
outputzip is the fixed zip archive
|
outputzip is the fixed zip archive
|
||||||
"""
|
""")
|
||||||
|
|
||||||
|
|
||||||
def repairBook(infile, outfile):
|
def repairBook(infile, outfile):
|
||||||
if not os.path.exists(infile):
|
if not os.path.exists(infile):
|
||||||
print "Error: Input Zip File does not exist"
|
print("Error: Input Zip File does not exist")
|
||||||
return 1
|
return 1
|
||||||
try:
|
try:
|
||||||
fr = fixZip(infile, outfile)
|
fr = fixZip(infile, outfile)
|
||||||
fr.fix()
|
fr.fix()
|
||||||
return 0
|
return 0
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "Error Occurred ", e
|
print("Error Occurred ", e)
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,7 @@
|
||||||
# after all.
|
# after all.
|
||||||
#
|
#
|
||||||
"""Manage all Kobo books, either encrypted or DRM-free."""
|
"""Manage all Kobo books, either encrypted or DRM-free."""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
__version__ = '3.2.4'
|
__version__ = '3.2.4'
|
||||||
__about__ = u"Obok v{0}\nCopyright © 2012-2016 Physisticated et al.".format(__version__)
|
__about__ = u"Obok v{0}\nCopyright © 2012-2016 Physisticated et al.".format(__version__)
|
||||||
|
@ -291,7 +292,7 @@ class KoboLibrary(object):
|
||||||
of books, their titles, and the user's encryption key(s)."""
|
of books, their titles, and the user's encryption key(s)."""
|
||||||
|
|
||||||
def __init__ (self, serials = [], device_path = None):
|
def __init__ (self, serials = [], device_path = None):
|
||||||
print __about__
|
print(__about__)
|
||||||
self.kobodir = u""
|
self.kobodir = u""
|
||||||
kobodb = u""
|
kobodb = u""
|
||||||
|
|
||||||
|
@ -374,7 +375,7 @@ class KoboLibrary(object):
|
||||||
# make a copy of the database in a temporary file
|
# make a copy of the database in a temporary file
|
||||||
# so we can ensure it's not using WAL logging which sqlite3 can't do.
|
# so we can ensure it's not using WAL logging which sqlite3 can't do.
|
||||||
self.newdb = tempfile.NamedTemporaryFile(mode='wb', delete=False)
|
self.newdb = tempfile.NamedTemporaryFile(mode='wb', delete=False)
|
||||||
print self.newdb.name
|
print(self.newdb.name)
|
||||||
olddb = open(kobodb, 'rb')
|
olddb = open(kobodb, 'rb')
|
||||||
self.newdb.write(olddb.read(18))
|
self.newdb.write(olddb.read(18))
|
||||||
self.newdb.write('\x01\x01')
|
self.newdb.write('\x01\x01')
|
||||||
|
@ -591,32 +592,32 @@ class KoboFile(object):
|
||||||
# assume utf-8 with no BOM
|
# assume utf-8 with no BOM
|
||||||
textoffset = 0
|
textoffset = 0
|
||||||
stride = 1
|
stride = 1
|
||||||
print u"Checking text:{0}:".format(contents[:10])
|
print(u"Checking text:{0}:".format(contents[:10]))
|
||||||
# check for byte order mark
|
# check for byte order mark
|
||||||
if contents[:3]=="\xef\xbb\xbf":
|
if contents[:3]=="\xef\xbb\xbf":
|
||||||
# seems to be utf-8 with BOM
|
# seems to be utf-8 with BOM
|
||||||
print u"Could be utf-8 with BOM"
|
print(u"Could be utf-8 with BOM")
|
||||||
textoffset = 3
|
textoffset = 3
|
||||||
elif contents[:2]=="\xfe\xff":
|
elif contents[:2]=="\xfe\xff":
|
||||||
# seems to be utf-16BE
|
# seems to be utf-16BE
|
||||||
print u"Could be utf-16BE"
|
print(u"Could be utf-16BE")
|
||||||
textoffset = 3
|
textoffset = 3
|
||||||
stride = 2
|
stride = 2
|
||||||
elif contents[:2]=="\xff\xfe":
|
elif contents[:2]=="\xff\xfe":
|
||||||
# seems to be utf-16LE
|
# seems to be utf-16LE
|
||||||
print u"Could be utf-16LE"
|
print(u"Could be utf-16LE")
|
||||||
textoffset = 2
|
textoffset = 2
|
||||||
stride = 2
|
stride = 2
|
||||||
else:
|
else:
|
||||||
print u"Perhaps utf-8 without BOM"
|
print(u"Perhaps utf-8 without BOM")
|
||||||
|
|
||||||
# now check that the first few characters are in the ASCII range
|
# now check that the first few characters are in the ASCII range
|
||||||
for i in xrange(textoffset,textoffset+5*stride,stride):
|
for i in xrange(textoffset,textoffset+5*stride,stride):
|
||||||
if ord(contents[i])<32 or ord(contents[i])>127:
|
if ord(contents[i])<32 or ord(contents[i])>127:
|
||||||
# Non-ascii, so decryption probably failed
|
# Non-ascii, so decryption probably failed
|
||||||
print u"Bad character at {0}, value {1}".format(i,ord(contents[i]))
|
print(u"Bad character at {0}, value {1}".format(i,ord(contents[i])))
|
||||||
raise ValueError
|
raise ValueError
|
||||||
print u"Seems to be good text"
|
print(u"Seems to be good text")
|
||||||
return True
|
return True
|
||||||
if contents[:5]=="<?xml" or contents[:8]=="\xef\xbb\xbf<?xml":
|
if contents[:5]=="<?xml" or contents[:8]=="\xef\xbb\xbf<?xml":
|
||||||
# utf-8
|
# utf-8
|
||||||
|
@ -637,13 +638,13 @@ class KoboFile(object):
|
||||||
# utf-16LE of weird <!DOCTYPE start
|
# utf-16LE of weird <!DOCTYPE start
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print u"Bad XML: {0}".format(contents[:8])
|
print(u"Bad XML: {0}".format(contents[:8]))
|
||||||
raise ValueError
|
raise ValueError
|
||||||
elif self.mimetype == 'image/jpeg':
|
elif self.mimetype == 'image/jpeg':
|
||||||
if contents[:3] == '\xff\xd8\xff':
|
if contents[:3] == '\xff\xd8\xff':
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print u"Bad JPEG: {0}".format(contents[:3].encode('hex'))
|
print(u"Bad JPEG: {0}".format(contents[:3].encode('hex')))
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -666,18 +667,18 @@ class KoboFile(object):
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
def decrypt_book(book, lib):
|
def decrypt_book(book, lib):
|
||||||
print u"Converting {0}".format(book.title)
|
print(u"Converting {0}".format(book.title))
|
||||||
zin = zipfile.ZipFile(book.filename, "r")
|
zin = zipfile.ZipFile(book.filename, "r")
|
||||||
# make filename out of Unicode alphanumeric and whitespace equivalents from title
|
# make filename out of Unicode alphanumeric and whitespace equivalents from title
|
||||||
outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
|
outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
|
||||||
if (book.type == 'drm-free'):
|
if (book.type == 'drm-free'):
|
||||||
print u"DRM-free book, conversion is not needed"
|
print(u"DRM-free book, conversion is not needed")
|
||||||
shutil.copyfile(book.filename, outname)
|
shutil.copyfile(book.filename, outname)
|
||||||
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
|
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
|
||||||
return 0
|
return 0
|
||||||
result = 1
|
result = 1
|
||||||
for userkey in lib.userkeys:
|
for userkey in lib.userkeys:
|
||||||
print u"Trying key: {0}".format(userkey.encode('hex_codec'))
|
print(u"Trying key: {0}".format(userkey.encode('hex_codec')))
|
||||||
try:
|
try:
|
||||||
zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
|
zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
|
||||||
for filename in zin.namelist():
|
for filename in zin.namelist():
|
||||||
|
@ -689,12 +690,12 @@ def decrypt_book(book, lib):
|
||||||
file.check(contents)
|
file.check(contents)
|
||||||
zout.writestr(filename, contents)
|
zout.writestr(filename, contents)
|
||||||
zout.close()
|
zout.close()
|
||||||
print u"Decryption succeeded."
|
print(u"Decryption succeeded.")
|
||||||
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
|
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
|
||||||
result = 0
|
result = 0
|
||||||
break
|
break
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print u"Decryption failed."
|
print(u"Decryption failed.")
|
||||||
zout.close()
|
zout.close()
|
||||||
os.remove(outname)
|
os.remove(outname)
|
||||||
zin.close()
|
zin.close()
|
||||||
|
@ -719,8 +720,8 @@ def cli_main():
|
||||||
books = lib.books
|
books = lib.books
|
||||||
else:
|
else:
|
||||||
for i, book in enumerate(lib.books):
|
for i, book in enumerate(lib.books):
|
||||||
print u"{0}: {1}".format(i + 1, book.title)
|
print(u"{0}: {1}".format(i + 1, book.title))
|
||||||
print u"Or 'all'"
|
print(u"Or 'all'")
|
||||||
|
|
||||||
choice = raw_input(u"Convert book number... ")
|
choice = raw_input(u"Convert book number... ")
|
||||||
if choice == u'all':
|
if choice == u'all':
|
||||||
|
@ -730,14 +731,14 @@ def cli_main():
|
||||||
num = int(choice)
|
num = int(choice)
|
||||||
books = [lib.books[num - 1]]
|
books = [lib.books[num - 1]]
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
print u"Invalid choice. Exiting..."
|
print(u"Invalid choice. Exiting...")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
results = [decrypt_book(book, lib) for book in books]
|
results = [decrypt_book(book, lib) for book in books]
|
||||||
lib.close()
|
lib.close()
|
||||||
overall_result = all(result != 0 for result in results)
|
overall_result = all(result != 0 for result in results)
|
||||||
if overall_result != 0:
|
if overall_result != 0:
|
||||||
print u"Could not decrypt book with any of the keys found."
|
print(u"Could not decrypt book with any of the keys found.")
|
||||||
return overall_result
|
return overall_result
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue