tools v5.6.1

This commit is contained in:
Apprentice Alf 2013-02-04 14:25:25 +00:00
parent c23b903420
commit 490ee4e5d8
19 changed files with 141 additions and 129 deletions

View File

@ -1,4 +1,4 @@
Kindle and Mobipocket Plugin - K4MobiDeDRM_v04.18_plugin.zip Kindle and Mobipocket Plugin - K4MobiDeDRM_v04.19_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. 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.
@ -13,7 +13,7 @@ This plugin is meant to remove the DRM from .prc, .mobi, .azw, .azw1, .azw3, .az
Installation Installation
------------ ------------
Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Change calibre behavior" to go to Calibre's Preferences page. Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (K4MobiDeDRM_v04.18_plugin.zip) and click the 'Add' button. Click 'Yes' in the the "Are you sure?" dialog. Click OK in the "Success" dialog. Do **NOT** select "Get plugins to enhance calibre" as this is reserved for "official" calibre plugins, instead select "Change calibre behavior" to go to Calibre's Preferences page. Under "Advanced" click on the Plugins button. Use the "Load plugin from file" button to select the plugin's zip file (K4MobiDeDRM_v04.19_plugin.zip) and click the 'Add' button. Click 'Yes' in the the "Are you sure?" dialog. Click OK in the "Success" dialog.
Make sure that you delete any old versions of the plugin. They might interfere with the operation of the new one. Make sure that you delete any old versions of the plugin. They might interfere with the operation of the new one.

View File

@ -27,13 +27,14 @@ __docformat__ = 'restructuredtext en'
# 0.4.16 - Yet another Topaz fix # 0.4.16 - Yet another Topaz fix
# 0.4.17 - Manage to include the actual fix. # 0.4.17 - Manage to include the actual fix.
# 0.4.18 - More Topaz fixes # 0.4.18 - More Topaz fixes
# 0.4.19 - MobiDeDRM PalmDoc fix
""" """
Decrypt Amazon Kindle and Mobipocket encrypted ebooks. Decrypt Amazon Kindle and Mobipocket encrypted ebooks.
""" """
PLUGIN_NAME = u"Kindle and Mobipocket DeDRM" PLUGIN_NAME = u"Kindle and Mobipocket DeDRM"
PLUGIN_VERSION_TUPLE = (0, 4, 18) PLUGIN_VERSION_TUPLE = (0, 4, 19)
PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE]) PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE])
import sys, os, re import sys, os, re

View File

@ -34,10 +34,14 @@ def _load_libalfcrypto():
else: else:
name_of_lib = 'libalfcrypto64.so' name_of_lib = 'libalfcrypto64.so'
# hard code to local location for libalfcrypto
libalfcrypto = os.path.join(sys.path[0],name_of_lib) libalfcrypto = os.path.join(sys.path[0],name_of_lib)
if not os.path.isfile(libalfcrypto): if not os.path.isfile(libalfcrypto):
raise Exception('libalfcrypto not found') libalfcrypto = os.path.join(sys.path[0], 'lib', name_of_lib)
if not os.path.isfile(libalfcrypto):
libalfcrypto = os.path.join('.',name_of_lib)
if not os.path.isfile(libalfcrypto):
raise Exception('libalfcrypto not found at %s' % libalfcrypto)
libalfcrypto = CDLL(libalfcrypto) libalfcrypto = CDLL(libalfcrypto)

View File

@ -248,6 +248,7 @@ def decryptBook(infile, outdir, kInfoFiles, serials, pids):
# remove internal temporary directory of Topaz pieces # remove internal temporary directory of Topaz pieces
book.cleanup() book.cleanup()
return 0
def usage(progname): def usage(progname):

View File

