# Include an html helpfile in the plugin's zipfile with the following name.
RESOURCE_NAME=PLUGIN_NAME+'_Help.htm'
@ -109,11 +107,11 @@ class SafeUnbuffered:
ifself.encoding==None:
self.encoding="utf-8"
defwrite(self,data):
ifisinstance(data,bytes):
ifisinstance(data,str):
data=data.encode(self.encoding,"replace")
try:
self.stream.write(data)
self.stream.flush()
self.stream.buffer.write(data)
self.stream.buffer.flush()
except:
# We can do nothing if a write fails
pass
@ -122,11 +120,11 @@ class SafeUnbuffered:
classDeDRM(FileTypePlugin):
name=PLUGIN_NAME
description=u"Removes DRM from Amazon Kindle, Adobe Adept (including Kobo), Barnes & Noble, Mobipocket and eReader ebooks. Credit given to i♥cabbages and The Dark Reverser for the original stand-alone scripts."
description="Removes DRM from Amazon Kindle, Adobe Adept (including Kobo), Barnes & Noble, Mobipocket and eReader ebooks. Credit given to i♥cabbages and The Dark Reverser for the original stand-alone scripts."
supported_platforms=['linux','osx','windows']
author=u"Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages"
author="Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages"
version=PLUGIN_VERSION_TUPLE
minimum_calibre_version=(1,0,0)# Compiled python libraries cannot be imported in earlier versions.
print("{0} v{1}: Exception when getting default NOOK Study Key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
@ -274,7 +272,7 @@ class DeDRM(FileTypePlugin):
fori,userkeyinenumerate(newkeys):
print("{0} v{1}: Trying a new default key".format(PLUGIN_NAME,PLUGIN_VERSION))
of=self.temporary_file(u".epub")
of=self.temporary_file(".epub")
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
try:
@ -300,12 +298,12 @@ class DeDRM(FileTypePlugin):
# Return the modified PersistentTemporary file to calibre.
returnof.name
print(u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
print("{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
exceptExceptionase:
pass
print("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
# import the Adobe Adept ePub handler
importcalibre_plugins.dedrm.ineptepubasineptepub
@ -316,8 +314,8 @@ class DeDRM(FileTypePlugin):
# Attempt to decrypt epub with each encryption key (generated or provided).
print("{0} v{1}: Saved a new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
except:
@ -399,20 +397,20 @@ class DeDRM(FileTypePlugin):
# Return the modified PersistentTemporary file to calibre.
returnof.name
print(u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
print("{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
exceptExceptionase:
print(u"{0} v{1}: Unexpected Exception trying a new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
print("{0} v{1}: Unexpected Exception trying a new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
traceback.print_exc()
pass
# Something went wrong with decryption.
print("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
# Not a Barnes & Noble nor an Adobe Adept
# Import the fixed epub.
print("{0} v{1}: “{2}” is neither an Adobe Adept nor a Barnes & Noble encrypted ePub".format(PLUGIN_NAME,PLUGIN_VERSION,os.path.basename(path_to_ebook)))
raiseDeDRMError(u"{0} v{1}: Couldn't decrypt after {2:.1f} seconds. DRM free perhaps?".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError("{0} v{1}: Couldn't decrypt after {2:.1f} seconds. DRM free perhaps?".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
defPDFDecrypt(self,path_to_ebook):
importcalibre_plugins.dedrm.prefsasprefs
@ -422,9 +420,9 @@ class DeDRM(FileTypePlugin):
# Attempt to decrypt epub with each encryption key (generated or provided).
print("{0} v{1}: {2} is a PDF ebook".format(PLUGIN_NAME,PLUGIN_VERSION,os.path.basename(path_to_ebook)))
print("{0} v{1}: Trying a new default key".format(PLUGIN_NAME,PLUGIN_VERSION))
of=self.temporary_file(u".pdf")
of=self.temporary_file(".pdf")
# Give the user key, ebook and TemporaryPersistent file to the decryption function.
try:
@ -501,13 +499,13 @@ class DeDRM(FileTypePlugin):
# Return the modified PersistentTemporary file to calibre.
returnof.name
print(u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
print("{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
exceptExceptionase:
pass
# Something went wrong with decryption.
print("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
#if you reached here then no luck raise and exception
print("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
of=self.temporary_file(book.getBookExtension())
book.getFile(of.name)
@ -592,9 +590,9 @@ class DeDRM(FileTypePlugin):
dedrmprefs=prefs.DeDRM_Prefs()
# Attempt to decrypt epub with each encryption key (generated or provided).
print("{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME,PLUGIN_VERSION,keyname_masked,time.time()-self.starttime))
print("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
raiseDeDRMError("{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME,PLUGIN_VERSION,time.time()-self.starttime))
@ -341,7 +329,7 @@ class ManageKeysDialog(QDialog):
# rename cancelled or moot.
return
keyname=self.listy.currentItem().text()
ifnotquestion_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):
ifnotquestion_dialog(self,"{0}{1}: Confirm Rename".format(PLUGIN_NAME,PLUGIN_VERSION),"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):
@ -353,7 +341,7 @@ class ManageKeysDialog(QDialog):
ifnotself.listy.currentItem():
return
keyname=self.listy.currentItem().text()
ifnotquestion_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):
ifnotquestion_dialog(self,"{0}{1}: Confirm Delete".format(PLUGIN_NAME,PLUGIN_VERSION),"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
iftype(self.plugin_keys)==dict:
delself.plugin_keys[keyname]
@ -367,8 +355,8 @@ class ManageKeysDialog(QDialog):
defget_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.
@ -400,7 +388,7 @@ class ManageKeysDialog(QDialog):
forkeyinself.plugin_keys.keys():
ifuStrCmp(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)
msg="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)
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)
"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
@ -418,9 +406,9 @@ class ManageKeysDialog(QDialog):
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.")
self.key_ledit.setToolTip("<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)
name_group=QHBoxLayout()
data_group_box_layout.addLayout(name_group)
name_group.addWidget(QLabel(u"Your Name:",self))
name_group.addWidget(QLabel("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)")
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(_(u"(Will not be saved in configuration data)"),self)
name_disclaimer_label=QLabel(_("(Will not be saved in configuration data)"),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.")
self.cc_ledit.setToolTip("<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)
@ -853,7 +841,7 @@ 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))
self.setWindowTitle("{0}{1}: Add New EInk Kindle Serial Number".format(PLUGIN_NAME,PLUGIN_VERSION))
layout=QVBoxLayout(self)
self.setLayout(layout)
@ -864,9 +852,9 @@ class AddSerialDialog(QDialog):
key_group=QHBoxLayout()
data_group_box_layout.addLayout(key_group)
key_group.addWidget(QLabel(u"EInk Kindle Serial Number:",self))
key_group.addWidget(QLabel("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.")
self.key_ledit.setToolTip("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.")
self.setWindowTitle(u"{0}{1}: Add New Mobipocket PID".format(PLUGIN_NAME,PLUGIN_VERSION))
self.setWindowTitle("{0}{1}: Add New Mobipocket PID".format(PLUGIN_NAME,PLUGIN_VERSION))
layout=QVBoxLayout(self)
self.setLayout(layout)
@ -992,9 +980,9 @@ class AddPIDDialog(QDialog):
key_group=QHBoxLayout()
data_group_box_layout.addLayout(key_group)
key_group.addWidget(QLabel(u"PID:",self))
key_group.addWidget(QLabel("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.")
self.key_ledit.setToolTip("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.")
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"ifaddedkeycount==1elseu"keys"))
print("{0} v{1}: {2:d} Barnes and Noble {3} imported from old Ignoble plugin configuration string".format(PLUGIN_NAME,PLUGIN_VERSION,addedkeycount,"key"ifaddedkeycount==1else"keys"))
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"ifaddedpidcount==1elseu"PIDs",addedserialcount,u"serial number"ifaddedserialcount==1elseu"serial numbers"))
print("{0} v{1}: {2:d}{3} and {4:d}{5} imported from old Kindle plugin configuration string.".format(PLUGIN_NAME,PLUGIN_VERSION,addedpidcount,"PID"ifaddedpidcount==1else"PIDs",addedserialcount,"serial number"ifaddedserialcount==1else"serial numbers"))
raiseDrmException(u"No key found in {0:d} keys tried. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(len(pidlst)))
raiseDrmException("No key found in {0:d} keys tried. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(len(pidlst)))
u"This {0} is already in the list of {0}s has not been added.".format(self.key_type_name),show=True)
"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)
@ -166,7 +160,7 @@ class ManageKeysDialog(QDialog):
ifnotself.listy.currentItem():
return
keyname=self.listy.currentItem().text()
ifnotquestion_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):
ifnotquestion_dialog(self,"{0}{1}: Confirm Delete".format(PLUGIN_NAME,PLUGIN_VERSION),"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
self.plugin_keys.remove(keyname)
@ -177,7 +171,7 @@ class AddSerialDialog(QDialog):
def__init__(self,parent=None,):
QDialog.__init__(self,parent)
self.parent=parent
self.setWindowTitle(u"{0}{1}: Add New eInk Kobo Serial Number".format(PLUGIN_NAME,PLUGIN_VERSION))
self.setWindowTitle("{0}{1}: Add New eInk Kobo Serial Number".format(PLUGIN_NAME,PLUGIN_VERSION))
layout=QVBoxLayout(self)
self.setLayout(layout)
@ -188,9 +182,9 @@ class AddSerialDialog(QDialog):
key_group=QHBoxLayout()
data_group_box_layout.addLayout(key_group)
key_group.addWidget(QLabel(u"EInk Kobo Serial Number:",self))
key_group.addWidget(QLabel("EInk Kobo Serial Number:",self))
self.key_ledit=QLineEdit("",self)
self.key_ledit.setToolTip(u"Enter an eInk Kobo serial number. EInk Kobo serial numbers are 13 characters long and usually start with a 'N'. Kobo Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged.")
self.key_ledit.setToolTip("Enter an eInk Kobo serial number. EInk Kobo serial numbers are 13 characters long and usually start with a 'N'. Kobo Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged.")