2
0
mirror of https://github.com/apprenticeharper/DeDRM_tools synced 2024-11-18 21:25:39 +00:00

tools v3.8

This commit is contained in:
Apprentice Alf 2011-03-28 13:01:05 +01:00
parent 867ac35b45
commit 4163d5ccf4
22 changed files with 346 additions and 306 deletions

View File

@ -323,12 +323,12 @@ def generateBook(bookDir, raw, fixedimage):
meta_array = getMetaArray(metaFile) meta_array = getMetaArray(metaFile)
# replace special chars in title and authors like & < > # replace special chars in title and authors like & < >
title = meta_array['Title'] title = meta_array.get('Title','No Title Provided')
title = title.replace('&','&amp;') title = title.replace('&','&amp;')
title = title.replace('<','&lt;') title = title.replace('<','&lt;')
title = title.replace('>','&gt;') title = title.replace('>','&gt;')
meta_array['Title'] = title meta_array['Title'] = title
authors = meta_array['Authors'] authors = meta_array.get('Authors','No Authors Provided')
authors = authors.replace('&','&amp;') authors = authors.replace('&','&amp;')
authors = authors.replace('<','&lt;') authors = authors.replace('<','&lt;')
authors = authors.replace('>','&gt;') authors = authors.replace('>','&gt;')
@ -413,8 +413,10 @@ def generateBook(bookDir, raw, fixedimage):
htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n' htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n'
htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n' htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n'
htmlstr += '</head>\n<body>\n' htmlstr += '</head>\n<body>\n'
@ -430,8 +432,10 @@ def generateBook(bookDir, raw, fixedimage):
svgindex += '<title>' + meta_array['Title'] + '</title>\n' svgindex += '<title>' + meta_array['Title'] + '</title>\n'
svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
svgindex += '</head>\n' svgindex += '</head>\n'
svgindex += '<body>\n' svgindex += '<body>\n'
@ -485,9 +489,12 @@ def generateBook(bookDir, raw, fixedimage):
opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n' opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n'
# adding metadata # adding metadata
opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n' opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n'
opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n' if 'GUID' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n' opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n'
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n' if 'ASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n'
if 'oASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n'
opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n' opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n'
opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n' opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n'
opfstr += ' <dc:language>en</dc:language>\n' opfstr += ' <dc:language>en</dc:language>\n'

View File

@ -18,9 +18,9 @@ global charMap3
global charMap4 global charMap4
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
from k4pcutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4pcutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin'):
from k4mutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4mutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M" charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M"
charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
@ -67,22 +67,6 @@ def decode(data,map):
result += pack("B",value) result += pack("B",value)
return result return result
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = openKindleInfo(kInfoFile)
infoReader.read(1)
data = infoReader.read()
if sys.platform.startswith('win'):
items = data.split('{')
else :
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB
# Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded). # Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded).
# Return the decoded and decrypted record # Return the decoded and decrypted record
def getKindleInfoValueForHash(hashedKey): def getKindleInfoValueForHash(hashedKey):
@ -241,7 +225,7 @@ def getKindlePid(pidlst, rec209, token, serialnum):
# Parse the EXTH header records and parse the Kindleinfo # Parse the EXTH header records and parse the Kindleinfo
# file to calculate the book pid. # file to calculate the book pid.
def getK4Pids(pidlst, rec209, token, kInfoFile=None): def getK4Pids(pidlst, rec209, token, kInfoFile):
global kindleDatabase global kindleDatabase
global charMap1 global charMap1
kindleDatabase = None kindleDatabase = None
@ -254,10 +238,17 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
if kindleDatabase == None : if kindleDatabase == None :
return pidlst return pidlst
try:
# Get the Mazama Random number
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber")
# Get the Mazama Random number # Get the kindle account token
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber") kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
except KeyError:
print "Keys not found in " + kInfoFile
return pidlst
# Get the HDD serial # Get the HDD serial
encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1) encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1)
@ -273,10 +264,7 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
devicePID = checksumPid(devicePID) devicePID = checksumPid(devicePID)
pidlst.append(devicePID) pidlst.append(devicePID)
# Compute book PID # Compute book PIDs
# Get the kindle account token
kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
# book pid # book pid
pidHash = SHA1(DSN+kindleAccountToken+rec209+token) pidHash = SHA1(DSN+kindleAccountToken+rec209+token)
@ -300,8 +288,10 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
def getPidList(md1, md2, k4, pids, serials, kInfoFiles): def getPidList(md1, md2, k4, pids, serials, kInfoFiles):
pidlst = [] pidlst = []
if kInfoFiles is None:
kInfoFiles = []
if k4: if k4:
pidlst = getK4Pids(pidlst, md1, md2) kInfoFiles = getKindleInfoFiles(kInfoFiles)
for infoFile in kInfoFiles: for infoFile in kInfoFiles:
pidlst = getK4Pids(pidlst, md1, md2, infoFile) pidlst = getK4Pids(pidlst, md1, md2, infoFile)
for serialnum in serials: for serialnum in serials:

View File

@ -29,7 +29,7 @@ from __future__ import with_statement
# and import that ZIP into Calibre using its plugin configuration GUI. # and import that ZIP into Calibre using its plugin configuration GUI.
__version__ = '2.7' __version__ = '2.8'
class Unbuffered: class Unbuffered:
def __init__(self, stream): def __init__(self, stream):
@ -250,7 +250,7 @@ if not __name__ == "__main__" and inCalibre:
Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.' Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.'
supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on
author = 'DiapDealer, SomeUpdates' # The author of this plugin author = 'DiapDealer, SomeUpdates' # The author of this plugin
version = (0, 2, 7) # The version number of this plugin version = (0, 2, 8) # The version number of this plugin
file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to
on_import = True # Run this plugin during the import on_import = True # Run this plugin during the import
priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm

View File

@ -168,27 +168,33 @@ def CryptUnprotectData(encryptedData):
return cleartext return cleartext
# Locate and open the .kindle-info file # Locate the .kindle-info files
def openKindleInfo(kInfoFile=None): def getKindleInfoFiles(kInfoFiles):
if kInfoFile == None: home = os.getenv('HOME')
home = os.getenv('HOME') cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"'
cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"' cmdline = cmdline.encode(sys.getfilesystemencoding())
cmdline = cmdline.encode(sys.getfilesystemencoding()) p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False)
p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) out1, out2 = p1.communicate()
out1, out2 = p1.communicate() reslst = out1.split('\n')
reslst = out1.split('\n') kinfopath = 'NONE'
kinfopath = 'NONE' found = False
cnt = len(reslst) cnt = len(reslst)
for j in xrange(cnt): for resline in reslst:
resline = reslst[j] if os.path.isfile(resline):
pp = resline.find('.kindle-info') kInfoFiles.append(resline)
if pp >= 0: found = True
kinfopath = resline if not found:
break print('No .kindle-info files have been found.')
if not os.path.isfile(kinfopath): return kInfoFiles
raise DrmException('Error: .kindle-info file can not be found')
return open(kinfopath,'r') # Parse the Kindle.info file and return the records as a list of key-values
else: def parseKindleInfo(kInfoFile):
if not os.path.isfile(kInfoFile): DB = {}
raise DrmException('Error: kindle-info file can not be found') infoReader = open(kInfoFile, 'r')
return open(kInfoFile, 'r') infoReader.read(1)
data = infoReader.read()
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -93,18 +93,25 @@ def CryptUnprotectData():
return CryptUnprotectData return CryptUnprotectData
CryptUnprotectData = CryptUnprotectData() CryptUnprotectData = CryptUnprotectData()
# # Locate the .kindle-info files
# Locate and open the Kindle.info file. def getKindleInfoFiles(kInfoFiles):
# regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
def openKindleInfo(kInfoFile=None): path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
if kInfoFile == None: kinfopath = path +'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info'
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\") if not os.path.isfile(kinfopath):
path = winreg.QueryValueEx(regkey, 'Local AppData')[0] print('The kindle.info files has not been found.')
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: else:
if not os.path.isfile(kInfoFile): kInfoFiles.append(kinfopath)
raise DrmException('Error: kindle.info file can not be found') return kInfoFiles
return open(kInfoFile, 'r')
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = open(kInfoFile, 'r')
infoReader.read(1)
data = infoReader.read()
items = data.split('{')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -24,7 +24,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>droplet</string> <string>droplet</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>DeDRM 2.5, Written 20102011 by Apprentice Alf and others.</string> <string>DeDRM 2.6, Written 20102011 by Apprentice Alf and others.</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>droplet</string> <string>droplet</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
@ -34,7 +34,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.5</string> <string>2.6</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>dplt</string> <string>dplt</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>

View File

@ -323,12 +323,12 @@ def generateBook(bookDir, raw, fixedimage):
meta_array = getMetaArray(metaFile) meta_array = getMetaArray(metaFile)
# replace special chars in title and authors like & < > # replace special chars in title and authors like & < >
title = meta_array['Title'] title = meta_array.get('Title','No Title Provided')
title = title.replace('&','&amp;') title = title.replace('&','&amp;')
title = title.replace('<','&lt;') title = title.replace('<','&lt;')
title = title.replace('>','&gt;') title = title.replace('>','&gt;')
meta_array['Title'] = title meta_array['Title'] = title
authors = meta_array['Authors'] authors = meta_array.get('Authors','No Authors Provided')
authors = authors.replace('&','&amp;') authors = authors.replace('&','&amp;')
authors = authors.replace('<','&lt;') authors = authors.replace('<','&lt;')
authors = authors.replace('>','&gt;') authors = authors.replace('>','&gt;')
@ -413,8 +413,10 @@ def generateBook(bookDir, raw, fixedimage):
htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n' htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n'
htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n' htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n'
htmlstr += '</head>\n<body>\n' htmlstr += '</head>\n<body>\n'
@ -430,8 +432,10 @@ def generateBook(bookDir, raw, fixedimage):
svgindex += '<title>' + meta_array['Title'] + '</title>\n' svgindex += '<title>' + meta_array['Title'] + '</title>\n'
svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
svgindex += '</head>\n' svgindex += '</head>\n'
svgindex += '<body>\n' svgindex += '<body>\n'
@ -485,9 +489,12 @@ def generateBook(bookDir, raw, fixedimage):
opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n' opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n'
# adding metadata # adding metadata
opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n' opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n'
opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n' if 'GUID' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n' opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n'
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n' if 'ASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n'
if 'oASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n'
opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n' opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n'
opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n' opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n'
opfstr += ' <dc:language>en</dc:language>\n' opfstr += ' <dc:language>en</dc:language>\n'

View File

@ -29,7 +29,7 @@ from __future__ import with_statement
# and import that ZIP into Calibre using its plugin configuration GUI. # and import that ZIP into Calibre using its plugin configuration GUI.
__version__ = '2.7' __version__ = '2.8'
class Unbuffered: class Unbuffered:
def __init__(self, stream): def __init__(self, stream):
@ -250,7 +250,7 @@ if not __name__ == "__main__" and inCalibre:
Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.' Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.'
supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on
author = 'DiapDealer, SomeUpdates' # The author of this plugin author = 'DiapDealer, SomeUpdates' # The author of this plugin
version = (0, 2, 7) # The version number of this plugin version = (0, 2, 8) # The version number of this plugin
file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to
on_import = True # Run this plugin during the import on_import = True # Run this plugin during the import
priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm

View File

@ -168,27 +168,33 @@ def CryptUnprotectData(encryptedData):
return cleartext return cleartext
# Locate and open the .kindle-info file # Locate the .kindle-info files
def openKindleInfo(kInfoFile=None): def getKindleInfoFiles(kInfoFiles):
if kInfoFile == None: home = os.getenv('HOME')
home = os.getenv('HOME') cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"'
cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"' cmdline = cmdline.encode(sys.getfilesystemencoding())
cmdline = cmdline.encode(sys.getfilesystemencoding()) p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False)
p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) out1, out2 = p1.communicate()
out1, out2 = p1.communicate() reslst = out1.split('\n')
reslst = out1.split('\n') kinfopath = 'NONE'
kinfopath = 'NONE' found = False
cnt = len(reslst) cnt = len(reslst)
for j in xrange(cnt): for resline in reslst:
resline = reslst[j] if os.path.isfile(resline):
pp = resline.find('.kindle-info') kInfoFiles.append(resline)
if pp >= 0: found = True
kinfopath = resline if not found:
break print('No .kindle-info files have been found.')
if not os.path.isfile(kinfopath): return kInfoFiles
raise DrmException('Error: .kindle-info file can not be found')
return open(kinfopath,'r') # Parse the Kindle.info file and return the records as a list of key-values
else: def parseKindleInfo(kInfoFile):
if not os.path.isfile(kInfoFile): DB = {}
raise DrmException('Error: kindle-info file can not be found') infoReader = open(kInfoFile, 'r')
return open(kInfoFile, 'r') infoReader.read(1)
data = infoReader.read()
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -93,18 +93,25 @@ def CryptUnprotectData():
return CryptUnprotectData return CryptUnprotectData
CryptUnprotectData = CryptUnprotectData() CryptUnprotectData = CryptUnprotectData()
# # Locate the .kindle-info files
# Locate and open the Kindle.info file. def getKindleInfoFiles(kInfoFiles):
# regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
def openKindleInfo(kInfoFile=None): path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
if kInfoFile == None: kinfopath = path +'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info'
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\") if not os.path.isfile(kinfopath):
path = winreg.QueryValueEx(regkey, 'Local AppData')[0] print('The kindle.info files has not been found.')
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: else:
if not os.path.isfile(kInfoFile): kInfoFiles.append(kinfopath)
raise DrmException('Error: kindle.info file can not be found') return kInfoFiles
return open(kInfoFile, 'r')
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = open(kInfoFile, 'r')
infoReader.read(1)
data = infoReader.read()
items = data.split('{')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -18,9 +18,9 @@ global charMap3
global charMap4 global charMap4
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
from k4pcutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4pcutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin'):
from k4mutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4mutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M" charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M"
charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
@ -67,22 +67,6 @@ def decode(data,map):
result += pack("B",value) result += pack("B",value)
return result return result
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = openKindleInfo(kInfoFile)
infoReader.read(1)
data = infoReader.read()
if sys.platform.startswith('win'):
items = data.split('{')
else :
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB
# Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded). # Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded).
# Return the decoded and decrypted record # Return the decoded and decrypted record
def getKindleInfoValueForHash(hashedKey): def getKindleInfoValueForHash(hashedKey):
@ -241,7 +225,7 @@ def getKindlePid(pidlst, rec209, token, serialnum):
# Parse the EXTH header records and parse the Kindleinfo # Parse the EXTH header records and parse the Kindleinfo
# file to calculate the book pid. # file to calculate the book pid.
def getK4Pids(pidlst, rec209, token, kInfoFile=None): def getK4Pids(pidlst, rec209, token, kInfoFile):
global kindleDatabase global kindleDatabase
global charMap1 global charMap1
kindleDatabase = None kindleDatabase = None
@ -254,10 +238,17 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
if kindleDatabase == None : if kindleDatabase == None :
return pidlst return pidlst
try:
# Get the Mazama Random number
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber")
# Get the Mazama Random number # Get the kindle account token
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber") kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
except KeyError:
print "Keys not found in " + kInfoFile
return pidlst
# Get the HDD serial # Get the HDD serial
encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1) encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1)
@ -273,10 +264,7 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
devicePID = checksumPid(devicePID) devicePID = checksumPid(devicePID)
pidlst.append(devicePID) pidlst.append(devicePID)
# Compute book PID # Compute book PIDs
# Get the kindle account token
kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
# book pid # book pid
pidHash = SHA1(DSN+kindleAccountToken+rec209+token) pidHash = SHA1(DSN+kindleAccountToken+rec209+token)
@ -300,8 +288,10 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
def getPidList(md1, md2, k4, pids, serials, kInfoFiles): def getPidList(md1, md2, k4, pids, serials, kInfoFiles):
pidlst = [] pidlst = []
if kInfoFiles is None:
kInfoFiles = []
if k4: if k4:
pidlst = getK4Pids(pidlst, md1, md2) kInfoFiles = getKindleInfoFiles(kInfoFiles)
for infoFile in kInfoFiles: for infoFile in kInfoFiles:
pidlst = getK4Pids(pidlst, md1, md2, infoFile) pidlst = getK4Pids(pidlst, md1, md2, infoFile)
for serialnum in serials: for serialnum in serials:

View File

@ -323,12 +323,12 @@ def generateBook(bookDir, raw, fixedimage):
meta_array = getMetaArray(metaFile) meta_array = getMetaArray(metaFile)
# replace special chars in title and authors like & < > # replace special chars in title and authors like & < >
title = meta_array['Title'] title = meta_array.get('Title','No Title Provided')
title = title.replace('&','&amp;') title = title.replace('&','&amp;')
title = title.replace('<','&lt;') title = title.replace('<','&lt;')
title = title.replace('>','&gt;') title = title.replace('>','&gt;')
meta_array['Title'] = title meta_array['Title'] = title
authors = meta_array['Authors'] authors = meta_array.get('Authors','No Authors Provided')
authors = authors.replace('&','&amp;') authors = authors.replace('&','&amp;')
authors = authors.replace('<','&lt;') authors = authors.replace('<','&lt;')
authors = authors.replace('>','&gt;') authors = authors.replace('>','&gt;')
@ -413,8 +413,10 @@ def generateBook(bookDir, raw, fixedimage):
htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n' htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n'
htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n' htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n'
htmlstr += '</head>\n<body>\n' htmlstr += '</head>\n<body>\n'
@ -430,8 +432,10 @@ def generateBook(bookDir, raw, fixedimage):
svgindex += '<title>' + meta_array['Title'] + '</title>\n' svgindex += '<title>' + meta_array['Title'] + '</title>\n'
svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
svgindex += '</head>\n' svgindex += '</head>\n'
svgindex += '<body>\n' svgindex += '<body>\n'
@ -485,9 +489,12 @@ def generateBook(bookDir, raw, fixedimage):
opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n' opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n'
# adding metadata # adding metadata
opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n' opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n'
opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n' if 'GUID' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n' opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n'
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n' if 'ASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n'
if 'oASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n'
opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n' opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n'
opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n' opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n'
opfstr += ' <dc:language>en</dc:language>\n' opfstr += ' <dc:language>en</dc:language>\n'

View File

@ -29,7 +29,7 @@ from __future__ import with_statement
# and import that ZIP into Calibre using its plugin configuration GUI. # and import that ZIP into Calibre using its plugin configuration GUI.
__version__ = '2.7' __version__ = '2.8'
class Unbuffered: class Unbuffered:
def __init__(self, stream): def __init__(self, stream):
@ -250,7 +250,7 @@ if not __name__ == "__main__" and inCalibre:
Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.' Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.'
supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on
author = 'DiapDealer, SomeUpdates' # The author of this plugin author = 'DiapDealer, SomeUpdates' # The author of this plugin
version = (0, 2, 7) # The version number of this plugin version = (0, 2, 8) # The version number of this plugin
file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to
on_import = True # Run this plugin during the import on_import = True # Run this plugin during the import
priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm

View File

@ -168,27 +168,33 @@ def CryptUnprotectData(encryptedData):
return cleartext return cleartext
# Locate and open the .kindle-info file # Locate the .kindle-info files
def openKindleInfo(kInfoFile=None): def getKindleInfoFiles(kInfoFiles):
if kInfoFile == None: home = os.getenv('HOME')
home = os.getenv('HOME') cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"'
cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"' cmdline = cmdline.encode(sys.getfilesystemencoding())
cmdline = cmdline.encode(sys.getfilesystemencoding()) p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False)
p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) out1, out2 = p1.communicate()
out1, out2 = p1.communicate() reslst = out1.split('\n')
reslst = out1.split('\n') kinfopath = 'NONE'
kinfopath = 'NONE' found = False
cnt = len(reslst) cnt = len(reslst)
for j in xrange(cnt): for resline in reslst:
resline = reslst[j] if os.path.isfile(resline):
pp = resline.find('.kindle-info') kInfoFiles.append(resline)
if pp >= 0: found = True
kinfopath = resline if not found:
break print('No .kindle-info files have been found.')
if not os.path.isfile(kinfopath): return kInfoFiles
raise DrmException('Error: .kindle-info file can not be found')
return open(kinfopath,'r') # Parse the Kindle.info file and return the records as a list of key-values
else: def parseKindleInfo(kInfoFile):
if not os.path.isfile(kInfoFile): DB = {}
raise DrmException('Error: kindle-info file can not be found') infoReader = open(kInfoFile, 'r')
return open(kInfoFile, 'r') infoReader.read(1)
data = infoReader.read()
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -93,18 +93,25 @@ def CryptUnprotectData():
return CryptUnprotectData return CryptUnprotectData
CryptUnprotectData = CryptUnprotectData() CryptUnprotectData = CryptUnprotectData()
# # Locate the .kindle-info files
# Locate and open the Kindle.info file. def getKindleInfoFiles(kInfoFiles):
# regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
def openKindleInfo(kInfoFile=None): path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
if kInfoFile == None: kinfopath = path +'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info'
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\") if not os.path.isfile(kinfopath):
path = winreg.QueryValueEx(regkey, 'Local AppData')[0] print('The kindle.info files has not been found.')
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: else:
if not os.path.isfile(kInfoFile): kInfoFiles.append(kinfopath)
raise DrmException('Error: kindle.info file can not be found') return kInfoFiles
return open(kInfoFile, 'r')
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = open(kInfoFile, 'r')
infoReader.read(1)
data = infoReader.read()
items = data.split('{')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -18,9 +18,9 @@ global charMap3
global charMap4 global charMap4
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
from k4pcutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4pcutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin'):
from k4mutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4mutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M" charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M"
charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
@ -67,22 +67,6 @@ def decode(data,map):
result += pack("B",value) result += pack("B",value)
return result return result
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = openKindleInfo(kInfoFile)
infoReader.read(1)
data = infoReader.read()
if sys.platform.startswith('win'):
items = data.split('{')
else :
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB
# Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded). # Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded).
# Return the decoded and decrypted record # Return the decoded and decrypted record
def getKindleInfoValueForHash(hashedKey): def getKindleInfoValueForHash(hashedKey):
@ -241,7 +225,7 @@ def getKindlePid(pidlst, rec209, token, serialnum):
# Parse the EXTH header records and parse the Kindleinfo # Parse the EXTH header records and parse the Kindleinfo
# file to calculate the book pid. # file to calculate the book pid.
def getK4Pids(pidlst, rec209, token, kInfoFile=None): def getK4Pids(pidlst, rec209, token, kInfoFile):
global kindleDatabase global kindleDatabase
global charMap1 global charMap1
kindleDatabase = None kindleDatabase = None
@ -254,10 +238,17 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
if kindleDatabase == None : if kindleDatabase == None :
return pidlst return pidlst
try:
# Get the Mazama Random number
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber")
# Get the Mazama Random number # Get the kindle account token
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber") kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
except KeyError:
print "Keys not found in " + kInfoFile
return pidlst
# Get the HDD serial # Get the HDD serial
encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1) encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1)
@ -273,10 +264,7 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
devicePID = checksumPid(devicePID) devicePID = checksumPid(devicePID)
pidlst.append(devicePID) pidlst.append(devicePID)
# Compute book PID # Compute book PIDs
# Get the kindle account token
kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
# book pid # book pid
pidHash = SHA1(DSN+kindleAccountToken+rec209+token) pidHash = SHA1(DSN+kindleAccountToken+rec209+token)
@ -300,8 +288,10 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
def getPidList(md1, md2, k4, pids, serials, kInfoFiles): def getPidList(md1, md2, k4, pids, serials, kInfoFiles):
pidlst = [] pidlst = []
if kInfoFiles is None:
kInfoFiles = []
if k4: if k4:
pidlst = getK4Pids(pidlst, md1, md2) kInfoFiles = getKindleInfoFiles(kInfoFiles)
for infoFile in kInfoFiles: for infoFile in kInfoFiles:
pidlst = getK4Pids(pidlst, md1, md2, infoFile) pidlst = getK4Pids(pidlst, md1, md2, infoFile)
for serialnum in serials: for serialnum in serials:

View File

@ -323,12 +323,12 @@ def generateBook(bookDir, raw, fixedimage):
meta_array = getMetaArray(metaFile) meta_array = getMetaArray(metaFile)
# replace special chars in title and authors like & < > # replace special chars in title and authors like & < >
title = meta_array['Title'] title = meta_array.get('Title','No Title Provided')
title = title.replace('&','&amp;') title = title.replace('&','&amp;')
title = title.replace('<','&lt;') title = title.replace('<','&lt;')
title = title.replace('>','&gt;') title = title.replace('>','&gt;')
meta_array['Title'] = title meta_array['Title'] = title
authors = meta_array['Authors'] authors = meta_array.get('Authors','No Authors Provided')
authors = authors.replace('&','&amp;') authors = authors.replace('&','&amp;')
authors = authors.replace('<','&lt;') authors = authors.replace('<','&lt;')
authors = authors.replace('>','&gt;') authors = authors.replace('>','&gt;')
@ -413,8 +413,10 @@ def generateBook(bookDir, raw, fixedimage):
htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n' htmlstr += '<title>' + meta_array['Title'] + ' by ' + meta_array['Authors'] + '</title>\n'
htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' htmlstr += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' htmlstr += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' htmlstr += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
htmlstr += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n' htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n'
htmlstr += '</head>\n<body>\n' htmlstr += '</head>\n<body>\n'
@ -430,8 +432,10 @@ def generateBook(bookDir, raw, fixedimage):
svgindex += '<title>' + meta_array['Title'] + '</title>\n' svgindex += '<title>' + meta_array['Title'] + '</title>\n'
svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n' svgindex += '<meta name="Author" content="' + meta_array['Authors'] + '" />\n'
svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n' svgindex += '<meta name="Title" content="' + meta_array['Title'] + '" />\n'
svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n' if 'ASIN' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n' svgindex += '<meta name="ASIN" content="' + meta_array['ASIN'] + '" />\n'
if 'GUID' in meta_array:
svgindex += '<meta name="GUID" content="' + meta_array['GUID'] + '" />\n'
svgindex += '</head>\n' svgindex += '</head>\n'
svgindex += '<body>\n' svgindex += '<body>\n'
@ -485,9 +489,12 @@ def generateBook(bookDir, raw, fixedimage):
opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n' opfstr += '<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="guid_id">\n'
# adding metadata # adding metadata
opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n' opfstr += ' <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">\n'
opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n' if 'GUID' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n' opfstr += ' <dc:identifier opf:scheme="GUID" id="guid_id">' + meta_array['GUID'] + '</dc:identifier>\n'
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n' if 'ASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="ASIN">' + meta_array['ASIN'] + '</dc:identifier>\n'
if 'oASIN' in meta_array:
opfstr += ' <dc:identifier opf:scheme="oASIN">' + meta_array['oASIN'] + '</dc:identifier>\n'
opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n' opfstr += ' <dc:title>' + meta_array['Title'] + '</dc:title>\n'
opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n' opfstr += ' <dc:creator opf:role="aut">' + meta_array['Authors'] + '</dc:creator>\n'
opfstr += ' <dc:language>en</dc:language>\n' opfstr += ' <dc:language>en</dc:language>\n'

