diff options
Diffstat (limited to 'DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py')
-rw-r--r-- | DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py | 1103 |
1 files changed, 773 insertions, 330 deletions
diff --git a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py index 04d87c6..f2cd005 100644 --- a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py +++ b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py @@ -6,15 +6,14 @@ from __future__ import with_statement __license__ = 'GPL v3' # Standard Python modules. -import os, sys, re, hashlib +import os, traceback # PyQT4 modules (part of calibre). from PyQt4.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit, QGroupBox, QPushButton, QListWidget, QListWidgetItem, - QAbstractItemView, QIcon, QDialog, QUrl, QString) + QAbstractItemView, QIcon, QDialog, QDialogButtonBox, QUrl, QString) from PyQt4 import QtGui -import zipfile from zipfile import ZipFile # calibre modules and constants. @@ -26,50 +25,21 @@ from calibre.constants import iswindows, isosx # modules from this plugin's zipfile. from calibre_plugins.dedrm.__init__ import PLUGIN_NAME, PLUGIN_VERSION from calibre_plugins.dedrm.__init__ import RESOURCE_NAME as help_file_name -from calibre_plugins.dedrm.utilities import (uStrCmp, DETAILED_MESSAGE) - -import calibre_plugins.dedrm.dialogs as dialogs -import calibre_plugins.dedrm.ignoblekeygen as bandn -import calibre_plugins.dedrm.erdr2pml as ereader -import calibre_plugins.dedrm.adobekey as adobe -import calibre_plugins.dedrm.kindlekey as amazon - -JSON_NAME = PLUGIN_NAME.strip().lower().replace(' ', '_') -JSON_PATH = os.path.join(u"plugins", JSON_NAME + '.json') - -IGNOBLEPLUGINNAME = "Ignoble Epub DeDRM" -EREADERPLUGINNAME = "eReader PDB 2 PML" -OLDKINDLEPLUGINNAME = "K4PC, K4Mac, Kindle Mobi and Topaz DeDRM" - -# This is where all preferences for this plugin will be stored -# You should always prefix your config file name with plugins/, -# so as to ensure you dont accidentally clobber a calibre config file -dedrmprefs = JSONConfig(JSON_PATH) - -# get prefs from older tools -kindleprefs = JSONConfig(os.path.join(u"plugins", u"K4MobiDeDRM")) -ignobleprefs = JSONConfig(os.path.join(u"plugins", u"ignoble_epub_dedrm")) - -# Set defaults for the prefs -dedrmprefs.defaults['configured'] = False -dedrmprefs.defaults['bandnkeys'] = {} -dedrmprefs.defaults['adeptkeys'] = {} -dedrmprefs.defaults['ereaderkeys'] = {} -dedrmprefs.defaults['kindlekeys'] = {} -dedrmprefs.defaults['pids'] = [] -dedrmprefs.defaults['serials'] = [] +from calibre_plugins.dedrm.utilities import uStrCmp +import calibre_plugins.dedrm.prefs as prefs class ConfigWidget(QWidget): - def __init__(self, plugin_path): + def __init__(self, plugin_path, alfdir): QWidget.__init__(self) self.plugin_path = plugin_path + self.alfdir = alfdir - # get copy of the prefs from the file - # Otherwise we seem to get a persistent local copy. - self.dedrmprefs = JSONConfig(JSON_PATH) + # get the prefs + self.dedrmprefs = prefs.DeDRM_Prefs() + # make a local copy self.tempdedrmprefs = {} self.tempdedrmprefs['bandnkeys'] = self.dedrmprefs['bandnkeys'].copy() self.tempdedrmprefs['adeptkeys'] = self.dedrmprefs['adeptkeys'].copy() @@ -77,6 +47,8 @@ class ConfigWidget(QWidget): self.tempdedrmprefs['kindlekeys'] = self.dedrmprefs['kindlekeys'].copy() self.tempdedrmprefs['pids'] = list(self.dedrmprefs['pids']) self.tempdedrmprefs['serials'] = list(self.dedrmprefs['serials']) + self.tempdedrmprefs['adobewineprefix'] = self.dedrmprefs['adobewineprefix'] + self.tempdedrmprefs['kindlewineprefix'] = self.dedrmprefs['kindlewineprefix'] # Start Qt Gui dialog layout layout = QVBoxLayout(self) @@ -133,27 +105,37 @@ class ConfigWidget(QWidget): self.resize(self.sizeHint()) def kindle_serials(self): - d = dialogs.ManageKeysDialog(self,u"EInk Kindle Serial Number",self.tempdedrmprefs['serials'], dialogs.AddSerialDialog) + d = ManageKeysDialog(self,u"EInk Kindle Serial Number",self.tempdedrmprefs['serials'], AddSerialDialog) d.exec_() def kindle_keys(self): - d = dialogs.ManageKeysDialog(self,u"Kindle for Mac and PC Key",self.tempdedrmprefs['kindlekeys'], dialogs.AddKindleDialog, 'k4i') + if isosx or iswindows: + d = ManageKeysDialog(self,u"Kindle for Mac and PC Key",self.tempdedrmprefs['kindlekeys'], AddKindleDialog, 'k4i') + else: + # linux + d = ManageKeysDialog(self,u"Kindle for Mac and PC Key",self.tempdedrmprefs['kindlekeys'], AddKindleDialog, 'k4i', self.tempdedrmprefs['kindlewineprefix']) d.exec_() + self.tempdedrmprefs['kindlewineprefix'] = d.getwineprefix() def adept_keys(self): - d = dialogs.ManageKeysDialog(self,u"Adobe Digital Editions Key",self.tempdedrmprefs['adeptkeys'], dialogs.AddAdeptDialog, 'der') + if isosx or iswindows: + d = ManageKeysDialog(self,u"Adobe Digital Editions Key",self.tempdedrmprefs['adeptkeys'], AddAdeptDialog, 'der') + else: + # linux + d = ManageKeysDialog(self,u"Adobe Digital Editions Key",self.tempdedrmprefs['adeptkeys'], AddAdeptDialog, 'der', self.tempdedrmprefs['adobewineprefix']) d.exec_() + self.tempdedrmprefs['adobewineprefix'] = d.getwineprefix() def mobi_keys(self): - d = dialogs.ManageKeysDialog(self,u"Mobipocket PID",self.tempdedrmprefs['pids'], dialogs.AddPIDDialog) + d = ManageKeysDialog(self,u"Mobipocket PID",self.tempdedrmprefs['pids'], AddPIDDialog) d.exec_() def bandn_keys(self): - d = dialogs.ManageKeysDialog(self,u"Barnes and Noble Key",self.tempdedrmprefs['bandnkeys'], dialogs.AddBandNKeyDialog, 'b64') + d = ManageKeysDialog(self,u"Barnes and Noble Key",self.tempdedrmprefs['bandnkeys'], AddBandNKeyDialog, 'b64') d.exec_() def ereader_keys(self): - d = dialogs.ManageKeysDialog(self,u"eReader Key",self.tempdedrmprefs['ereaderkeys'], dialogs.AddEReaderDialog, 'b63') + d = ManageKeysDialog(self,u"eReader Key",self.tempdedrmprefs['ereaderkeys'], AddEReaderDialog, 'b63') d.exec_() def help_link_activated(self, url): @@ -168,13 +150,16 @@ class ConfigWidget(QWidget): open_url(QUrl(url)) def save_settings(self): - self.dedrmprefs['bandnkeys'] = self.tempdedrmprefs['bandnkeys'] - self.dedrmprefs['adeptkeys'] = self.tempdedrmprefs['adeptkeys'] - self.dedrmprefs['ereaderkeys'] = self.tempdedrmprefs['ereaderkeys'] - self.dedrmprefs['kindlekeys'] = self.tempdedrmprefs['kindlekeys'] - self.dedrmprefs['pids'] = self.tempdedrmprefs['pids'] - self.dedrmprefs['serials'] = self.tempdedrmprefs['serials'] - self.dedrmprefs['configured'] = True + self.dedrmprefs.set('bandnkeys', self.tempdedrmprefs['bandnkeys']) + self.dedrmprefs.set('adeptkeys', self.tempdedrmprefs['adeptkeys']) + self.dedrmprefs.set('ereaderkeys', self.tempdedrmprefs['ereaderkeys']) + self.dedrmprefs.set('kindlekeys', self.tempdedrmprefs['kindlekeys']) + self.dedrmprefs.set('pids', self.tempdedrmprefs['pids']) + self.dedrmprefs.set('serials', self.tempdedrmprefs['serials']) + self.dedrmprefs.set('adobewineprefix', self.tempdedrmprefs['adobewineprefix']) + self.dedrmprefs.set('kindlewineprefix', self.tempdedrmprefs['kindlewineprefix']) + self.dedrmprefs.set('configured', True) + self.dedrmprefs.writeprefs() def load_resource(self, name): with ZipFile(self.plugin_path, 'r') as zf: @@ -182,283 +167,741 @@ class ConfigWidget(QWidget): return zf.read(name) return "" -def writeprefs(value = True): - dedrmprefs['configured'] = value - -def addnamedvaluetoprefs(prefkind, keyname, keyvalue): - try: - if keyvalue not in dedrmprefs[prefkind].values(): - # ensure that the keyname is unique - # by adding a number (starting with 2) to the name if it is not - namecount = 1 - newname = keyname - while newname in dedrmprefs[prefkind]: - namecount += 1 - newname = "{0:s}_{1:d}".format(keyname,namecount) - # add to the preferences - dedrmprefs[prefkind][newname] = keyvalue - return (True, newname) - except: - pass - return (False, keyname) - -def addvaluetoprefs(prefkind, prefsvalue): - # ensure the keyvalue isn't already in the preferences - if prefsvalue not in dedrmprefs[prefkind]: - dedrmprefs[prefkind].append(prefsvalue) - return True - return False - -def convertprefs(always = False): - - def parseIgnobleString(keystuff): - userkeys = {} - ar = keystuff.split(':') - for i, keystring in enumerate(ar): - try: - name, ccn = keystring.split(',') - # Generate Barnes & Noble EPUB user key from name and credit card number. - keyname = u"{0}_{1}_{2:d}".format(name.strip(),ccn.strip()[-4:],i+1) - keyvalue = bandn.generate_key(name, ccn) - if keyvalue not in userkeys.values(): - while keyname in dedrmprefs['bandnkeys']: - keyname = keyname + keyname[-1] - userkeys[keyname] = keyvalue - except Exception, e: - print e.args[0] - pass - return userkeys - - def parseeReaderString(keystuff): - userkeys = {} - ar = keystuff.split(':') - for i, keystring in enumerate(ar): - try: - name, cc = keystring.split(',') - # Generate eReader user key from name and credit card number. - keyname = u"{0}_{1}_{2:d}".format(name.strip(),cc.strip()[-4:],i+1) - keyvalue = ereader.getuser_key(name,cc).encode('hex') - if keyvalue not in userkeys.values(): - while keyname in dedrmprefs['ereaderkeys']: - keyname = keyname + keyname[-1] - userkeys[keyname] = keyvalue - except Exception, e: - print e.args[0] - pass - return userkeys - - def parseKindleString(keystuff): - pids = [] - serials = [] - ar = keystuff.split(',') - for keystring in ar: - keystring = str(keystring).strip().replace(" ","") - if len(keystring) == 10 or len(keystring) == 8 and keystring not in pids: - pids.append(keystring) - elif len(keystring) == 16 and keystring[0] == 'B' and keystring not in serials: - serials.append(keystring) - return (pids,serials) - - def addConfigFiles(extension, prefskey, encoding = ''): - # get any files with extension 'extension' in the config dir - files = [f for f in os.listdir(config_dir) if f.endswith(extension)] - try: - priorkeycount = len(dedrmprefs[prefskey]) + + +class ManageKeysDialog(QDialog): + def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext = u"", 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.binary_file = (keyfile_ext == u".der") + self.json_file = (keyfile_ext == u".k4i") + self.wineprefix = wineprefix + + self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name)) + + # Start Qt Gui dialog layout + layout = QVBoxLayout(self) + self.setLayout(layout) + + help_layout = QHBoxLayout() + layout.addLayout(help_layout) + # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. + help_label = QLabel('<a href="http://www.foo.com/">Help</a>', self) + help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) + help_label.setAlignment(Qt.AlignRight) + help_label.linkActivated.connect(self.help_link_activated) + help_layout.addWidget(help_label) + + keys_group_box = QGroupBox(_(u"{0}s".format(self.key_type_name)), self) + layout.addWidget(keys_group_box) + keys_group_box_layout = QHBoxLayout() + keys_group_box.setLayout(keys_group_box_layout) + + self.listy = QListWidget(self) + self.listy.setToolTip(u"{0}s that will be used to decrypt ebooks".format(self.key_type_name)) + self.listy.setSelectionMode(QAbstractItemView.SingleSelection) + self.populate_list() + keys_group_box_layout.addWidget(self.listy) + + button_layout = QVBoxLayout() + keys_group_box_layout.addLayout(button_layout) + self._add_key_button = QtGui.QToolButton(self) + self._add_key_button.setToolTip(u"Create new {0}".format(self.key_type_name)) + self._add_key_button.setIcon(QIcon(I('plus.png'))) + self._add_key_button.clicked.connect(self.add_key) + button_layout.addWidget(self._add_key_button) + + self._delete_key_button = QtGui.QToolButton(self) + self._delete_key_button.setToolTip(_(u"Delete highlighted key")) + self._delete_key_button.setIcon(QIcon(I('list_remove.png'))) + self._delete_key_button.clicked.connect(self.delete_key) + button_layout.addWidget(self._delete_key_button) + + if type(self.plugin_keys) == dict and self.import_key: + self._rename_key_button = QtGui.QToolButton(self) + self._rename_key_button.setToolTip(_(u"Rename highlighted key")) + self._rename_key_button.setIcon(QIcon(I('edit-select-all.png'))) + self._rename_key_button.clicked.connect(self.rename_key) + button_layout.addWidget(self._rename_key_button) + + self.export_key_button = QtGui.QToolButton(self) + self.export_key_button.setToolTip(u"Save highlighted key to a .{0} file".format(self.keyfile_ext)) + self.export_key_button.setIcon(QIcon(I('save.png'))) + self.export_key_button.clicked.connect(self.export_key) + button_layout.addWidget(self.export_key_button) + spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + button_layout.addItem(spacerItem) + + if self.wineprefix is not None: + layout.addSpacing(5) + wineprefix_layout = QHBoxLayout() + layout.addLayout(wineprefix_layout) + wineprefix_layout.setAlignment(Qt.AlignCenter) + self.wp_label = QLabel(u"WINEPREFIX:") + wineprefix_layout.addWidget(self.wp_label) + self.wp_lineedit = QLineEdit(self) + wineprefix_layout.addWidget(self.wp_lineedit) + self.wp_label.setBuddy(self.wp_lineedit) + self.wp_lineedit.setText(self.wineprefix) + + layout.addSpacing(5) + migrate_layout = QHBoxLayout() + layout.addLayout(migrate_layout) + if self.import_key: + migrate_layout.setAlignment(Qt.AlignJustify) + self.migrate_btn = QPushButton(u"Import Existing Keyfiles", self) + self.migrate_btn.setToolTip(u"Import *.{0} files (created using other tools).".format(self.keyfile_ext)) + self.migrate_btn.clicked.connect(self.migrate_wrapper) + migrate_layout.addWidget(self.migrate_btn) + migrate_layout.addStretch() + self.button_box = QDialogButtonBox(QDialogButtonBox.Close) + self.button_box.rejected.connect(self.close) + migrate_layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + def getwineprefix(self): + if self.wineprefix is not None: + return unicode(self.wp_lineedit.text().toUtf8(), 'utf8').strip() + return u"" + + def populate_list(self): + if type(self.plugin_keys) == dict: + for key in self.plugin_keys.keys(): + self.listy.addItem(QListWidgetItem(key)) + else: + for key in self.plugin_keys: + self.listy.addItem(QListWidgetItem(key)) + + def add_key(self): + d = self.create_key(self) + d.exec_() + + if d.result() != d.Accepted: + # New key generation cancelled. + return + 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] + info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), + u"The new {1} is the same as the existing {1} named <strong>{0}</strong> and has not been added.".format(old_key_name,self.key_type_name), show=True) + return + self.plugin_keys[d.key_name] = new_key_value + else: + if new_key_value in self.plugin_keys: + info_dialog(None, "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION,self.key_type_name), + u"This {0} is already in the list of {0}s has not been added.".format(self.key_type_name), show=True) + return + + self.plugin_keys.append(d.key_value) + self.listy.clear() + self.populate_list() + + def rename_key(self): + if not self.listy.currentItem(): + errmsg = u"No {0} selected to rename. Highlight a keyfile first.".format(self.key_type_name) + r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + _(errmsg), show=True, show_copy_button=False) + return + + d = RenameKeyDialog(self) + d.exec_() + + if d.result() != d.Accepted: + # rename cancelled or moot. + return + keyname = unicode(self.listy.currentItem().text().toUtf8(),'utf8') + if not question_dialog(self, "{0} {1}: Confirm Rename".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to rename the {2} named <strong>{0}</strong> to <strong>{1}</strong>?".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] + del self.plugin_keys[keyname] + + self.listy.clear() + self.populate_list() + + def delete_key(self): + if not self.listy.currentItem(): + return + keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') + if not question_dialog(self, "{0} {1}: Confirm Delete".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to delete the {1} <strong>{0}</strong>?".format(keyname, self.key_type_name), show_copy_button=False, default_yes=False): + return + if type(self.plugin_keys) == dict: + del self.plugin_keys[keyname] + else: + self.plugin_keys.remove(keyname) + + self.listy.clear() + self.populate_list() + + def help_link_activated(self, url): + def get_help_file_resource(): + # Copy the HTML helpfile to the plugin directory each time the + # link is clicked in case the helpfile is updated in newer plugins. + help_file_name = u"{0}_{1}_Help.htm".format(PLUGIN_NAME, self.key_type_name) + file_path = os.path.join(config_dir, u"plugins", u"DeDRM", u"help", help_file_name) + 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() + open_url(QUrl(url)) + + def migrate_files(self): + dynamic[PLUGIN_NAME + u"config_dir"] = config_dir + files = choose_files(self, PLUGIN_NAME + u"config_dir", + u"Select {0} files to import".format(self.key_type_name), [(u"{0} files".format(self.key_type_name), [self.keyfile_ext])], False) + counter = 0 + skipped = 0 + if files: for filename in files: fpath = os.path.join(config_dir, filename) - key = os.path.splitext(filename)[0] - value = open(fpath, 'rb').read() - if encoding is not '': - value = value.encode(encoding) - if value not in dedrmprefs[prefskey].values(): - while key in dedrmprefs[prefskey]: - key = key+key[-1] - dedrmprefs[prefskey][key] = value - #os.remove(fpath) - return len(dedrmprefs[prefskey])-priorkeycount - except IOError: - return -1 - - if (not always) and dedrmprefs['configured']: - # We've already converted old preferences, - # and we're not being forced to do it again, so just return - return - - # initialise - # we must actually set the prefs that are dictionaries and lists - # to empty dictionaries and lists, otherwise we are unable to add to them - # as then it just adds to the (memory only) dedrmprefs.defaults versions! - if dedrmprefs['bandnkeys'] == {}: - dedrmprefs['bandnkeys'] = {} - if dedrmprefs['adeptkeys'] == {}: - dedrmprefs['adeptkeys'] = {} - if dedrmprefs['ereaderkeys'] == {}: - dedrmprefs['ereaderkeys'] = {} - if dedrmprefs['kindlekeys'] == {}: - dedrmprefs['kindlekeys'] = {} - if dedrmprefs['pids'] == []: - dedrmprefs['pids'] = [] - if dedrmprefs['serials'] == []: - dedrmprefs['serials'] = [] - - # get default adobe adept key(s) - priorkeycount = len(dedrmprefs['adeptkeys']) - try: - defaultkeys = adobe.adeptkeys() - except: - defaultkeys = [] - defaultcount = 1 - for keyvalue in defaultkeys: - keyname = u"default_key_{0:d}".format(defaultcount) - keyvaluehex = keyvalue.encode('hex') - if keyvaluehex not in dedrmprefs['adeptkeys'].values(): - while keyname in dedrmprefs['adeptkeys']: - defaultcount += 1 - keyname = u"default_key_{0:d}".format(defaultcount) - dedrmprefs['adeptkeys'][keyname] = keyvaluehex - addedkeycount = len(dedrmprefs['adeptkeys']) - priorkeycount - if addedkeycount > 0: - print u"{0} v{1}: {2:d} Default Adobe Adept {3} found.".format(PLUGIN_NAME, PLUGIN_VERSION, addedkeycount, u"key" if addedkeycount==1 else u"keys") - # Make the json write all the prefs to disk - writeprefs(False) - - - # get default kindle key(s) - priorkeycount = len(dedrmprefs['kindlekeys']) - try: - defaultkeys = amazon.kindlekeys() - except: - defaultkeys = [] - defaultcount = 1 - for keyvalue in defaultkeys: - keyname = u"default_key_{0:d}".format(defaultcount) - if keyvalue not in dedrmprefs['kindlekeys'].values(): - while keyname in dedrmprefs['kindlekeys']: - defaultcount += 1 - keyname = u"default_key_{0:d}".format(defaultcount) - dedrmprefs['kindlekeys'][keyname] = keyvalue - addedkeycount = len(dedrmprefs['kindlekeys']) - priorkeycount - if addedkeycount > 0: - print u"{0} v{1}: {2:d} Default Kindle for Mac/PC {3} found.".format(PLUGIN_NAME, PLUGIN_VERSION, addedkeycount, u"key" if addedkeycount==1 else u"keys") - # Make the json write all the prefs to disk - writeprefs(False) - - print u"{0} v{1}: Importing configuration data from old DeDRM plugins".format(PLUGIN_NAME, PLUGIN_VERSION) - - # Handle the old ignoble plugin's customization string by converting the - # old string to stored keys... get that personal data out of plain sight. - from calibre.customize.ui import config - sc = config['plugin_customization'] - val = sc.pop(IGNOBLEPLUGINNAME, None) - if val is not None: - print u"{0} v{1}: Converting old Ignoble plugin configuration string.".format(PLUGIN_NAME, PLUGIN_VERSION) - priorkeycount = len(dedrmprefs['bandnkeys']) - userkeys = parseIgnobleString(str(val)) - for key in userkeys: - value = userkeys[key] - if value not in dedrmprefs['bandnkeys'].values(): - while key in dedrmprefs['bandnkeys']: - key = key+key[-1] - dedrmprefs['bandnkeys'][key] = value - addedkeycount = len(dedrmprefs['bandnkeys'])-priorkeycount - print u"{0} v{1}: {2:d} Barnes and Noble {3} imported from old Ignoble plugin configuration string".format(PLUGIN_NAME, PLUGIN_VERSION, addedkeycount, u"key" if addedkeycount==1 else u"keys") - # Make the json write all the prefs to disk - writeprefs(False) - - # Handle the old eReader plugin's customization string by converting the - # old string to stored keys... get that personal data out of plain sight. - val = sc.pop(EREADERPLUGINNAME, None) - if val is not None: - print u"{0} v{1}: Converting old eReader plugin configuration string.".format(PLUGIN_NAME, PLUGIN_VERSION) - priorkeycount = len(dedrmprefs['ereaderkeys']) - userkeys = parseeReaderString(str(val)) - for key in userkeys: - value = userkeys[key] - if value not in dedrmprefs['ereaderkeys'].values(): - while key in dedrmprefs['ereaderkeys']: - key = key+key[-1] - dedrmprefs['ereaderkeys'][key] = value - addedkeycount = len(dedrmprefs['ereaderkeys'])-priorkeycount - print u"{0} v{1}: {2:d} eReader {3} imported from old eReader plugin configuration string".format(PLUGIN_NAME, PLUGIN_VERSION, addedkeycount, u"key" if addedkeycount==1 else u"keys") - # Make the json write all the prefs to disk - writeprefs(False) - - # get old Kindle plugin configuration string - val = sc.pop(OLDKINDLEPLUGINNAME, None) - if val is not None: - print u"{0} v{1}: Converting old Kindle plugin configuration string.".format(PLUGIN_NAME, PLUGIN_VERSION) - priorpidcount = len(dedrmprefs['pids']) - priorserialcount = len(dedrmprefs['serials']) - pids, serials = parseKindleString(val) - for pid in pids: - if pid not in dedrmprefs['pids']: - dedrmprefs['pids'].append(pid) - for serial in serials: - if serial not in dedrmprefs['serials']: - dedrmprefs['serials'].append(serial) - addedpidcount = len(dedrmprefs['pids']) - priorpidcount - addedserialcount = len(dedrmprefs['serials']) - priorserialcount - print u"{0} v{1}: {2:d} {3} and {4:d} {5} imported from old Kindle plugin configuration string.".format(PLUGIN_NAME, PLUGIN_VERSION, addedpidcount, u"PID" if addedpidcount==1 else u"PIDs", addedserialcount, u"serial number" if addedserialcount==1 else u"serial numbers") - # Make the json write all the prefs to disk - writeprefs(False) - - # copy the customisations back into calibre preferences, as we've now removed the nasty plaintext - config['plugin_customization'] = sc - - # get any .b64 files in the config dir - ignoblecount = addConfigFiles('.b64', 'bandnkeys') - if ignoblecount > 0: - print u"{0} v{1}: {2:d} Barnes and Noble {3} imported from config folder.".format(PLUGIN_NAME, PLUGIN_VERSION, ignoblecount, u"key file" if ignoblecount==1 else u"key files") - elif ignoblecount < 0: - print u"{0} v{1}: Error reading Barnes & Noble keyfiles from config directory.".format(PLUGIN_NAME, PLUGIN_VERSION) - # Make the json write all the prefs to disk - writeprefs(False) - - # get any .der files in the config dir - ineptcount = addConfigFiles('.der', 'adeptkeys','hex') - if ineptcount > 0: - print u"{0} v{1}: {2:d} Adobe Adept {3} imported from config folder.".format(PLUGIN_NAME, PLUGIN_VERSION, ineptcount, u"keyfile" if ineptcount==1 else u"keyfiles") - elif ineptcount < 0: - print u"{0} v{1}: Error reading Adobe Adept keyfiles from config directory.".format(PLUGIN_NAME, PLUGIN_VERSION) - # Make the json write all the prefs to disk - writeprefs(False) - - # get ignoble json prefs - if 'keys' in ignobleprefs: - priorkeycount = len(dedrmprefs['bandnkeys']) - for key in ignobleprefs['keys']: - value = ignobleprefs['keys'][key] - if value not in dedrmprefs['bandnkeys'].values(): - while key in dedrmprefs['bandnkeys']: - key = key+key[-1] - dedrmprefs['bandnkeys'][key] = value - addedkeycount = len(dedrmprefs['bandnkeys']) - priorkeycount - # no need to delete old prefs, since they contain no recoverable private data - if addedkeycount > 0: - print u"{0} v{1}: {2:d} Barnes and Noble {3} imported from Ignoble plugin preferences.".format(PLUGIN_NAME, PLUGIN_VERSION, addedkeycount, u"key" if addedkeycount==1 else u"keys") - # Make the json write all the prefs to disk - writeprefs(False) - - # get kindle json prefs - priorpidcount = len(dedrmprefs['pids']) - priorserialcount = len(dedrmprefs['serials']) - if 'pids' in kindleprefs: - pids, serials = parseKindleString(kindleprefs['pids']) - for pid in pids: - if pid not in dedrmprefs['pids']: - dedrmprefs['pids'].append(pid) - if 'serials' in kindleprefs: - pids, serials = parseKindleString(kindleprefs['serials']) - for serial in serials: - if serial not in dedrmprefs['serials']: - dedrmprefs['serials'].append(serial) - addedpidcount = len(dedrmprefs['pids']) - priorpidcount - if addedpidcount > 0: - print u"{0} v{1}: {2:d} {3} imported from Kindle plugin preferences".format(PLUGIN_NAME, PLUGIN_VERSION, addedpidcount, u"PID" if addedpidcount==1 else u"PIDs") - addedserialcount = len(dedrmprefs['serials']) - priorserialcount - if addedserialcount > 0: - print u"{0} v{1}: {2:d} {3} imported from Kindle plugin preferences".format(PLUGIN_NAME, PLUGIN_VERSION, addedserialcount, u"serial number" if addedserialcount==1 else u"serial numbers") - - # Make the json write all the prefs to disk - writeprefs() - print u"{0} v{1}: Finished setting up configuration data.".format(PLUGIN_NAME, PLUGIN_VERSION) + filename = os.path.basename(filename) + new_key_name = os.path.splitext(os.path.basename(filename))[0] + with open(fpath,'rb') as keyfile: + new_key_value = keyfile.read() + if self.binary_file: + new_key_value = new_key_value.encode('hex') + elif self.json_file: + new_key_value = json.loads(new_key_value) + match = False + for key in self.plugin_keys.keys(): + if uStrCmp(new_key_name, key, True): + skipped += 1 + msg = u"A key with the name <strong>{0}</strong> already exists!\nSkipping key file <strong>{1}</strong>.\nRename the existing key and import again".format(new_key_name,filename) + inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + _(msg), show_copy_button=False, show=True) + match = True + 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] + skipped += 1 + info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + u"The key in file {0} is the same as the existing key <strong>{1}</strong> and has been skipped.".format(filename,old_key_name), show_copy_button=False, show=True) + else: + counter += 1 + self.plugin_keys[new_key_name] = new_key_value + + msg = u"" + if counter+skipped > 1: + if counter > 0: + msg += u"Imported <strong>{0:d}</strong> key {1}. ".format(counter, u"file" if counter == 1 else u"files") + if skipped > 0: + msg += u"Skipped <strong>{0:d}</strong> key {1}.".format(skipped, u"file" if counter == 1 else u"files") + inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + _(msg), show_copy_button=False, show=True) + return counter > 0 + + def migrate_wrapper(self): + if self.migrate_files(): + self.listy.clear() + self.populate_list() + + def export_key(self): + if not self.listy.currentItem(): + errmsg = u"No keyfile selected to export. Highlight a keyfile first." + r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + _(errmsg), show=True, show_copy_button=False) + return + filter = QString(u"{0} Files (*.{1})".format(self.key_type_name, self.keyfile_ext)) + keyname = unicode(self.listy.currentItem().text().toUtf8(), 'utf8') + if dynamic.get(PLUGIN_NAME + 'save_dir'): + defaultname = os.path.join(dynamic.get(PLUGIN_NAME + 'save_dir'), u"{0}.{1}".format(keyname , self.keyfile_ext)) + else: + defaultname = os.path.join(os.path.expanduser('~'), u"{0}.{1}".format(keyname , self.keyfile_ext)) + filename = unicode(QtGui.QFileDialog.getSaveFileName(self, u"Save {0} File as...".format(self.key_type_name), defaultname, + u"{0} Files (*.{1})".format(self.key_type_name,self.keyfile_ext), filter)) + if filename: + dynamic[PLUGIN_NAME + 'save_dir'] = os.path.split(filename)[0] + with file(filename, 'w') 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])) + else: + fname.write(self.plugin_keys[keyname]) + + + + +class RenameKeyDialog(QDialog): + def __init__(self, parent=None,): + print repr(self), repr(parent) + QDialog.__init__(self, parent) + self.parent = parent + self.setWindowTitle("{0} {1}: Rename {0}".format(PLUGIN_NAME, PLUGIN_VERSION, parent.key_type_name)) + layout = QVBoxLayout(self) + self.setLayout(layout) + + data_group_box = QGroupBox('', self) + layout.addWidget(data_group_box) + data_group_box_layout = QVBoxLayout() + data_group_box.setLayout(data_group_box_layout) + + data_group_box_layout.addWidget(QLabel('New Key Name:', self)) + self.key_ledit = QLineEdit(self.parent.listy.currentItem().text(), self) + self.key_ledit.setToolTip(u"Enter a new name for this existing {0}.".format(parent.key_type_name)) + data_group_box_layout.addWidget(self.key_ledit) + + layout.addSpacing(20) + + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + self.button_box.accepted.connect(self.accept) + self.button_box.rejected.connect(self.reject) + layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + def accept(self): + if self.key_ledit.text().isEmpty() or unicode(self.key_ledit.text()).isspace(): + errmsg = u"Key name field cannot be empty!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + _(errmsg), show=True, show_copy_button=False) + if len(self.key_ledit.text()) < 4: + errmsg = u"Key name must be at <i>least</i> 4 characters long!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + _(errmsg), show=True, show_copy_button=False) + if uStrCmp(self.key_ledit.text(), self.parent.listy.currentItem().text()): + # Same exact name ... do nothing. + return QDialog.reject(self) + for k in self.parent.plugin_keys.keys(): + if (uStrCmp(self.key_ledit.text(), k, True) and + not uStrCmp(k, self.parent.listy.currentItem().text(), True)): + errmsg = u"The key name <strong>{0}</strong> is already being used.".format(self.key_ledit.text()) + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), + _(errmsg), show=True, show_copy_button=False) + QDialog.accept(self) + + @property + def key_name(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + + + + + + + +class AddBandNKeyDialog(QDialog): + def __init__(self, parent=None,): + QDialog.__init__(self, parent) + self.parent = parent + self.setWindowTitle(u"{0} {1}: Create New Barnes & Noble Key".format(PLUGIN_NAME, PLUGIN_VERSION)) + layout = QVBoxLayout(self) + self.setLayout(layout) + + data_group_box = QGroupBox(u"", self) + layout.addWidget(data_group_box) + data_group_box_layout = QVBoxLayout() + data_group_box.setLayout(data_group_box_layout) + + key_group = QHBoxLayout() + data_group_box_layout.addLayout(key_group) + key_group.addWidget(QLabel(u"Unique Key Name:", self)) + self.key_ledit = QLineEdit("", self) + self.key_ledit.setToolTip(_(u"<p>Enter an identifying name for this new key.</p>" + + u"<p>It should be something that will help you remember " + + u"what personal information was used to create it.")) + key_group.addWidget(self.key_ledit) + key_label = QLabel(_(''), self) + key_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(key_label) + + name_group = QHBoxLayout() + data_group_box_layout.addLayout(name_group) + name_group.addWidget(QLabel(u"Your Name:", self)) + self.name_ledit = QLineEdit(u"", self) + self.name_ledit.setToolTip(_(u"<p>Enter your name as it appears in your B&N " + + u"account or on your credit card.</p>" + + u"<p>It will only be used to generate this " + + u"one-time key and won\'t be stored anywhere " + + u"in calibre or on your computer.</p>" + + u"<p>(ex: Jonathan Smith)")) + name_group.addWidget(self.name_ledit) + name_disclaimer_label = QLabel(_(u"(Will not be saved in configuration data)"), self) + name_disclaimer_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(name_disclaimer_label) + + ccn_group = QHBoxLayout() + data_group_box_layout.addLayout(ccn_group) + ccn_group.addWidget(QLabel(u"Credit Card#:", self)) + self.cc_ledit = QLineEdit(u"", self) + self.cc_ledit.setToolTip(_(u"<p>Enter the full credit card number on record " + + u"in your B&N account.</p>" + + u"<p>No spaces or dashes... just the numbers. " + + u"This number will only be used to generate this " + + u"one-time key and won\'t be stored anywhere in " + + u"calibre or on your computer.")) + ccn_group.addWidget(self.cc_ledit) + ccn_disclaimer_label = QLabel(_('(Will not be saved in configuration data)'), self) + ccn_disclaimer_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(ccn_disclaimer_label) + layout.addSpacing(10) + + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + self.button_box.accepted.connect(self.accept) + self.button_box.rejected.connect(self.reject) + layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + @property + def key_name(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + @property + def key_value(self): + from calibre_plugins.dedrm.ignoblekeygen import generate_key as generate_bandn_key + return generate_bandn_key(self.user_name,self.cc_number) + + @property + def user_name(self): + return unicode(self.name_ledit.text().toUtf8(), 'utf8').strip().lower().replace(' ','') + + @property + def cc_number(self): + return unicode(self.cc_ledit.text().toUtf8(), 'utf8').strip().replace(' ', '').replace('-','') + + + def accept(self): + if len(self.key_name) == 0 or len(self.user_name) == 0 or len(self.cc_number) == 0 or self.key_name.isspace() or self.user_name.isspace() or self.cc_number.isspace(): + errmsg = u"All fields are required!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if not self.cc_number.isdigit(): + errmsg = u"Numbers only in the credit card number field!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if len(self.key_name) < 4: + errmsg = u"Key name must be at <i>least</i> 4 characters long!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + QDialog.accept(self) + +class AddEReaderDialog(QDialog): + def __init__(self, parent=None,): + QDialog.__init__(self, parent) + self.parent = parent + self.setWindowTitle(u"{0} {1}: Create New eReader Key".format(PLUGIN_NAME, PLUGIN_VERSION)) + layout = QVBoxLayout(self) + self.setLayout(layout) + + data_group_box = QGroupBox(u"", self) + layout.addWidget(data_group_box) + data_group_box_layout = QVBoxLayout() + data_group_box.setLayout(data_group_box_layout) + + key_group = QHBoxLayout() + data_group_box_layout.addLayout(key_group) + key_group.addWidget(QLabel(u"Unique Key Name:", self)) + self.key_ledit = QLineEdit("", self) + self.key_ledit.setToolTip(u"<p>Enter an identifying name for this new key.\nIt should be something that will help you remember what personal information was used to create it.") + key_group.addWidget(self.key_ledit) + key_label = QLabel(_(''), self) + key_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(key_label) + + name_group = QHBoxLayout() + data_group_box_layout.addLayout(name_group) + name_group.addWidget(QLabel(u"Your Name:", self)) + self.name_ledit = QLineEdit(u"", self) + self.name_ledit.setToolTip(u"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(_(u"(Will not be saved in configuration data)"), self) + name_disclaimer_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(name_disclaimer_label) + + ccn_group = QHBoxLayout() + data_group_box_layout.addLayout(ccn_group) + ccn_group.addWidget(QLabel(u"Credit Card#:", self)) + self.cc_ledit = QLineEdit(u"", self) + self.cc_ledit.setToolTip(u"<p>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) + ccn_disclaimer_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(ccn_disclaimer_label) + layout.addSpacing(10) + + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + self.button_box.accepted.connect(self.accept) + self.button_box.rejected.connect(self.reject) + layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + @property + def key_name(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + @property + def key_value(self): + from calibre_plugins.dedrm.erdr2pml import getuser_key as generate_ereader_key + return generate_ereader_key(self.user_name,self.cc_number).encode('hex') + + @property + def user_name(self): + return unicode(self.name_ledit.text().toUtf8(), 'utf8').strip().lower().replace(' ','') + + @property + def cc_number(self): + return unicode(self.cc_ledit.text().toUtf8(), 'utf8').strip().replace(' ', '').replace('-','') + + + def accept(self): + if len(self.key_name) == 0 or len(self.user_name) == 0 or len(self.cc_number) == 0 or self.key_name.isspace() or self.user_name.isspace() or self.cc_number.isspace(): + errmsg = u"All fields are required!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if not self.cc_number.isdigit(): + errmsg = u"Numbers only in the credit card number field!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if len(self.key_name) < 4: + errmsg = u"Key name must be at <i>least</i> 4 characters long!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + QDialog.accept(self) + + +class AddAdeptDialog(QDialog): + def __init__(self, parent=None,): + QDialog.__init__(self, parent) + self.parent = parent + self.setWindowTitle(u"{0} {1}: Getting Default Adobe Digital Editions Key".format(PLUGIN_NAME, PLUGIN_VERSION)) + layout = QVBoxLayout(self) + self.setLayout(layout) + + try: + if iswindows or isosx: + from calibre_plugins.dedrm.adobekey import adeptkeys + + defaultkeys = adeptkeys() + else: # linux + from wineutils import WineGetKeys + + scriptpath = os.path.join(parent.parent.alfdir,u"adobekey.py") + defaultkeys = WineGetKeys(scriptpath, u".der",parent.getwineprefix()) + + self.default_key = defaultkeys[0] + except: + traceback.print_exc() + self.default_key = u"" + + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + + if len(self.default_key)>0: + data_group_box = QGroupBox(u"", self) + layout.addWidget(data_group_box) + data_group_box_layout = QVBoxLayout() + data_group_box.setLayout(data_group_box_layout) + + key_group = QHBoxLayout() + data_group_box_layout.addLayout(key_group) + key_group.addWidget(QLabel(u"Unique Key Name:", self)) + self.key_ledit = QLineEdit(u"default_key", self) + self.key_ledit.setToolTip(u"<p>Enter an identifying name for the current default Adobe Digital Editions key.") + key_group.addWidget(self.key_ledit) + key_label = QLabel(_(''), self) + key_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(key_label) + self.button_box.accepted.connect(self.accept) + else: + default_key_error = QLabel(u"The default encryption key for Adobe Digital Editions could not be found.", self) + default_key_error.setAlignment(Qt.AlignHCenter) + layout.addWidget(default_key_error) + # if no default, bot buttons do the same + self.button_box.accepted.connect(self.reject) + + self.button_box.rejected.connect(self.reject) + layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + @property + def key_name(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + @property + def key_value(self): + return self.default_key.encode('hex') + + + def accept(self): + if len(self.key_name) == 0 or self.key_name.isspace(): + errmsg = u"All fields are required!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if len(self.key_name) < 4: + errmsg = u"Key name must be at <i>least</i> 4 characters long!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + QDialog.accept(self) + + +class AddKindleDialog(QDialog): + def __init__(self, parent=None,): + QDialog.__init__(self, parent) + self.parent = parent + self.setWindowTitle(u"{0} {1}: Getting Default Kindle for Mac/PC Key".format(PLUGIN_NAME, PLUGIN_VERSION)) + layout = QVBoxLayout(self) + self.setLayout(layout) + + try: + if iswindows or isosx: + from calibre_plugins.dedrm.kindlekey import kindlekeys + + defaultkeys = kindlekeys() + else: # linux + from wineutils import WineGetKeys + + scriptpath = os.path.join(parent.parent.alfdir,u"kindlekey.py") + defaultkeys = WineGetKeys(scriptpath, u".k4i",parent.getwineprefix()) + + self.default_key = defaultkeys[0] + except: + traceback.print_exc() + self.default_key = u"" + + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + + if len(self.default_key)>0: + data_group_box = QGroupBox(u"", self) + layout.addWidget(data_group_box) + data_group_box_layout = QVBoxLayout() + data_group_box.setLayout(data_group_box_layout) + + key_group = QHBoxLayout() + data_group_box_layout.addLayout(key_group) + key_group.addWidget(QLabel(u"Unique Key Name:", self)) + self.key_ledit = QLineEdit(u"default_key", self) + self.key_ledit.setToolTip(u"<p>Enter an identifying name for the current default Kindle for Mac/PC key.") + key_group.addWidget(self.key_ledit) + key_label = QLabel(_(''), self) + key_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(key_label) + self.button_box.accepted.connect(self.accept) + else: + default_key_error = QLabel(u"The default encryption key for Kindle for Mac/PC could not be found.", self) + default_key_error.setAlignment(Qt.AlignHCenter) + layout.addWidget(default_key_error) + # if no default, bot buttons do the same + self.button_box.accepted.connect(self.reject) + + self.button_box.rejected.connect(self.reject) + layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + @property + def key_name(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + @property + def key_value(self): + return self.default_key + + + def accept(self): + if len(self.key_name) == 0 or self.key_name.isspace(): + errmsg = u"All fields are required!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if len(self.key_name) < 4: + errmsg = u"Key name must be at <i>least</i> 4 characters long!" + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + QDialog.accept(self) + + +class AddSerialDialog(QDialog): + def __init__(self, parent=None,): + QDialog.__init__(self, parent) + self.parent = parent + self.setWindowTitle(u"{0} {1}: Add New EInk Kindle Serial Number".format(PLUGIN_NAME, PLUGIN_VERSION)) + layout = QVBoxLayout(self) + self.setLayout(layout) + + data_group_box = QGroupBox(u"", self) + layout.addWidget(data_group_box) + data_group_box_layout = QVBoxLayout() + data_group_box.setLayout(data_group_box_layout) + + key_group = QHBoxLayout() + data_group_box_layout.addLayout(key_group) + key_group.addWidget(QLabel(u"EInk Kindle Serial Number:", self)) + self.key_ledit = QLineEdit("", self) + self.key_ledit.setToolTip(u"Enter an eInk Kindle serial number. EInk Kindle serial numbers are 16 characters long and usually start with a 'B' or a '9'. Kindle Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged.") + key_group.addWidget(self.key_ledit) + key_label = QLabel(_(''), self) + key_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(key_label) + + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + self.button_box.accepted.connect(self.accept) + self.button_box.rejected.connect(self.reject) + layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + @property + def key_name(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + @property + def key_value(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + def accept(self): + if len(self.key_name) == 0 or self.key_name.isspace(): + errmsg = u"Please enter an eInk Kindle Serial Number or click Cancel in the dialog." + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if len(self.key_name) != 16: + errmsg = u"EInk Kindle Serial Numbers must be 16 characters long. This is {0:d} characters long.".format(len(self.key_name)) + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + QDialog.accept(self) + + +class AddPIDDialog(QDialog): + def __init__(self, parent=None,): + QDialog.__init__(self, parent) + self.parent = parent + self.setWindowTitle(u"{0} {1}: Add New Mobipocket PID".format(PLUGIN_NAME, PLUGIN_VERSION)) + layout = QVBoxLayout(self) + self.setLayout(layout) + + data_group_box = QGroupBox(u"", self) + layout.addWidget(data_group_box) + data_group_box_layout = QVBoxLayout() + data_group_box.setLayout(data_group_box_layout) + + key_group = QHBoxLayout() + data_group_box_layout.addLayout(key_group) + key_group.addWidget(QLabel(u"PID:", self)) + self.key_ledit = QLineEdit("", self) + self.key_ledit.setToolTip(u"Enter a Mobipocket PID. Mobipocket PIDs are 8 or 10 characters long. Mobipocket PIDs are case-sensitive, so be sure to enter the upper and lower case letters unchanged.") + key_group.addWidget(self.key_ledit) + key_label = QLabel(_(''), self) + key_label.setAlignment(Qt.AlignHCenter) + data_group_box_layout.addWidget(key_label) + + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + self.button_box.accepted.connect(self.accept) + self.button_box.rejected.connect(self.reject) + layout.addWidget(self.button_box) + + self.resize(self.sizeHint()) + + @property + def key_name(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + @property + def key_value(self): + return unicode(self.key_ledit.text().toUtf8(), 'utf8').strip() + + def accept(self): + if len(self.key_name) == 0 or self.key_name.isspace(): + errmsg = u"Please enter a Mobipocket PID or click Cancel in the dialog." + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + if len(self.key_name) != 8 and len(self.key_name) != 10: + errmsg = u"Mobipocket PIDs must be 8 or 10 characters long. This is {0:d} characters long.".format(len(self.key_name)) + return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False) + QDialog.accept(self) + + |