@ -8,6 +8,7 @@
# 0.2 Added support for generating PID for iPhone (thanks to mbp) # 0.2 Added support for generating PID for iPhone (thanks to mbp)
# 0.3 changed to autoflush stdout, fixed return code usage # 0.3 changed to autoflush stdout, fixed return code usage
# 0.3 updated for unicode # 0.3 updated for unicode
# 0.4 Added support for serial numbers starting with '9', fixed unicode bugs.
import sys import sys
import binascii import binascii
@ -63,7 +64,7 @@ def unicode_argv():
xrange(start, argc.value)] xrange(start, argc.value)]
# if we don't have any arguments at all, just pass back script name # if we don't have any arguments at all, just pass back script name
# this should never happen # this should never happen
return [u"mobidedrm.py"] return [u"kindlepid.py"]
else: else:
argvencoding = sys.stdin.encoding argvencoding = sys.stdin.encoding
if argvencoding == None: if argvencoding == None:
@ -92,7 +93,6 @@ def checksumPid(s):
return res return res
def pidFromSerial(s, l): def pidFromSerial(s, l):
crc = crc32(s) crc = crc32(s)
@ -113,27 +113,27 @@ def pidFromSerial(s, l):
def cli_main(argv=unicode_argv()): def cli_main(argv=unicode_argv()):
print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky" print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky"
if len(sys.argv)==2: if len(argv)==2:
serial = sys.argv[1] serial = argv[1]
else: else:
print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>" print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>"
return 1 return 1
if len(serial)==16: if len(serial)==16:
if serial.startswith("B"): if serial.startswith("B") or serial.startswith("9"):
print u"Kindle serial number detected" print u"Kindle serial number detected"
else: else:
print u"Warning: unrecognized serial number. Please recheck input." print u"Warning: unrecognized serial number. Please recheck input."
return 1 return 1
pid = pidFromSerial(serial.encode("utf-8"),7)+'*' pid = pidFromSerial(serial.encode("utf-8"),7)+'*'
print u"Mobipocket PID for Kindle serial#{0} is {1} ".format(serial,checksumPid(pid)) print u"Mobipocket PID for Kindle serial#{0} is {1}".format(serial,checksumPid(pid))
return 0 return 0
elif len(serial)==40: elif len(serial)==40:
print u"iPhone serial number (UDID) detected" print u"iPhone serial number (UDID) detected"
pid = pidFromSerial(serial.encode("utf-8"),8) pid = pidFromSerial(serial.encode("utf-8"),8)
print u"Mobipocket PID for iPhone serial#{0} is {1} ".format(serial,checksumPid(pid)) print u"Mobipocket PID for iPhone serial#{0} is {1}".format(serial,checksumPid(pid))
return 0 return 0
print u"Warning: unrecognized serial number. Please recheck input." print u"Warning: unrecognized serial number. Please recheck input."
return 1 return 1
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -208,7 +208,7 @@ CryptUnprotectData = CryptUnprotectData()
def getKindleInfoFiles(): def getKindleInfoFiles():
kInfoFiles = [] kInfoFiles = []
# some 64 bit machines do not have the proper registry key for some reason # some 64 bit machines do not have the proper registry key for some reason
# or the pythonn interface to the 32 vs 64 bit registry is broken # or the python interface to the 32 vs 64 bit registry is broken
path = "" path = ""
if 'LOCALAPPDATA' in os.environ.keys(): if 'LOCALAPPDATA' in os.environ.keys():
path = os.environ['LOCALAPPDATA'] path = os.environ['LOCALAPPDATA']
@ -217,17 +217,17 @@ def getKindleInfoFiles():
try: try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\") regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0] path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
except WindowsError:
pass
if not os.path.isdir(path):
path = ""
try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
except WindowsError:
pass
if not os.path.isdir(path): if not os.path.isdir(path):
path = "" path = ""
try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
if not os.path.isdir(path):
path = ""
except RegError:
pass
except RegError:
pass
found = False found = False
if path == "": if path == "":

View File

@ -66,9 +66,10 @@
# 0.36 - fixed problem with TEXtREAd and getBookTitle interface # 0.36 - fixed problem with TEXtREAd and getBookTitle interface
# 0.37 - Fixed double announcement for stand-alone operation # 0.37 - Fixed double announcement for stand-alone operation
# 0.38 - Unicode used wherever possible, cope with absent alfcrypto # 0.38 - Unicode used wherever possible, cope with absent alfcrypto
# 0.39 - Fixed problem with TEXtREAd and getBookType interface
__version__ = u"0.38" __version__ = u"0.39"
import sys import sys
import os import os
@ -268,19 +269,22 @@ class MobiBook:
self.records, = struct.unpack('>H', self.sect[0x8:0x8+2]) self.records, = struct.unpack('>H', self.sect[0x8:0x8+2])
self.compression, = struct.unpack('>H', self.sect[0x0:0x0+2]) self.compression, = struct.unpack('>H', self.sect[0x0:0x0+2])
# det default values before PalmDoc test
self.print_replica = False
self.extra_data_flags = 0
self.meta_array = {}
self.mobi_length = 0
self.mobi_codepage = 1252
self.mobi_version = -1
if self.magic == 'TEXtREAd': if self.magic == 'TEXtREAd':
print u"PalmDoc format book detected." print u"PalmDoc format book detected."
self.extra_data_flags = 0
self.mobi_length = 0
self.mobi_codepage = 1252
self.mobi_version = -1
self.meta_array = {}
return return
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18]) self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20]) self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20])
self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C]) self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C])
print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length) print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length)
self.extra_data_flags = 0
if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5): if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5):
self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4]) self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4])
print u"Extra Data Flags: {0:d}".format(self.extra_data_flags) print u"Extra Data Flags: {0:d}".format(self.extra_data_flags)
@ -290,7 +294,6 @@ class MobiBook:
self.extra_data_flags &= 0xFFFE self.extra_data_flags &= 0xFFFE
# if exth region exists parse it for metadata array # if exth region exists parse it for metadata array
self.meta_array = {}
try: try:
exth_flag, = struct.unpack('>L', self.sect[0x80:0x84]) exth_flag, = struct.unpack('>L', self.sect[0x80:0x84])
exth = '' exth = ''
@ -313,9 +316,7 @@ class MobiBook:
# print type, size, content, content.encode('hex') # print type, size, content, content.encode('hex')
pos += size pos += size
except: except:
self.meta_array = {}
pass pass
self.print_replica = False
def getBookTitle(self): def getBookTitle(self):
codec_map = { codec_map = {
@ -406,7 +407,9 @@ class MobiBook:
return u"Print Replica" return u"Print Replica"
if self.mobi_version >= 8: if self.mobi_version >= 8:
return u"Kindle Format 8" return u"Kindle Format 8"
return u"Mobipocket" if self.mobi_version >= 0:
return u"Mobipocket {0:d}".format(self.mobi_version)
return u"PalmDoc"
def getBookExtension(self): def getBookExtension(self):
if self.print_replica: if self.print_replica:

View File

@ -41,7 +41,7 @@ Mac OS X 10.5 and above: You do
\i not \i not
\i0 need to install Python.\ \i0 need to install Python.\
\ \
Drag the DeDRM application from from tools_v5.6\\DeDRM_Applications\\Macintosh (the location of this ReadMe) to your Applications folder, or anywhere else you find convenient.\ Drag the DeDRM application from from tools_v5.6.1\\DeDRM_Applications\\Macintosh (the location of this ReadMe) to your Applications folder, or anywhere else you find convenient.\
\ \
\ \

View File

@ -24,17 +24,17 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>droplet</string> <string>droplet</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>DeDRM 5.6. AppleScript written 20102013 by Apprentice Alf and others.</string> <string>DeDRM 5.6.1. AppleScript written 20102013 by Apprentice Alf and others.</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>DeDRM</string> <string>DeDRM</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>DeDRM 5.6</string> <string>DeDRM 5.6.1</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>5.6</string> <string>5.6.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>dplt</string> <string>dplt</string>
<key>LSRequiresCarbon</key> <key>LSRequiresCarbon</key>

View File

@ -208,7 +208,7 @@ CryptUnprotectData = CryptUnprotectData()
def getKindleInfoFiles(): def getKindleInfoFiles():
kInfoFiles = [] kInfoFiles = []
# some 64 bit machines do not have the proper registry key for some reason # some 64 bit machines do not have the proper registry key for some reason
# or the pythonn interface to the 32 vs 64 bit registry is broken # or the python interface to the 32 vs 64 bit registry is broken
path = "" path = ""
if 'LOCALAPPDATA' in os.environ.keys(): if 'LOCALAPPDATA' in os.environ.keys():
path = os.environ['LOCALAPPDATA'] path = os.environ['LOCALAPPDATA']
@ -217,17 +217,17 @@ def getKindleInfoFiles():
try: try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\") regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0] path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
except WindowsError:
pass
if not os.path.isdir(path):
path = ""
try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
except WindowsError:
pass
if not os.path.isdir(path): if not os.path.isdir(path):
path = "" path = ""
try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
if not os.path.isdir(path):
path = ""
except RegError:
pass
except RegError:
pass
found = False found = False
if path == "": if path == "":

View File

@ -8,6 +8,7 @@
# 0.2 Added support for generating PID for iPhone (thanks to mbp) # 0.2 Added support for generating PID for iPhone (thanks to mbp)
# 0.3 changed to autoflush stdout, fixed return code usage # 0.3 changed to autoflush stdout, fixed return code usage
# 0.3 updated for unicode # 0.3 updated for unicode
# 0.4 Added support for serial numbers starting with '9', fixed unicode bugs.
import sys import sys
import binascii import binascii
@ -63,7 +64,7 @@ def unicode_argv():
xrange(start, argc.value)] xrange(start, argc.value)]
# if we don't have any arguments at all, just pass back script name # if we don't have any arguments at all, just pass back script name
# this should never happen # this should never happen
return [u"mobidedrm.py"] return [u"kindlepid.py"]
else: else:
argvencoding = sys.stdin.encoding argvencoding = sys.stdin.encoding
if argvencoding == None: if argvencoding == None:
@ -92,7 +93,6 @@ def checksumPid(s):
return res return res
def pidFromSerial(s, l): def pidFromSerial(s, l):
crc = crc32(s) crc = crc32(s)
@ -113,27 +113,27 @@ def pidFromSerial(s, l):
def cli_main(argv=unicode_argv()): def cli_main(argv=unicode_argv()):
print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky" print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky"
if len(sys.argv)==2: if len(argv)==2:
serial = sys.argv[1] serial = argv[1]
else: else:
print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>" print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>"
return 1 return 1
if len(serial)==16: if len(serial)==16:
if serial.startswith("B"): if serial.startswith("B") or serial.startswith("9"):
print u"Kindle serial number detected" print u"Kindle serial number detected"
else: else:
print u"Warning: unrecognized serial number. Please recheck input." print u"Warning: unrecognized serial number. Please recheck input."
return 1 return 1
pid = pidFromSerial(serial.encode("utf-8"),7)+'*' pid = pidFromSerial(serial.encode("utf-8"),7)+'*'
print u"Mobipocket PID for Kindle serial#{0} is {1} ".format(serial,checksumPid(pid)) print u"Mobipocket PID for Kindle serial#{0} is {1}".format(serial,checksumPid(pid))
return 0 return 0
elif len(serial)==40: elif len(serial)==40:
print u"iPhone serial number (UDID) detected" print u"iPhone serial number (UDID) detected"
pid = pidFromSerial(serial.encode("utf-8"),8) pid = pidFromSerial(serial.encode("utf-8"),8)
print u"Mobipocket PID for iPhone serial#{0} is {1} ".format(serial,checksumPid(pid)) print u"Mobipocket PID for iPhone serial#{0} is {1}".format(serial,checksumPid(pid))
return 0 return 0
print u"Warning: unrecognized serial number. Please recheck input." print u"Warning: unrecognized serial number. Please recheck input."
return 1 return 1
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -66,9 +66,10 @@
# 0.36 - fixed problem with TEXtREAd and getBookTitle interface # 0.36 - fixed problem with TEXtREAd and getBookTitle interface
# 0.37 - Fixed double announcement for stand-alone operation # 0.37 - Fixed double announcement for stand-alone operation
# 0.38 - Unicode used wherever possible, cope with absent alfcrypto # 0.38 - Unicode used wherever possible, cope with absent alfcrypto
# 0.39 - Fixed problem with TEXtREAd and getBookType interface
__version__ = u"0.38" __version__ = u"0.39"
import sys import sys
import os import os
@ -268,19 +269,22 @@ class MobiBook:
self.records, = struct.unpack('>H', self.sect[0x8:0x8+2]) self.records, = struct.unpack('>H', self.sect[0x8:0x8+2])
self.compression, = struct.unpack('>H', self.sect[0x0:0x0+2]) self.compression, = struct.unpack('>H', self.sect[0x0:0x0+2])
# det default values before PalmDoc test
self.print_replica = False
self.extra_data_flags = 0
self.meta_array = {}
self.mobi_length = 0
self.mobi_codepage = 1252
self.mobi_version = -1
if self.magic == 'TEXtREAd': if self.magic == 'TEXtREAd':
print u"PalmDoc format book detected." print u"PalmDoc format book detected."
self.extra_data_flags = 0
self.mobi_length = 0
self.mobi_codepage = 1252
self.mobi_version = -1
self.meta_array = {}
return return
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18]) self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20]) self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20])
self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C]) self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C])
print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length) print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length)
self.extra_data_flags = 0
if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5): if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5):
self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4]) self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4])
print u"Extra Data Flags: {0:d}".format(self.extra_data_flags) print u"Extra Data Flags: {0:d}".format(self.extra_data_flags)
@ -290,7 +294,6 @@ class MobiBook:
self.extra_data_flags &= 0xFFFE self.extra_data_flags &= 0xFFFE
# if exth region exists parse it for metadata array # if exth region exists parse it for metadata array
self.meta_array = {}
try: try:
exth_flag, = struct.unpack('>L', self.sect[0x80:0x84]) exth_flag, = struct.unpack('>L', self.sect[0x80:0x84])
exth = '' exth = ''
@ -313,9 +316,7 @@ class MobiBook:
# print type, size, content, content.encode('hex') # print type, size, content, content.encode('hex')
pos += size pos += size
except: except:
self.meta_array = {}
pass pass
self.print_replica = False
def getBookTitle(self): def getBookTitle(self):
codec_map = { codec_map = {
@ -406,7 +407,9 @@ class MobiBook:
return u"Print Replica" return u"Print Replica"
if self.mobi_version >= 8: if self.mobi_version >= 8:
return u"Kindle Format 8" return u"Kindle Format 8"
return u"Mobipocket" if self.mobi_version >= 0:
return u"Mobipocket {0:d}".format(self.mobi_version)
return u"PalmDoc"
def getBookExtension(self): def getBookExtension(self):
if self.print_replica: if self.print_replica:

View File

@ -1,4 +1,4 @@
echo off echo off
set PWD=%~dp0 set PWD=%~dp0
cd /d %PWD%\DeDRM_lib && start /min python DeDRM_app.pyw %* cd /d %PWD%DeDRM_lib && start /min python DeDRM_app.pyw %*
exit exit

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# DeDRM.pyw, version 5.6 # DeDRM.pyw, version 5.6.1
# By some_updates and Apprentice Alf # By some_updates and Apprentice Alf
import sys import sys
@ -34,23 +34,19 @@ from scriptinterface import decryptepub, decryptpdb, decryptpdf, decryptk4mobi
# Wrap a stream so that output gets flushed immediately # Wrap a stream so that output gets flushed immediately
# and appended to shared queue # and appended to shared queue
class QueuedStream: class QueuedUTF8Stream:
def __init__(self, stream, q): def __init__(self, stream, q):
self.stream = stream self.stream = stream
self.encoding = stream.encoding self.encoding = 'utf-8'
self.q = q self.q = q
if self.encoding == None:
self.encoding = "utf-8"
def write(self, data): def write(self, data):
if isinstance(data,unicode): if isinstance(data,unicode):
data = data.encode(self.encoding,"replace") data = data.encode('utf-8',"replace")
self.q.put(data) self.q.put(data)
# self.stream.write(data)
# self.stream.flush()
def __getattr__(self, attr): def __getattr__(self, attr):
return getattr(self.stream, attr) return getattr(self.stream, attr)
__version__ = '5.6' __version__ = '5.6.1'
class DrmException(Exception): class DrmException(Exception):
pass pass
@ -280,7 +276,7 @@ class PrefsDialog(Toplevel):
def get_altinfopath(self): def get_altinfopath(self):
cpath = self.altinfopath.get() cpath = self.altinfopath.get()
altinfopath = tkFileDialog.askopenfilename(parent=None, title='Select Alternative kindle.info or .kinf File', altinfopath = tkFileDialog.askopenfilename(parent=None, title='Select Alternative kindle.info or .kinf File',
defaultextension='.info', filetypes=[('Kindle Info', '.info'),('Kindle KInf','.kinf')('All Files', '.*')], defaultextension='.info', filetypes=[('Kindle Info', '.info'),('Kindle KInf','.kinf'),('All Files', '.*')],
initialdir=cpath) initialdir=cpath)
if altinfopath: if altinfopath:
altinfopath = os.path.normpath(altinfopath) altinfopath = os.path.normpath(altinfopath)
@ -291,17 +287,17 @@ class PrefsDialog(Toplevel):
def get_bookpath(self): def get_bookpath(self):
cpath = self.bookpath.get() cpath = self.bookpath.get()
bookpath = tkFileDialog.askopenfilename(parent=None, title='Select eBook for DRM Removal', bookpath = tkFileDialog.askopenfilename(parent=None, title='Select eBook for DRM Removal',
filetypes=[('ePub Files','.epub'), filetypes=[('All Files', '.*'),
('Kindle','.azw'), ('ePub Files','.epub'),
('Kindle','.azw1'), ('Kindle','.azw'),
('Kindle','.azw3'), ('Kindle','.azw1'),
('Kindle','.azw4'), ('Kindle','.azw3'),
('Kindle','.tpz'), ('Kindle','.azw4'),
('Kindle','.mobi'), ('Kindle','.tpz'),
('Kindle','.prc'), ('Kindle','.mobi'),
('eReader','.pdb'), ('Kindle','.prc'),
('PDF','.pdf'), ('eReader','.pdb'),
('All Files', '.*')], ('PDF','.pdf')],
initialdir=cpath) initialdir=cpath)
if bookpath: if bookpath:
bookpath = os.path.normpath(bookpath) bookpath = os.path.normpath(bookpath)
@ -412,8 +408,9 @@ class ConvDialog(Toplevel):
self.showCmdOutput(msg) self.showCmdOutput(msg)
if self.numbad == 0: if self.numbad == 0:
self.after(2000,self.conversion_done()) self.after(2000,self.conversion_done())
logfile = os.path.join(rscpath,'dedrm.log') logfile = os.path.join(os.path.expanduser('~'),'DeDRM.log')
file(logfile,'wb').write(self.log) file(logfile,'w').write(self.log)
self.log=''
return return
infile = filename infile = filename
bname = os.path.basename(infile) bname = os.path.basename(infile)
@ -537,8 +534,8 @@ class ConvDialog(Toplevel):
def processK4MOBI(q, infile, outdir, rscpath): def processK4MOBI(q, infile, outdir, rscpath):
add_cp65001_codec() add_cp65001_codec()
set_utf8_default_encoding() set_utf8_default_encoding()
sys.stdout = QueuedStream(sys.stdout, q) sys.stdout = QueuedUTF8Stream(sys.stdout, q)
sys.stderr = QueuedStream(sys.stderr, q) sys.stderr = QueuedUTF8Stream(sys.stderr, q)
rv = decryptk4mobi(infile, outdir, rscpath) rv = decryptk4mobi(infile, outdir, rscpath)
sys.exit(rv) sys.exit(rv)
@ -546,8 +543,8 @@ def processK4MOBI(q, infile, outdir, rscpath):
def processPDF(q, infile, outdir, rscpath): def processPDF(q, infile, outdir, rscpath):
add_cp65001_codec() add_cp65001_codec()
set_utf8_default_encoding() set_utf8_default_encoding()
sys.stdout = QueuedStream(sys.stdout, q) sys.stdout = QueuedUTF8Stream(sys.stdout, q)
sys.stderr = QueuedStream(sys.stderr, q) sys.stderr = QueuedUTF8Stream(sys.stderr, q)
rv = decryptpdf(infile, outdir, rscpath) rv = decryptpdf(infile, outdir, rscpath)
sys.exit(rv) sys.exit(rv)
@ -555,8 +552,8 @@ def processPDF(q, infile, outdir, rscpath):
def processEPUB(q, infile, outdir, rscpath): def processEPUB(q, infile, outdir, rscpath):
add_cp65001_codec() add_cp65001_codec()
set_utf8_default_encoding() set_utf8_default_encoding()
sys.stdout = QueuedStream(sys.stdout, q) sys.stdout = QueuedUTF8Stream(sys.stdout, q)
sys.stderr = QueuedStream(sys.stderr, q) sys.stderr = QueuedUTF8Stream(sys.stderr, q)
rv = decryptepub(infile, outdir, rscpath) rv = decryptepub(infile, outdir, rscpath)
sys.exit(rv) sys.exit(rv)
@ -564,8 +561,8 @@ def processEPUB(q, infile, outdir, rscpath):
def processPDB(q, infile, outdir, rscpath): def processPDB(q, infile, outdir, rscpath):
add_cp65001_codec() add_cp65001_codec()
set_utf8_default_encoding() set_utf8_default_encoding()
sys.stdout = QueuedStream(sys.stdout, q) sys.stdout = QueuedUTF8Stream(sys.stdout, q)
sys.stderr = QueuedStream(sys.stderr, q) sys.stderr = QueuedUTF8Stream(sys.stderr, q)
rv = decryptpdb(infile, outdir, rscpath) rv = decryptpdb(infile, outdir, rscpath)
sys.exit(rv) sys.exit(rv)

View File

@ -208,7 +208,7 @@ CryptUnprotectData = CryptUnprotectData()
def getKindleInfoFiles(): def getKindleInfoFiles():
kInfoFiles = [] kInfoFiles = []
# some 64 bit machines do not have the proper registry key for some reason # some 64 bit machines do not have the proper registry key for some reason
# or the pythonn interface to the 32 vs 64 bit registry is broken # or the python interface to the 32 vs 64 bit registry is broken
path = "" path = ""
if 'LOCALAPPDATA' in os.environ.keys(): if 'LOCALAPPDATA' in os.environ.keys():
path = os.environ['LOCALAPPDATA'] path = os.environ['LOCALAPPDATA']
@ -217,17 +217,17 @@ def getKindleInfoFiles():
try: try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\") regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0] path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
except WindowsError:
pass
if not os.path.isdir(path):
path = ""
try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
except WindowsError:
pass
if not os.path.isdir(path): if not os.path.isdir(path):
path = "" path = ""
try:
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
if not os.path.isdir(path):
path = ""
except RegError:
pass
except RegError:
pass
found = False found = False
if path == "": if path == "":

View File

@ -8,6 +8,7 @@
# 0.2 Added support for generating PID for iPhone (thanks to mbp) # 0.2 Added support for generating PID for iPhone (thanks to mbp)
# 0.3 changed to autoflush stdout, fixed return code usage # 0.3 changed to autoflush stdout, fixed return code usage
# 0.3 updated for unicode # 0.3 updated for unicode
# 0.4 Added support for serial numbers starting with '9', fixed unicode bugs.
import sys import sys
import binascii import binascii
@ -63,7 +64,7 @@ def unicode_argv():
xrange(start, argc.value)] xrange(start, argc.value)]
# if we don't have any arguments at all, just pass back script name # if we don't have any arguments at all, just pass back script name
# this should never happen # this should never happen
return [u"mobidedrm.py"] return [u"kindlepid.py"]
else: else:
argvencoding = sys.stdin.encoding argvencoding = sys.stdin.encoding
if argvencoding == None: if argvencoding == None:
@ -92,7 +93,6 @@ def checksumPid(s):
return res return res
def pidFromSerial(s, l): def pidFromSerial(s, l):
crc = crc32(s) crc = crc32(s)
@ -113,27 +113,27 @@ def pidFromSerial(s, l):
def cli_main(argv=unicode_argv()): def cli_main(argv=unicode_argv()):
print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky" print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky"
if len(sys.argv)==2: if len(argv)==2:
serial = sys.argv[1] serial = argv[1]
else: else:
print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>" print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>"
return 1 return 1
if len(serial)==16: if len(serial)==16:
if serial.startswith("B"): if serial.startswith("B") or serial.startswith("9"):
print u"Kindle serial number detected" print u"Kindle serial number detected"
else: else:
print u"Warning: unrecognized serial number. Please recheck input." print u"Warning: unrecognized serial number. Please recheck input."
return 1 return 1
pid = pidFromSerial(serial.encode("utf-8"),7)+'*' pid = pidFromSerial(serial.encode("utf-8"),7)+'*'
print u"Mobipocket PID for Kindle serial#{0} is {1} ".format(serial,checksumPid(pid)) print u"Mobipocket PID for Kindle serial#{0} is {1}".format(serial,checksumPid(pid))
return 0 return 0
elif len(serial)==40: elif len(serial)==40:
print u"iPhone serial number (UDID) detected" print u"iPhone serial number (UDID) detected"
pid = pidFromSerial(serial.encode("utf-8"),8) pid = pidFromSerial(serial.encode("utf-8"),8)
print u"Mobipocket PID for iPhone serial#{0} is {1} ".format(serial,checksumPid(pid)) print u"Mobipocket PID for iPhone serial#{0} is {1}".format(serial,checksumPid(pid))
return 0 return 0
print u"Warning: unrecognized serial number. Please recheck input." print u"Warning: unrecognized serial number. Please recheck input."
return 1 return 1
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -66,9 +66,10 @@
# 0.36 - fixed problem with TEXtREAd and getBookTitle interface # 0.36 - fixed problem with TEXtREAd and getBookTitle interface
# 0.37 - Fixed double announcement for stand-alone operation # 0.37 - Fixed double announcement for stand-alone operation
# 0.38 - Unicode used wherever possible, cope with absent alfcrypto # 0.38 - Unicode used wherever possible, cope with absent alfcrypto
# 0.39 - Fixed problem with TEXtREAd and getBookType interface
__version__ = u"0.38" __version__ = u"0.39"
import sys import sys
import os import os
@ -268,19 +269,22 @@ class MobiBook:
self.records, = struct.unpack('>H', self.sect[0x8:0x8+2]) self.records, = struct.unpack('>H', self.sect[0x8:0x8+2])
self.compression, = struct.unpack('>H', self.sect[0x0:0x0+2]) self.compression, = struct.unpack('>H', self.sect[0x0:0x0+2])
# det default values before PalmDoc test
self.print_replica = False
self.extra_data_flags = 0
self.meta_array = {}
self.mobi_length = 0
self.mobi_codepage = 1252
self.mobi_version = -1
if self.magic == 'TEXtREAd': if self.magic == 'TEXtREAd':
print u"PalmDoc format book detected." print u"PalmDoc format book detected."
self.extra_data_flags = 0
self.mobi_length = 0
self.mobi_codepage = 1252
self.mobi_version = -1
self.meta_array = {}
return return
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18]) self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20]) self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20])
self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C]) self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C])
print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length) print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length)
self.extra_data_flags = 0
if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5): if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5):
self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4]) self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4])
print u"Extra Data Flags: {0:d}".format(self.extra_data_flags) print u"Extra Data Flags: {0:d}".format(self.extra_data_flags)
@ -290,7 +294,6 @@ class MobiBook:
self.extra_data_flags &= 0xFFFE self.extra_data_flags &= 0xFFFE
# if exth region exists parse it for metadata array # if exth region exists parse it for metadata array
self.meta_array = {}
try: try:
exth_flag, = struct.unpack('>L', self.sect[0x80:0x84]) exth_flag, = struct.unpack('>L', self.sect[0x80:0x84])
exth = '' exth = ''
@ -313,9 +316,7 @@ class MobiBook:
# print type, size, content, content.encode('hex') # print type, size, content, content.encode('hex')
pos += size pos += size
except: except:
self.meta_array = {}
pass pass
self.print_replica = False
def getBookTitle(self): def getBookTitle(self):
codec_map = { codec_map = {
@ -406,7 +407,9 @@ class MobiBook:
return u"Print Replica" return u"Print Replica"
if self.mobi_version >= 8: if self.mobi_version >= 8:
return u"Kindle Format 8" return u"Kindle Format 8"
return u"Mobipocket" if self.mobi_version >= 0:
return u"Mobipocket {0:d}".format(self.mobi_version)
return u"PalmDoc"
def getBookExtension(self): def getBookExtension(self):
if self.print_replica: if self.print_replica: