tools v5.2
This commit is contained in:
@@ -1,40 +1,38 @@
|
||||
Ignoble Epub DeDRM - ignobleepub_vXX_plugin.zip
|
||||
|
||||
Requires Calibre version 0.6.44 or higher.
|
||||
|
||||
|
||||
|
||||
All credit given to I <3 Cabbages for the original standalone scripts.
|
||||
|
||||
I had the much easier job of converting them to a Calibre plugin.
|
||||
|
||||
|
||||
|
||||
This plugin is meant to decrypt Barnes & Noble Epubs that are protected
|
||||
|
||||
with Adobe's Adept encryption. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. It will still work if you have Python and PyCrypto already installed, but they aren't necessary.
|
||||
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Change calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (ignobleepub_vXX_plugin.zip) and
|
||||
|
||||
click the 'Add' button. you're done.
|
||||
|
||||
|
||||
Please note: Calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
|
||||
|
||||
1) The easiest way to configure the plugin is to enter your name (Barnes & Noble account name) and credit card number (the one used to purchase the books) into the plugin's customization window. It's the same info you would enter into the ignoblekeygen script. Highlight the plugin (Ignoble Epub DeDRM) and click the "Customize Plugin" button on
|
||||
|
||||
Calibre's Preferences->Plugins page. Enter the name and credit card number separated by a comma: Your Name,1234123412341234
|
||||
|
||||
|
||||
Ignoble Epub DeDRM - ignobleepub_v01.6_plugin.zip
|
||||
|
||||
All credit given to I♥Cabbages for the original standalone scripts.
|
||||
I had the much easier job of converting them to a calibre plugin.
|
||||
|
||||
This plugin is meant to decrypt Barnes & Noble Epubs that are protected with Adobe's Adept encryption. It is meant to function without having to install any dependencies... other than having calibre installed, of course. It will still work if you have Python and PyCrypto already installed, but they aren't necessary.
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Go to calibre's Preferences page. Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Change calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (ignobleepub_vXX_plugin.zip) and click the 'Add' button. you're done.
|
||||
|
||||
Please note: calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
1) The easiest way to configure the plugin is to enter your name (Barnes & Noble account name) and credit card number (the one used to purchase the books) into the plugin's customization window. It's the same info you would enter into the ignoblekeygen script. Highlight the plugin (Ignoble Epub DeDRM) and click the "Customize Plugin" button on calibre's Preferences->Plugins page. Enter the name and credit card number separated by a comma: Your Name,1234123412341234
|
||||
|
||||
If you've purchased books with more than one credit card, separate that other info with a colon: Your Name,1234123412341234:Other Name,2345234523452345
|
||||
|
||||
** NOTE ** The above method is your only option if you don't have/can't run the original I♥Cabbages scripts on your particular machine. Your credit card number will be on display in calibre's Plugin configuration page when using the above method. If other people have access to your computer, you may want to use the second configuration method below.
|
||||
|
||||
|
||||
2) If you already have keyfiles generated with I <3 Cabbages' ignoblekeygen.pyw script, you can put those keyfiles into calibre's configuration directory. The easiest way to find the correct directory is to go to calibre's Preferences page... click on the 'Miscellaneous' button (looks like a gear), and then click the 'Open calibre configuration directory' button. Paste your keyfiles in there. Just make sure that they have different names and are saved with the '.b64' extension (like the ignoblekeygen script produces). This directory isn't touched when upgrading calibre, so it's quite safe to leave them there.
|
||||
|
||||
All keyfiles from method 2 and all data entered from method 1 will be used to attempt to decrypt a book. You can use method 1 or method 2, or a combination of both.
|
||||
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
If you find that it's not working for you (imported epubs still have DRM), you can save a lot of time and trouble by trying to add the epub to calibre with the command line tools. This will print out a lot of helpful debugging info that can be copied into any online help requests. I'm going to ask you to do it first, anyway, so you might as well get used to it. ;)
|
||||
|
||||
Open a command prompt (terminal) and change to the directory where the ebook you're trying to import resides. Then type the command "calibredb add your_ebook.epub". Don't type the quotes and obviously change the 'your_ebook.epub' to whatever the filename of your book is. Copy the resulting output and paste it into any online help request you make.
|
||||
|
||||
** Note: the Mac version of calibre doesn't install the command line tools by default. If you go to the 'Preferences' page and click on the miscellaneous button, you'll see the option to install the command line tools.
|
||||
|
||||
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
Inept Epub DeDRM - ineptepub_vXX_plugin.zip
|
||||
|
||||
Requires Calibre version 0.6.44 or higher.
|
||||
|
||||
|
||||
|
||||
All credit given to I <3 Cabbages for the original standalone scripts.
|
||||
|
||||
I had the much easier job of converting them to a Calibre plugin.
|
||||
|
||||
|
||||
|
||||
This plugin is meant to decrypt Adobe Digital Edition Epubs that are protected with Adobe's Adept encryption. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. It will still work if you have Python and PyCrypto already installed, but they aren't necessary.
|
||||
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Cahnge calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (ineptepub_vXX_plugin.zip) and click the 'Add' button. you're done.
|
||||
|
||||
Please note: Calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
|
||||
|
||||
When first run, the plugin will attempt to find your Adobe Digital Editions installation (on Windows and Mac OS's). If successful, it will create an 'adeptkey.der' file and save it in Calibre's configuration directory. It will use that file on subsequent runs. If there are already '*.der' files in the directory, the plugin won't attempt to
|
||||
|
||||
find the Adobe Digital Editions installation installation.
|
||||
|
||||
|
||||
|
||||
So if you have Adobe Digital Editions installation installed on the same machine as Calibre... you are ready to go. If not... keep reading.
|
||||
Inept Epub DeDRM - ineptepub_v01.7_plugin.zip
|
||||
|
||||
All credit given to I♥Cabbages for the original standalone scripts.
|
||||
I had the much easier job of converting them to a Calibre plugin.
|
||||
|
||||
This plugin is meant to decrypt Adobe Digital Edition Epubs that are protected with Adobe's Adept encryption. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. It will still work if you have Python and PyCrypto already installed, but they aren't necessary.
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Cahnge calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (ineptepub_vXX_plugin.zip) and click the 'Add' button. you're done.
|
||||
|
||||
Please note: Calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
When first run, the plugin will attempt to find your Adobe Digital Editions installation (on Windows and Mac OS's). If successful, it will create an 'adeptkey.der' file and save it in Calibre's configuration directory. It will use that file on subsequent runs. If there are already '*.der' files in the directory, the plugin won't attempt to find the Adobe Digital Editions installation installation.
|
||||
|
||||
So if you have Adobe Digital Editions installation installed on the same machine as Calibre... you are ready to go. If not... keep reading.
|
||||
|
||||
If you already have keyfiles generated with I♥Cabbages' ineptkey.pyw script, you can put those keyfiles in Calibre's configuration directory. The easiest way to find the correct directory is to go to Calibre's Preferences page... click on the 'Miscellaneous' button (looks like a gear), and then click the 'Open Calibre configuration directory' button. Paste your keyfiles in there. Just make sure that they have different names and are saved with the '.der' extension (like the ineptkey script produces). This directory isn't touched when upgrading Calibre, so it's quite safe to leave them there.
|
||||
|
||||
Since there is no Linux version of Adobe Digital Editions, Linux users will have to obtain a keyfile through other methods and put the file in Calibre's configuration directory.
|
||||
|
||||
All keyfiles with a '.der' extension found in Calibre's configuration directory will be used to attempt to decrypt a book.
|
||||
|
||||
|
||||
** NOTE ** There is no plugin customization data for the Inept Epub DeDRM plugin.
|
||||
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
If you find that it's not working for you (imported epubs still have DRM), you can save a lot of time and trouble by trying to add the epub to Calibre with the command line tools. This will print out a lot of helpful debugging info that can be copied into any online help requests. I'm going to ask you to do it first, anyway, so you might as well get used to it. ;)
|
||||
|
||||
Open a command prompt (terminal) and change to the directory where the ebook you're trying to import resides. Then type the command "calibredb add your_ebook.epub". Don't type the quotes and obviously change the 'your_ebook.epub' to whatever the filename of your book is. Copy the resulting output and paste it into any online help request you make.
|
||||
|
||||
** Note: the Mac version of Calibre doesn't install the command line tools by default. If you go to the 'Preferences' page and click on the miscellaneous button, you'll see the option to install the command line tools.
|
||||
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
Inept PDF Plugin - ineptpdf_vXX_plugin.zip
|
||||
|
||||
Requires Calibre version 0.6.44 or higher.
|
||||
|
||||
|
||||
|
||||
All credit given to IHeartCabbages for the original standalone scripts.
|
||||
|
||||
I had the much easier job of converting them to a Calibre plugin.
|
||||
|
||||
|
||||
|
||||
This plugin is meant to decrypt Adobe Digital Edition PDFs that are protected with Adobe's Adept encryption. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. It will still work if you have Python, PyCrypto and/or OpenSSL already installed, but they aren't necessary.
|
||||
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" plugins, instead select "Change calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (ineptpdf_vXX_plugin.zip) and click the 'Add' button. you're done.
|
||||
|
||||
Please note: Calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
|
||||
|
||||
When first run, the plugin will attempt to find your Adobe Digital Editions installation (on Windows and Mac OS's). If successful, it will create an 'adeptkey.der' file and save it in Calibre's configuration directory. It will use that file on subsequent runs. If there are already '*.der' files in the directory, the plugin won't attempt to
|
||||
|
||||
find the Adobe Digital Editions installation installation.
|
||||
|
||||
|
||||
|
||||
So if you have Adobe Digital Editions installation installed on the same machine as Calibre... you are ready to go. If not... keep reading.
|
||||
Inept PDF Plugin - ineptpdf_v01.5_plugin.zip
|
||||
|
||||
All credit given to I♥Cabbages for the original standalone scripts.
|
||||
I had the much easier job of converting them to a Calibre plugin.
|
||||
|
||||
This plugin is meant to decrypt Adobe Digital Edition PDFs that are protected with Adobe's Adept encryption. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. It will still work if you have Python, PyCrypto and/or OpenSSL already installed, but they aren't necessary.
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" plugins, instead select "Change calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (ineptpdf_vXX_plugin.zip) and click the 'Add' button. you're done.
|
||||
|
||||
Please note: Calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
When first run, the plugin will attempt to find your Adobe Digital Editions installation (on Windows and Mac OS's). If successful, it will create an 'adeptkey.der' file and save it in Calibre's configuration directory. It will use that file on subsequent runs. If there are already '*.der' files in the directory, the plugin won't attempt to find the Adobe Digital Editions installation installation.
|
||||
|
||||
So if you have Adobe Digital Editions installation installed on the same machine as Calibre... you are ready to go. If not... keep reading.
|
||||
|
||||
If you already have keyfiles generated with I <3 Cabbages' ineptkey.pyw script, you can put those keyfiles in Calibre's configuration directory. The easiest way to find the correct directory is to go to Calibre's Preferences page... click on the 'Miscellaneous' button (looks like a gear), and then click the 'Open Calibre configuration directory' button. Paste your keyfiles in there. Just make sure that
|
||||
they have different names and are saved with the '.der' extension (like the ineptkey script produces). This directory isn't touched when upgrading Calibre, so it's quite safe to leave them there.
|
||||
|
||||
Since there is no Linux version of Adobe Digital Editions, Linux users will have to obtain a keyfile through other methods and put the file in Calibre's configuration directory.
|
||||
|
||||
All keyfiles with a '.der' extension found in Calibre's configuration directory will be used to attempt to decrypt a book.
|
||||
|
||||
** NOTE ** There is no plugin customization data for the Inept PDF plugin.
|
||||
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
If you find that it's not working for you (imported PDFs still have DRM), you can save a lot of time and trouble by trying to add the PDF to Calibre with the command line tools. This will print out a lot of helpful debugging info that can be copied into any online help requests. I'm going to ask you to do it first, anyway, so you might as well get used to it. ;)
|
||||
|
||||
Open a command prompt (terminal) and change to the directory where the ebook you're trying to import resides. Then type the command "calibredb add your_ebook.pdf". Don't type the quotes and obviously change the 'your_ebook.pdf' to whatever the filename of your book is. Copy the resulting output and paste it into any online help request you make.
|
||||
|
||||
** Note: the Mac version of Calibre doesn't install the command line tools by default. If you go to the 'Preferences' page and click on the miscellaneous button, you'll see the option to install the command line tools.
|
||||
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
Plugin for K4PC, K4Mac, standalone Kindles, Mobi Books, and for Devices with Fixed PIDs.
|
||||
|
||||
This plugin supersedes MobiDeDRM, K4DeDRM, and K4PCDeDRM and K4X plugins. If you install this plugin, those plugins can be safely removed.
|
||||
|
||||
|
||||
|
||||
This plugin is meant to remove the DRM from .prc, .azw, .azw1, and .tpz ebooks. Calibre can then convert them to whatever format you desire. It is meant to function without having to install any dependencies except for Calibre being on your same machine and in the same account as your "Kindle for PC" or "Kindle for Mac" application if you are going to remove the DRM from those types of books.
|
||||
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get Plugins to enhance calibre" as this is reserved for official calibre plugins", instead select "Change calibre behavior". Under "Advanced" click on the on the Plugins button. Click on the "Load plugin from file" button at the bottom of the screen. Use the file dialog button to select the plugin's zip file (K4MobiDeDRM_vXX_plugin.zip) and click the "Add" (or it may say "Open" button. Then click on the "Yes" button in the warning dialog that appears. A Confirmation dialog appears that says the plugin has been installed.
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
Highlight the plugin (K4MobiDeDRM under the "File type plugins" category) and click the "Customize Plugin" button on Calibre's Preferences->Plugins page. Enter your 10 digit PID. If you have more than one PID separate them with a comma (no spaces). If you have a standalone Kindle include the 16 digit serial number (these typically begin "B0...") in this list (again separated from the PIDs or other serial numbers with a comma (no spaces). This configuration is not needed if you only want to decode "Kindle for PC" or "Kindle for Mac" books.
|
||||
|
||||
|
||||
|
||||
Troubleshooting:
|
||||
K4MobiDeDRM_v04.4_plugin.zip
|
||||
|
||||
Credit given to The Dark Reverser for the original standalone script. Credit also to the many people who have updated and expanded that script since then.
|
||||
|
||||
Plugin for K4PC, K4Mac, eInk Kindles and Mobipocket.
|
||||
|
||||
This plugin supersedes MobiDeDRM, K4DeDRM, and K4PCDeDRM and K4X plugins. If you install this plugin, those plugins can be safely removed.
|
||||
|
||||
This plugin is meant to remove the DRM from .prc, .mobi, .azw, .azw1, .azw3, .azw4 and .tpz ebooks. Calibre can then convert them to whatever format you desire. It is meant to function without having to install any dependencies except for Calibre being on your same machine and in the same account as your "Kindle for PC" or "Kindle for Mac" application if you are going to remove the DRM from those types of books.
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get Plugins to enhance calibre" as this is reserved for official calibre plugins", instead select "Change calibre behavior". Under "Advanced" click on the on the Plugins button. Click on the "Load plugin from file" button at the bottom of the screen. Use the file dialog button to select the plugin's zip file (K4MobiDeDRM_vXX_plugin.zip) and click the "Add" (or it may say "Open" button. Then click on the "Yes" button in the warning dialog that appears. A Confirmation dialog appears that says the plugin has been installed.
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
Highlight the plugin (K4MobiDeDRM under the "File type plugins" category) and click the "Customize Plugin" button on Calibre's Preferences->Plugins page. If you have an eInk Kindle enter the 16 digit serial number (these typically begin "B0..."). If you have more than one eInk Kindle, you can enter multiple serial numbers separated by commas (no spaces). If you have Mobipocket books, enter your 10 digit PID. If you have more than one PID, separate them with commax (no spaces).
|
||||
|
||||
This configuration step is not needed if you only want to decode "Kindle for PC" or "Kindle for Mac" books.
|
||||
|
||||
|
||||
Linux Systems Only:
|
||||
|
||||
If you install Kindle for PC in Wine, the plugin should be able to decode files from that Kindle for PC installation under Wine. You might need to enter a Wine Prefix if it's not already set in your Environment variables.
|
||||
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
If you find that it's not working for you, you can save a lot of time and trouble by trying to add the DRMed ebook to Calibre with the command line tools. This will print out a lot of helpful debugging info that can be copied into any online help requests. I'm going to ask you to do it first, anyway, so you might as well get used to it. ;)
|
||||
|
||||
Open a command prompt (terminal) and change to the directory where the ebook you're trying to import resides. Then type the command "calibredb add your_ebook_file". Don't type the quotes and obviously change the 'your_ebook_file' to whatever the filename of your book is (including any file name extension like .azw). Copy the resulting output and paste it into any online help request you make.
|
||||
|
||||
** Note: the Mac version of Calibre doesn't install the command line tools by default. If you go to the 'Preferences' page and click on the miscellaneous button, you'll see the option to install the command line tools.
|
||||
|
||||
|
||||
|
||||
@@ -15,16 +15,16 @@ import re
|
||||
from zipfile import ZipFile
|
||||
|
||||
class K4DeDRM(FileTypePlugin):
|
||||
name = 'K4PC, K4Mac, Kindle Mobi and Topaz DeDRM' # Name of the plugin
|
||||
description = 'Removes DRM from Mobipocket, Kindle/Mobi, Kindle/Topaz and Kindle/Print Replica files. Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.'
|
||||
name = 'Kindle and Mobipocket DeDRM' # Name of the plugin
|
||||
description = 'Removes DRM from eInk Kindle, Kindle 4 Mac and Kindle 4 PC ebooks, and from Mobipocket ebooks. Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, mdlnx, ApprenticeAlf, etc.'
|
||||
supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on
|
||||
author = 'DiapDealer, SomeUpdates' # The author of this plugin
|
||||
version = (0, 4, 2) # The version number of this plugin
|
||||
author = 'DiapDealer, SomeUpdates, mdlnx, Apprentice Alf' # The author of this plugin
|
||||
version = (0, 4, 4) # The version number of this plugin
|
||||
file_types = set(['prc','mobi','azw','azw1','azw3','azw4','tpz']) # The file types that this plugin will be applied to
|
||||
on_import = True # Run this plugin during the import
|
||||
priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm
|
||||
priority = 520 # run this plugin before earlier versions
|
||||
minimum_calibre_version = (0, 7, 55)
|
||||
|
||||
|
||||
def initialize(self):
|
||||
"""
|
||||
Dynamic modules can't be imported/loaded from a zipfile... so this routine
|
||||
@@ -39,7 +39,7 @@ class K4DeDRM(FileTypePlugin):
|
||||
elif isosx:
|
||||
names = ['libalfcrypto.dylib']
|
||||
else:
|
||||
names = ['libalfcrypto32.so','libalfcrypto64.so']
|
||||
names = ['libalfcrypto32.so','libalfcrypto64.so','alfcrypto.py','alfcrypto.dll','alfcrypto64.dll','getk4pcpids.py','mobidedrm.py','kgenpids.py','k4pcutils.py','topazextract.py']
|
||||
lib_dict = self.load_resources(names)
|
||||
self.alfdir = os.path.join(config_dir, 'alfcrypto')
|
||||
if not os.path.exists(self.alfdir):
|
||||
@@ -62,35 +62,45 @@ class K4DeDRM(FileTypePlugin):
|
||||
|
||||
plug_ver = '.'.join(str(self.version).strip('()').replace(' ', '').split(','))
|
||||
k4 = True
|
||||
if sys.platform.startswith('linux'):
|
||||
k4 = False
|
||||
pids = []
|
||||
serials = []
|
||||
kInfoFiles = []
|
||||
self.config()
|
||||
|
||||
# Get supplied list of PIDs to try from plugin customization.
|
||||
customvalues = self.site_customization.split(',')
|
||||
for customvalue in customvalues:
|
||||
customvalue = str(customvalue)
|
||||
customvalue = customvalue.strip()
|
||||
if len(customvalue) == 10 or len(customvalue) == 8:
|
||||
pids.append(customvalue)
|
||||
else :
|
||||
if len(customvalue) == 16 and customvalue[0] == 'B':
|
||||
serials.append(customvalue)
|
||||
else:
|
||||
print "%s is not a valid Kindle serial number or PID." % str(customvalue)
|
||||
|
||||
pidstringlistt = self.pids_string.split(',')
|
||||
for pid in pidstringlistt:
|
||||
pid = str(pid).strip()
|
||||
if len(pid) == 10 or len(pid) == 8:
|
||||
pids.append(pid)
|
||||
else:
|
||||
if len(pid) > 0:
|
||||
print "'%s' is not a valid Mobipocket PID." % pid
|
||||
|
||||
# For linux, get PIDs by calling the right routines under WINE
|
||||
if sys.platform.startswith('linux'):
|
||||
k4 = False
|
||||
pids.extend(self.WINEgetPIDs(path_to_ebook))
|
||||
|
||||
# Get supplied list of Kindle serial numbers to try from plugin customization.
|
||||
serialstringlistt = self.serials_string.split(',')
|
||||
for serial in serialstringlistt:
|
||||
serial = str(serial).strip()
|
||||
if len(serial) == 16 and serial[0] == 'B':
|
||||
serials.append(serial)
|
||||
else:
|
||||
if len(serial) > 0:
|
||||
print "'%s' is not a valid Kindle serial number." % serial
|
||||
|
||||
# Load any kindle info files (*.info) included Calibre's config directory.
|
||||
try:
|
||||
# Find Calibre's configuration directory.
|
||||
confpath = os.path.split(os.path.split(self.plugin_path)[0])[0]
|
||||
print 'K4MobiDeDRM v%s: Calibre configuration directory = %s' % (plug_ver, confpath)
|
||||
files = os.listdir(confpath)
|
||||
print 'K4MobiDeDRM v%s: Calibre configuration directory = %s' % (plug_ver, config_dir)
|
||||
files = os.listdir(config_dir)
|
||||
filefilter = re.compile("\.info$|\.kinf$", re.IGNORECASE)
|
||||
files = filter(filefilter.search, files)
|
||||
if files:
|
||||
for filename in files:
|
||||
fpath = os.path.join(confpath, filename)
|
||||
fpath = os.path.join(config_dir, filename)
|
||||
kInfoFiles.append(fpath)
|
||||
print 'K4MobiDeDRM v%s: Kindle info/kinf file %s found in config folder.' % (plug_ver, filename)
|
||||
except IOError:
|
||||
@@ -152,8 +162,77 @@ class K4DeDRM(FileTypePlugin):
|
||||
mb.cleanup()
|
||||
return of.name
|
||||
|
||||
def customization_help(self, gui=False):
|
||||
return 'Enter 10 character PIDs and/or Kindle serial numbers, use a comma (no spaces) to separate each PID or SerialNumber from the next.'
|
||||
def WINEgetPIDs(self, infile):
|
||||
|
||||
import subprocess
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
import subasyncio
|
||||
from subasyncio import Process
|
||||
|
||||
print " Getting PIDs from WINE"
|
||||
|
||||
outfile = os.path.join(self.alfdir + 'winepids.txt')
|
||||
|
||||
cmdline = 'wine python.exe ' \
|
||||
+ '"'+self.alfdir + '/getk4pcpids.py"' \
|
||||
+ ' "' + infile + '"' \
|
||||
+ ' "' + outfile + '"'
|
||||
|
||||
env = os.environ
|
||||
|
||||
print "My wine_prefix from tweaks is ", self.wine_prefix
|
||||
|
||||
if ("WINEPREFIX" in env):
|
||||
print "Using WINEPREFIX from the environment: ", env["WINEPREFIX"]
|
||||
elif (self.wine_prefix is not None):
|
||||
env['WINEPREFIX'] = self.wine_prefix
|
||||
print "Using WINEPREFIX from tweaks: ", self.wine_prefix
|
||||
else:
|
||||
print "No wine prefix used"
|
||||
|
||||
print cmdline
|
||||
|
||||
cmdline = cmdline.encode(sys.getfilesystemencoding())
|
||||
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
|
||||
result = p2.wait("wait")
|
||||
print "Conversion returned ", result
|
||||
WINEpids = []
|
||||
customvalues = file(outfile, 'r').readline().split(',')
|
||||
for customvalue in customvalues:
|
||||
customvalue = str(customvalue)
|
||||
customvalue = customvalue.strip()
|
||||
if len(customvalue) == 10 or len(customvalue) == 8:
|
||||
WINEpids.append(customvalue)
|
||||
else:
|
||||
print "'%s' is not a valid PID." % customvalue
|
||||
return WINEpids
|
||||
|
||||
def is_customizable(self):
|
||||
# return true to allow customization via the Plugin->Preferences.
|
||||
return True
|
||||
|
||||
def config_widget(self):
|
||||
# It is important to put this import statement here rather than at the
|
||||
# top of the module as importing the config class will also cause the
|
||||
# GUI libraries to be loaded, which we do not want when using calibre
|
||||
# from the command line
|
||||
from calibre_plugins.k4mobidedrm.config import ConfigWidget
|
||||
return config.ConfigWidget()
|
||||
|
||||
def config(self):
|
||||
from calibre_plugins.k4mobidedrm.config import prefs
|
||||
|
||||
self.pids_string = prefs['pids']
|
||||
self.serials_string = prefs['serials']
|
||||
self.wine_prefix = prefs['WINEPREFIX']
|
||||
|
||||
def save_settings(self, config_widget):
|
||||
'''
|
||||
Save the settings specified by the user with config_widget.
|
||||
'''
|
||||
config_widget.save_settings()
|
||||
self.config()
|
||||
|
||||
def load_resources(self, names):
|
||||
ans = {}
|
||||
@@ -161,4 +240,4 @@ class K4DeDRM(FileTypePlugin):
|
||||
for candidate in zf.namelist():
|
||||
if candidate in names:
|
||||
ans[candidate] = zf.read(candidate)
|
||||
return ans
|
||||
return ans
|
||||
|
||||
59
Calibre_Plugins/K4MobiDeDRM_plugin/config.py
Normal file
59
Calibre_Plugins/K4MobiDeDRM_plugin/config.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from PyQt4.Qt import QWidget, QVBoxLayout, QLabel, QLineEdit
|
||||
|
||||
from calibre.utils.config import JSONConfig
|
||||
|
||||
# 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
|
||||
prefs = JSONConfig('plugins/K4MobiDeDRM')
|
||||
|
||||
# Set defaults
|
||||
prefs.defaults['pids'] = ""
|
||||
prefs.defaults['serials'] = ""
|
||||
prefs.defaults['WINEPREFIX'] = None
|
||||
|
||||
|
||||
class ConfigWidget(QWidget):
|
||||
|
||||
def __init__(self):
|
||||
QWidget.__init__(self)
|
||||
self.l = QVBoxLayout()
|
||||
self.setLayout(self.l)
|
||||
|
||||
self.serialLabel = QLabel('Kindle Serial numbers (separate with commas, no spaces)')
|
||||
self.l.addWidget(self.serialLabel)
|
||||
|
||||
self.serials = QLineEdit(self)
|
||||
self.serials.setText(prefs['serials'])
|
||||
self.l.addWidget(self.serials)
|
||||
self.serialLabel.setBuddy(self.serials)
|
||||
|
||||
self.pidLabel = QLabel('Mobipocket PIDs (separate with commas, no spaces)')
|
||||
self.l.addWidget(self.pidLabel)
|
||||
|
||||
self.pids = QLineEdit(self)
|
||||
self.pids.setText(prefs['pids'])
|
||||
self.l.addWidget(self.pids)
|
||||
self.pidLabel.setBuddy(self.serials)
|
||||
|
||||
self.wpLabel = QLabel('For Linux only: WINEPREFIX (enter absolute path)')
|
||||
self.l.addWidget(self.wpLabel)
|
||||
|
||||
self.wineprefix = QLineEdit(self)
|
||||
wineprefix = prefs['WINEPREFIX']
|
||||
if wineprefix is not None:
|
||||
self.wineprefix.setText(wineprefix)
|
||||
else:
|
||||
self.wineprefix.setText('')
|
||||
|
||||
self.l.addWidget(self.wineprefix)
|
||||
self.wpLabel.setBuddy(self.wineprefix)
|
||||
|
||||
def save_settings(self):
|
||||
prefs['pids'] = str(self.pids.text())
|
||||
prefs['serials'] = str(self.serials.text())
|
||||
winepref=str(self.wineprefix.text())
|
||||
if winepref.strip() != '':
|
||||
prefs['WINEPREFIX'] = winepref
|
||||
else:
|
||||
prefs['WINEPREFIX'] = None
|
||||
@@ -214,6 +214,7 @@ class PageParser(object):
|
||||
'links.title' : (1, 'text', 0, 0),
|
||||
'links.href' : (1, 'text', 0, 0),
|
||||
'links.type' : (1, 'text', 0, 0),
|
||||
'links.id' : (1, 'number', 0, 0),
|
||||
|
||||
'paraCont' : (0, 'number', 1, 1),
|
||||
'paraCont.rootID' : (1, 'number', 0, 0),
|
||||
@@ -239,6 +240,7 @@ class PageParser(object):
|
||||
'group' : (1, 'snippets', 1, 0),
|
||||
'group.type' : (1, 'scalar_text', 0, 0),
|
||||
'group._tag' : (1, 'scalar_text', 0, 0),
|
||||
'group.orientation': (1, 'scalar_text', 0, 0),
|
||||
|
||||
'region' : (1, 'snippets', 1, 0),
|
||||
'region.type' : (1, 'scalar_text', 0, 0),
|
||||
@@ -246,7 +248,7 @@ class PageParser(object):
|
||||
'region.y' : (1, 'scalar_number', 0, 0),
|
||||
'region.h' : (1, 'scalar_number', 0, 0),
|
||||
'region.w' : (1, 'scalar_number', 0, 0),
|
||||
'region.orientation' : (1, 'scalar_number', 0, 0),
|
||||
'region.orientation' : (1, 'scalar_text', 0, 0),
|
||||
|
||||
'empty_text_region' : (1, 'snippets', 1, 0),
|
||||
|
||||
|
||||
77
Calibre_Plugins/K4MobiDeDRM_plugin/getk4pcpids.py
Normal file
77
Calibre_Plugins/K4MobiDeDRM_plugin/getk4pcpids.py
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# This is a python script. You need a Python interpreter to run it.
|
||||
# For example, ActiveState Python, which exists for windows.
|
||||
#
|
||||
# Changelog
|
||||
# 1.00 - Initial version
|
||||
|
||||
__version__ = '1.00'
|
||||
|
||||
import sys
|
||||
|
||||
class Unbuffered:
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
def write(self, data):
|
||||
self.stream.write(data)
|
||||
self.stream.flush()
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self.stream, attr)
|
||||
sys.stdout=Unbuffered(sys.stdout)
|
||||
|
||||
import os
|
||||
import struct
|
||||
import binascii
|
||||
import kgenpids
|
||||
import topazextract
|
||||
import mobidedrm
|
||||
from alfcrypto import Pukall_Cipher
|
||||
|
||||
class DrmException(Exception):
|
||||
pass
|
||||
|
||||
def getK4PCpids(path_to_ebook):
|
||||
# Return Kindle4PC PIDs. Assumes that the caller checked that we are not on Linux, which will raise an exception
|
||||
|
||||
mobi = True
|
||||
magic3 = file(path_to_ebook,'rb').read(3)
|
||||
if magic3 == 'TPZ':
|
||||
mobi = False
|
||||
|
||||
if mobi:
|
||||
mb = mobidedrm.MobiBook(path_to_ebook,False)
|
||||
else:
|
||||
mb = topazextract.TopazBook(path_to_ebook)
|
||||
|
||||
md1, md2 = mb.getPIDMetaInfo()
|
||||
|
||||
return kgenpids.getPidList(md1, md2, True, [], [], [])
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
print ('getk4pcpids.py v%(__version__)s. '
|
||||
'Copyright 2012 Apprentic Alf' % globals())
|
||||
|
||||
if len(argv)<2 or len(argv)>3:
|
||||
print "Gets the possible book-specific PIDs from K4PC for a particular book"
|
||||
print "Usage:"
|
||||
print " %s <bookfile> [<outfile>]" % sys.argv[0]
|
||||
return 1
|
||||
else:
|
||||
infile = argv[1]
|
||||
try:
|
||||
pidlist = getK4PCpids(infile)
|
||||
except DrmException, e:
|
||||
print "Error: %s" % e
|
||||
return 1
|
||||
pidstring = ','.join(pidlist)
|
||||
print "Possible PIDs are: ", pidstring
|
||||
if len(argv) is 3:
|
||||
outfile = argv[2]
|
||||
file(outfile, 'w').write(pidstring)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -17,7 +17,7 @@ from __future__ import with_statement
|
||||
# and many many others
|
||||
|
||||
|
||||
__version__ = '4.2'
|
||||
__version__ = '4.3'
|
||||
|
||||
class Unbuffered:
|
||||
def __init__(self, stream):
|
||||
@@ -58,7 +58,7 @@ else:
|
||||
# borrowed from calibre from calibre/src/calibre/__init__.py
|
||||
# added in removal of non-printing chars
|
||||
# and removal of . at start
|
||||
# convert spaces to underscores
|
||||
# convert underscores to spaces (we're OK with spaces in file names)
|
||||
def cleanup_name(name):
|
||||
_filename_sanitize = re.compile(r'[\xae\0\\|\?\*<":>\+/]')
|
||||
substitute='_'
|
||||
@@ -73,7 +73,7 @@ def cleanup_name(name):
|
||||
# Mac and Unix don't like file names that begin with a full stop
|
||||
if len(one) > 0 and one[0] == '.':
|
||||
one = substitute+one[1:]
|
||||
one = one.replace(' ','_')
|
||||
one = one.replace('_',' ')
|
||||
return one
|
||||
|
||||
def decryptBook(infile, outdir, k4, kInfoFiles, serials, pids):
|
||||
@@ -99,11 +99,20 @@ def decryptBook(infile, outdir, k4, kInfoFiles, serials, pids):
|
||||
title = mb.getBookTitle()
|
||||
print "Processing Book: ", title
|
||||
filenametitle = cleanup_name(title)
|
||||
outfilename = bookname
|
||||
if len(outfilename)<=8 or len(filenametitle)<=8:
|
||||
outfilename = outfilename + "_" + filenametitle
|
||||
elif outfilename[:8] != filenametitle[:8]:
|
||||
outfilename = outfilename[:8] + "_" + filenametitle
|
||||
outfilename = cleanup_name(bookname)
|
||||
|
||||
# generate 'sensible' filename, that will sort with the original name,
|
||||
# but is close to the name from the file.
|
||||
outlength = len(outfilename)
|
||||
comparelength = min(8,min(outlength,len(filenametitle)))
|
||||
copylength = min(max(outfilename.find(' '),8),len(outfilename))
|
||||
if outlength==0:
|
||||
outfilename = filenametitle
|
||||
elif comparelength > 0:
|
||||
if outfilename[:comparelength] == filenametitle[:comparelength]:
|
||||
outfilename = filenametitle
|
||||
else:
|
||||
outfilename = outfilename[:copylength] + " " + filenametitle
|
||||
|
||||
# avoid excessively long file names
|
||||
if len(outfilename)>150:
|
||||
|
||||
@@ -262,9 +262,15 @@ def getPidList(md1, md2, k4, pids, serials, kInfoFiles):
|
||||
if k4:
|
||||
kInfoFiles = getKindleInfoFiles(kInfoFiles)
|
||||
for infoFile in kInfoFiles:
|
||||
pidlst = getK4Pids(pidlst, md1, md2, infoFile)
|
||||
try:
|
||||
pidlst = getK4Pids(pidlst, md1, md2, infoFile)
|
||||
except Exception, message:
|
||||
print("Error getting PIDs from " + infoFile + ": " + message)
|
||||
for serialnum in serials:
|
||||
pidlst = getKindlePid(pidlst, md1, md2, serialnum)
|
||||
try:
|
||||
pidlst = getKindlePid(pidlst, md1, md2, serialnum)
|
||||
except Exception, message:
|
||||
print("Error getting PIDs from " + serialnum + ": " + message)
|
||||
for pid in pids:
|
||||
pidlst.append(pid)
|
||||
return pidlst
|
||||
|
||||
@@ -164,6 +164,9 @@ class DocParser(object):
|
||||
scale = self.pw
|
||||
elif attr == 'line-space':
|
||||
scale = self.fontsize * 2.0
|
||||
|
||||
if val == "":
|
||||
val = 0
|
||||
|
||||
if not ((attr == 'hang') and (int(val) == 0)) :
|
||||
pv = float(val)/scale
|
||||
|
||||
@@ -31,11 +31,8 @@ class TpzDRMError(Exception):
|
||||
# local support routines
|
||||
if inCalibre:
|
||||
from calibre_plugins.k4mobidedrm import kgenpids
|
||||
from calibre_plugins.k4mobidedrm import genbook
|
||||
else:
|
||||
import kgenpids
|
||||
import genbook
|
||||
|
||||
|
||||
# recursive zip creation support routine
|
||||
def zipUpDir(myzip, tdir, localname):
|
||||
@@ -271,6 +268,11 @@ class TopazBook:
|
||||
self.createBookDirectory()
|
||||
self.extractFiles()
|
||||
print "Successfully Extracted Topaz contents"
|
||||
if inCalibre:
|
||||
from calibre_plugins.k4mobidedrm import genbook
|
||||
else:
|
||||
import genbook
|
||||
|
||||
rv = genbook.generateBook(self.outdir, raw, fixedimage)
|
||||
if rv == 0:
|
||||
print "\nBook Successfully generated"
|
||||
@@ -300,6 +302,11 @@ class TopazBook:
|
||||
self.createBookDirectory()
|
||||
self.extractFiles()
|
||||
print "Successfully Extracted Topaz contents"
|
||||
if inCalibre:
|
||||
from calibre_plugins.k4mobidedrm import genbook
|
||||
else:
|
||||
import genbook
|
||||
|
||||
rv = genbook.generateBook(self.outdir, raw, fixedimage)
|
||||
if rv == 0:
|
||||
print "\nBook Successfully generated"
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
eReader PDB2PML - eReaderPDB2PML_vXX_plugin.zip
|
||||
|
||||
|
||||
|
||||
All credit given to The Dark Reverser for the original standalone script. I had the much easier job of converting it to a Calibre plugin.
|
||||
|
||||
|
||||
|
||||
This plugin is meant to convert secure Ereader files (PDB) to unsecured PMLZ files. Calibre can then convert it to whatever format you desire. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. I've included the psyco libraries (compiled for each platform) for speed. If your system can use them, great! Otherwise, they won't be used and things will just work slower.
|
||||
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get Plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Change calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (eReaderPDB2PML_vXX_plugin.zip) and click the 'Add' button. You're done.
|
||||
|
||||
Please note: Calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
Highlight the plugin (eReader PDB 2 PML under the "File type plugins" category) and click the "Customize Plugin" button on Calibre's Preferences->Plugins page. Enter your name and last 8 digits of the credit card number separated by a comma: Your Name,12341234
|
||||
eReader PDB2PML - eReaderPDB2PML_v06_plugin.zip
|
||||
|
||||
All credit given to The Dark Reverser for the original standalone script. I had the much easier job of converting it to a Calibre plugin.
|
||||
|
||||
This plugin is meant to convert secure Ereader files (PDB) to unsecured PMLZ files. Calibre can then convert it to whatever format you desire. It is meant to function without having to install any dependencies... other than having Calibre installed, of course. I've included the psyco libraries (compiled for each platform) for speed. If your system can use them, great! Otherwise, they won't be used and things will just work slower.
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
Go to Calibre's Preferences page. Do **NOT** select "Get Plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Change calibre behavior". Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (eReaderPDB2PML_vXX_plugin.zip) and click the 'Add' button. You're done.
|
||||
|
||||
|
||||
Please note: Calibre does not provide any immediate feedback to indicate that adding the plugin was a success. You can always click on the File-Type plugins to see if the plugin was added.
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
Highlight the plugin (eReader PDB 2 PML under the "File type plugins" category) and click the "Customize Plugin" button on Calibre's Preferences->Plugins page. Enter your name and last 8 digits of the credit card number separated by a comma: Your Name,12341234
|
||||
|
||||
If you've purchased books with more than one credit card, separate the info with a colon: Your Name,12341234:Other Name,23452345 (NOTE: Do NOT put quotes around your name like you do with the original script!!)
|
||||
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
If you find that it's not working for you (imported pdb's are not converted to pmlz format), you can save a lot of time and trouble by trying to add the pdb to Calibre with the command line tools. This will print out a lot of helpful debugging info that can be copied into any online help requests. I'm going to ask you to do it first, anyway, so you might as well get used to it. ;)
|
||||
|
||||
Open a command prompt (terminal) and change to the directory where the ebook you're trying to import resides. Then type the command "calibredb add your_ebook.pdb". Don't type the quotes and obviously change the 'your_ebook.pdb' to whatever the filename of your book is. Copy the resulting output and paste it into any online help request you make.
|
||||
|
||||
** Note: the Mac version of Calibre doesn't install the command line tools by default. If you go to the 'Preferences' page and click on the miscellaneous button, you'll see the option to install the command line tools.
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,8 @@
|
||||
#! /usr/bin/env python
|
||||
# ineptpdf plugin __init__.py, version 0.1.5
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
# ineptpdf plugin __init__.py
|
||||
# Released under the terms of the GNU General Public Licence, version 3 or
|
||||
# later. <http://www.gnu.org/licenses/>
|
||||
|
||||
@@ -52,13 +54,11 @@
|
||||
# 0.1.2 - back port ineptpdf 8.4.X bug fixes
|
||||
# 0.1.3 - add in fix for improper rejection of session bookkeys with len(bookkey) = length + 1
|
||||
# 0.1.4 - update to the new calibre plugin interface
|
||||
|
||||
# 0.1.5 - synced to ineptpdf 7.11
|
||||
"""
|
||||
Decrypts Adobe ADEPT-encrypted PDF files.
|
||||
"""
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
|
||||
import sys
|
||||
@@ -116,13 +116,13 @@ def _load_crypto_libcrypto():
|
||||
class RSA(Structure):
|
||||
pass
|
||||
RSA_p = POINTER(RSA)
|
||||
|
||||
|
||||
def F(restype, name, argtypes):
|
||||
func = getattr(libcrypto, name)
|
||||
func.restype = restype
|
||||
func.argtypes = argtypes
|
||||
return func
|
||||
|
||||
|
||||
AES_cbc_encrypt = F(None, 'AES_cbc_encrypt',[c_char_p, c_char_p, c_ulong, AES_KEY_p, c_char_p,c_int])
|
||||
AES_set_decrypt_key = F(c_int, 'AES_set_decrypt_key',[c_char_p, c_int, AES_KEY_p])
|
||||
|
||||
@@ -143,7 +143,7 @@ def _load_crypto_libcrypto():
|
||||
rsa = self._rsa = d2i_RSAPrivateKey(None, pp, len(der))
|
||||
if rsa is None:
|
||||
raise ADEPTError('Error parsing ADEPT user key DER')
|
||||
|
||||
|
||||
def decrypt(self, from_):
|
||||
rsa = self._rsa
|
||||
to = create_string_buffer(RSA_size(rsa))
|
||||
@@ -152,7 +152,7 @@ def _load_crypto_libcrypto():
|
||||
if dlen < 0:
|
||||
raise ADEPTError('RSA decryption failed')
|
||||
return to[1:dlen]
|
||||
|
||||
|
||||
def __del__(self):
|
||||
if self._rsa is not None:
|
||||
RSA_free(self._rsa)
|
||||
@@ -214,13 +214,13 @@ def _load_crypto_pycrypto():
|
||||
# ASN.1 parsing code from tlslite
|
||||
class ASN1Error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ASN1Parser(object):
|
||||
class Parser(object):
|
||||
def __init__(self, bytes):
|
||||
self.bytes = bytes
|
||||
self.index = 0
|
||||
|
||||
|
||||
def get(self, length):
|
||||
if self.index + length > len(self.bytes):
|
||||
raise ASN1Error("Error decoding ASN.1")
|
||||
@@ -230,22 +230,22 @@ def _load_crypto_pycrypto():
|
||||
x |= self.bytes[self.index]
|
||||
self.index += 1
|
||||
return x
|
||||
|
||||
|
||||
def getFixBytes(self, lengthBytes):
|
||||
bytes = self.bytes[self.index : self.index+lengthBytes]
|
||||
self.index += lengthBytes
|
||||
return bytes
|
||||
|
||||
|
||||
def getVarBytes(self, lengthLength):
|
||||
lengthBytes = self.get(lengthLength)
|
||||
return self.getFixBytes(lengthBytes)
|
||||
|
||||
|
||||
def getFixList(self, length, lengthList):
|
||||
l = [0] * lengthList
|
||||
for x in range(lengthList):
|
||||
l[x] = self.get(length)
|
||||
return l
|
||||
|
||||
|
||||
def getVarList(self, length, lengthLength):
|
||||
lengthList = self.get(lengthLength)
|
||||
if lengthList % length != 0:
|
||||
@@ -255,19 +255,19 @@ def _load_crypto_pycrypto():
|
||||
for x in range(lengthList):
|
||||
l[x] = self.get(length)
|
||||
return l
|
||||
|
||||
|
||||
def startLengthCheck(self, lengthLength):
|
||||
self.lengthCheck = self.get(lengthLength)
|
||||
self.indexCheck = self.index
|
||||
|
||||
|
||||
def setLengthCheck(self, length):
|
||||
self.lengthCheck = length
|
||||
self.indexCheck = self.index
|
||||
|
||||
|
||||
def stopLengthCheck(self):
|
||||
if (self.index - self.indexCheck) != self.lengthCheck:
|
||||
raise ASN1Error("Error decoding ASN.1")
|
||||
|
||||
|
||||
def atLengthCheck(self):
|
||||
if (self.index - self.indexCheck) < self.lengthCheck:
|
||||
return False
|
||||
@@ -275,13 +275,13 @@ def _load_crypto_pycrypto():
|
||||
return True
|
||||
else:
|
||||
raise ASN1Error("Error decoding ASN.1")
|
||||
|
||||
|
||||
def __init__(self, bytes):
|
||||
p = self.Parser(bytes)
|
||||
p.get(1)
|
||||
self.length = self._getASN1Length(p)
|
||||
self.value = p.getFixBytes(self.length)
|
||||
|
||||
|
||||
def getChild(self, which):
|
||||
p = self.Parser(self.value)
|
||||
for x in range(which+1):
|
||||
@@ -290,7 +290,7 @@ def _load_crypto_pycrypto():
|
||||
length = self._getASN1Length(p)
|
||||
p.getFixBytes(length)
|
||||
return ASN1Parser(p.bytes[markIndex:p.index])
|
||||
|
||||
|
||||
def _getASN1Length(self, p):
|
||||
firstLength = p.get(1)
|
||||
if firstLength<=127:
|
||||
@@ -311,6 +311,7 @@ def _load_crypto_pycrypto():
|
||||
return self._arc4.decrypt(data)
|
||||
|
||||
class AES(object):
|
||||
MODE_CBC = _AES.MODE_CBC
|
||||
@classmethod
|
||||
def new(cls, userkey, mode, iv):
|
||||
self = AES()
|
||||
@@ -333,7 +334,7 @@ def _load_crypto_pycrypto():
|
||||
for byte in bytes:
|
||||
total = (total << 8) + byte
|
||||
return total
|
||||
|
||||
|
||||
def decrypt(self, data):
|
||||
return self._rsa.decrypt(data)
|
||||
|
||||
@@ -426,7 +427,7 @@ class PSLiteral(PSObject):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
return
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
name = []
|
||||
for char in self.name:
|
||||
@@ -445,22 +446,22 @@ class PSKeyword(PSObject):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
return
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
# PSSymbolTable
|
||||
class PSSymbolTable(object):
|
||||
|
||||
|
||||
'''
|
||||
Symbol table that stores PSLiteral or PSKeyword.
|
||||
'''
|
||||
|
||||
|
||||
def __init__(self, classe):
|
||||
self.dic = {}
|
||||
self.classe = classe
|
||||
return
|
||||
|
||||
|
||||
def intern(self, name):
|
||||
if name in self.dic:
|
||||
lit = self.dic[name]
|
||||
@@ -530,11 +531,11 @@ class PSBaseParser(object):
|
||||
|
||||
def flush(self):
|
||||
return
|
||||
|
||||
|
||||
def close(self):
|
||||
self.flush()
|
||||
return
|
||||
|
||||
|
||||
def tell(self):
|
||||
return self.bufpos+self.charpos
|
||||
|
||||
@@ -570,7 +571,7 @@ class PSBaseParser(object):
|
||||
raise PSEOF('Unexpected EOF')
|
||||
self.charpos = 0
|
||||
return
|
||||
|
||||
|
||||
def parse_main(self, s, i):
|
||||
m = NONSPC.search(s, i)
|
||||
if not m:
|
||||
@@ -605,11 +606,11 @@ class PSBaseParser(object):
|
||||
return (self.parse_wclose, j+1)
|
||||
self.add_token(KWD(c))
|
||||
return (self.parse_main, j+1)
|
||||
|
||||
|
||||
def add_token(self, obj):
|
||||
self.tokens.append((self.tokenstart, obj))
|
||||
return
|
||||
|
||||
|
||||
def parse_comment(self, s, i):
|
||||
m = EOL.search(s, i)
|
||||
if not m:
|
||||
@@ -620,7 +621,7 @@ class PSBaseParser(object):
|
||||
# We ignore comments.
|
||||
#self.tokens.append(self.token)
|
||||
return (self.parse_main, j)
|
||||
|
||||
|
||||
def parse_literal(self, s, i):
|
||||
m = END_LITERAL.search(s, i)
|
||||
if not m:
|
||||
@@ -634,7 +635,7 @@ class PSBaseParser(object):
|
||||
return (self.parse_literal_hex, j+1)
|
||||
self.add_token(LIT(self.token))
|
||||
return (self.parse_main, j)
|
||||
|
||||
|
||||
def parse_literal_hex(self, s, i):
|
||||
c = s[i]
|
||||
if HEX.match(c) and len(self.hex) < 2:
|
||||
@@ -669,7 +670,7 @@ class PSBaseParser(object):
|
||||
self.token += s[i:j]
|
||||
self.add_token(float(self.token))
|
||||
return (self.parse_main, j)
|
||||
|
||||
|
||||
def parse_keyword(self, s, i):
|
||||
m = END_KEYWORD.search(s, i)
|
||||
if not m:
|
||||
@@ -817,7 +818,7 @@ class PSStackParser(PSBaseParser):
|
||||
PSBaseParser.__init__(self, fp)
|
||||
self.reset()
|
||||
return
|
||||
|
||||
|
||||
def reset(self):
|
||||
self.context = []
|
||||
self.curtype = None
|
||||
@@ -858,10 +859,10 @@ class PSStackParser(PSBaseParser):
|
||||
|
||||
def do_keyword(self, pos, token):
|
||||
return
|
||||
|
||||
|
||||
def nextobject(self, direct=False):
|
||||
'''
|
||||
Yields a list of objects: keywords, literals, strings,
|
||||
Yields a list of objects: keywords, literals, strings,
|
||||
numbers, arrays and dictionaries. Arrays and dictionaries
|
||||
are represented as Python sequence and dictionaries.
|
||||
'''
|
||||
@@ -930,7 +931,7 @@ class PDFNotImplementedError(PSException): pass
|
||||
## PDFObjRef
|
||||
##
|
||||
class PDFObjRef(PDFObject):
|
||||
|
||||
|
||||
def __init__(self, doc, objid, genno):
|
||||
if objid == 0:
|
||||
if STRICT:
|
||||
@@ -1045,25 +1046,25 @@ def stream_value(x):
|
||||
|
||||
# ascii85decode(data)
|
||||
def ascii85decode(data):
|
||||
n = b = 0
|
||||
out = ''
|
||||
for c in data:
|
||||
if '!' <= c and c <= 'u':
|
||||
n += 1
|
||||
b = b*85+(ord(c)-33)
|
||||
if n == 5:
|
||||
out += struct.pack('>L',b)
|
||||
n = b = 0
|
||||
elif c == 'z':
|
||||
assert n == 0
|
||||
out += '\0\0\0\0'
|
||||
elif c == '~':
|
||||
if n:
|
||||
for _ in range(5-n):
|
||||
b = b*85+84
|
||||
out += struct.pack('>L',b)[:n-1]
|
||||
break
|
||||
return out
|
||||
n = b = 0
|
||||
out = ''
|
||||
for c in data:
|
||||
if '!' <= c and c <= 'u':
|
||||
n += 1
|
||||
b = b*85+(ord(c)-33)
|
||||
if n == 5:
|
||||
out += struct.pack('>L',b)
|
||||
n = b = 0
|
||||
elif c == 'z':
|
||||
assert n == 0
|
||||
out += '\0\0\0\0'
|
||||
elif c == '~':
|
||||
if n:
|
||||
for _ in range(5-n):
|
||||
b = b*85+84
|
||||
out += struct.pack('>L',b)[:n-1]
|
||||
break
|
||||
return out
|
||||
|
||||
|
||||
## PDFStream type
|
||||
@@ -1080,7 +1081,7 @@ class PDFStream(PDFObject):
|
||||
else:
|
||||
if eol in ('\r', '\n', '\r\n'):
|
||||
rawdata = rawdata[:length]
|
||||
|
||||
|
||||
self.dic = dic
|
||||
self.rawdata = rawdata
|
||||
self.decipher = decipher
|
||||
@@ -1094,7 +1095,7 @@ class PDFStream(PDFObject):
|
||||
self.objid = objid
|
||||
self.genno = genno
|
||||
return
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
if self.rawdata:
|
||||
return '<PDFStream(%r): raw=%d, %r>' % \
|
||||
@@ -1178,7 +1179,7 @@ class PDFStream(PDFObject):
|
||||
data = self.decipher(self.objid, self.genno, data)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
## PDF Exceptions
|
||||
##
|
||||
class PDFSyntaxError(PDFException): pass
|
||||
@@ -1243,7 +1244,7 @@ class PDFXRef(object):
|
||||
self.offsets[objid] = (int(genno), int(pos))
|
||||
self.load_trailer(parser)
|
||||
return
|
||||
|
||||
|
||||
KEYWORD_TRAILER = PSKeywordTable.intern('trailer')
|
||||
def load_trailer(self, parser):
|
||||
try:
|
||||
@@ -1284,7 +1285,7 @@ class PDFXRefStream(object):
|
||||
for first, size in self.index:
|
||||
for objid in xrange(first, first + size):
|
||||
yield objid
|
||||
|
||||
|
||||
def load(self, parser, debug=0):
|
||||
(_,objid) = parser.nexttoken() # ignored
|
||||
(_,genno) = parser.nexttoken() # ignored
|
||||
@@ -1302,7 +1303,7 @@ class PDFXRefStream(object):
|
||||
self.entlen = self.fl1+self.fl2+self.fl3
|
||||
self.trailer = stream.dic
|
||||
return
|
||||
|
||||
|
||||
def getpos(self, objid):
|
||||
offset = 0
|
||||
for first, size in self.index:
|
||||
@@ -1353,7 +1354,7 @@ class PDFDocument(object):
|
||||
self.parser = parser
|
||||
# The document is set to be temporarily ready during collecting
|
||||
# all the basic information about the document, e.g.
|
||||
# the header, the encryption information, and the access rights
|
||||
# the header, the encryption information, and the access rights
|
||||
# for the document.
|
||||
self.ready = True
|
||||
# Retrieve the information of each header that was appended
|
||||
@@ -1429,7 +1430,7 @@ class PDFDocument(object):
|
||||
length = int_value(param.get('Length', 0)) / 8
|
||||
edcdata = str_value(param.get('EDCData')).decode('base64')
|
||||
pdrllic = str_value(param.get('PDRLLic')).decode('base64')
|
||||
pdrlpol = str_value(param.get('PDRLPol')).decode('base64')
|
||||
pdrlpol = str_value(param.get('PDRLPol')).decode('base64')
|
||||
edclist = []
|
||||
for pair in edcdata.split('\n'):
|
||||
edclist.append(pair)
|
||||
@@ -1449,9 +1450,9 @@ class PDFDocument(object):
|
||||
raise ADEPTError('Could not decrypt PDRLPol, aborting ...')
|
||||
else:
|
||||
cutter = -1 * ord(pdrlpol[-1])
|
||||
pdrlpol = pdrlpol[:cutter]
|
||||
pdrlpol = pdrlpol[:cutter]
|
||||
return plaintext[:16]
|
||||
|
||||
|
||||
PASSWORD_PADDING = '(\xbfN^Nu\x8aAd\x00NV\xff\xfa\x01\x08..' \
|
||||
'\x00\xb6\xd0h>\x80/\x0c\xa9\xfedSiz'
|
||||
# experimental aes pw support
|
||||
@@ -1471,14 +1472,14 @@ class PDFDocument(object):
|
||||
EncMetadata = str_value(param['EncryptMetadata'])
|
||||
except:
|
||||
EncMetadata = 'True'
|
||||
self.is_printable = bool(P & 4)
|
||||
self.is_printable = bool(P & 4)
|
||||
self.is_modifiable = bool(P & 8)
|
||||
self.is_extractable = bool(P & 16)
|
||||
self.is_annotationable = bool(P & 32)
|
||||
self.is_formsenabled = bool(P & 256)
|
||||
self.is_textextractable = bool(P & 512)
|
||||
self.is_assemblable = bool(P & 1024)
|
||||
self.is_formprintable = bool(P & 2048)
|
||||
self.is_formprintable = bool(P & 2048)
|
||||
# Algorithm 3.2
|
||||
password = (password+self.PASSWORD_PADDING)[:32] # 1
|
||||
hash = hashlib.md5(password) # 2
|
||||
@@ -1587,7 +1588,7 @@ class PDFDocument(object):
|
||||
hash = hashlib.md5(key)
|
||||
key = hash.digest()[:min(len(self.decrypt_key) + 5, 16)]
|
||||
return key
|
||||
|
||||
|
||||
def genkey_v3(self, objid, genno):
|
||||
objid = struct.pack('<L', objid ^ 0x3569ac)
|
||||
genno = struct.pack('<L', genno ^ 0xca96)
|
||||
@@ -1627,14 +1628,14 @@ class PDFDocument(object):
|
||||
#print cutter
|
||||
plaintext = plaintext[:cutter]
|
||||
return plaintext
|
||||
|
||||
|
||||
def decrypt_rc4(self, objid, genno, data):
|
||||
key = self.genkey(objid, genno)
|
||||
return ARC4.new(key).decrypt(data)
|
||||
|
||||
|
||||
KEYWORD_OBJ = PSKeywordTable.intern('obj')
|
||||
|
||||
|
||||
def getobj(self, objid):
|
||||
if not self.ready:
|
||||
raise PDFException('PDFDocument not initialized')
|
||||
@@ -1704,7 +1705,7 @@ class PDFDocument(object):
|
||||
## if x:
|
||||
## objid1 = x[-2]
|
||||
## genno = x[-1]
|
||||
##
|
||||
##
|
||||
if kwd is not self.KEYWORD_OBJ:
|
||||
raise PDFSyntaxError(
|
||||
'Invalid object spec: offset=%r' % index)
|
||||
@@ -1716,7 +1717,7 @@ class PDFDocument(object):
|
||||
self.objs[objid] = obj
|
||||
return obj
|
||||
|
||||
|
||||
|
||||
class PDFObjStmRef(object):
|
||||
maxindex = 0
|
||||
def __init__(self, objid, stmid, index):
|
||||
@@ -1726,7 +1727,7 @@ class PDFObjStmRef(object):
|
||||
if index > PDFObjStmRef.maxindex:
|
||||
PDFObjStmRef.maxindex = index
|
||||
|
||||
|
||||
|
||||
## PDFParser
|
||||
##
|
||||
class PDFParser(PSStackParser):
|
||||
@@ -1752,7 +1753,7 @@ class PDFParser(PSStackParser):
|
||||
if token is self.KEYWORD_ENDOBJ:
|
||||
self.add_results(*self.pop(4))
|
||||
return
|
||||
|
||||
|
||||
if token is self.KEYWORD_R:
|
||||
# reference to indirect object
|
||||
try:
|
||||
@@ -1763,7 +1764,7 @@ class PDFParser(PSStackParser):
|
||||
except PSSyntaxError:
|
||||
pass
|
||||
return
|
||||
|
||||
|
||||
if token is self.KEYWORD_STREAM:
|
||||
# stream object
|
||||
((_,dic),) = self.pop(1)
|
||||
@@ -1803,7 +1804,7 @@ class PDFParser(PSStackParser):
|
||||
obj = PDFStream(dic, data, self.doc.decipher)
|
||||
self.push((pos, obj))
|
||||
return
|
||||
|
||||
|
||||
# others
|
||||
self.push((pos, token))
|
||||
return
|
||||
@@ -1839,7 +1840,7 @@ class PDFParser(PSStackParser):
|
||||
xref.load(self)
|
||||
else:
|
||||
if token is not self.KEYWORD_XREF:
|
||||
raise PDFNoValidXRef('xref not found: pos=%d, token=%r' %
|
||||
raise PDFNoValidXRef('xref not found: pos=%d, token=%r' %
|
||||
(pos, token))
|
||||
self.nextline()
|
||||
xref = PDFXRef()
|
||||
@@ -1854,7 +1855,7 @@ class PDFParser(PSStackParser):
|
||||
pos = int_value(trailer['Prev'])
|
||||
self.read_xref_from(pos, xrefs)
|
||||
return
|
||||
|
||||
|
||||
# read xref tables and trailers
|
||||
def read_xref(self):
|
||||
xrefs = []
|
||||
@@ -1973,7 +1974,7 @@ class PDFSerializer(object):
|
||||
self.write("%010d 00000 n \n" % xrefs[objid][0])
|
||||
else:
|
||||
self.write("%010d %05d f \n" % (0, 65535))
|
||||
|
||||
|
||||
self.write('trailer\n')
|
||||
self.serialize_object(trailer)
|
||||
self.write('\nstartxref\n%d\n%%%%EOF' % startxref)
|
||||
@@ -1993,7 +1994,7 @@ class PDFSerializer(object):
|
||||
while maxindex >= power:
|
||||
fl3 += 1
|
||||
power *= 256
|
||||
|
||||
|
||||
index = []
|
||||
first = None
|
||||
prev = None
|
||||
@@ -2020,14 +2021,14 @@ class PDFSerializer(object):
|
||||
# we force all generation numbers to be 0
|
||||
# f3 = objref[1]
|
||||
f3 = 0
|
||||
|
||||
|
||||
data.append(struct.pack('>B', f1))
|
||||
data.append(struct.pack('>L', f2)[-fl2:])
|
||||
data.append(struct.pack('>L', f3)[-fl3:])
|
||||
index.extend((first, prev - first + 1))
|
||||
data = zlib.compress(''.join(data))
|
||||
dic = {'Type': LITERAL_XREF, 'Size': prev + 1, 'Index': index,
|
||||
'W': [1, fl2, fl3], 'Length': len(data),
|
||||
'W': [1, fl2, fl3], 'Length': len(data),
|
||||
'Filter': LITERALS_FLATE_DECODE[0],
|
||||
'Root': trailer['Root'],}
|
||||
if 'Info' in trailer:
|
||||
@@ -2049,9 +2050,9 @@ class PDFSerializer(object):
|
||||
string = string.replace(')', r'\)')
|
||||
# get rid of ciando id
|
||||
regularexp = re.compile(r'http://www.ciando.com/index.cfm/intRefererID/\d{5}')
|
||||
if regularexp.match(string): return ('http://www.ciando.com')
|
||||
if regularexp.match(string): return ('http://www.ciando.com')
|
||||
return string
|
||||
|
||||
|
||||
def serialize_object(self, obj):
|
||||
if isinstance(obj, dict):
|
||||
# Correct malformed Mac OS resource forks for Stanza
|
||||
@@ -2075,21 +2076,21 @@ class PDFSerializer(object):
|
||||
elif isinstance(obj, bool):
|
||||
if self.last.isalnum():
|
||||
self.write(' ')
|
||||
self.write(str(obj).lower())
|
||||
self.write(str(obj).lower())
|
||||
elif isinstance(obj, (int, long, float)):
|
||||
if self.last.isalnum():
|
||||
self.write(' ')
|
||||
self.write(str(obj))
|
||||
elif isinstance(obj, PDFObjRef):
|
||||
if self.last.isalnum():
|
||||
self.write(' ')
|
||||
self.write(' ')
|
||||
self.write('%d %d R' % (obj.objid, 0))
|
||||
elif isinstance(obj, PDFStream):
|
||||
### If we don't generate cross ref streams the object streams
|
||||
### are no longer useful, as we have extracted all objects from
|
||||
### them. Therefore leave them out from the output.
|
||||
if obj.dic.get('Type') == LITERAL_OBJSTM and not gen_xref_stm:
|
||||
self.write('(deleted)')
|
||||
self.write('(deleted)')
|
||||
else:
|
||||
data = obj.get_decdata()
|
||||
self.serialize_object(obj.dic)
|
||||
@@ -2101,7 +2102,7 @@ class PDFSerializer(object):
|
||||
if data[0].isalnum() and self.last.isalnum():
|
||||
self.write(' ')
|
||||
self.write(data)
|
||||
|
||||
|
||||
def serialize_indirect(self, objid, obj):
|
||||
self.write('%d 0 obj' % (objid,))
|
||||
self.serialize_object(obj)
|
||||
@@ -2136,7 +2137,7 @@ class IneptPDFDeDRM(FileTypePlugin):
|
||||
Credit given to I <3 Cabbages for the original stand-alone scripts.'
|
||||
supported_platforms = ['linux', 'osx', 'windows']
|
||||
author = 'DiapDealer'
|
||||
version = (0, 1, 4)
|
||||
version = (0, 1, 5)
|
||||
minimum_calibre_version = (0, 7, 55) # for the new plugin interface
|
||||
file_types = set(['pdf'])
|
||||
on_import = True
|
||||
|
||||
Binary file not shown.
@@ -385,17 +385,22 @@ def GetIDString():
|
||||
if isNewInstall():
|
||||
mungedmac = GetMACAddressMunged()
|
||||
if len(mungedmac) > 7:
|
||||
print('Using Munged MAC Address for ID: '+mungedmac)
|
||||
return mungedmac
|
||||
sernum = GetVolumeSerialNumber()
|
||||
if len(sernum) > 7:
|
||||
print('Using Volume Serial Number for ID: '+sernum)
|
||||
return sernum
|
||||
diskpart = GetUserHomeAppSupKindleDirParitionName()
|
||||
uuidnum = GetDiskPartitionUUID(diskpart)
|
||||
if len(uuidnum) > 7:
|
||||
print('Using Disk Partition UUID for ID: '+uuidnum)
|
||||
return uuidnum
|
||||
mungedmac = GetMACAddressMunged()
|
||||
if len(mungedmac) > 7:
|
||||
print('Using Munged MAC Address for ID: '+mungedmac)
|
||||
return mungedmac
|
||||
print('Using Fixed constant 9999999999 for ID.')
|
||||
return '9999999999'
|
||||
|
||||
|
||||
@@ -498,6 +503,7 @@ def getKindleInfoFiles(kInfoFiles):
|
||||
for resline in reslst:
|
||||
if os.path.isfile(resline):
|
||||
kInfoFiles.append(resline)
|
||||
print('Found K4Mac kindle-info file: ' + resline)
|
||||
found = True
|
||||
# add any .rainier*-kinf files
|
||||
cmdline = 'find "' + home + '/Library/Application Support" -name ".rainier*-kinf"'
|
||||
@@ -508,6 +514,7 @@ def getKindleInfoFiles(kInfoFiles):
|
||||
for resline in reslst:
|
||||
if os.path.isfile(resline):
|
||||
kInfoFiles.append(resline)
|
||||
print('Found k4Mac kinf file: ' + resline)
|
||||
found = True
|
||||
# add any .kinf2011 files
|
||||
cmdline = 'find "' + home + '/Library/Application Support" -name ".kinf2011"'
|
||||
@@ -518,9 +525,10 @@ def getKindleInfoFiles(kInfoFiles):
|
||||
for resline in reslst:
|
||||
if os.path.isfile(resline):
|
||||
kInfoFiles.append(resline)
|
||||
print('Found k4Mac kinf2011 file: ' + resline)
|
||||
found = True
|
||||
if not found:
|
||||
print('No kindle-info files have been found.')
|
||||
print('No k4Mac kindle-info/kinf/kinf2011 files have been found.')
|
||||
return kInfoFiles
|
||||
|
||||
# determine type of kindle info provided and return a
|
||||
|
||||
@@ -151,7 +151,9 @@ def GetVolumeSerialNumber():
|
||||
GetVolumeSerialNumber = GetVolumeSerialNumber()
|
||||
|
||||
def GetIDString():
|
||||
return GetVolumeSerialNumber()
|
||||
vsn = GetVolumeSerialNumber()
|
||||
print('Using Volume Serial Number for ID: '+vsn)
|
||||
return vsn
|
||||
|
||||
def getLastError():
|
||||
GetLastError = kernel32.GetLastError
|
||||
@@ -210,37 +212,40 @@ def getKindleInfoFiles(kInfoFiles):
|
||||
if 'LOCALAPPDATA' in os.environ.keys():
|
||||
path = os.environ['LOCALAPPDATA']
|
||||
|
||||
print "searching for kinfoFiles in ", path
|
||||
print('searching for kinfoFiles in ' + path)
|
||||
found = False
|
||||
|
||||
# first look for older kindle-info files
|
||||
kinfopath = path +'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info'
|
||||
if not os.path.isfile(kinfopath):
|
||||
print('No kindle.info files have not been found.')
|
||||
else:
|
||||
if os.path.isfile(kinfopath):
|
||||
found = True
|
||||
print('Found K4PC kindle.info file: ' + kinfopath)
|
||||
kInfoFiles.append(kinfopath)
|
||||
|
||||
# now look for newer (K4PC 1.5.0 and later rainier.2.1.1.kinf file
|
||||
|
||||
kinfopath = path +'\\Amazon\\Kindle For PC\\storage\\rainier.2.1.1.kinf'
|
||||
if not os.path.isfile(kinfopath):
|
||||
print('No K4PC 1.5.X .kinf files have not been found.')
|
||||
else:
|
||||
if os.path.isfile(kinfopath):
|
||||
found = True
|
||||
print('Found K4PC 1.5.X kinf file: ' + kinfopath)
|
||||
kInfoFiles.append(kinfopath)
|
||||
|
||||
# now look for even newer (K4PC 1.6.0 and later) rainier.2.1.1.kinf file
|
||||
kinfopath = path +'\\Amazon\\Kindle\\storage\\rainier.2.1.1.kinf'
|
||||
if not os.path.isfile(kinfopath):
|
||||
print('No K4PC 1.6.X .kinf files have not been found.')
|
||||
else:
|
||||
if os.path.isfile(kinfopath):
|
||||
found = True
|
||||
print('Found K4PC 1.6.X kinf file: ' + kinfopath)
|
||||
kInfoFiles.append(kinfopath)
|
||||
|
||||
# now look for even newer (K4PC 1.9.0 and later) .kinf2011 file
|
||||
kinfopath = path +'\\Amazon\\Kindle\\storage\\.kinf2011'
|
||||
if not os.path.isfile(kinfopath):
|
||||
print('No K4PC 1.9.X .kinf files have not been found.')
|
||||
else:
|
||||
if os.path.isfile(kinfopath):
|
||||
found = True
|
||||
print('Found K4PC kinf2011 file: ' + kinfopath)
|
||||
kInfoFiles.append(kinfopath)
|
||||
|
||||
if not found:
|
||||
print('No K4PC kindle.info/kinf/kinf2011 files have been found.')
|
||||
return kInfoFiles
|
||||
|
||||
|
||||
|
||||
@@ -57,8 +57,11 @@
|
||||
# 0.33 - Performance improvements for large files (concatenation)
|
||||
# 0.34 - Performance improvements in decryption (libalfcrypto)
|
||||
# 0.35 - add interface to get mobi_version
|
||||
# 0.36 - fixed problem with TEXtREAd and getBookTitle interface
|
||||
# 0.37 - Fixed double announcement for stand-alone operation
|
||||
|
||||
__version__ = '0.35'
|
||||
|
||||
__version__ = '0.37'
|
||||
|
||||
import sys
|
||||
|
||||
@@ -168,9 +171,10 @@ class MobiBook:
|
||||
off = self.sections[section][0]
|
||||
return self.data_file[off:endoff]
|
||||
|
||||
def __init__(self, infile):
|
||||
print ('MobiDeDrm v%(__version__)s. '
|
||||
'Copyright 2008-2011 The Dark Reverser et al.' % globals())
|
||||
def __init__(self, infile, announce = True):
|
||||
if announce:
|
||||
print ('MobiDeDrm v%(__version__)s. '
|
||||
'Copyright 2008-2012 The Dark Reverser et al.' % globals())
|
||||
|
||||
# initial sanity check on file
|
||||
self.data_file = file(infile, 'rb').read()
|
||||
@@ -198,6 +202,7 @@ class MobiBook:
|
||||
print "Book has format: ", self.magic
|
||||
self.extra_data_flags = 0
|
||||
self.mobi_length = 0
|
||||
self.mobi_codepage = 1252
|
||||
self.mobi_version = -1
|
||||
self.meta_array = {}
|
||||
return
|
||||
@@ -248,18 +253,19 @@ class MobiBook:
|
||||
65001 : 'utf-8',
|
||||
}
|
||||
title = ''
|
||||
if 503 in self.meta_array:
|
||||
title = self.meta_array[503]
|
||||
else :
|
||||
toff, tlen = struct.unpack('>II', self.sect[0x54:0x5c])
|
||||
tend = toff + tlen
|
||||
title = self.sect[toff:tend]
|
||||
codec = 'windows-1252'
|
||||
if self.magic == 'BOOKMOBI':
|
||||
if 503 in self.meta_array:
|
||||
title = self.meta_array[503]
|
||||
else:
|
||||
toff, tlen = struct.unpack('>II', self.sect[0x54:0x5c])
|
||||
tend = toff + tlen
|
||||
title = self.sect[toff:tend]
|
||||
if self.mobi_codepage in codec_map.keys():
|
||||
codec = codec_map[self.mobi_codepage]
|
||||
if title == '':
|
||||
title = self.header[:32]
|
||||
title = title.split("\0")[0]
|
||||
codec = 'windows-1252'
|
||||
if self.mobi_codepage in codec_map.keys():
|
||||
codec = codec_map[self.mobi_codepage]
|
||||
return unicode(title, codec).encode('utf-8')
|
||||
|
||||
def getPIDMetaInfo(self):
|
||||
@@ -375,7 +381,7 @@ class MobiBook:
|
||||
raise DrmException("Not yet initialised with PID. Must be opened with Mobipocket Reader first.")
|
||||
found_key, pid = self.parseDRM(self.sect[drm_ptr:drm_ptr+drm_size], drm_count, goodpids)
|
||||
if not found_key:
|
||||
raise DrmException("No key found. Please report this failure for help.")
|
||||
raise DrmException("No key found in " + str(len(goodpids)) + " keys tried. Please report this failure for help.")
|
||||
# kill the drm keys
|
||||
self.patchSection(0, "\0" * drm_size, drm_ptr)
|
||||
# kill the drm pointers
|
||||
@@ -411,26 +417,26 @@ class MobiBook:
|
||||
print "done"
|
||||
return
|
||||
|
||||
def getUnencryptedBook(infile,pid):
|
||||
def getUnencryptedBook(infile,pid,announce=True):
|
||||
if not os.path.isfile(infile):
|
||||
raise DrmException('Input File Not Found')
|
||||
book = MobiBook(infile)
|
||||
book = MobiBook(infile,announce)
|
||||
book.processBook([pid])
|
||||
return book.mobi_data
|
||||
|
||||
def getUnencryptedBookWithList(infile,pidlist):
|
||||
def getUnencryptedBookWithList(infile,pidlist,announce=True):
|
||||
if not os.path.isfile(infile):
|
||||
raise DrmException('Input File Not Found')
|
||||
book = MobiBook(infile)
|
||||
book = MobiBook(infile, announce)
|
||||
book.processBook(pidlist)
|
||||
return book.mobi_data
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
print ('MobiDeDrm v%(__version__)s. '
|
||||
'Copyright 2008-2011 The Dark Reverser et al.' % globals())
|
||||
'Copyright 2008-2012 The Dark Reverser et al.' % globals())
|
||||
if len(argv)<3 or len(argv)>4:
|
||||
print "Removes protection from Kindle/Mobipocket and Kindle/Print Replica ebooks"
|
||||
print "Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks"
|
||||
print "Usage:"
|
||||
print " %s <infile> <outfile> [<Comma separated list of PIDs to try>]" % sys.argv[0]
|
||||
return 1
|
||||
@@ -442,7 +448,7 @@ def main(argv=sys.argv):
|
||||
else:
|
||||
pidlist = {}
|
||||
try:
|
||||
stripped_file = getUnencryptedBookWithList(infile, pidlist)
|
||||
stripped_file = getUnencryptedBookWithList(infile, pidlist, False)
|
||||
file(outfile, 'wb').write(stripped_file)
|
||||
except DrmException, e:
|
||||
print "Error: %s" % e
|
||||
|
||||
Reference in New Issue
Block a user