tools v3.1
This commit is contained in:
@@ -55,7 +55,7 @@ on GetTools()
|
||||
set AdobePDFTool to POSIX path of file (path to me as text) & "Contents/Resources/ineptpdf.pyw"
|
||||
set ZipFixTool to POSIX path of file (path to me as text) & "Contents/Resources/zipfix.py"
|
||||
set ProgressApp to POSIX path of file ((path to resource "DeDRM Progress.app") as string)
|
||||
if not fileexists(eReaderTool) or not fileexists(MobipocketTool) or not fileexists(BNKeyGenTool) or not fileexists(BNePubTool) or not fileexists(AdobeKeyGenTool) or not fileexists(AdobeePubTool) or not folderexists(ProgressApp) then
|
||||
if not fileexists(eReaderTool) or not fileexists(MobipocketTool) or not fileexists(BNKeyGenTool) or not fileexists(BNePubTool) or not fileexists(AdobeKeyGenTool) or not fileexists(AdobePDFTool) or not fileexists(AdobeePubTool) or not folderexists(ProgressApp) then
|
||||
display dialog "De-drm scripts or support files are missing from this package. Get a fresh copy." buttons {"Bother"} default button 1 with title "DeDRM Applescript" with icon stop
|
||||
return false
|
||||
end if
|
||||
@@ -68,7 +68,7 @@ on unlockmobifile(encryptedFile)
|
||||
try
|
||||
set BOOKMOBI to read file encryptedFile from 61 for 8
|
||||
end try
|
||||
if BOOKMOBI is not "BOOKMOBI" then
|
||||
if BOOKMOBI is not "BOOKMOBI" and BOOKMOBI is not "TEXtREAd" then
|
||||
set TOPAZ to "NOT"
|
||||
try
|
||||
set TOPAZ to read file encryptedFile from 1 for 4
|
||||
@@ -98,9 +98,9 @@ on unlockmobifile(encryptedFile)
|
||||
set shellcommand to shellcommand & " -k " & quoted form of KindleInfoPath
|
||||
end repeat
|
||||
set Serialstring to GetSerialstring()
|
||||
if Serialstring is not "" then set shellcommand to shellcommand & " -s " & Serialstring
|
||||
if Serialstring is not "" then set shellcommand to shellcommand & " -s " & quoted form of Serialstring
|
||||
set PIDstring to GetPIDstring()
|
||||
if PIDstring is not "" then set shellcommand to shellcommand & " -p " & PIDstring
|
||||
if PIDstring is not "" then set shellcommand to shellcommand & " -p " & quoted form of PIDstring
|
||||
set shellcommand to shellcommand & " " & (quoted form of encryptedFilePath) & " " & (quoted form of unlockedFileParentFolderPath)
|
||||
--display dialog "shellcommand: " default answer shellcommand buttons {"OK"} default button 1 giving up after 10
|
||||
try
|
||||
@@ -108,8 +108,34 @@ on unlockmobifile(encryptedFile)
|
||||
on error errmsg
|
||||
set shellresult to errmsg
|
||||
end try
|
||||
--display dialog shellresult
|
||||
try
|
||||
if (offset of "Error" in shellresult) > 0 then
|
||||
repeat
|
||||
if (totalebooks > 1) or (offset of "No key found" in shellresult) is 0 then
|
||||
exit repeat
|
||||
end if
|
||||
-- ask for another PID as we're only doing one ebook
|
||||
set newPID to "None"
|
||||
set DialogPrompt to "Couldn't decode " & fileName & ". Do you have another PID to try?"
|
||||
try
|
||||
set dialogresult to (display dialog DialogPrompt default answer "" buttons {"Try This One", "No Extra PID"} with title "DeDRM Applescript" default button 2)
|
||||
if button returned of dialogresult is "Try This One" then
|
||||
set newPID to text returned of dialogresult
|
||||
end if
|
||||
end try
|
||||
if newPID is "None" or (length of newPID is not 10 and length of newPID is not 8) then
|
||||
exit repeat
|
||||
end if
|
||||
set shellcommand to "python " & (quoted form of MobipocketTool) & " -p " & quoted form of newPID & " " & (quoted form of encryptedFilePath) & " " & (quoted form of unlockedFileParentFolderPath)
|
||||
--display dialog "shellcommand: " default answer shellcommand buttons {"OK"} default button 1 giving up after 10
|
||||
try
|
||||
set shellresult to do shell script shellcommand
|
||||
on error errmsg
|
||||
set shellresult to errmsg
|
||||
end try
|
||||
--display dialog shellresult
|
||||
end repeat
|
||||
if (offset of "Error" in shellresult) > 0 or (offset of "No key found" in shellresult) > 0 then
|
||||
set ErrorCount to ErrorCount + 1
|
||||
set ErrorList to (ErrorList & fileName & fileExtension & " couldn't be decoded:
|
||||
" & shellresult as text) & "
|
||||
@@ -322,6 +348,7 @@ on unlockepubfile(encryptedFile)
|
||||
end repeat
|
||||
|
||||
if decoded is "NO" then
|
||||
set shellresult to "no keys"
|
||||
-- now try Adobe ePub
|
||||
repeat with AdeptKey in AdeptKeyList
|
||||
set shellcommand to "python " & (quoted form of AdobeePubTool) & " " & (quoted form of AdeptKey) & " " & (quoted form of fixedFilePath) & " " & (quoted form of unlockedFilePath)
|
||||
@@ -350,6 +377,11 @@ on unlockepubfile(encryptedFile)
|
||||
set ErrorCount to ErrorCount + 1
|
||||
set ErrorList to (ErrorList & fileName & fileExtension & " couldn't be decoded: no keys.
|
||||
|
||||
")
|
||||
else if (offset of "not an ADEPT EPUB" in shellresult) is not 0 then
|
||||
set WarningCount to WarningCount + 1
|
||||
set WarningList to (WarningList & fileName & " doesn't seem to be encrypted.
|
||||
|
||||
")
|
||||
else
|
||||
set ErrorCount to ErrorCount + 1
|
||||
@@ -392,7 +424,7 @@ on unlockpdffile(encryptedFile)
|
||||
|
||||
set decoded to "NO"
|
||||
-- first we must check we have a PDF script
|
||||
GetIneptPDF(false)
|
||||
--GetIneptPDF(false)
|
||||
if not fileexists(AdobePDFTool) then
|
||||
set ErrorCount to ErrorCount + 1
|
||||
set ErrorList to ErrorList & encryptedFile & " is a PDF file and no ineptpdf script found.
|
||||
@@ -591,7 +623,7 @@ on GetPIDs()
|
||||
Enter any additional Mobipocket PIDs for your Mobipocket books one at a time:"
|
||||
set FinishedButton to "No More"
|
||||
end if
|
||||
set dialogresult to (display dialog DialogPrompt default answer "" buttons {"Delete All", "Add", FinishedButton} with title "DeDRM Applescript 2/6" default button 2)
|
||||
set dialogresult to (display dialog DialogPrompt default answer "" buttons {"Delete All", "Add", FinishedButton} with title "DeDRM Applescript 2/5" default button 2)
|
||||
if button returned of dialogresult is "Add" then
|
||||
set PID to text returned of dialogresult
|
||||
set PIDlength to length of PID
|
||||
@@ -627,7 +659,7 @@ on GetSerials()
|
||||
Enter any additional Kindle Serial Numbers one at a time:"
|
||||
set FinishedButton to "No More"
|
||||
end if
|
||||
set dialogresult to (display dialog DialogPrompt default answer "" buttons {"Delete All", "Add", FinishedButton} with title "DeDRM Applescript 3/6" default button 2)
|
||||
set dialogresult to (display dialog DialogPrompt default answer "" buttons {"Delete All", "Add", FinishedButton} with title "DeDRM Applescript 3/5" default button 2)
|
||||
if button returned of dialogresult is "Add" then
|
||||
set Serial to text returned of dialogresult
|
||||
set Seriallength to length of Serial
|
||||
@@ -735,7 +767,7 @@ Please enter any additional "
|
||||
set DialogPrompt to DialogPrompt & "eReader/Barnes & Noble Name,Number key pairs one at a time. If you're only decoding eReader files, the last 8 digits of the Number will do. The full 15 or 16 are only needed for Barnes & Noble ePubs. Only the last eight will be stored or displayed. Please separate the name and number with a comma and click \"Add\". Or to add a an already generated .b64 file, just click \"Add\" with nothing in the text field."
|
||||
set dialogtitle to "DeDRM Applescript"
|
||||
if (running) then
|
||||
set dialogtitle to dialogtitle & " 4/6"
|
||||
set dialogtitle to dialogtitle & " 4/5"
|
||||
end if
|
||||
set dialogresult to (display dialog DialogPrompt default answer bnKeyText buttons {"Delete All", "Add", FinishedButton} with title dialogtitle default button 2)
|
||||
if button returned of dialogresult is "Add" then
|
||||
@@ -823,7 +855,7 @@ on GetAdeptKeyFiles()
|
||||
To add extra key files (.der), click the Add<64> button."
|
||||
set FinishedButton to "No More"
|
||||
end if
|
||||
set dialogresult to (display dialog DialogPrompt buttons {"Forget All", "Add<64>", FinishedButton} with title "DeDRM Applescript 5/6" default button 2)
|
||||
set dialogresult to (display dialog DialogPrompt buttons {"Forget All", "Add<64>", FinishedButton} with title "DeDRM Applescript 5/5" default button 2)
|
||||
if button returned of dialogresult is "Add<64>" then
|
||||
try
|
||||
set newFile to (choose file with prompt "Please select an Adept key file") as text
|
||||
@@ -1023,9 +1055,9 @@ on ReadPrefs()
|
||||
try
|
||||
set AdeptKeyList to value of property list item "AdeptKeys" of property list file preferencesFilePath
|
||||
end try
|
||||
try
|
||||
set AdobePDFTool to value of property list item "IneptPDF" of property list file preferencesFilePath
|
||||
end try
|
||||
--try
|
||||
--set AdobePDFTool to value of property list item "IneptPDF" of property list file preferencesFilePath
|
||||
--end try
|
||||
end tell
|
||||
end if
|
||||
set newList to {}
|
||||
@@ -1053,7 +1085,7 @@ on WritePrefs()
|
||||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"KindleInfoFiles", value:KindleInfoList}
|
||||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"bnKeys", value:bnKeys}
|
||||
make new property list item at end of property list items of contents of myPrefs with properties {kind:list, name:"AdeptKeys", value:AdeptKeyList}
|
||||
make new property list item at end of property list items of contents of myPrefs with properties {kind:string, name:"IneptPDF", value:AdobePDFTool}
|
||||
--make new property list item at end of property list items of contents of myPrefs with properties {kind:string, name:"IneptPDF", value:AdobePDFTool}
|
||||
end tell
|
||||
end WritePrefs
|
||||
|
||||
@@ -1103,9 +1135,9 @@ on run
|
||||
if GetTools() then
|
||||
display dialog "Drag&Drop encrypted ebooks onto this AppleScript's icon in the Finder to decode them after you have finished configuring it and it has quit.
|
||||
|
||||
Click the Continue button to enter any PIDs for Mobipocket ebooks; serial numbers for Kindle ebooks; name,number key pairs for Barnes & Noble/eReader ebooks; to select extra Barnes & Noble .b64 key files; to select extra Adobe Adept .der key files; and to find th optional ineptpdf.pyw script.
|
||||
Click the Continue button to enter any PIDs for Mobipocket ebooks; serial numbers for Kindle ebooks; name,number key pairs for Barnes & Noble/eReader ebooks; to select extra Barnes & Noble .b64 key files; or to select extra Adobe Adept .der key files.
|
||||
|
||||
***You do not need to enter any extra info if decoding ebooks downloaded to your installation of Kindle for Mac, or Adobe Digital Editions. If you do not have any PIDS; serial numbers; name,number keys, .b64 or .der files to add or want to decode PDF files, just click the Cancel button.***
|
||||
***You do not need to enter any extra info if decoding ebooks downloaded to your installation of Kindle for Mac, or Adobe Digital Editions. If you do not have any PIDS; serial numbers; name,number keys, .b64 or .der files, just click the Cancel button.***
|
||||
|
||||
Please only use to get access to your own books. Authors, publishers and ebook stores need to make money to produce more ebooks. Don't cheat them.
|
||||
|
||||
@@ -1117,7 +1149,7 @@ Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
|
||||
For more information, please refer to
|
||||
<http://unlicense.org/>
|
||||
" with title "DeDRM Applescript 1/6" buttons {"Cancel", "Continue"} default button 2
|
||||
" with title "DeDRM Applescript 1/5" buttons {"Cancel", "Continue"} default button 2
|
||||
ReadPrefs()
|
||||
GetAdeptKey(true)
|
||||
|
||||
@@ -1125,7 +1157,7 @@ For more information, please refer to
|
||||
GetSerials()
|
||||
GetKeys(true)
|
||||
GetAdeptKeyFiles()
|
||||
GetIneptPDF(true)
|
||||
--GetIneptPDF(true)
|
||||
--GetKindleInfoFiles()
|
||||
WritePrefs()
|
||||
end if
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>droplet</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>DeDRM 1.4, Copyright © 2010 by Apprentice Alf.</string>
|
||||
<string>DeDRM 1.6, Copyright © 2010–2011 by Apprentice Alf.</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>droplet</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
@@ -34,11 +34,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.4</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.5.0</string>
|
||||
<string>1.6</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>dplt</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.5.0</string>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>WindowState</key>
|
||||
@@ -46,9 +46,9 @@
|
||||
<key>name</key>
|
||||
<string>ScriptWindowState</string>
|
||||
<key>positionOfDivider</key>
|
||||
<real>739</real>
|
||||
<real>686</real>
|
||||
<key>savedFrame</key>
|
||||
<string>1533 -24 1262 818 1440 -150 1680 1050 </string>
|
||||
<string>2161 -75 907 765 1440 -150 1680 1050 </string>
|
||||
<key>selectedTabView</key>
|
||||
<string>result</string>
|
||||
</dict>
|
||||
|
||||
Binary file not shown.
@@ -55,29 +55,10 @@
|
||||
# 0.14 - contributed enhancement to support --make-pmlz switch
|
||||
# 0.15 - enabled high-ascii to pml character encoding. DropBook now works on Mac.
|
||||
# 0.16 - convert to use openssl DES (very very fast) or pure python DES if openssl's libcrypto is not available
|
||||
# 0.17 - added support for pycrypto's DES as well
|
||||
# 0.18 - on Windows try PyCrypto first and OpenSSL next
|
||||
|
||||
Des = None
|
||||
|
||||
import openssl_des
|
||||
Des = openssl_des.load_libcrypto()
|
||||
|
||||
# if that did not work then use pure python implementation
|
||||
# of DES and try to speed it up with Psycho
|
||||
if Des == None:
|
||||
import python_des
|
||||
Des = python_des.Des
|
||||
# Import Psyco if available
|
||||
try:
|
||||
# Dumb speed hack 1
|
||||
# http://psyco.sourceforge.net
|
||||
import psyco
|
||||
psyco.full()
|
||||
pass
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
__version__='0.16'
|
||||
__version__='0.18'
|
||||
|
||||
class Unbuffered:
|
||||
def __init__(self, stream):
|
||||
@@ -93,6 +74,37 @@ sys.stdout=Unbuffered(sys.stdout)
|
||||
|
||||
import struct, binascii, getopt, zlib, os, os.path, urllib, tempfile
|
||||
|
||||
Des = None
|
||||
if sys.platform.startswith('win'):
|
||||
# first try with pycrypto
|
||||
import pycrypto_des
|
||||
Des = pycrypto_des.load_pycrypto()
|
||||
if Des == None:
|
||||
# they try with openssl
|
||||
import openssl_des
|
||||
Des = openssl_des.load_libcrypto()
|
||||
else:
|
||||
# first try with openssl
|
||||
import openssl_des
|
||||
Des = openssl_des.load_libcrypto()
|
||||
if Des == None:
|
||||
# then try with pycrypto
|
||||
import pycrypto_des
|
||||
Des = pycrypto_des.load_pycrypto()
|
||||
|
||||
# if that did not work then use pure python implementation
|
||||
# of DES and try to speed it up with Psycho
|
||||
if Des == None:
|
||||
import python_des
|
||||
Des = python_des.Des
|
||||
# Import Psyco if available
|
||||
try:
|
||||
# http://psyco.sourceforge.net
|
||||
import psyco
|
||||
psyco.full()
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
from hashlib import sha1
|
||||
except ImportError:
|
||||
@@ -456,7 +468,7 @@ def main(argv=None):
|
||||
myZipFile.write(imagePath, localname)
|
||||
myZipFile.close()
|
||||
# remove temporary directory
|
||||
shutil.rmtree(outdir)
|
||||
shutil.rmtree(outdir, True)
|
||||
|
||||
end_time = time.time()
|
||||
search_time = end_time - start_time
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
# ignobleepub.pyw, version 3
|
||||
# ignobleepub.pyw, version 3.3
|
||||
|
||||
# To run this program install Python 2.6 from <http://www.python.org/download/>
|
||||
# and OpenSSL or PyCrypto from http://www.voidspace.org.uk/python/modules.shtml#pycrypto
|
||||
@@ -12,6 +12,9 @@
|
||||
# 2 - Added OS X support by using OpenSSL when available
|
||||
# 3 - screen out improper key lengths to prevent segfaults on Linux
|
||||
# 3.1 - Allow Windows versions of libcrypto to be found
|
||||
# 3.2 - add support for encoding to 'utf-8' when building up list of files to cecrypt from encryption.xml
|
||||
# 3.3 - On Windows try PyCrypto first and OpenSSL next
|
||||
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
@@ -105,15 +108,18 @@ def _load_crypto_pycrypto():
|
||||
|
||||
def _load_crypto():
|
||||
AES = None
|
||||
for loader in (_load_crypto_libcrypto, _load_crypto_pycrypto):
|
||||
cryptolist = (_load_crypto_libcrypto, _load_crypto_pycrypto)
|
||||
if sys.platform.startswith('win'):
|
||||
cryptolist = (_load_crypto_pycrypto, _load_crypto_libcrypto)
|
||||
for loader in cryptolist:
|
||||
try:
|
||||
AES = loader()
|
||||
break
|
||||
except (ImportError, IGNOBLEError):
|
||||
pass
|
||||
return AES
|
||||
AES = _load_crypto()
|
||||
|
||||
AES = _load_crypto()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
# ignoblekeygen.pyw, version 2
|
||||
# ignoblekeygen.pyw, version 2.2
|
||||
|
||||
# To run this program install Python 2.6 from <http://www.python.org/download/>
|
||||
# and OpenSSL or PyCrypto from http://www.voidspace.org.uk/python/modules.shtml#pycrypto
|
||||
@@ -11,7 +11,7 @@
|
||||
# 1 - Initial release
|
||||
# 2 - Add OS X support by using OpenSSL when available (taken/modified from ineptepub v5)
|
||||
# 2.1 - Allow Windows versions of libcrypto to be found
|
||||
|
||||
# 2.2 - On Windows try PyCrypto first and then OpenSSL next
|
||||
"""
|
||||
Generate Barnes & Noble EPUB user key from name and credit card number.
|
||||
"""
|
||||
@@ -102,11 +102,12 @@ def _load_crypto_pycrypto():
|
||||
|
||||
return AES
|
||||
|
||||
|
||||
|
||||
def _load_crypto():
|
||||
AES = None
|
||||
for loader in (_load_crypto_libcrypto, _load_crypto_pycrypto):
|
||||
cryptolist = (_load_crypto_libcrypto, _load_crypto_pycrypto)
|
||||
if sys.platform.startswith('win'):
|
||||
cryptolist = (_load_crypto_pycrypto, _load_crypto_libcrypto)
|
||||
for loader in cryptolist:
|
||||
try:
|
||||
AES = loader()
|
||||
break
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#! /usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ineptepub.pyw, version 5.4
|
||||
# ineptepub.pyw, version 5.5
|
||||
# Copyright © 2009-2010 i♥cabbages
|
||||
|
||||
# Released under the terms of the GNU General Public Licence, version 3 or
|
||||
@@ -26,6 +26,7 @@
|
||||
# 5.2 - Fix ctypes error causing segfaults on some systems
|
||||
# 5.3 - add support for OpenSSL on Windows, fix bug with some versions of libcrypto 0.9.8 prior to path level o
|
||||
# 5.4 - add support for encoding to 'utf-8' when building up list of files to decrypt from encryption.xml
|
||||
# 5.5 - On Windows try PyCrypto first, OpenSSL next
|
||||
|
||||
"""
|
||||
Decrypt Adobe ADEPT-encrypted EPUB books.
|
||||
@@ -259,7 +260,10 @@ def _load_crypto_pycrypto():
|
||||
|
||||
def _load_crypto():
|
||||
AES = RSA = None
|
||||
for loader in (_load_crypto_libcrypto, _load_crypto_pycrypto):
|
||||
cryptolist = (_load_crypto_libcrypto, _load_crypto_pycrypto)
|
||||
if sys.platform.startswith('win'):
|
||||
cryptolist = (_load_crypto_pycrypto, _load_crypto_libcrypto)
|
||||
for loader in cryptolist:
|
||||
try:
|
||||
AES, RSA = loader()
|
||||
break
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#! /usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ineptkey.pyw, version 5
|
||||
# ineptkey.pyw, version 5.3
|
||||
# Copyright © 2009-2010 i♥cabbages
|
||||
|
||||
# Released under the terms of the GNU General Public Licence, version 3 or
|
||||
@@ -32,6 +32,7 @@
|
||||
# Clean up and merge OS X support by unknown
|
||||
# 5.1 - add support for using OpenSSL on Windows in place of PyCrypto
|
||||
# 5.2 - added support for output of key to a particular file
|
||||
# 5.3 - On Windows try PyCrypto first, OpenSSL next
|
||||
|
||||
"""
|
||||
Retrieve Adobe ADEPT user key.
|
||||
@@ -115,7 +116,7 @@ if sys.platform.startswith('win'):
|
||||
|
||||
def _load_crypto():
|
||||
AES = None
|
||||
for loader in (_load_crypto_libcrypto, _load_crypto_pycrypto):
|
||||
for loader in (_load_crypto_pycrypto, _load_crypto_libcrypto):
|
||||
try:
|
||||
AES = loader()
|
||||
break
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -163,6 +163,7 @@ def main(argv=sys.argv):
|
||||
myzip = zipfile.ZipFile(zipname,'w',zipfile.ZIP_DEFLATED, False)
|
||||
zipUpDir(myzip, tempdir, '')
|
||||
myzip.close()
|
||||
shutil.rmtree(tempdir, True)
|
||||
return 1
|
||||
|
||||
if mobi:
|
||||
@@ -198,7 +199,7 @@ def main(argv=sys.argv):
|
||||
zipUpDir(myzip3, tempdir, 'img')
|
||||
myzip3.close()
|
||||
|
||||
shutil.rmtree(tempdir)
|
||||
shutil.rmtree(tempdir, True)
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -6,7 +6,7 @@ import os
|
||||
import subprocess
|
||||
|
||||
|
||||
class K4MDrmException(Exception):
|
||||
class DrmException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ def _load_crypto_libcrypto():
|
||||
|
||||
libcrypto = find_library('crypto')
|
||||
if libcrypto is None:
|
||||
raise K4MDrmException('libcrypto not found')
|
||||
raise DrmException('libcrypto not found')
|
||||
libcrypto = CDLL(libcrypto)
|
||||
|
||||
AES_MAXNR = 14
|
||||
@@ -51,19 +51,19 @@ def _load_crypto_libcrypto():
|
||||
def set_decrypt_key(self, userkey, iv):
|
||||
self._blocksize = len(userkey)
|
||||
if (self._blocksize != 16) and (self._blocksize != 24) and (self._blocksize != 32) :
|
||||
raise K4MDrmException('AES improper key used')
|
||||
raise DrmException('AES improper key used')
|
||||
return
|
||||
keyctx = self._keyctx = AES_KEY()
|
||||
self.iv = iv
|
||||
rv = AES_set_decrypt_key(userkey, len(userkey) * 8, keyctx)
|
||||
if rv < 0:
|
||||
raise K4MDrmException('Failed to initialize AES key')
|
||||
raise DrmException('Failed to initialize AES key')
|
||||
|
||||
def decrypt(self, data):
|
||||
out = create_string_buffer(len(data))
|
||||
rv = AES_cbc_encrypt(data, out, len(data), self._keyctx, self.iv, 0)
|
||||
if rv == 0:
|
||||
raise K4MDrmException('AES decryption failed')
|
||||
raise DrmException('AES decryption failed')
|
||||
return out.raw
|
||||
|
||||
def keyivgen(self, passwd):
|
||||
@@ -81,7 +81,7 @@ def _load_crypto():
|
||||
LibCrypto = None
|
||||
try:
|
||||
LibCrypto = _load_crypto_libcrypto()
|
||||
except (ImportError, K4MDrmException):
|
||||
except (ImportError, DrmException):
|
||||
pass
|
||||
return LibCrypto
|
||||
|
||||
@@ -185,8 +185,10 @@ def openKindleInfo(kInfoFile=None):
|
||||
if pp >= 0:
|
||||
kinfopath = resline
|
||||
break
|
||||
if not os.path.exists(kinfopath):
|
||||
raise K4MDrmException('Error: .kindle-info file can not be found')
|
||||
if not os.path.isfile(kinfopath):
|
||||
raise DrmException('Error: .kindle-info file can not be found')
|
||||
return open(kinfopath,'r')
|
||||
else:
|
||||
if not os.path.isfile(kinfoFile):
|
||||
raise DrmException('Error: kindle-info file can not be found')
|
||||
return open(kInfoFile, 'r')
|
||||
|
||||
@@ -19,17 +19,12 @@ advapi32 = windll.advapi32
|
||||
crypt32 = windll.crypt32
|
||||
|
||||
|
||||
#
|
||||
# Various character maps used to decrypt books. Probably supposed to act as obfuscation
|
||||
#
|
||||
charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M"
|
||||
charMap2 = "AaZzB0bYyCc1XxDdW2wEeVv3FfUuG4g-TtHh5SsIiR6rJjQq7KkPpL8lOoMm9Nn_"
|
||||
charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
charMap4 = "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789"
|
||||
|
||||
#
|
||||
# Exceptions for all the problems that might happen during the script
|
||||
#
|
||||
class DrmException(Exception):
|
||||
pass
|
||||
|
||||
@@ -104,7 +99,12 @@ CryptUnprotectData = CryptUnprotectData()
|
||||
def openKindleInfo(kInfoFile=None):
|
||||
if kInfoFile == None:
|
||||
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
|
||||
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
|
||||
return open(path+'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info','r')
|
||||
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
|
||||
kinfopath = path +'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info'
|
||||
if not os.path.isfile(kinfopath):
|
||||
raise DrmException('Error: kindle.info file can not be found')
|
||||
return open(kinfopath,'r')
|
||||
else:
|
||||
if not os.path.isfile(kInfoFile):
|
||||
raise DrmException('Error: kindle.info file can not be found')
|
||||
return open(kInfoFile, 'r')
|
||||
|
||||
@@ -83,7 +83,8 @@ def parseKindleInfo(kInfoFile):
|
||||
DB[splito[0]] =splito[1]
|
||||
return DB
|
||||
|
||||
# Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded). Return the decoded and decrypted record
|
||||
# Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded).
|
||||
# Return the decoded and decrypted record
|
||||
def getKindleInfoValueForHash(hashedKey):
|
||||
global kindleDatabase
|
||||
global charMap1
|
||||
@@ -95,12 +96,14 @@ def getKindleInfoValueForHash(hashedKey):
|
||||
cleartext = CryptUnprotectData(encryptedValue)
|
||||
return decode(cleartext, charMap1)
|
||||
|
||||
# Get a record from the Kindle.info file for the string in "key" (plaintext). Return the decoded and decrypted record
|
||||
# Get a record from the Kindle.info file for the string in "key" (plaintext).
|
||||
# Return the decoded and decrypted record
|
||||
def getKindleInfoValueForKey(key):
|
||||
global charMap2
|
||||
return getKindleInfoValueForHash(encodeHash(key,charMap2))
|
||||
|
||||
# Find if the original string for a hashed/encoded string is known. If so return the original string othwise return an empty string.
|
||||
# Find if the original string for a hashed/encoded string is known.
|
||||
# If so return the original string othwise return an empty string.
|
||||
def findNameForHash(hash):
|
||||
global charMap2
|
||||
names = ["kindle.account.tokens","kindle.cookie.item","eulaVersionAccepted","login_date","kindle.token.item","login","kindle.key.item","kindle.name.info","kindle.device.info", "MazamaRandomNumber"]
|
||||
@@ -222,7 +225,7 @@ def pidFromSerial(s, l):
|
||||
# Parse the EXTH header records and use the Kindle serial number to calculate the book pid.
|
||||
def getKindlePid(pidlst, rec209, token, serialnum):
|
||||
|
||||
if rec209 != None:
|
||||
if rec209 != None and token != None:
|
||||
# Compute book PID
|
||||
pidHash = SHA1(serialnum+rec209+token)
|
||||
bookPID = encodePID(pidHash)
|
||||
@@ -248,6 +251,7 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
|
||||
kindleDatabase = parseKindleInfo(kInfoFile)
|
||||
except Exception, message:
|
||||
print(message)
|
||||
kindleDatabase = None
|
||||
pass
|
||||
|
||||
if kindleDatabase == None :
|
||||
@@ -272,8 +276,8 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
|
||||
pidlst.append(devicePID)
|
||||
|
||||
# Compute book PID
|
||||
if rec209 == None:
|
||||
print "\nNo EXTH record type 209 - Perhaps not a K4 file?"
|
||||
if rec209 == None or token == None:
|
||||
print "\nNo EXTH record type 209 or token - Perhaps not a K4 file?"
|
||||
return pidlst
|
||||
|
||||
# Get the kindle account token
|
||||
|
||||
@@ -42,8 +42,10 @@
|
||||
# 0.20 - Correction: It seems that multibyte entries are encrypted in a v6 file.
|
||||
# 0.21 - Added support for multiple pids
|
||||
# 0.22 - revised structure to hold MobiBook as a class to allow an extended interface
|
||||
# 0.23 - fixed problem with older files with no EXTH section
|
||||
# 0.24 - add support for type 1 encryption and 'TEXtREAd' books as well
|
||||
|
||||
__version__ = '0.22'
|
||||
__version__ = '0.24'
|
||||
|
||||
import sys
|
||||
|
||||
@@ -57,6 +59,7 @@ class Unbuffered:
|
||||
return getattr(self.stream, attr)
|
||||
sys.stdout=Unbuffered(sys.stdout)
|
||||
|
||||
import os
|
||||
import struct
|
||||
import binascii
|
||||
|
||||
@@ -154,8 +157,10 @@ class MobiBook:
|
||||
# initial sanity check on file
|
||||
self.data_file = file(infile, 'rb').read()
|
||||
self.header = self.data_file[0:78]
|
||||
if self.header[0x3C:0x3C+8] != 'BOOKMOBI':
|
||||
if self.header[0x3C:0x3C+8] != 'BOOKMOBI' and self.header[0x3C:0x3C+8] != 'TEXtREAd':
|
||||
raise DrmException("invalid file format")
|
||||
self.magic = self.header[0x3C:0x3C+8]
|
||||
self.crypto_type = -1
|
||||
|
||||
# build up section offset and flag info
|
||||
self.num_sections, = struct.unpack('>H', self.header[76:78])
|
||||
@@ -168,6 +173,14 @@ class MobiBook:
|
||||
# parse information from section 0
|
||||
self.sect = self.loadSection(0)
|
||||
self.records, = struct.unpack('>H', self.sect[0x8:0x8+2])
|
||||
|
||||
if self.magic == 'TEXtREAd':
|
||||
print "Book has format: ", self.magic
|
||||
self.extra_data_flags = 0
|
||||
self.mobi_length = 0
|
||||
self.mobi_version = -1
|
||||
self.meta_array = {}
|
||||
return
|
||||
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
|
||||
self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C])
|
||||
print "MOBI header version = %d, length = %d" %(self.mobi_version, self.mobi_length)
|
||||
@@ -182,18 +195,23 @@ class MobiBook:
|
||||
|
||||
# if exth region exists parse it for metadata array
|
||||
self.meta_array = {}
|
||||
exth_flag, = struct.unpack('>L', self.sect[0x80:0x84])
|
||||
exth = ''
|
||||
if exth_flag & 0x40:
|
||||
exth = self.sect[16 + self.mobi_length:]
|
||||
nitems, = struct.unpack('>I', exth[8:12])
|
||||
pos = 12
|
||||
for i in xrange(nitems):
|
||||
type, size = struct.unpack('>II', exth[pos: pos + 8])
|
||||
content = exth[pos + 8: pos + size]
|
||||
self.meta_array[type] = content
|
||||
pos += size
|
||||
|
||||
try:
|
||||
exth_flag, = struct.unpack('>L', self.sect[0x80:0x84])
|
||||
exth = 'NONE'
|
||||
if exth_flag & 0x40:
|
||||
exth = self.sect[16 + self.mobi_length:]
|
||||
if (len(exth) >= 4) and (exth[:4] == 'EXTH'):
|
||||
nitems, = struct.unpack('>I', exth[8:12])
|
||||
pos = 12
|
||||
for i in xrange(nitems):
|
||||
type, size = struct.unpack('>II', exth[pos: pos + 8])
|
||||
content = exth[pos + 8: pos + size]
|
||||
self.meta_array[type] = content
|
||||
pos += size
|
||||
except:
|
||||
self.meta_array = {}
|
||||
pass
|
||||
|
||||
def getBookTitle(self):
|
||||
title = ''
|
||||
if 503 in self.meta_array:
|
||||
@@ -269,12 +287,12 @@ class MobiBook:
|
||||
|
||||
def processBook(self, pidlist):
|
||||
crypto_type, = struct.unpack('>H', self.sect[0xC:0xC+2])
|
||||
print 'Crypto Type is: ', crypto_type
|
||||
self.crypto_type = crypto_type
|
||||
if crypto_type == 0:
|
||||
print "This book is not encrypted."
|
||||
return self.data_file
|
||||
if crypto_type == 1:
|
||||
raise DrmException("Cannot decode Mobipocket encryption type 1")
|
||||
if crypto_type != 2:
|
||||
if crypto_type != 2 and crypto_type != 1:
|
||||
raise DrmException("Cannot decode unknown Mobipocket encryption type %d" % crypto_type)
|
||||
|
||||
goodpids = []
|
||||
@@ -286,23 +304,32 @@ class MobiBook:
|
||||
elif len(pid)==8:
|
||||
goodpids.append(pid)
|
||||
|
||||
# calculate the keys
|
||||
drm_ptr, drm_count, drm_size, drm_flags = struct.unpack('>LLLL', self.sect[0xA8:0xA8+16])
|
||||
if drm_count == 0:
|
||||
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. Most likely the correct PID has not been given.")
|
||||
if self.crypto_type == 1:
|
||||
t1_keyvec = "QDCVEPMU675RUBSZ"
|
||||
if self.magic == 'TEXtREAd':
|
||||
bookkey_data = self.sect[0x0E:0x0E+16]
|
||||
else:
|
||||
bookkey_data = self.sect[0x90:0x90+16]
|
||||
pid = "00000000"
|
||||
found_key = PC1(t1_keyvec, bookkey_data)
|
||||
else :
|
||||
# calculate the keys
|
||||
drm_ptr, drm_count, drm_size, drm_flags = struct.unpack('>LLLL', self.sect[0xA8:0xA8+16])
|
||||
if drm_count == 0:
|
||||
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. Most likely the correct PID has not been given.")
|
||||
# kill the drm keys
|
||||
self.patchSection(0, "\0" * drm_size, drm_ptr)
|
||||
# kill the drm pointers
|
||||
self.patchSection(0, "\xff" * 4 + "\0" * 12, 0xA8)
|
||||
|
||||
if pid=="00000000":
|
||||
print "File has default encryption, no specific PID."
|
||||
else:
|
||||
print "File is encoded with PID "+checksumPid(pid)+"."
|
||||
|
||||
# kill the drm keys
|
||||
self.patchSection(0, "\0" * drm_size, drm_ptr)
|
||||
# kill the drm pointers
|
||||
self.patchSection(0, "\xff" * 4 + "\0" * 12, 0xA8)
|
||||
# clear the crypto type
|
||||
self.patchSection(0, "\0" * 2, 0xC)
|
||||
|
||||
|
||||
@@ -164,9 +164,10 @@ class TopazBook:
|
||||
|
||||
def getPIDMetaInfo(self):
|
||||
keysRecord = None
|
||||
KeysRecordRecord = None
|
||||
keysRecordRecord = None
|
||||
if 'keys' in self.bookMetadata:
|
||||
keysRecord = self.bookMetadata['keys']
|
||||
if keysRecord in self.bookMetadata:
|
||||
keysRecordRecord = self.bookMetadata[keysRecord]
|
||||
return keysRecord, keysRecordRecord
|
||||
|
||||
@@ -395,6 +396,7 @@ def main(argv=sys.argv):
|
||||
myzip = zipfile.ZipFile(zipname,'w',zipfile.ZIP_DEFLATED, False)
|
||||
zipUpDir(myzip, tempdir, '')
|
||||
myzip.close()
|
||||
shutil.rmtree(tempdir, True)
|
||||
return 1
|
||||
|
||||
print " Creating HTML ZIP Archive"
|
||||
@@ -424,7 +426,7 @@ def main(argv=sys.argv):
|
||||
zipUpDir(myzip3, tempdir, 'img')
|
||||
myzip3.close()
|
||||
|
||||
shutil.rmtree(tempdir)
|
||||
shutil.rmtree(tempdir, True)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user