View File

@ -29,7 +29,7 @@ from __future__ import with_statement
# and import that ZIP into Calibre using its plugin configuration GUI. # and import that ZIP into Calibre using its plugin configuration GUI.
__version__ = '2.7' __version__ = '2.8'
class Unbuffered: class Unbuffered:
def __init__(self, stream): def __init__(self, stream):
@ -250,7 +250,7 @@ if not __name__ == "__main__" and inCalibre:
Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.' Provided by the work of many including DiapDealer, SomeUpdates, IHeartCabbages, CMBDTC, Skindle, DarkReverser, ApprenticeAlf, etc.'
supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on supported_platforms = ['osx', 'windows', 'linux'] # Platforms this plugin will run on
author = 'DiapDealer, SomeUpdates' # The author of this plugin author = 'DiapDealer, SomeUpdates' # The author of this plugin
version = (0, 2, 7) # The version number of this plugin version = (0, 2, 8) # The version number of this plugin
file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to file_types = set(['prc','mobi','azw','azw1','tpz']) # The file types that this plugin will be applied to
on_import = True # Run this plugin during the import on_import = True # Run this plugin during the import
priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm priority = 210 # run this plugin before mobidedrm, k4pcdedrm, k4dedrm

View File

@ -168,27 +168,33 @@ def CryptUnprotectData(encryptedData):
return cleartext return cleartext
# Locate and open the .kindle-info file # Locate the .kindle-info files
def openKindleInfo(kInfoFile=None): def getKindleInfoFiles(kInfoFiles):
if kInfoFile == None: home = os.getenv('HOME')
home = os.getenv('HOME') cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"'
cmdline = 'find "' + home + '/Library/Application Support" -name ".kindle-info"' cmdline = cmdline.encode(sys.getfilesystemencoding())
cmdline = cmdline.encode(sys.getfilesystemencoding()) p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False)
p1 = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False) out1, out2 = p1.communicate()
out1, out2 = p1.communicate() reslst = out1.split('\n')
reslst = out1.split('\n') kinfopath = 'NONE'
kinfopath = 'NONE' found = False
cnt = len(reslst) cnt = len(reslst)
for j in xrange(cnt): for resline in reslst:
resline = reslst[j] if os.path.isfile(resline):
pp = resline.find('.kindle-info') kInfoFiles.append(resline)
if pp >= 0: found = True
kinfopath = resline if not found:
break print('No .kindle-info files have been found.')
if not os.path.isfile(kinfopath): return kInfoFiles
raise DrmException('Error: .kindle-info file can not be found')
return open(kinfopath,'r') # Parse the Kindle.info file and return the records as a list of key-values
else: def parseKindleInfo(kInfoFile):
if not os.path.isfile(kInfoFile): DB = {}
raise DrmException('Error: kindle-info file can not be found') infoReader = open(kInfoFile, 'r')
return open(kInfoFile, 'r') infoReader.read(1)
data = infoReader.read()
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -93,18 +93,25 @@ def CryptUnprotectData():
return CryptUnprotectData return CryptUnprotectData
CryptUnprotectData = CryptUnprotectData() CryptUnprotectData = CryptUnprotectData()
# # Locate the .kindle-info files
# Locate and open the Kindle.info file. def getKindleInfoFiles(kInfoFiles):
# regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\")
def openKindleInfo(kInfoFile=None): path = winreg.QueryValueEx(regkey, 'Local AppData')[0]
if kInfoFile == None: kinfopath = path +'\\Amazon\\Kindle For PC\\{AMAwzsaPaaZAzmZzZQzgZCAkZ3AjA_AY}\\kindle.info'
regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\") if not os.path.isfile(kinfopath):
path = winreg.QueryValueEx(regkey, 'Local AppData')[0] print('The kindle.info files has not been found.')
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: else:
if not os.path.isfile(kInfoFile): kInfoFiles.append(kinfopath)
raise DrmException('Error: kindle.info file can not be found') return kInfoFiles
return open(kInfoFile, 'r')
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = open(kInfoFile, 'r')
infoReader.read(1)
data = infoReader.read()
items = data.split('{')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB

View File

@ -18,9 +18,9 @@ global charMap3
global charMap4 global charMap4
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
from k4pcutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4pcutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
if sys.platform.startswith('darwin'): if sys.platform.startswith('darwin'):
from k4mutils import openKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2 from k4mutils import getKindleInfoFiles, parseKindleInfo, CryptUnprotectData, GetUserName, GetVolumeSerialNumber, charMap2
charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M" charMap1 = "n5Pr6St7Uv8Wx9YzAb0Cd1Ef2Gh3Jk4M"
charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" charMap3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
@ -67,22 +67,6 @@ def decode(data,map):
result += pack("B",value) result += pack("B",value)
return result return result
# Parse the Kindle.info file and return the records as a list of key-values
def parseKindleInfo(kInfoFile):
DB = {}
infoReader = openKindleInfo(kInfoFile)
infoReader.read(1)
data = infoReader.read()
if sys.platform.startswith('win'):
items = data.split('{')
else :
items = data.split('[')
for item in items:
splito = item.split(':')
DB[splito[0]] =splito[1]
return DB
# Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded). # Get a record from the Kindle.info file for the key "hashedKey" (already hashed and encoded).
# Return the decoded and decrypted record # Return the decoded and decrypted record
def getKindleInfoValueForHash(hashedKey): def getKindleInfoValueForHash(hashedKey):
@ -241,7 +225,7 @@ def getKindlePid(pidlst, rec209, token, serialnum):
# Parse the EXTH header records and parse the Kindleinfo # Parse the EXTH header records and parse the Kindleinfo
# file to calculate the book pid. # file to calculate the book pid.
def getK4Pids(pidlst, rec209, token, kInfoFile=None): def getK4Pids(pidlst, rec209, token, kInfoFile):
global kindleDatabase global kindleDatabase
global charMap1 global charMap1
kindleDatabase = None kindleDatabase = None
@ -254,10 +238,17 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
if kindleDatabase == None : if kindleDatabase == None :
return pidlst return pidlst
try:
# Get the Mazama Random number
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber")
# Get the Mazama Random number # Get the kindle account token
MazamaRandomNumber = getKindleInfoValueForKey("MazamaRandomNumber") kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
except KeyError:
print "Keys not found in " + kInfoFile
return pidlst
# Get the HDD serial # Get the HDD serial
encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1) encodedSystemVolumeSerialNumber = encodeHash(GetVolumeSerialNumber(),charMap1)
@ -273,10 +264,7 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
devicePID = checksumPid(devicePID) devicePID = checksumPid(devicePID)
pidlst.append(devicePID) pidlst.append(devicePID)
# Compute book PID # Compute book PIDs
# Get the kindle account token
kindleAccountToken = getKindleInfoValueForKey("kindle.account.tokens")
# book pid # book pid
pidHash = SHA1(DSN+kindleAccountToken+rec209+token) pidHash = SHA1(DSN+kindleAccountToken+rec209+token)
@ -300,8 +288,10 @@ def getK4Pids(pidlst, rec209, token, kInfoFile=None):
def getPidList(md1, md2, k4, pids, serials, kInfoFiles): def getPidList(md1, md2, k4, pids, serials, kInfoFiles):
pidlst = [] pidlst = []
if kInfoFiles is None:
kInfoFiles = []
if k4: if k4:
pidlst = getK4Pids(pidlst, md1, md2) kInfoFiles = getKindleInfoFiles(kInfoFiles)
for infoFile in kInfoFiles: for infoFile in kInfoFiles:
pidlst = getK4Pids(pidlst, md1, md2, infoFile) pidlst = getK4Pids(pidlst, md1, md2, infoFile)
for serialnum in serials: for serialnum in serials: