From 781268e17ec51757359db152a820f20b8be51bd5 Mon Sep 17 00:00:00 2001 From: Apprentice Harper Date: Wed, 14 Oct 2020 16:23:49 +0100 Subject: [PATCH] More general changes, and get mobidedrm and kindlekey to work on Mac. --- DeDRM_plugin/__init__.py | 8 +-- DeDRM_plugin/activitybar.py | 12 ++-- DeDRM_plugin/adobekey.py | 2 +- DeDRM_plugin/aescbc.py | 4 +- DeDRM_plugin/androidkindlekey.py | 2 +- DeDRM_plugin/argv_utils.py | 11 ++-- DeDRM_plugin/askfolder_ed.py | 10 +-- DeDRM_plugin/config.py | 106 +++++++++++++++---------------- DeDRM_plugin/epubtest.py | 15 ++--- DeDRM_plugin/flatxml2html.py | 29 ++++----- DeDRM_plugin/flatxml2svg.py | 18 +++--- DeDRM_plugin/genbook.py | 8 +-- DeDRM_plugin/ignobleepub.py | 68 ++++++++++---------- DeDRM_plugin/ignoblekey.py | 35 +++++----- DeDRM_plugin/ignoblekeyfetch.py | 67 +++++++++---------- DeDRM_plugin/ignoblekeygen.py | 65 +++++++++---------- DeDRM_plugin/ignoblepdf.py | 106 +++++++++++++++---------------- DeDRM_plugin/ineptepub.py | 75 +++++++++++----------- DeDRM_plugin/ineptpdf.py | 103 ++++++++++++++---------------- DeDRM_plugin/ion.py | 12 +--- DeDRM_plugin/k4mobidedrm.py | 23 +++---- DeDRM_plugin/kfxdedrm.py | 14 ++-- DeDRM_plugin/kgenpids.py | 6 +- DeDRM_plugin/kindlekey.py | 88 ++++++++++++------------- DeDRM_plugin/kindlepid.py | 19 +++--- DeDRM_plugin/mobidedrm.py | 21 +++--- DeDRM_plugin/scriptinterface.py | 4 +- DeDRM_plugin/scrolltextwidget.py | 20 +++--- DeDRM_plugin/stylexml2css.py | 6 +- DeDRM_plugin/topazextract.py | 13 ++-- DeDRM_plugin/utilities.py | 4 +- DeDRM_plugin/zipfix.py | 2 +- 32 files changed, 479 insertions(+), 497 deletions(-) diff --git a/DeDRM_plugin/__init__.py b/DeDRM_plugin/__init__.py index 1fe97a1..3b1e151 100644 --- a/DeDRM_plugin/__init__.py +++ b/DeDRM_plugin/__init__.py @@ -220,7 +220,7 @@ class DeDRM(FileTypePlugin): # Attempt to decrypt epub with each encryption key (generated or provided). for keyname, userkey in dedrmprefs['bandnkeys'].items(): - keyname_masked = u"".join(("X" if (x.isdigit()) else x) for x in keyname) + keyname_masked = "".join(("X" if (x.isdigit()) else x) for x in keyname) print("{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname_masked)) of = self.temporary_file(".epub") @@ -359,7 +359,7 @@ class DeDRM(FileTypePlugin): except: print("{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() - self.default_key = u"" + self.default_key = "" newkeys = [] for keyvalue in defaultkeys: @@ -462,7 +462,7 @@ class DeDRM(FileTypePlugin): except: print("{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() - self.default_key = u"" + self.default_key = "" newkeys = [] for keyvalue in defaultkeys: @@ -590,7 +590,7 @@ class DeDRM(FileTypePlugin): dedrmprefs = prefs.DeDRM_Prefs() # Attempt to decrypt epub with each encryption key (generated or provided). for keyname, userkey in dedrmprefs['ereaderkeys'].items(): - keyname_masked = u"".join(("X" if (x.isdigit()) else x) for x in keyname) + keyname_masked = "".join(("X" if (x.isdigit()) else x) for x in keyname) print("{0} v{1}: Trying Encryption key {2:s}".format(PLUGIN_NAME, PLUGIN_VERSION, keyname_masked)) of = self.temporary_file(".pmlz") diff --git a/DeDRM_plugin/activitybar.py b/DeDRM_plugin/activitybar.py index b21c01d..bec991a 100644 --- a/DeDRM_plugin/activitybar.py +++ b/DeDRM_plugin/activitybar.py @@ -1,12 +1,12 @@ import sys -import Tkinter -import Tkconstants +import tkinter +import tkinter.constants -class ActivityBar(Tkinter.Frame): +class ActivityBar(tkinter.Frame): def __init__(self, master, length=300, height=20, barwidth=15, interval=50, bg='white', fillcolor='orchid1',\ - bd=2, relief=Tkconstants.GROOVE, *args, **kw): - Tkinter.Frame.__init__(self, master, bg=bg, width=length, height=height, *args, **kw) + bd=2, relief=tkinter.constants.GROOVE, *args, **kw): + tkinter.Frame.__init__(self, master, bg=bg, width=length, height=height, *args, **kw) self._master = master self._interval = interval self._maximum = length @@ -20,7 +20,7 @@ class ActivityBar(Tkinter.Frame): stopx = self._maximum # self._canv = Tkinter.Canvas(self, bg=self['bg'], width=self['width'], height=self['height'],\ # highlightthickness=0, relief='flat', bd=0) - self._canv = Tkinter.Canvas(self, bg=self['bg'], width=self['width'], height=self['height'],\ + self._canv = tkinter.Canvas(self, bg=self['bg'], width=self['width'], height=self['height'],\ highlightthickness=0, relief=relief, bd=bd) self._canv.pack(fill='both', expand=1) self._rect = self._canv.create_rectangle(0, 0, self._canv.winfo_reqwidth(), self._canv.winfo_reqheight(), fill=fillcolor, width=0) diff --git a/DeDRM_plugin/adobekey.py b/DeDRM_plugin/adobekey.py index a0c5ebd..caa1613 100644 --- a/DeDRM_plugin/adobekey.py +++ b/DeDRM_plugin/adobekey.py @@ -496,7 +496,7 @@ def cli_main(): # save to the specified file or directory outpath = args[0] if not os.path.isabs(outpath): - outpath = os.path.abspath(outpath) + outpath = os.path.abspath(outpath) else: # save to the same directory as the script outpath = os.path.dirname(argv[0]) diff --git a/DeDRM_plugin/aescbc.py b/DeDRM_plugin/aescbc.py index 59c763e..ae08d28 100644 --- a/DeDRM_plugin/aescbc.py +++ b/DeDRM_plugin/aescbc.py @@ -176,8 +176,8 @@ class Rijndael(BlockCipher): self.blockSize = blockSize # blockSize is in bytes self.padding = padding # change default to noPadding() to get normal ECB behavior - assert( keySize%4==0 and NrTable[4].has_key(keySize/4)),'key size must be 16,20,24,29 or 32 bytes' - assert( blockSize%4==0 and NrTable.has_key(blockSize/4)), 'block size must be 16,20,24,29 or 32 bytes' + assert( keySize%4==0 and keySize/4 in NrTable[4]),'key size must be 16,20,24,29 or 32 bytes' + assert( blockSize%4==0 and blockSize/4 in NrTable), 'block size must be 16,20,24,29 or 32 bytes' self.Nb = self.blockSize/4 # Nb is number of columns of 32 bit words self.Nk = keySize/4 # Nk is the key length in 32-bit words diff --git a/DeDRM_plugin/androidkindlekey.py b/DeDRM_plugin/androidkindlekey.py index dcd4d04..0e4b648 100644 --- a/DeDRM_plugin/androidkindlekey.py +++ b/DeDRM_plugin/androidkindlekey.py @@ -324,7 +324,7 @@ def usage(progname): print("Get backup.ab file using adb backup com.amazon.kindle for Android 4.0+.") print("Otherwise extract AmazonSecureStorage.xml from /data/data/com.amazon.kindle/shared_prefs/AmazonSecureStorage.xml") print("Or map_data_storage.db from /data/data/com.amazon.kindle/databases/map_data_storage.db") - print(u"") + print("") print("Usage:") print(" {0:s} [-h] [-b ] []".format(progname)) diff --git a/DeDRM_plugin/argv_utils.py b/DeDRM_plugin/argv_utils.py index b904903..fd4e03b 100644 --- a/DeDRM_plugin/argv_utils.py +++ b/DeDRM_plugin/argv_utils.py @@ -4,6 +4,7 @@ import sys, os import locale import codecs +import importlib # get sys.argv arguments and encode them into utf-8 def unicode_argv(): @@ -34,15 +35,13 @@ def unicode_argv(): # Remove Python executable and commands if present start = argc.value - len(sys.argv) return [argv[i] for i in - xrange(start, argc.value)] + range(start, argc.value)] # if we don't have any arguments at all, just pass back script name # this should never happen return ["DeDRM.py"] else: - argvencoding = sys.stdin.encoding - if argvencoding == None: - argvencoding = "utf-8" - return arg + argvencoding = sys.stdin.encoding or "utf-8" + return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv] def add_cp65001_codec(): @@ -59,7 +58,7 @@ def set_utf8_default_encoding(): return # Regenerate setdefaultencoding. - reload(sys) + importlib.reload(sys) sys.setdefaultencoding('utf-8') for attr in dir(locale): diff --git a/DeDRM_plugin/askfolder_ed.py b/DeDRM_plugin/askfolder_ed.py index 4f64c1f..8c586fe 100644 --- a/DeDRM_plugin/askfolder_ed.py +++ b/DeDRM_plugin/askfolder_ed.py @@ -17,10 +17,10 @@ # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: -# +# # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -166,15 +166,15 @@ def AskFolder( def BrowseCallback(hwnd, uMsg, lParam, lpData): if uMsg == BFFM_INITIALIZED: if actionButtonLabel: - label = actionButtonLabel.decode('utf-8', 'replace') + label = str(actionButtonLabel, errors='replace') user32.SendMessageW(hwnd, BFFM_SETOKTEXT, 0, label) if cancelButtonLabel: - label = cancelButtonLabel.decode('utf-8', 'replace') + label = str(cancelButtonLabel, errors='replace') cancelButton = user32.GetDlgItem(hwnd, IDCANCEL) if cancelButton: user32.SetWindowTextW(cancelButton, label) if windowTitle: - title = windowTitle.decode('utf-8', 'replace') + title = str(windowTitle, errors='replace') user32.SetWindowTextW(hwnd, title) if defaultLocation: user32.SendMessageW(hwnd, BFFM_SETSELECTIONW, 1, defaultLocation.replace('/', '\\')) diff --git a/DeDRM_plugin/config.py b/DeDRM_plugin/config.py index 68c6c28..3fb5baa 100644 --- a/DeDRM_plugin/config.py +++ b/DeDRM_plugin/config.py @@ -153,7 +153,7 @@ class ConfigWidget(QWidget): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. file_path = os.path.join(config_dir, "plugins", "DeDRM", "help", help_file_name) - with open(file_path,'wb') as f: + with open(file_path,'w') as f: f.write(self.load_resource(help_file_name)) return file_path url = 'file:///' + get_help_file_resource() @@ -181,14 +181,14 @@ class ConfigWidget(QWidget): class ManageKeysDialog(QDialog): - def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext = u"", wineprefix = None): + def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext = "", wineprefix = None): QDialog.__init__(self,parent) self.parent = parent self.key_type_name = key_type_name self.plugin_keys = plugin_keys self.create_key = create_key self.keyfile_ext = keyfile_ext - self.import_key = (keyfile_ext != u"") + self.import_key = (keyfile_ext != "") self.binary_file = (keyfile_ext == "der") self.json_file = (keyfile_ext == "k4i") self.android_file = (keyfile_ext == "k4a") @@ -279,8 +279,8 @@ class ManageKeysDialog(QDialog): def getwineprefix(self): if self.wineprefix is not None: - return self.wp_lineedit.text().strip() - return u"" + return str(self.wp_lineedit.text()).strip() + return "" def populate_list(self): if type(self.plugin_keys) == dict: @@ -300,7 +300,7 @@ class ManageKeysDialog(QDialog): new_key_value = d.key_value if type(self.plugin_keys) == dict: if new_key_value in self.plugin_keys.values(): - old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0] + old_key_name = [name for name, value in self.plugin_keys.items() if value == new_key_value][0] info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), "The new {1} is the same as the existing {1} named {0} and has not been added.".format(old_key_name,self.key_type_name), show=True) return @@ -328,7 +328,7 @@ class ManageKeysDialog(QDialog): if d.result() != d.Accepted: # rename cancelled or moot. return - keyname = self.listy.currentItem().text() + keyname = str(self.listy.currentItem().text()) if not question_dialog(self, "{0} {1}: Confirm Rename".format(PLUGIN_NAME, PLUGIN_VERSION), "Do you really want to rename the {2} named {0} to {1}?".format(keyname,d.key_name,self.key_type_name), show_copy_button=False, default_yes=False): return self.plugin_keys[d.key_name] = self.plugin_keys[keyname] @@ -340,7 +340,7 @@ class ManageKeysDialog(QDialog): def delete_key(self): if not self.listy.currentItem(): return - keyname = self.listy.currentItem().text() + keyname = str(self.listy.currentItem().text()) if not question_dialog(self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), "Do you really want to delete the {1} {0}?".format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): return if type(self.plugin_keys) == dict: @@ -357,7 +357,7 @@ class ManageKeysDialog(QDialog): # link is clicked in case the helpfile is updated in newer plugins. help_file_name = "{0}_{1}_Help.htm".format(PLUGIN_NAME, self.key_type_name) file_path = os.path.join(config_dir, "plugins", "DeDRM", "help", help_file_name) - with open(file_path,'wb') as f: + with open(file_path,'w') as f: f.write(self.parent.load_resource(help_file_name)) return file_path url = 'file:///' + get_help_file_resource() @@ -378,7 +378,7 @@ class ManageKeysDialog(QDialog): with open(fpath,'rb') as keyfile: new_key_value = keyfile.read() if self.binary_file: - new_key_value = new_key_value.hex() + new_key_value = new_key_value.encode('hex') elif self.json_file: new_key_value = json.loads(new_key_value) elif self.android_file: @@ -395,7 +395,7 @@ class ManageKeysDialog(QDialog): break if not match: if new_key_value in self.plugin_keys.values(): - old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0] + old_key_name = [name for name, value in self.plugin_keys.items() if value == new_key_value][0] skipped += 1 info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), "The key in file {0} is the same as the existing key {1} and has been skipped.".format(filename,old_key_name), show_copy_button=False, show=True) @@ -403,7 +403,7 @@ class ManageKeysDialog(QDialog): counter += 1 self.plugin_keys[new_key_name] = new_key_value - msg = u"" + msg = "" if counter+skipped > 1: if counter > 0: msg += "Imported {0:d} key {1}. ".format(counter, "file" if counter == 1 else "files") @@ -424,22 +424,22 @@ class ManageKeysDialog(QDialog): r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) return - keyname = self.listy.currentItem().text() + keyname = str(self.listy.currentItem().text()) unique_dlg_name = PLUGIN_NAME + "export {0} keys".format(self.key_type_name).replace(' ', '_') #takes care of automatically remembering last directory caption = "Save {0} File as...".format(self.key_type_name) filters = [("{0} Files".format(self.key_type_name), ["{0}".format(self.keyfile_ext)])] defaultname = "{0}.{1}".format(keyname, self.keyfile_ext) filename = choose_save_file(self, unique_dlg_name, caption, filters, all_files=False, initial_filename=defaultname) if filename: - with open(filename, 'wb') as fname: + with file(filename, 'wb') as fname: if self.binary_file: fname.write(self.plugin_keys[keyname].decode('hex')) elif self.json_file: - fname.write(json.dumps(self.plugin_keys[keyname]).encode()) + fname.write(json.dumps(self.plugin_keys[keyname])) elif self.android_file: for key in self.plugin_keys[keyname]: - fname.write(key.encode()) - fname.write(b"\n") + fname.write(key) + fname.write("\n") else: fname.write(self.plugin_keys[keyname]) @@ -475,7 +475,7 @@ class RenameKeyDialog(QDialog): self.resize(self.sizeHint()) def accept(self): - if not self.key_ledit.text() or self.key_ledit.text().isspace(): + if not str(self.key_ledit.text()) or str(self.key_ledit.text()).isspace(): errmsg = "Key name field cannot be empty!" return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), _(errmsg), show=True, show_copy_button=False) @@ -496,7 +496,7 @@ class RenameKeyDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @@ -513,7 +513,7 @@ class AddBandNKeyDialog(QDialog): layout = QVBoxLayout(self) self.setLayout(layout) - data_group_box = QGroupBox(u"", self) + data_group_box = QGroupBox("", self) layout.addWidget(data_group_box) data_group_box_layout = QVBoxLayout() data_group_box.setLayout(data_group_box_layout) @@ -530,7 +530,7 @@ class AddBandNKeyDialog(QDialog): name_group = QHBoxLayout() data_group_box_layout.addLayout(name_group) name_group.addWidget(QLabel("B&N/nook account email address:", self)) - self.name_ledit = QLineEdit(u"", self) + self.name_ledit = QLineEdit("", self) self.name_ledit.setToolTip(_("

Enter your email address as it appears in your B&N " + "account.

" + "

It will only be used to generate this " + @@ -545,7 +545,7 @@ class AddBandNKeyDialog(QDialog): ccn_group = QHBoxLayout() data_group_box_layout.addLayout(ccn_group) ccn_group.addWidget(QLabel("B&N/nook account password:", self)) - self.cc_ledit = QLineEdit(u"", self) + self.cc_ledit = QLineEdit("", self) self.cc_ledit.setToolTip(_("

Enter the password " + "for your B&N account.

" + "

The password will only be used to generate this " + @@ -560,7 +560,7 @@ class AddBandNKeyDialog(QDialog): key_group = QHBoxLayout() data_group_box_layout.addLayout(key_group) key_group.addWidget(QLabel("Retrieved key:", self)) - self.key_display = QLabel(u"", self) + self.key_display = QLabel("", self) self.key_display.setToolTip(_("Click the Retrieve Key button to fetch your B&N encryption key from the B&N servers")) key_group.addWidget(self.key_display) self.retrieve_button = QtGui.QPushButton(self) @@ -579,19 +579,19 @@ class AddBandNKeyDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @property def key_value(self): - return self.key_display.text().strip() + return str(self.key_display.text()).strip() @property def user_name(self): - return self.name_ledit.text().strip().lower().replace(' ','') + return str(self.name_ledit.text()).strip().lower().replace(' ','') @property def cc_number(self): - return self.cc_ledit.text().strip() + return str(self.cc_ledit.text()).strip() def retrieve_key(self): from calibre_plugins.dedrm.ignoblekeyfetch import fetch_key as fetch_bandn_key @@ -623,7 +623,7 @@ class AddEReaderDialog(QDialog): layout = QVBoxLayout(self) self.setLayout(layout) - data_group_box = QGroupBox(u"", self) + data_group_box = QGroupBox("", self) layout.addWidget(data_group_box) data_group_box_layout = QVBoxLayout() data_group_box.setLayout(data_group_box_layout) @@ -638,7 +638,7 @@ class AddEReaderDialog(QDialog): name_group = QHBoxLayout() data_group_box_layout.addLayout(name_group) name_group.addWidget(QLabel("Your Name:", self)) - self.name_ledit = QLineEdit(u"", self) + self.name_ledit = QLineEdit("", self) self.name_ledit.setToolTip("Enter the name for this eReader key, usually the name on your credit card.\nIt will only be used to generate this one-time key and won\'t be stored anywhere in calibre or on your computer.\n(ex: Mr Jonathan Q Smith)") name_group.addWidget(self.name_ledit) name_disclaimer_label = QLabel(_("(Will not be saved in configuration data)"), self) @@ -648,7 +648,7 @@ class AddEReaderDialog(QDialog): ccn_group = QHBoxLayout() data_group_box_layout.addLayout(ccn_group) ccn_group.addWidget(QLabel("Credit Card#:", self)) - self.cc_ledit = QLineEdit(u"", self) + self.cc_ledit = QLineEdit("", self) self.cc_ledit.setToolTip("

Enter the last 8 digits of credit card number for this eReader key.\nThey will only be used to generate this one-time key and won\'t be stored anywhere in calibre or on your computer.") ccn_group.addWidget(self.cc_ledit) ccn_disclaimer_label = QLabel(_('(Will not be saved in configuration data)'), self) @@ -665,7 +665,7 @@ class AddEReaderDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @property def key_value(self): @@ -674,11 +674,11 @@ class AddEReaderDialog(QDialog): @property def user_name(self): - return self.name_ledit.text().strip().lower().replace(' ','') + return str(self.name_ledit.text()).strip().lower().replace(' ','') @property def cc_number(self): - return self.cc_ledit.text().strip().replace(' ', '').replace('-','') + return str(self.cc_ledit.text()).strip().replace(' ', '').replace('-','') def accept(self): @@ -708,7 +708,7 @@ class AddAdeptDialog(QDialog): defaultkeys = adeptkeys() else: # linux - from wineutils import WineGetKeys + from .wineutils import WineGetKeys scriptpath = os.path.join(parent.parent.alfdir,"adobekey.py") defaultkeys = WineGetKeys(scriptpath, ".der",parent.getwineprefix()) @@ -716,12 +716,12 @@ class AddAdeptDialog(QDialog): self.default_key = defaultkeys[0] except: traceback.print_exc() - self.default_key = u"" + self.default_key = "" self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) if len(self.default_key)>0: - data_group_box = QGroupBox(u"", self) + data_group_box = QGroupBox("", self) layout.addWidget(data_group_box) data_group_box_layout = QVBoxLayout() data_group_box.setLayout(data_group_box_layout) @@ -748,7 +748,7 @@ class AddAdeptDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @property def key_value(self): @@ -779,7 +779,7 @@ class AddKindleDialog(QDialog): defaultkeys = kindlekeys() else: # linux - from wineutils import WineGetKeys + from .wineutils import WineGetKeys scriptpath = os.path.join(parent.parent.alfdir,"kindlekey.py") defaultkeys = WineGetKeys(scriptpath, ".k4i",parent.getwineprefix()) @@ -787,12 +787,12 @@ class AddKindleDialog(QDialog): self.default_key = defaultkeys[0] except: traceback.print_exc() - self.default_key = u"" + self.default_key = "" self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) if len(self.default_key)>0: - data_group_box = QGroupBox(u"", self) + data_group_box = QGroupBox("", self) layout.addWidget(data_group_box) data_group_box_layout = QVBoxLayout() data_group_box.setLayout(data_group_box_layout) @@ -820,7 +820,7 @@ class AddKindleDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @property def key_value(self): @@ -845,7 +845,7 @@ class AddSerialDialog(QDialog): layout = QVBoxLayout(self) self.setLayout(layout) - data_group_box = QGroupBox(u"", self) + data_group_box = QGroupBox("", self) layout.addWidget(data_group_box) data_group_box_layout = QVBoxLayout() data_group_box.setLayout(data_group_box_layout) @@ -866,11 +866,11 @@ class AddSerialDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @property def key_value(self): - return self.key_ledit.text().replace(' ', '') + return str(self.key_ledit.text()).replace(' ', '') def accept(self): if len(self.key_name) == 0 or self.key_name.isspace(): @@ -892,7 +892,7 @@ class AddAndroidDialog(QDialog): self.setLayout(layout) self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) - data_group_box = QGroupBox(u"", self) + data_group_box = QGroupBox("", self) layout.addWidget(data_group_box) data_group_box_layout = QVBoxLayout() data_group_box.setLayout(data_group_box_layout) @@ -903,14 +903,14 @@ class AddAndroidDialog(QDialog): add_btn.setToolTip("Import Kindle for Android backup file.") add_btn.clicked.connect(self.get_android_file) file_group.addWidget(add_btn) - self.selected_file_name = QLabel(u"",self) + self.selected_file_name = QLabel("",self) self.selected_file_name.setAlignment(Qt.AlignHCenter) file_group.addWidget(self.selected_file_name) key_group = QHBoxLayout() data_group_box_layout.addLayout(key_group) key_group.addWidget(QLabel("Unique Key Name:", self)) - self.key_ledit = QLineEdit(u"", self) + self.key_ledit = QLineEdit("", self) self.key_ledit.setToolTip("

Enter an identifying name for the Android for Kindle key.") key_group.addWidget(self.key_ledit) #key_label = QLabel(_(''), self) @@ -924,11 +924,11 @@ class AddAndroidDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @property def file_name(self): - return self.selected_file_name.text().strip() + return str(self.selected_file_name.text()).strip() @property def key_value(self): @@ -940,7 +940,7 @@ class AddAndroidDialog(QDialog): filters = [("Kindle for Android backup files", ['db','ab','xml'])] files = choose_files(self, unique_dlg_name, caption, filters, all_files=False) self.serials_from_file = [] - file_name = u"" + file_name = "" if files: # find the first selected file that yields some serial numbers for filename in files: @@ -973,7 +973,7 @@ class AddPIDDialog(QDialog): layout = QVBoxLayout(self) self.setLayout(layout) - data_group_box = QGroupBox(u"", self) + data_group_box = QGroupBox("", self) layout.addWidget(data_group_box) data_group_box_layout = QVBoxLayout() data_group_box.setLayout(data_group_box_layout) @@ -994,11 +994,11 @@ class AddPIDDialog(QDialog): @property def key_name(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() @property def key_value(self): - return self.key_ledit.text().strip() + return str(self.key_ledit.text()).strip() def accept(self): if len(self.key_name) == 0 or self.key_name.isspace(): diff --git a/DeDRM_plugin/epubtest.py b/DeDRM_plugin/epubtest.py index baede6a..71b79cc 100644 --- a/DeDRM_plugin/epubtest.py +++ b/DeDRM_plugin/epubtest.py @@ -66,10 +66,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,unicode): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -107,15 +108,13 @@ def unicode_argv(): # Remove Python executable and commands if present start = argc.value - len(sys.argv) return [argv[i] for i in - xrange(start, argc.value)] + range(start, argc.value)] # if we don't have any arguments at all, just pass back script name # this should never happen return ["epubtest.py"] else: - argvencoding = sys.stdin.encoding - if argvencoding == None: - argvencoding = "utf-8" - return arg + argvencoding = sys.stdin.encoding or "utf-8" + return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv] _FILENAME_LEN_OFFSET = 26 _EXTRA_LEN_OFFSET = 28 diff --git a/DeDRM_plugin/flatxml2html.py b/DeDRM_plugin/flatxml2html.py index 78cff11..6f839ce 100644 --- a/DeDRM_plugin/flatxml2html.py +++ b/DeDRM_plugin/flatxml2html.py @@ -2,7 +2,6 @@ # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # For use with Topaz Scripts Version 2.6 -from __future__ import print_function import sys import csv import os @@ -95,7 +94,7 @@ class DocParser(object): # change the origin to minx, miny and calc max height and width maxw = maxws[0] + xs[0] - minx maxh = maxhs[0] + ys[0] - miny - for j in xrange(0, len(xs)): + for j in range(0, len(xs)): xs[j] = xs[j] - minx ys[j] = ys[j] - miny maxw = max( maxw, (maxws[j] + xs[j]) ) @@ -107,10 +106,10 @@ class DocParser(object): ifile.write('\n') ifile.write('\n' % (math.floor(maxw/10), math.floor(maxh/10), maxw, maxh)) ifile.write('\n') - for j in xrange(0,len(gdefs)): + for j in range(0,len(gdefs)): ifile.write(gdefs[j]) ifile.write('\n') - for j in xrange(0,len(gids)): + for j in range(0,len(gids)): ifile.write('\n' % (gids[j], xs[j], ys[j])) ifile.write('') ifile.close() @@ -139,7 +138,7 @@ class DocParser(object): else: end = min(self.docSize, end) foundat = -1 - for j in xrange(pos, end): + for j in range(pos, end): item = self.docList[j] if item.find('=') >= 0: (name, argres) = item.split('=',1) @@ -300,7 +299,7 @@ class DocParser(object): if not makeImage : # standard all word paragraph - for wordnum in xrange(first, last): + for wordnum in range(first, last): result.append(('ocr', wordnum)) return pclass, result @@ -320,17 +319,17 @@ class DocParser(object): # by reverting to text based paragraph if firstGlyph >= lastGlyph: # revert to standard text based paragraph - for wordnum in xrange(first, last): + for wordnum in range(first, last): result.append(('ocr', wordnum)) return pclass, result - for glyphnum in xrange(firstGlyph, lastGlyph): + for glyphnum in range(firstGlyph, lastGlyph): glyphList.append(glyphnum) # include any extratokens if they exist (pos, sfg) = self.findinDoc('extratokens.firstGlyph',start,end) (pos, slg) = self.findinDoc('extratokens.lastGlyph',start,end) if (sfg != None) and (slg != None): - for glyphnum in xrange(int(sfg), int(slg)): + for glyphnum in range(int(sfg), int(slg)): glyphList.append(glyphnum) num = self.svgcount self.glyphs_to_image(glyphList) @@ -405,14 +404,14 @@ class DocParser(object): result.append(('img' + word_class, int(argres))) if (sp_first != -1) and (sp_last != -1): - for wordnum in xrange(sp_first, sp_last): + for wordnum in range(sp_first, sp_last): result.append(('ocr', wordnum)) sp_first = -1 sp_last = -1 if (gl_first != -1) and (gl_last != -1): glyphList = [] - for glyphnum in xrange(gl_first, gl_last): + for glyphnum in range(gl_first, gl_last): glyphList.append(glyphnum) num = self.svgcount self.glyphs_to_image(glyphList) @@ -422,7 +421,7 @@ class DocParser(object): gl_last = -1 if (ws_first != -1) and (ws_last != -1): - for wordnum in xrange(ws_first, ws_last): + for wordnum in range(ws_first, ws_last): result.append(('ocr', wordnum)) ws_first = -1 ws_last = -1 @@ -454,7 +453,7 @@ class DocParser(object): cnt = len(pdesc) - for j in xrange( 0, cnt) : + for j in range( 0, cnt) : (wtype, num) = pdesc[j] @@ -541,7 +540,7 @@ class DocParser(object): lstart = 0 cnt = len(pdesc) - for j in xrange( 0, cnt) : + for j in range( 0, cnt) : (wtype, num) = pdesc[j] @@ -654,7 +653,7 @@ class DocParser(object): # process each region on the page and convert what you can to html - for j in xrange(regcnt): + for j in range(regcnt): (etype, start) = pageDesc[j] (ntype, end) = pageDesc[j+1] diff --git a/DeDRM_plugin/flatxml2svg.py b/DeDRM_plugin/flatxml2svg.py index 4dfd6c7..72c7e3c 100644 --- a/DeDRM_plugin/flatxml2svg.py +++ b/DeDRM_plugin/flatxml2svg.py @@ -73,7 +73,7 @@ class PParser(object): else: end = min(self.docSize, end) foundat = -1 - for j in xrange(pos, end): + for j in range(pos, end): item = self.flatdoc[j] if item.find('=') >= 0: (name, argres) = item.split('=',1) @@ -101,7 +101,7 @@ class PParser(object): def getData(self, path): result = None cnt = len(self.flatdoc) - for j in xrange(cnt): + for j in range(cnt): item = self.flatdoc[j] if item.find('=') >= 0: (name, argt) = item.split('=') @@ -113,7 +113,7 @@ class PParser(object): result = argres break if (len(argres) > 0) : - for j in xrange(0,len(argres)): + for j in range(0,len(argres)): argres[j] = int(argres[j]) return result @@ -127,7 +127,7 @@ class PParser(object): name = item argres = [] if (len(argres) > 0) : - for j in xrange(0,len(argres)): + for j in range(0,len(argres)): argres[j] = int(argres[j]) if (name.endswith(path)): result = argres @@ -136,7 +136,7 @@ class PParser(object): def getDataTemp(self, path): result = None cnt = len(self.temp) - for j in xrange(cnt): + for j in range(cnt): item = self.temp[j] if item.find('=') >= 0: (name, argt) = item.split('=') @@ -149,7 +149,7 @@ class PParser(object): self.temp.pop(j) break if (len(argres) > 0) : - for j in xrange(0,len(argres)): + for j in range(0,len(argres)): argres[j] = int(argres[j]) return result @@ -220,15 +220,15 @@ def convert2SVG(gdict, flat_xml, pageid, previd, nextid, svgDir, raw, meta_array if (pp.gid != None): mlst.append('\n') gdefs = pp.getGlyphs() - for j in xrange(0,len(gdefs)): + for j in range(0,len(gdefs)): mlst.append(gdefs[j]) mlst.append('\n') img = pp.getImages() if (img != None): - for j in xrange(0,len(img)): + for j in range(0,len(img)): mlst.append(img[j]) if (pp.gid != None): - for j in xrange(0,len(pp.gid)): + for j in range(0,len(pp.gid)): mlst.append('\n' % (pp.gid[j], pp.gx[j], pp.gy[j])) if (img == None or len(img) == 0) and (pp.gid == None or len(pp.gid) == 0): xpos = "%d" % (pp.pw // 3) diff --git a/DeDRM_plugin/genbook.py b/DeDRM_plugin/genbook.py index dca5697..ea1ca38 100644 --- a/DeDRM_plugin/genbook.py +++ b/DeDRM_plugin/genbook.py @@ -44,10 +44,10 @@ if inCalibre : from calibre_plugins.dedrm import flatxml2svg from calibre_plugins.dedrm import stylexml2css else : - import convert2xml - import flatxml2html - import flatxml2svg - import stylexml2css + from . import convert2xml + from . import flatxml2html + from . import flatxml2svg + from . import stylexml2css # global switch buildXML = False diff --git a/DeDRM_plugin/ignobleepub.py b/DeDRM_plugin/ignobleepub.py index 66c1e99..9649e4f 100644 --- a/DeDRM_plugin/ignobleepub.py +++ b/DeDRM_plugin/ignobleepub.py @@ -322,79 +322,79 @@ def cli_main(): def gui_main(): try: - import Tkinter - import Tkconstants - import tkFileDialog - import tkMessageBox + import tkinter + import tkinter.constants + import tkinter.filedialog + import tkinter.messagebox import traceback except: return cli_main() - class DecryptionDialog(Tkinter.Frame): + class DecryptionDialog(tkinter.Frame): def __init__(self, root): - Tkinter.Frame.__init__(self, root, border=5) - self.status = Tkinter.Label(self, text="Select files for decryption") - self.status.pack(fill=Tkconstants.X, expand=1) - body = Tkinter.Frame(self) - body.pack(fill=Tkconstants.X, expand=1) - sticky = Tkconstants.E + Tkconstants.W + tkinter.Frame.__init__(self, root, border=5) + self.status = tkinter.Label(self, text="Select files for decryption") + self.status.pack(fill=tkinter.constants.X, expand=1) + body = tkinter.Frame(self) + body.pack(fill=tkinter.constants.X, expand=1) + sticky = tkinter.constants.E + tkinter.constants.W body.grid_columnconfigure(1, weight=2) - Tkinter.Label(body, text="Key file").grid(row=0) - self.keypath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Key file").grid(row=0) + self.keypath = tkinter.Entry(body, width=30) self.keypath.grid(row=0, column=1, sticky=sticky) if os.path.exists("bnepubkey.b64"): self.keypath.insert(0, "bnepubkey.b64") - button = Tkinter.Button(body, text="...", command=self.get_keypath) + button = tkinter.Button(body, text="...", command=self.get_keypath) button.grid(row=0, column=2) - Tkinter.Label(body, text="Input file").grid(row=1) - self.inpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Input file").grid(row=1) + self.inpath = tkinter.Entry(body, width=30) self.inpath.grid(row=1, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_inpath) + button = tkinter.Button(body, text="...", command=self.get_inpath) button.grid(row=1, column=2) - Tkinter.Label(body, text="Output file").grid(row=2) - self.outpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Output file").grid(row=2) + self.outpath = tkinter.Entry(body, width=30) self.outpath.grid(row=2, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_outpath) + button = tkinter.Button(body, text="...", command=self.get_outpath) button.grid(row=2, column=2) - buttons = Tkinter.Frame(self) + buttons = tkinter.Frame(self) buttons.pack() - botton = Tkinter.Button( + botton = tkinter.Button( buttons, text="Decrypt", width=10, command=self.decrypt) - botton.pack(side=Tkconstants.LEFT) - Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT) - button = Tkinter.Button( + botton.pack(side=tkinter.constants.LEFT) + tkinter.Frame(buttons, width=10).pack(side=tkinter.constants.LEFT) + button = tkinter.Button( buttons, text="Quit", width=10, command=self.quit) - button.pack(side=Tkconstants.RIGHT) + button.pack(side=tkinter.constants.RIGHT) def get_keypath(self): - keypath = tkFileDialog.askopenfilename( + keypath = tkinter.filedialog.askopenfilename( parent=None, title="Select Barnes & Noble \'.b64\' key file", defaultextension=".b64", filetypes=[('base64-encoded files', '.b64'), ('All Files', '.*')]) if keypath: keypath = os.path.normpath(keypath) - self.keypath.delete(0, Tkconstants.END) + self.keypath.delete(0, tkinter.constants.END) self.keypath.insert(0, keypath) return def get_inpath(self): - inpath = tkFileDialog.askopenfilename( + inpath = tkinter.filedialog.askopenfilename( parent=None, title="Select B&N-encrypted ePub file to decrypt", defaultextension=".epub", filetypes=[('ePub files', '.epub')]) if inpath: inpath = os.path.normpath(inpath) - self.inpath.delete(0, Tkconstants.END) + self.inpath.delete(0, tkinter.constants.END) self.inpath.insert(0, inpath) return def get_outpath(self): - outpath = tkFileDialog.asksaveasfilename( + outpath = tkinter.filedialog.asksaveasfilename( parent=None, title="Select unencrypted ePub file to produce", defaultextension=".epub", filetypes=[('ePub files', '.epub')]) if outpath: outpath = os.path.normpath(outpath) - self.outpath.delete(0, Tkconstants.END) + self.outpath.delete(0, tkinter.constants.END) self.outpath.insert(0, outpath) return @@ -426,11 +426,11 @@ def gui_main(): else: self.status['text'] = "The was an error decrypting the file." - root = Tkinter.Tk() + root = tkinter.Tk() root.title("Barnes & Noble ePub Decrypter v.{0}".format(__version__)) root.resizable(True, False) root.minsize(300, 0) - DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1) + DecryptionDialog(root).pack(fill=tkinter.constants.X, expand=1) root.mainloop() return 0 diff --git a/DeDRM_plugin/ignoblekey.py b/DeDRM_plugin/ignoblekey.py index ce3fe0c..646a64e 100644 --- a/DeDRM_plugin/ignoblekey.py +++ b/DeDRM_plugin/ignoblekey.py @@ -19,7 +19,7 @@ Get Barnes & Noble EPUB user key from nook Studio log file """ __license__ = 'GPL v3' -__version__ = "1.1" +__version__ = "2.0" import sys import os @@ -37,10 +37,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,str): + if isinstance(data, str): data = data.encode(self.encoding,"replace") self.stream.buffer.write(data) self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -276,27 +277,27 @@ def cli_main(): def gui_main(): try: - import Tkinter - import Tkconstants - import tkMessageBox + import tkinter + import tkinter.constants + import tkinter.messagebox import traceback except: return cli_main() - class ExceptionDialog(Tkinter.Frame): + class ExceptionDialog(tkinter.Frame): def __init__(self, root, text): - Tkinter.Frame.__init__(self, root, border=5) - label = Tkinter.Label(self, text="Unexpected error:", - anchor=Tkconstants.W, justify=Tkconstants.LEFT) - label.pack(fill=Tkconstants.X, expand=0) - self.text = Tkinter.Text(self) - self.text.pack(fill=Tkconstants.BOTH, expand=1) + tkinter.Frame.__init__(self, root, border=5) + label = tkinter.Label(self, text="Unexpected error:", + anchor=tkinter.constants.W, justify=tkinter.constants.LEFT) + label.pack(fill=tkinter.constants.X, expand=0) + self.text = tkinter.Text(self) + self.text.pack(fill=tkinter.constants.BOTH, expand=1) - self.text.insert(Tkconstants.END, text) + self.text.insert(tkinter.constants.END, text) argv=unicode_argv() - root = Tkinter.Tk() + root = tkinter.Tk() root.withdraw() progpath, progname = os.path.split(argv[0]) success = False @@ -314,14 +315,14 @@ def gui_main(): with open(outfile, 'w') as keyfileout: keyfileout.write(key) success = True - tkMessageBox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile)) + tkinter.messagebox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile)) except DrmException as e: - tkMessageBox.showerror(progname, "Error: {0}".format(str(e))) + tkinter.messagebox.showerror(progname, "Error: {0}".format(str(e))) except Exception: root.wm_state('normal') root.title(progname) text = traceback.format_exc() - ExceptionDialog(root, text).pack(fill=Tkconstants.BOTH, expand=1) + ExceptionDialog(root, text).pack(fill=tkinter.constants.BOTH, expand=1) root.mainloop() if not success: return 1 diff --git a/DeDRM_plugin/ignoblekeyfetch.py b/DeDRM_plugin/ignoblekeyfetch.py index 89e6d62..a0375f9 100644 --- a/DeDRM_plugin/ignoblekeyfetch.py +++ b/DeDRM_plugin/ignoblekeyfetch.py @@ -44,10 +44,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -99,9 +100,9 @@ class IGNOBLEError(Exception): def fetch_key(email, password): # change email and password to utf-8 if unicode - if type(email)==bytes: + if type(email)==str: email = email.encode('utf-8') - if type(password)==bytes: + if type(password)==str: password = password.encode('utf-8') import random @@ -163,54 +164,54 @@ def cli_main(): def gui_main(): try: - import Tkinter - import tkFileDialog - import Tkconstants - import tkMessageBox + import tkinter + import tkinter.filedialog + import tkinter.constants + import tkinter.messagebox import traceback except: return cli_main() - class DecryptionDialog(Tkinter.Frame): + class DecryptionDialog(tkinter.Frame): def __init__(self, root): - Tkinter.Frame.__init__(self, root, border=5) - self.status = Tkinter.Label(self, text="Enter parameters") - self.status.pack(fill=Tkconstants.X, expand=1) - body = Tkinter.Frame(self) - body.pack(fill=Tkconstants.X, expand=1) - sticky = Tkconstants.E + Tkconstants.W + tkinter.Frame.__init__(self, root, border=5) + self.status = tkinter.Label(self, text="Enter parameters") + self.status.pack(fill=tkinter.constants.X, expand=1) + body = tkinter.Frame(self) + body.pack(fill=tkinter.constants.X, expand=1) + sticky = tkinter.constants.E + tkinter.constants.W body.grid_columnconfigure(1, weight=2) - Tkinter.Label(body, text="Account email address").grid(row=0) - self.name = Tkinter.Entry(body, width=40) + tkinter.Label(body, text="Account email address").grid(row=0) + self.name = tkinter.Entry(body, width=40) self.name.grid(row=0, column=1, sticky=sticky) - Tkinter.Label(body, text="Account password").grid(row=1) - self.ccn = Tkinter.Entry(body, width=40) + tkinter.Label(body, text="Account password").grid(row=1) + self.ccn = tkinter.Entry(body, width=40) self.ccn.grid(row=1, column=1, sticky=sticky) - Tkinter.Label(body, text="Output file").grid(row=2) - self.keypath = Tkinter.Entry(body, width=40) + tkinter.Label(body, text="Output file").grid(row=2) + self.keypath = tkinter.Entry(body, width=40) self.keypath.grid(row=2, column=1, sticky=sticky) self.keypath.insert(2, "bnepubkey.b64") - button = Tkinter.Button(body, text="...", command=self.get_keypath) + button = tkinter.Button(body, text="...", command=self.get_keypath) button.grid(row=2, column=2) - buttons = Tkinter.Frame(self) + buttons = tkinter.Frame(self) buttons.pack() - botton = Tkinter.Button( + botton = tkinter.Button( buttons, text="Fetch", width=10, command=self.generate) - botton.pack(side=Tkconstants.LEFT) - Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT) - button = Tkinter.Button( + botton.pack(side=tkinter.constants.LEFT) + tkinter.Frame(buttons, width=10).pack(side=tkinter.constants.LEFT) + button = tkinter.Button( buttons, text="Quit", width=10, command=self.quit) - button.pack(side=Tkconstants.RIGHT) + button.pack(side=tkinter.constants.RIGHT) def get_keypath(self): - keypath = tkFileDialog.asksaveasfilename( + keypath = tkinter.filedialog.asksaveasfilename( parent=None, title="Select B&N ePub key file to produce", defaultextension=".b64", filetypes=[('base64-encoded files', '.b64'), ('All Files', '.*')]) if keypath: keypath = os.path.normpath(keypath) - self.keypath.delete(0, Tkconstants.END) + self.keypath.delete(0, tkinter.constants.END) self.keypath.insert(0, keypath) return @@ -239,11 +240,11 @@ def gui_main(): else: self.status['text'] = "Keyfile fetch failed." - root = Tkinter.Tk() + root = tkinter.Tk() root.title("Barnes & Noble ePub Keyfile Fetch v.{0}".format(__version__)) root.resizable(True, False) root.minsize(300, 0) - DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1) + DecryptionDialog(root).pack(fill=tkinter.constants.X, expand=1) root.mainloop() return 0 diff --git a/DeDRM_plugin/ignoblekeygen.py b/DeDRM_plugin/ignoblekeygen.py index 59a8085..07bfb51 100644 --- a/DeDRM_plugin/ignoblekeygen.py +++ b/DeDRM_plugin/ignoblekeygen.py @@ -54,10 +54,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -235,54 +236,54 @@ def cli_main(): def gui_main(): try: - import Tkinter - import Tkconstants - import tkMessageBox - import tkFileDialog + import tkinter + import tkinter.constants + import tkinter.messagebox + import tkinter.filedialog import traceback except: return cli_main() - class DecryptionDialog(Tkinter.Frame): + class DecryptionDialog(tkinter.Frame): def __init__(self, root): - Tkinter.Frame.__init__(self, root, border=5) - self.status = Tkinter.Label(self, text="Enter parameters") - self.status.pack(fill=Tkconstants.X, expand=1) - body = Tkinter.Frame(self) - body.pack(fill=Tkconstants.X, expand=1) - sticky = Tkconstants.E + Tkconstants.W + tkinter.Frame.__init__(self, root, border=5) + self.status = tkinter.Label(self, text="Enter parameters") + self.status.pack(fill=tkinter.constants.X, expand=1) + body = tkinter.Frame(self) + body.pack(fill=tkinter.constants.X, expand=1) + sticky = tkinter.constants.E + tkinter.constants.W body.grid_columnconfigure(1, weight=2) - Tkinter.Label(body, text="Account Name").grid(row=0) - self.name = Tkinter.Entry(body, width=40) + tkinter.Label(body, text="Account Name").grid(row=0) + self.name = tkinter.Entry(body, width=40) self.name.grid(row=0, column=1, sticky=sticky) - Tkinter.Label(body, text="CC#").grid(row=1) - self.ccn = Tkinter.Entry(body, width=40) + tkinter.Label(body, text="CC#").grid(row=1) + self.ccn = tkinter.Entry(body, width=40) self.ccn.grid(row=1, column=1, sticky=sticky) - Tkinter.Label(body, text="Output file").grid(row=2) - self.keypath = Tkinter.Entry(body, width=40) + tkinter.Label(body, text="Output file").grid(row=2) + self.keypath = tkinter.Entry(body, width=40) self.keypath.grid(row=2, column=1, sticky=sticky) self.keypath.insert(2, "bnepubkey.b64") - button = Tkinter.Button(body, text="...", command=self.get_keypath) + button = tkinter.Button(body, text="...", command=self.get_keypath) button.grid(row=2, column=2) - buttons = Tkinter.Frame(self) + buttons = tkinter.Frame(self) buttons.pack() - botton = Tkinter.Button( + botton = tkinter.Button( buttons, text="Generate", width=10, command=self.generate) - botton.pack(side=Tkconstants.LEFT) - Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT) - button = Tkinter.Button( + botton.pack(side=tkinter.constants.LEFT) + tkinter.Frame(buttons, width=10).pack(side=tkinter.constants.LEFT) + button = tkinter.Button( buttons, text="Quit", width=10, command=self.quit) - button.pack(side=Tkconstants.RIGHT) + button.pack(side=tkinter.constants.RIGHT) def get_keypath(self): - keypath = tkFileDialog.asksaveasfilename( + keypath = tkinter.filedialog.asksaveasfilename( parent=None, title="Select B&N ePub key file to produce", defaultextension=".b64", filetypes=[('base64-encoded files', '.b64'), ('All Files', '.*')]) if keypath: keypath = os.path.normpath(keypath) - self.keypath.delete(0, Tkconstants.END) + self.keypath.delete(0, tkinter.constants.END) self.keypath.insert(0, keypath) return @@ -308,10 +309,10 @@ def gui_main(): open(keypath,'wb').write(userkey) self.status['text'] = "Keyfile successfully generated" - root = Tkinter.Tk() + root = tkinter.Tk() if AES is None: root.withdraw() - tkMessageBox.showerror( + tkinter.messagebox.showerror( "Ignoble EPUB Keyfile Generator", "This script requires OpenSSL or PyCrypto, which must be installed " "separately. Read the top-of-script comment for details.") @@ -319,7 +320,7 @@ def gui_main(): root.title("Barnes & Noble ePub Keyfile Generator v.{0}".format(__version__)) root.resizable(True, False) root.minsize(300, 0) - DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1) + DecryptionDialog(root).pack(fill=tkinter.constants.X, expand=1) root.mainloop() return 0 diff --git a/DeDRM_plugin/ignoblepdf.py b/DeDRM_plugin/ignoblepdf.py index d594428..365eae2 100644 --- a/DeDRM_plugin/ignoblepdf.py +++ b/DeDRM_plugin/ignoblepdf.py @@ -19,10 +19,9 @@ """ Decrypts Barnes & Noble encrypted PDF files. """ -from __future__ import print_function __license__ = 'GPL v3' -__version__ = "0.1" +__version__ = "0.2" import sys import os @@ -44,10 +43,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,unicode): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -82,7 +82,7 @@ def unicode_argv(): # Remove Python executable and commands if present start = argc.value - len(sys.argv) return [argv[i] for i in - xrange(start, argc.value)] + range(start, argc.value)] return ["ignoblepdf.py"] else: argvencoding = sys.stdin.encoding or "utf-8" @@ -236,13 +236,7 @@ def _load_crypto(): ARC4, AES = _load_crypto() -try: - from cStringIO import StringIO -except ImportError: - try: - from StringIO import StringIO - except ImportError: - from io import StringIO +from io import BytesIO # Do we generate cross reference streams on output? @@ -1015,7 +1009,7 @@ class PDFStream(PDFObject): # will get errors if the document is encrypted. data = zlib.decompress(data) elif f in LITERALS_LZW_DECODE: - data = ''.join(LZWDecoder(StringIO(data)).run()) + data = ''.join(LZWDecoder(BytesIO(data)).run()) elif f in LITERALS_ASCII85_DECODE: data = ascii85decode(data) elif f == LITERAL_CRYPT: @@ -1039,7 +1033,7 @@ class PDFStream(PDFObject): columns = int_value(params['Columns']) buf = '' ent0 = '\x00' * columns - for i in xrange(0, len(data), columns+1): + for i in range(0, len(data), columns+1): pred = data[i] ent1 = data[i+1:i+1+columns] if pred == '\x02': @@ -1121,7 +1115,7 @@ class PDFXRef(object): (start, nobjs) = map(int, f) except ValueError: raise PDFNoValidXRef('Invalid line: %r: line=%r' % (parser, line)) - for objid in xrange(start, start+nobjs): + for objid in range(start, start+nobjs): try: (_, line) = parser.nextline() except PSEOF: @@ -1173,7 +1167,7 @@ class PDFXRefStream(object): def objids(self): for first, size in self.index: - for objid in xrange(first, first + size): + for objid in range(first, first + size): yield objid def load(self, parser, debug=0): @@ -1382,7 +1376,7 @@ class PDFDocument(object): hash.update('ffffffff'.decode('hex')) if 5 <= R: # 8 - for _ in xrange(50): + for _ in range(50): hash = hashlib.md5(hash.digest()[:length/8]) key = hash.digest()[:length/8] if R == 2: @@ -1393,7 +1387,7 @@ class PDFDocument(object): hash = hashlib.md5(self.PASSWORD_PADDING) # 2 hash.update(docid[0]) # 3 x = ARC4.new(key).decrypt(hash.digest()[:16]) # 4 - for i in xrange(1,19+1): + for i in range(1,19+1): k = ''.join( chr(ord(c) ^ i) for c in key ) x = ARC4.new(k).decrypt(x) u1 = x+x # 32bytes total @@ -1781,7 +1775,7 @@ class PDFParser(PSStackParser): class PDFObjStrmParser(PDFParser): def __init__(self, data, doc): - PSStackParser.__init__(self, StringIO(data)) + PSStackParser.__init__(self, BytesIO(data)) self.doc = doc return @@ -1856,7 +1850,7 @@ class PDFSerializer(object): if not gen_xref_stm: self.write('xref\n') self.write('0 %d\n' % (maxobj + 1,)) - for objid in xrange(0, maxobj + 1): + for objid in range(0, maxobj + 1): if objid in xrefs: # force the genno to be 0 self.write("%010d 00000 n \n" % xrefs[objid][0]) @@ -2043,79 +2037,79 @@ def cli_main(): def gui_main(): try: - import Tkinter - import Tkconstants - import tkFileDialog - import tkMessageBox + import tkinter + import tkinter.constants + import tkinter.filedialog + import tkinter.messagebox import traceback except: return cli_main() - class DecryptionDialog(Tkinter.Frame): + class DecryptionDialog(tkinter.Frame): def __init__(self, root): - Tkinter.Frame.__init__(self, root, border=5) - self.status = Tkinter.Label(self, text="Select files for decryption") - self.status.pack(fill=Tkconstants.X, expand=1) - body = Tkinter.Frame(self) - body.pack(fill=Tkconstants.X, expand=1) - sticky = Tkconstants.E + Tkconstants.W + tkinter.Frame.__init__(self, root, border=5) + self.status = tkinter.Label(self, text="Select files for decryption") + self.status.pack(fill=tkinter.constants.X, expand=1) + body = tkinter.Frame(self) + body.pack(fill=tkinter.constants.X, expand=1) + sticky = tkinter.constants.E + tkinter.constants.W body.grid_columnconfigure(1, weight=2) - Tkinter.Label(body, text="Key file").grid(row=0) - self.keypath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Key file").grid(row=0) + self.keypath = tkinter.Entry(body, width=30) self.keypath.grid(row=0, column=1, sticky=sticky) if os.path.exists("bnpdfkey.b64"): self.keypath.insert(0, "bnpdfkey.b64") - button = Tkinter.Button(body, text="...", command=self.get_keypath) + button = tkinter.Button(body, text="...", command=self.get_keypath) button.grid(row=0, column=2) - Tkinter.Label(body, text="Input file").grid(row=1) - self.inpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Input file").grid(row=1) + self.inpath = tkinter.Entry(body, width=30) self.inpath.grid(row=1, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_inpath) + button = tkinter.Button(body, text="...", command=self.get_inpath) button.grid(row=1, column=2) - Tkinter.Label(body, text="Output file").grid(row=2) - self.outpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Output file").grid(row=2) + self.outpath = tkinter.Entry(body, width=30) self.outpath.grid(row=2, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_outpath) + button = tkinter.Button(body, text="...", command=self.get_outpath) button.grid(row=2, column=2) - buttons = Tkinter.Frame(self) + buttons = tkinter.Frame(self) buttons.pack() - botton = Tkinter.Button( + botton = tkinter.Button( buttons, text="Decrypt", width=10, command=self.decrypt) - botton.pack(side=Tkconstants.LEFT) - Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT) - button = Tkinter.Button( + botton.pack(side=tkinter.constants.LEFT) + tkinter.Frame(buttons, width=10).pack(side=tkinter.constants.LEFT) + button = tkinter.Button( buttons, text="Quit", width=10, command=self.quit) - button.pack(side=Tkconstants.RIGHT) + button.pack(side=tkinter.constants.RIGHT) def get_keypath(self): - keypath = tkFileDialog.askopenfilename( + keypath = tkinter.filedialog.askopenfilename( parent=None, title="Select Barnes & Noble \'.b64\' key file", defaultextension=".b64", filetypes=[('base64-encoded files', '.b64'), ('All Files', '.*')]) if keypath: keypath = os.path.normpath(keypath) - self.keypath.delete(0, Tkconstants.END) + self.keypath.delete(0, tkinter.constants.END) self.keypath.insert(0, keypath) return def get_inpath(self): - inpath = tkFileDialog.askopenfilename( + inpath = tkinter.filedialog.askopenfilename( parent=None, title="Select B&N-encrypted PDF file to decrypt", defaultextension=".pdf", filetypes=[('PDF files', '.pdf')]) if inpath: inpath = os.path.normpath(inpath) - self.inpath.delete(0, Tkconstants.END) + self.inpath.delete(0, tkinter.constants.END) self.inpath.insert(0, inpath) return def get_outpath(self): - outpath = tkFileDialog.asksaveasfilename( + outpath = tkinter.filedialog.asksaveasfilename( parent=None, title="Select unencrypted PDF file to produce", defaultextension=".pdf", filetypes=[('PDF files', '.pdf')]) if outpath: outpath = os.path.normpath(outpath) - self.outpath.delete(0, Tkconstants.END) + self.outpath.delete(0, tkinter.constants.END) self.outpath.insert(0, outpath) return @@ -2148,10 +2142,10 @@ def gui_main(): self.status['text'] = "The was an error decrypting the file." - root = Tkinter.Tk() + root = tkinter.Tk() if AES is None: root.withdraw() - tkMessageBox.showerror( + tkinter.messagebox.showerror( "IGNOBLE PDF", "This script requires OpenSSL or PyCrypto, which must be installed " "separately. Read the top-of-script comment for details.") @@ -2159,7 +2153,7 @@ def gui_main(): root.title("Barnes & Noble PDF Decrypter v.{0}".format(__version__)) root.resizable(True, False) root.minsize(370, 0) - DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1) + DecryptionDialog(root).pack(fill=tkinter.constants.X, expand=1) root.mainloop() return 0 diff --git a/DeDRM_plugin/ineptepub.py b/DeDRM_plugin/ineptepub.py index 11661e7..1be1a89 100644 --- a/DeDRM_plugin/ineptepub.py +++ b/DeDRM_plugin/ineptepub.py @@ -58,10 +58,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -473,79 +474,79 @@ def cli_main(): def gui_main(): try: - import Tkinter - import Tkconstants - import tkFileDialog - import tkMessageBox + import tkinter + import tkinter_constants + import tkinter_filedialog + import tkinter_messagebox import traceback except: return cli_main() - class DecryptionDialog(Tkinter.Frame): + class DecryptionDialog(tkinter.Frame): def __init__(self, root): - Tkinter.Frame.__init__(self, root, border=5) - self.status = Tkinter.Label(self, text="Select files for decryption") - self.status.pack(fill=Tkconstants.X, expand=1) - body = Tkinter.Frame(self) - body.pack(fill=Tkconstants.X, expand=1) - sticky = Tkconstants.E + Tkconstants.W + tkinter.Frame.__init__(self, root, border=5) + self.status = tkinter.Label(self, text="Select files for decryption") + self.status.pack(fill=tkinter_constants.X, expand=1) + body = tkinter.Frame(self) + body.pack(fill=tkinter_constants.X, expand=1) + sticky = tkinter_constants.E + tkinter_constants.W body.grid_columnconfigure(1, weight=2) - Tkinter.Label(body, text="Key file").grid(row=0) - self.keypath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Key file").grid(row=0) + self.keypath = tkinter.Entry(body, width=30) self.keypath.grid(row=0, column=1, sticky=sticky) if os.path.exists("adeptkey.der"): self.keypath.insert(0, "adeptkey.der") - button = Tkinter.Button(body, text="...", command=self.get_keypath) + button = tkinter.Button(body, text="...", command=self.get_keypath) button.grid(row=0, column=2) - Tkinter.Label(body, text="Input file").grid(row=1) - self.inpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Input file").grid(row=1) + self.inpath = tkinter.Entry(body, width=30) self.inpath.grid(row=1, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_inpath) + button = tkinter.Button(body, text="...", command=self.get_inpath) button.grid(row=1, column=2) - Tkinter.Label(body, text="Output file").grid(row=2) - self.outpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Output file").grid(row=2) + self.outpath = tkinter.Entry(body, width=30) self.outpath.grid(row=2, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_outpath) + button = tkinter.Button(body, text="...", command=self.get_outpath) button.grid(row=2, column=2) - buttons = Tkinter.Frame(self) + buttons = tkinter.Frame(self) buttons.pack() - botton = Tkinter.Button( + botton = tkinter.Button( buttons, text="Decrypt", width=10, command=self.decrypt) - botton.pack(side=Tkconstants.LEFT) - Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT) - button = Tkinter.Button( + botton.pack(side=tkinter_constants.LEFT) + tkinter.Frame(buttons, width=10).pack(side=tkinter_constants.LEFT) + button = tkinter.Button( buttons, text="Quit", width=10, command=self.quit) - button.pack(side=Tkconstants.RIGHT) + button.pack(side=tkinter_constants.RIGHT) def get_keypath(self): - keypath = tkFileDialog.askopenfilename( + keypath = tkinter_filedialog.askopenfilename( parent=None, title="Select Adobe Adept \'.der\' key file", defaultextension=".der", filetypes=[('Adobe Adept DER-encoded files', '.der'), ('All Files', '.*')]) if keypath: keypath = os.path.normpath(keypath) - self.keypath.delete(0, Tkconstants.END) + self.keypath.delete(0, tkinter_constants.END) self.keypath.insert(0, keypath) return def get_inpath(self): - inpath = tkFileDialog.askopenfilename( + inpath = tkinter_filedialog.askopenfilename( parent=None, title="Select ADEPT-encrypted ePub file to decrypt", defaultextension=".epub", filetypes=[('ePub files', '.epub')]) if inpath: inpath = os.path.normpath(inpath) - self.inpath.delete(0, Tkconstants.END) + self.inpath.delete(0, tkinter_constants.END) self.inpath.insert(0, inpath) return def get_outpath(self): - outpath = tkFileDialog.asksaveasfilename( + outpath = tkinter_filedialog.asksaveasfilename( parent=None, title="Select unencrypted ePub file to produce", defaultextension=".epub", filetypes=[('ePub files', '.epub')]) if outpath: outpath = os.path.normpath(outpath) - self.outpath.delete(0, Tkconstants.END) + self.outpath.delete(0, tkinter_constants.END) self.outpath.insert(0, outpath) return @@ -577,11 +578,11 @@ def gui_main(): else: self.status['text'] = "The was an error decrypting the file." - root = Tkinter.Tk() + root = tkinter.Tk() root.title("Adobe Adept ePub Decrypter v.{0}".format(__version__)) root.resizable(True, False) root.minsize(300, 0) - DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1) + DecryptionDialog(root).pack(fill=tkinter_constants.X, expand=1) root.mainloop() return 0 diff --git a/DeDRM_plugin/ineptpdf.py b/DeDRM_plugin/ineptpdf.py index 5604fae..42f551c 100644 --- a/DeDRM_plugin/ineptpdf.py +++ b/DeDRM_plugin/ineptpdf.py @@ -71,13 +71,14 @@ class SafeUnbuffered: def __init__(self, stream): self.stream = stream self.encoding = stream.encoding - if self.encoding is None: + if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -115,10 +116,8 @@ def unicode_argv(): range(start, argc.value)] return ["ineptpdf.py"] else: - argvencoding = sys.stdin.encoding - if argvencoding is None: - argvencoding = "utf-8" - return sys.argv + argvencoding = sys.stdin.encoding or "utf-8" + return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv] class ADEPTError(Exception): @@ -404,13 +403,7 @@ def _load_crypto(): ARC4, RSA, AES = _load_crypto() -try: - from cStringIO import StringIO -except ImportError: - try: - from StringIO import StringIO - except ImportError: - from io import StringIO +from io import BytesIO # Do we generate cross reference streams on output? @@ -443,11 +436,11 @@ def nunpack(s, default=0): if not l: return default elif l == 1: - return s + return ord(s) elif l == 2: return struct.unpack('>H', s)[0] elif l == 3: - return struct.unpack('>L', b'\x00'+s)[0] + return struct.unpack('>L', '\x00'+s)[0] elif l == 4: return struct.unpack('>L', s)[0] else: @@ -486,7 +479,7 @@ class PSLiteral(PSObject): name = [] for char in self.name: if not char.isalnum(): - char = b'#%02x' % char + char = b'#%02x' % ord(char) name.append(char) return b'/%s' % ''.join(name) @@ -1183,7 +1176,7 @@ class PDFStream(PDFObject): # will get errors if the document is encrypted. data = zlib.decompress(data) elif f in LITERALS_LZW_DECODE: - data = ''.join(LZWDecoder(StringIO(data)).run()) + data = ''.join(LZWDecoder(BytesIO(data)).run()) elif f in LITERALS_ASCII85_DECODE: data = ascii85decode(data) elif f == LITERAL_CRYPT: @@ -1950,7 +1943,7 @@ class PDFParser(PSStackParser): class PDFObjStrmParser(PDFParser): def __init__(self, data, doc): - PSStackParser.__init__(self, StringIO(data)) + PSStackParser.__init__(self, BytesIO(data)) self.doc = doc return @@ -2212,79 +2205,79 @@ def cli_main(): def gui_main(): try: - import Tkinter - import Tkconstants - import tkFileDialog - import tkMessageBox + import tkinter + import tkinter.constants + import tkinter.filedialog + import tkinter.messagebox import traceback except: return cli_main() - class DecryptionDialog(Tkinter.Frame): + class DecryptionDialog(tkinter.Frame): def __init__(self, root): - Tkinter.Frame.__init__(self, root, border=5) - self.status = Tkinter.Label(self, text="Select files for decryption") - self.status.pack(fill=Tkconstants.X, expand=1) - body = Tkinter.Frame(self) - body.pack(fill=Tkconstants.X, expand=1) - sticky = Tkconstants.E + Tkconstants.W + tkinter.Frame.__init__(self, root, border=5) + self.status = tkinter.Label(self, text="Select files for decryption") + self.status.pack(fill=tkinter.constants.X, expand=1) + body = tkinter.Frame(self) + body.pack(fill=tkinter.constants.X, expand=1) + sticky = tkinter.constants.E + tkinter.constants.W body.grid_columnconfigure(1, weight=2) - Tkinter.Label(body, text="Key file").grid(row=0) - self.keypath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Key file").grid(row=0) + self.keypath = tkinter.Entry(body, width=30) self.keypath.grid(row=0, column=1, sticky=sticky) if os.path.exists("adeptkey.der"): self.keypath.insert(0, "adeptkey.der") - button = Tkinter.Button(body, text="...", command=self.get_keypath) + button = tkinter.Button(body, text="...", command=self.get_keypath) button.grid(row=0, column=2) - Tkinter.Label(body, text="Input file").grid(row=1) - self.inpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Input file").grid(row=1) + self.inpath = tkinter.Entry(body, width=30) self.inpath.grid(row=1, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_inpath) + button = tkinter.Button(body, text="...", command=self.get_inpath) button.grid(row=1, column=2) - Tkinter.Label(body, text="Output file").grid(row=2) - self.outpath = Tkinter.Entry(body, width=30) + tkinter.Label(body, text="Output file").grid(row=2) + self.outpath = tkinter.Entry(body, width=30) self.outpath.grid(row=2, column=1, sticky=sticky) - button = Tkinter.Button(body, text="...", command=self.get_outpath) + button = tkinter.Button(body, text="...", command=self.get_outpath) button.grid(row=2, column=2) - buttons = Tkinter.Frame(self) + buttons = tkinter.Frame(self) buttons.pack() - botton = Tkinter.Button( + botton = tkinter.Button( buttons, text="Decrypt", width=10, command=self.decrypt) - botton.pack(side=Tkconstants.LEFT) - Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT) - button = Tkinter.Button( + botton.pack(side=tkinter.constants.LEFT) + tkinter.Frame(buttons, width=10).pack(side=tkinter.constants.LEFT) + button = tkinter.Button( buttons, text="Quit", width=10, command=self.quit) - button.pack(side=Tkconstants.RIGHT) + button.pack(side=tkinter.constants.RIGHT) def get_keypath(self): - keypath = tkFileDialog.askopenfilename( + keypath = tkinter.filedialog.askopenfilename( parent=None, title="Select Adobe Adept \'.der\' key file", defaultextension=".der", filetypes=[('Adobe Adept DER-encoded files', '.der'), ('All Files', '.*')]) if keypath: keypath = os.path.normpath(keypath) - self.keypath.delete(0, Tkconstants.END) + self.keypath.delete(0, tkinter.constants.END) self.keypath.insert(0, keypath) return def get_inpath(self): - inpath = tkFileDialog.askopenfilename( + inpath = tkinter.filedialog.askopenfilename( parent=None, title="Select ADEPT-encrypted PDF file to decrypt", defaultextension=".pdf", filetypes=[('PDF files', '.pdf')]) if inpath: inpath = os.path.normpath(inpath) - self.inpath.delete(0, Tkconstants.END) + self.inpath.delete(0, tkinter.constants.END) self.inpath.insert(0, inpath) return def get_outpath(self): - outpath = tkFileDialog.asksaveasfilename( + outpath = tkinter.filedialog.asksaveasfilename( parent=None, title="Select unencrypted PDF file to produce", defaultextension=".pdf", filetypes=[('PDF files', '.pdf')]) if outpath: outpath = os.path.normpath(outpath) - self.outpath.delete(0, Tkconstants.END) + self.outpath.delete(0, tkinter.constants.END) self.outpath.insert(0, outpath) return @@ -2317,10 +2310,10 @@ def gui_main(): self.status['text'] = "The was an error decrypting the file." - root = Tkinter.Tk() + root = tkinter.Tk() if RSA is None: root.withdraw() - tkMessageBox.showerror( + tkinter.messagebox.showerror( "INEPT PDF", "This script requires OpenSSL or PyCrypto, which must be installed " "separately. Read the top-of-script comment for details.") @@ -2328,7 +2321,7 @@ def gui_main(): root.title("Adobe Adept PDF Decrypter v.{0}".format(__version__)) root.resizable(True, False) root.minsize(370, 0) - DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1) + DecryptionDialog(root).pack(fill=tkinter.constants.X, expand=1) root.mainloop() return 0 diff --git a/DeDRM_plugin/ion.py b/DeDRM_plugin/ion.py index ac1b6ad..9c8efc2 100644 --- a/DeDRM_plugin/ion.py +++ b/DeDRM_plugin/ion.py @@ -28,13 +28,7 @@ import os import os.path import struct -try: - from cStringIO import StringIO -except ImportError: - try: - from StringIO import StringIO - except ImportError: - from io import StringIO +from io import BytesIO from Crypto.Cipher import AES from Crypto.Util.py3compat import bchr, bord @@ -838,7 +832,7 @@ class DrmIonVoucher(object): b = aes.decrypt(self.ciphertext) b = pkcs7unpad(b, 16) - self.drmkey = BinaryIonParser(StringIO(b)) + self.drmkey = BinaryIonParser(BytesIO(b)) addprottable(self.drmkey) _assert(self.drmkey.hasnext() and self.drmkey.next() == TID_LIST and self.drmkey.gettypename() == "com.amazon.drm.KeySet@1.0", @@ -877,7 +871,7 @@ class DrmIonVoucher(object): self.envelope.next() field = self.envelope.getfieldname() if field == "voucher": - self.voucher = BinaryIonParser(StringIO(self.envelope.lobvalue())) + self.voucher = BinaryIonParser(BytesIO(self.envelope.lobvalue())) addprottable(self.voucher) continue elif field != "strategy": diff --git a/DeDRM_plugin/k4mobidedrm.py b/DeDRM_plugin/k4mobidedrm.py index d7775d6..34484ee 100644 --- a/DeDRM_plugin/k4mobidedrm.py +++ b/DeDRM_plugin/k4mobidedrm.py @@ -87,11 +87,11 @@ if inCalibre: from calibre_plugins.dedrm import androidkindlekey from calibre_plugins.dedrm import kfxdedrm else: - import mobidedrm - import topazextract - import kgenpids - import androidkindlekey - import kfxdedrm + from . import mobidedrm + from . import topazextract + from . import kgenpids + from . import androidkindlekey + from . import kfxdedrm # Wrap a stream so that output gets flushed immediately # and also make sure that any unicode strings get @@ -103,10 +103,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -157,13 +158,13 @@ def unicode_argv(): # and some improvements suggested by jhaisley def cleanup_name(name): # substitute filename unfriendly characters - name = name.replace("<","[").replace(">","]").replace(" : "," – ").replace(": "," – ").replace(":","—").replace("/","_").replace("\\","_").replace("|","_").replace("\"","\'").replace("*","_").replace("?",u"") + name = name.replace("<","[").replace(">","]").replace(" : "," – ").replace(": "," – ").replace(":","—").replace("/","_").replace("\\","_").replace("|","_").replace("\"","\'").replace("*","_").replace("?","") # white space to single space, delete leading and trailing while space name = re.sub(r"\s", " ", name).strip() # delete control characters - name = u"".join(char for char in name if ord(char)>=32) + name = "".join(char for char in name if ord(char)>=32) # delete non-ascii characters - name = u"".join(char for char in name if ord(char)<=126) + name = "".join(char for char in name if ord(char)<=126) # remove leading dots while len(name)>0 and name[0] == ".": name = name[1:] diff --git a/DeDRM_plugin/kfxdedrm.py b/DeDRM_plugin/kfxdedrm.py index 6c1d86a..5300018 100644 --- a/DeDRM_plugin/kfxdedrm.py +++ b/DeDRM_plugin/kfxdedrm.py @@ -10,13 +10,7 @@ import os import shutil import zipfile -try: - from cStringIO import StringIO -except ImportError: - try: - from StringIO import StringIO - except ImportError: - from io import StringIO +from io import BytesIO __license__ = 'GPL v3' @@ -47,8 +41,8 @@ class KFXZipBook: if self.voucher is None: self.decrypt_voucher(totalpids) print("Decrypting KFX DRMION: {0}".format(filename)) - outfile = StringIO() - ion.DrmIon(StringIO(data[8:-8]), lambda name: self.voucher).parse(outfile) + outfile = BytesIO() + ion.DrmIon(BytesIO(data[8:-8]), lambda name: self.voucher).parse(outfile) self.decrypted[filename] = outfile.getvalue() if not self.decrypted: @@ -78,7 +72,7 @@ class KFXZipBook: continue try: - voucher = ion.DrmIonVoucher(StringIO(data), pid[:dsn_len], pid[dsn_len:]) + voucher = ion.DrmIonVoucher(BytesIO(data), pid[:dsn_len], pid[dsn_len:]) voucher.parse() voucher.decryptvoucher() break diff --git a/DeDRM_plugin/kgenpids.py b/DeDRM_plugin/kgenpids.py index 373598e..466cf5c 100644 --- a/DeDRM_plugin/kgenpids.py +++ b/DeDRM_plugin/kgenpids.py @@ -52,11 +52,11 @@ def SHA1(message): def encode(data, map): result = '' for char in data: - value = char + value = ord(char) Q = (value ^ 0x80) // len(map) R = value % len(map) - result += chr(map[Q]) - result += chr(map[R]) + result += map[Q] + result += map[R] return result # Hash the bytes in data and then encode the digest with the characters in map diff --git a/DeDRM_plugin/kindlekey.py b/DeDRM_plugin/kindlekey.py index 6c81f4c..685b75b 100644 --- a/DeDRM_plugin/kindlekey.py +++ b/DeDRM_plugin/kindlekey.py @@ -154,14 +154,15 @@ def primes(n): return primeList # Encode the bytes in data with the characters in map +# data and map should be byte arrays def encode(data, map): result = b'' for char in data: value = char Q = (value ^ 0x80) // len(map) R = value % len(map) - result += bytes(map[Q]) - result += bytes(map[R]) + result += bytes([map[Q]]) + result += bytes([map[R]]) return result # Hash the bytes in data and then encode the digest with the characters in map @@ -932,6 +933,7 @@ if iswindows: CryptUnprotectData = CryptUnprotectData() # Returns Environmental Variables that contain unicode + # name must be unicode string, not byte string. def getEnvironmentVariable(name): import ctypes n = ctypes.windll.kernel32.GetEnvironmentVariableW(name, None, 0) @@ -1070,7 +1072,7 @@ if iswindows: if version == 5: # .kinf2011 added_entropy = build + guid elif version == 6: # .kinf2018 - salt = str(0x6d8 * int(build)) + guid + salt = str(0x6d8 * int(build)).encode('utf-8') + guid sp = GetUserName() + '+@#$%+' + GetIDString() passwd = encode(SHA256(sp), charMap5) key = KeyIVGen().pbkdf2(passwd, salt, 10000, 0x400)[:32] # this is very slow @@ -1162,8 +1164,8 @@ if iswindows: if len(DB)>6: # store values used in decryption - DB['IDString'] = GetIDString() - DB['UserName'] = GetUserName() + DB[b'IDString'] = GetIDString() + DB[b'UserName'] = GetUserName() print("Decrypted key file using IDString '{0:s}' and UserName '{1:s}'".format(GetIDString(), GetUserName().encode('hex'))) else: print("Couldn't decrypt file.") @@ -1525,14 +1527,14 @@ elif isosx: b'krx.notebookexportplugin.data.encryption_key',\ b'proxy.http.password',\ b'proxy.http.username' - ] + ] with open(kInfoFile, 'rb') as infoReader: filedata = infoReader.read() data = filedata[:-1] items = data.split(b'/') IDStrings = GetIDStrings() - print ("trying username ", GetUserName()) + print ("trying username ", GetUserName(), " on file ", kInfoFile) for IDString in IDStrings: print ("trying IDString:",IDString) try: @@ -1545,7 +1547,7 @@ elif isosx: encryptedValue = decode(headerblob, charMap1) #print ("encryptedvalue: ",encryptedValue) cleartext = UnprotectHeaderData(encryptedValue) - print ("cleartext: ",cleartext) + #print ("cleartext: ",cleartext) # now extract the pieces in the same way pattern = re.compile(rb'''\[Version:(\d+)\]\[Build:(\d+)\]\[Cksum:([^\]]+)\]\[Guid:([\{\}a-z0-9\-]+)\]''', re.IGNORECASE) @@ -1554,26 +1556,26 @@ elif isosx: build = m.group(2) guid = m.group(4) - print ("version",version) - print ("build",build) - print ("guid",guid,"\n") + #print ("version",version) + #print ("build",build) + #print ("guid",guid,"\n") if version == 5: # .kinf2011: identical to K4PC, except the build number gets multiplied - entropy = bytes(0x2df * int(build)) + guid + entropy = str(0x2df * int(build)).encode('utf-8') + guid cud = CryptUnprotectData(entropy,IDString) - print ("entropy",entropy) - print ("cud",cud) + #print ("entropy",entropy) + #print ("cud",cud) elif version == 6: # .kinf2018: identical to K4PC - salt = bytes(0x6d8 * int(build)) + guid + salt = str(0x6d8 * int(build)).encode('utf-8') + guid sp = GetUserName() + b'+@#$%+' + IDString passwd = encode(SHA256(sp), charMap5) key = LibCrypto().keyivgen(passwd, salt, 10000, 0x400)[:32] - print ("salt",salt) - print ("sp",sp) - print ("passwd",passwd) - print ("key",key) + #print ("salt",salt) + #print ("sp",sp) + #print ("passwd",passwd) + #print ("key",key) # loop through the item records until all are processed while len(items) > 0: @@ -1669,9 +1671,9 @@ elif isosx: pass if len(DB)>6: # store values used in decryption - print("Decrypted key file using IDString '{0:s}' and UserName '{1:s}'".format(IDString, GetUserName())) - DB['IDString'] = IDString - DB['UserName'] = GetUserName() + print("Decrypted key file using IDString '{0:s}' and UserName '{1:s}'".format(IDString.decode('utf-8'), GetUserName().decode('utf-8'))) + DB[b'IDString'] = IDString + DB[b'UserName'] = GetUserName() else: print("Couldn't decrypt file.") DB = {} @@ -1690,7 +1692,7 @@ def kindlekeys(files = []): if key: # convert all values to hex, just in case. for keyname in key: - key[keyname]=key[keyname].encode('hex') + key[keyname]=key[keyname].hex().encode('utf-8') keys.append(key) return keys @@ -1701,7 +1703,7 @@ def getkey(outpath, files=[]): if len(keys) > 0: if not os.path.isdir(outpath): outfile = outpath - with file(outfile, 'w') as keyfileout: + with open(outfile, 'w') as keyfileout: keyfileout.write(json.dumps(keys[0])) print("Saved a key to {0}".format(outfile)) else: @@ -1712,8 +1714,9 @@ def getkey(outpath, files=[]): outfile = os.path.join(outpath,"kindlekey{0:d}.k4i".format(keycount)) if not os.path.exists(outfile): break - with file(outfile, 'w') as keyfileout: - keyfileout.write(json.dumps(key)) + unikey = {k.decode("utf-8"):v.decode("utf-8") for k,v in key.items()} + with open(outfile, 'w') as keyfileout: + keyfileout.write(json.dumps(unikey)) print("Saved a key to {0}".format(outfile)) return True return False @@ -1771,27 +1774,27 @@ def cli_main(): def gui_main(): try: - import Tkinter - import Tkconstants - import tkMessageBox + import tkinter + import tkinter.constants + import tkinter.messagebox import traceback except: return cli_main() - class ExceptionDialog(Tkinter.Frame): + class ExceptionDialog(tkinter.Frame): def __init__(self, root, text): - Tkinter.Frame.__init__(self, root, border=5) - label = Tkinter.Label(self, text="Unexpected error:", - anchor=Tkconstants.W, justify=Tkconstants.LEFT) - label.pack(fill=Tkconstants.X, expand=0) - self.text = Tkinter.Text(self) - self.text.pack(fill=Tkconstants.BOTH, expand=1) + tkinter.Frame.__init__(self, root, border=5) + label = tkinter.Label(self, text="Unexpected error:", + anchor=tkinter.constants.W, justify=tkinter.constants.LEFT) + label.pack(fill=tkinter.constants.X, expand=0) + self.text = tkinter.Text(self) + self.text.pack(fill=tkinter.constants.BOTH, expand=1) - self.text.insert(Tkconstants.END, text) + self.text.insert(tkinter.constants.END, text) argv=unicode_argv() - root = Tkinter.Tk() + root = tkinter.Tk() root.withdraw() progpath, progname = os.path.split(argv[0]) success = False @@ -1805,24 +1808,23 @@ def gui_main(): if not os.path.exists(outfile): break - with file(outfile, 'w') as keyfileout: + with open(outfile, 'w') as keyfileout: keyfileout.write(json.dumps(key)) success = True - tkMessageBox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile)) + tkinter.messagebox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile)) except DrmException as e: - tkMessageBox.showerror(progname, "Error: {0}".format(str(e))) + tkinter.messagebox.showerror(progname, "Error: {0}".format(str(e))) except Exception: root.wm_state('normal') root.title(progname) text = traceback.format_exc() - ExceptionDialog(root, text).pack(fill=Tkconstants.BOTH, expand=1) + ExceptionDialog(root, text).pack(fill=tkinter.constants.BOTH, expand=1) root.mainloop() if not success: return 1 return 0 if __name__ == '__main__': - print ("here") if len(sys.argv) > 1: sys.exit(cli_main()) sys.exit(gui_main()) diff --git a/DeDRM_plugin/kindlepid.py b/DeDRM_plugin/kindlepid.py index b021e97..d640306 100644 --- a/DeDRM_plugin/kindlepid.py +++ b/DeDRM_plugin/kindlepid.py @@ -12,7 +12,7 @@ # 0.5 moved unicode_argv call inside main for Windows DeDRM compatibility # 1.0 Python 3 for calibre 5.0 -from __future__ import print_function + import sys import binascii @@ -26,10 +26,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -69,10 +70,8 @@ def unicode_argv(): # this should never happen return ["kindlepid.py"] else: - argvencoding = sys.stdin.encoding - if argvencoding == None: - argvencoding = "utf-8" - return sys.argv + argvencoding = sys.stdin.encoding or "utf-8" + return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv] letters = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789' @@ -137,6 +136,6 @@ def cli_main(): if __name__ == "__main__": - #sys.stdout=SafeUnbuffered(sys.stdout) - #sys.stderr=SafeUnbuffered(sys.stderr) + sys.stdout=SafeUnbuffered(sys.stdout) + sys.stderr=SafeUnbuffered(sys.stderr) sys.exit(cli_main()) diff --git a/DeDRM_plugin/mobidedrm.py b/DeDRM_plugin/mobidedrm.py index fff0969..e9b0fc1 100644 --- a/DeDRM_plugin/mobidedrm.py +++ b/DeDRM_plugin/mobidedrm.py @@ -73,7 +73,7 @@ __version__ = "1.00" # 0.40 - moved unicode_argv call inside main for Windows DeDRM compatibility # 0.41 - Fixed potential unicode problem in command line calls # 0.42 - Added GPL v3 licence. updated/removed some print statements -# 3.00 - Added Python 3 compatibility for calibre 5.0 +# 1.00 - Python 3 compatibility for calibre 5.0 import sys import os @@ -94,10 +94,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -152,12 +153,12 @@ class DrmException(Exception): # Implementation of Pukall Cipher 1 def PC1(key, src, decryption=True): # if we can get it from alfcrypto, use that - #try: - # return Pukall_Cipher().PC1(key,src,decryption) - #except NameError: - # pass - #except TypeError: - # pass + try: + return Pukall_Cipher().PC1(key,src,decryption) + except NameError: + pass + except TypeError: + pass # use slow python version, since Pukall_Cipher didn't load sum1 = 0; diff --git a/DeDRM_plugin/scriptinterface.py b/DeDRM_plugin/scriptinterface.py index 2b70266..25a6c09 100644 --- a/DeDRM_plugin/scriptinterface.py +++ b/DeDRM_plugin/scriptinterface.py @@ -2,10 +2,11 @@ # -*- coding: utf-8 -*- # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab -from __future__ import print_function + import sys import os import re +import traceback import calibre_plugins.dedrm.ineptepub import calibre_plugins.dedrm.ignobleepub import calibre_plugins.dedrm.epubtest @@ -13,7 +14,6 @@ import calibre_plugins.dedrm.zipfix import calibre_plugins.dedrm.ineptpdf import calibre_plugins.dedrm.erdr2pml import calibre_plugins.dedrm.k4mobidedrm -import traceback def decryptepub(infile, outdir, rscpath): errlog = '' diff --git a/DeDRM_plugin/scrolltextwidget.py b/DeDRM_plugin/scrolltextwidget.py index 98b4147..c95a264 100644 --- a/DeDRM_plugin/scrolltextwidget.py +++ b/DeDRM_plugin/scrolltextwidget.py @@ -1,23 +1,23 @@ #!/usr/bin/env python # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab -import Tkinter -import Tkconstants +import tkinter +import tkinter.constants # basic scrolled text widget -class ScrolledText(Tkinter.Text): +class ScrolledText(tkinter.Text): def __init__(self, master=None, **kw): - self.frame = Tkinter.Frame(master) - self.vbar = Tkinter.Scrollbar(self.frame) - self.vbar.pack(side=Tkconstants.RIGHT, fill=Tkconstants.Y) + self.frame = tkinter.Frame(master) + self.vbar = tkinter.Scrollbar(self.frame) + self.vbar.pack(side=tkinter.constants.RIGHT, fill=tkinter.constants.Y) kw.update({'yscrollcommand': self.vbar.set}) - Tkinter.Text.__init__(self, self.frame, **kw) - self.pack(side=Tkconstants.LEFT, fill=Tkconstants.BOTH, expand=True) + tkinter.Text.__init__(self, self.frame, **kw) + self.pack(side=tkinter.constants.LEFT, fill=tkinter.constants.BOTH, expand=True) self.vbar['command'] = self.yview # Copy geometry methods of self.frame without overriding Text # methods = hack! - text_meths = vars(Tkinter.Text).keys() - methods = vars(Tkinter.Pack).keys() + vars(Tkinter.Grid).keys() + vars(Tkinter.Place).keys() + text_meths = list(vars(tkinter.Text).keys()) + methods = list(vars(tkinter.Pack).keys()) + list(vars(tkinter.Grid).keys()) + list(vars(tkinter.Place).keys()) methods = set(methods).difference(text_meths) for m in methods: if m[0] != '_' and m != 'config' and m != 'configure': diff --git a/DeDRM_plugin/stylexml2css.py b/DeDRM_plugin/stylexml2css.py index 40b95a6..3e360a4 100644 --- a/DeDRM_plugin/stylexml2css.py +++ b/DeDRM_plugin/stylexml2css.py @@ -2,7 +2,7 @@ # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # For use with Topaz Scripts Version 2.6 -from __future__ import print_function + import csv import sys import os @@ -58,7 +58,7 @@ class DocParser(object): else: end = min(cnt,end) foundat = -1 - for j in xrange(pos, end): + for j in range(pos, end): item = docList[j] if item.find('=') >= 0: (name, argres) = item.split('=',1) @@ -116,7 +116,7 @@ class DocParser(object): # process each style converting what you can if debug: print(' ', 'Processing styles.') - for j in xrange(stylecnt): + for j in range(stylecnt): if debug: print(' ', 'Processing style %d' %(j)) start = styleList[j] end = styleList[j+1] diff --git a/DeDRM_plugin/topazextract.py b/DeDRM_plugin/topazextract.py index f56626b..1eb6b23 100644 --- a/DeDRM_plugin/topazextract.py +++ b/DeDRM_plugin/topazextract.py @@ -9,7 +9,6 @@ # 5.0 - Fixed potential unicode problem with command line interface # 6.0 - Added Python 3 compatibility for calibre 5.0 -from __future__ import print_function __version__ = '6.0' import sys @@ -23,6 +22,9 @@ try: except: from alfcrypto import Topaz_Cipher +# Wrap a stream so that output gets flushed immediately +# and also make sure that any unicode strings get +# encoded using "replace" before writing them. class SafeUnbuffered: def __init__(self, stream): self.stream = stream @@ -30,10 +32,11 @@ class SafeUnbuffered: if self.encoding == None: self.encoding = "utf-8" def write(self, data): - if isinstance(data,bytes): + if isinstance(data, str): data = data.encode(self.encoding,"replace") - self.stream.write(data) - self.stream.flush() + self.stream.buffer.write(data) + self.stream.buffer.flush() + def __getattr__(self, attr): return getattr(self.stream, attr) @@ -94,7 +97,7 @@ class DrmException(Exception): # recursive zip creation support routine def zipUpDir(myzip, tdir, localname): currentdir = tdir - if localname != u"": + if localname != "": currentdir = os.path.join(currentdir,localname) list = os.listdir(currentdir) for file in list: diff --git a/DeDRM_plugin/utilities.py b/DeDRM_plugin/utilities.py index 8472283..c6670cf 100644 --- a/DeDRM_plugin/utilities.py +++ b/DeDRM_plugin/utilities.py @@ -19,8 +19,8 @@ DETAILED_MESSAGE = \ def uStrCmp (s1, s2, caseless=False): import unicodedata as ud - str1 = s1 if isinstance(s1, unicode) else s1.decode('utf-8') - str2 = s2 if isinstance(s2, unicode) else s2.decode('utf-8') + str1 = s1 if isinstance(s1, str) else str(s1) + str2 = s2 if isinstance(s2, str) else str(s2) if caseless: return ud.normalize('NFC', str1.lower()) == ud.normalize('NFC', str2.lower()) else: diff --git a/DeDRM_plugin/zipfix.py b/DeDRM_plugin/zipfix.py index fb6558c..711e1be 100644 --- a/DeDRM_plugin/zipfix.py +++ b/DeDRM_plugin/zipfix.py @@ -15,7 +15,7 @@ """ Re-write zip (or ePub) fixing problems with file names (and mimetype entry). """ -from __future__ import print_function + __license__ = 'GPL v3' __version__ = "1.1"