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:
cclauss 2019-06-24 18:49:38 +02:00
parent b71ed3887e
commit 5bb6b58bc1
25 changed files with 353 additions and 328 deletions

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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__":

View File

@ -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))

View File

@ -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

View File

@ -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():

View File

@ -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))

View File

@ -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

View File

@ -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)

View File

@ -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":

View File

@ -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

View File

@ -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

View File

@ -5,6 +5,7 @@
# Copyright © 2008 The Dark Reverser # Copyright © 2008 The Dark Reverser
# Portions © 20082017 Apprentice Harper et al. # Portions © 20082017 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

View File

@ -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))

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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