Update of obok and change Scuolabook to a link

This commit is contained in:
apprenticeharper 2016-01-11 06:43:22 +00:00
parent 3e95168972
commit 72968d2124
6 changed files with 93 additions and 34 deletions

View File

@ -1,6 +1,16 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Version 6.3.5 January 2016
# Update for latest version of Windows Desktop app.
# Support Kobo devices in the command line version.
#
# Version 3.1.9 November 2015
# Handle Kobo Desktop under wine on Linux
#
# Version 3.1.8 November 2015
# Handle the case of Kobo Arc or Vox device (i.e. don't crash).
#
# Version 3.1.7 October 2015 # Version 3.1.7 October 2015
# Handle the case of no device or database more gracefully. # Handle the case of no device or database more gracefully.
# #
@ -126,7 +136,8 @@
# #
"""Manage all Kobo books, either encrypted or DRM-free.""" """Manage all Kobo books, either encrypted or DRM-free."""
__version__ = '3.1.7' __version__ = '3.1.9'
__about__ = u"Obok v{0}\nCopyright © 2012-2015 Physisticated et al.".format(__version__)
import sys import sys
import os import os
@ -140,6 +151,18 @@ import hashlib
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import string import string
import shutil import shutil
import argparse
can_parse_xml = True
try:
from xml.etree import ElementTree as ET
# print u"using xml.etree for xml parsing"
except ImportError:
can_parse_xml = False
# print u"Cannot find xml.etree, disabling extraction of serial numbers"
# List of all known hash keys
KOBO_HASH_KEYS = ['88b3a2e13', 'XzUhGYdFp', 'NoCanLook']
class ENCRYPTIONError(Exception): class ENCRYPTIONError(Exception):
pass pass
@ -252,24 +275,59 @@ class KoboLibrary(object):
of books, their titles, and the user's encryption key(s).""" of books, their titles, and the user's encryption key(s)."""
def __init__ (self, serials = [], device_path = None): def __init__ (self, serials = [], device_path = None):
print u"Obok v{0}\nCopyright © 2012-2015 Physisticated et al.".format(__version__) print __about__
self.kobodir = u"" self.kobodir = u""
kobodb = u"" kobodb = u""
# - first check whether serials have been found or are provided # Order of checks
# and a device is connected. In this case, use the device # 1. first check if a device_path has been passed in, and whether
# - otherwise fall back to Kobo Desktop Application for Windows and Mac # we can find the sqlite db in the respective place
if (device_path and (len(serials) > 0)): # 2. if 1., and we got some serials passed in (from saved
# settings in calibre), just use it
# 3. if 1. worked, but we didn't get serials, try to parse them
# from the device, if this didn't work, unset everything
# 4. if by now we don't have kobodir set, give up on device and
# try to use the Desktop app.
# step 1. check whether this looks like a real device
if (device_path):
# we got a device path
self.kobodir = os.path.join(device_path, u".kobo") self.kobodir = os.path.join(device_path, u".kobo")
# devices use KoboReader.sqlite # devices use KoboReader.sqlite
kobodb = os.path.join(self.kobodir, u"KoboReader.sqlite") kobodb = os.path.join(self.kobodir, u"KoboReader.sqlite")
if (not(os.path.isfile(kobodb))): if (not(os.path.isfile(kobodb))):
# give up here, we haven't found anything useful # device path seems to be wrong, unset it
device_path = u""
self.kobodir = u"" self.kobodir = u""
kobodb = u"" kobodb = u""
if (self.kobodir):
# step 3. we found a device but didn't get serials, try to get them
if (len(serials) == 0):
# we got a device path but no saved serial
# try to get the serial from the device
# print u"get_device_settings - device_path = {0}".format(device_path)
# get serial from device_path/.adobe-digital-editions/device.xml
if can_parse_xml:
devicexml = os.path.join(device_path, '.adobe-digital-editions', 'device.xml')
# print u"trying to load {0}".format(devicexml)
if (os.path.exists(devicexml)):
# print u"trying to parse {0}".format(devicexml)
xmltree = ET.parse(devicexml)
for node in xmltree.iter():
if "deviceSerial" in node.tag:
serial = node.text
# print u"found serial {0}".format(serial)
serials.append(serial)
break
else:
# print u"cannot get serials from device."
device_path = u""
self.kobodir = u""
kobodb = u""
if (self.kobodir == u""): if (self.kobodir == u""):
# we haven't found a device with serials, so try desktop apps # step 4. we haven't found a device with serials, so try desktop apps
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
import _winreg as winreg import _winreg as winreg
if sys.getwindowsversion().major > 5: if sys.getwindowsversion().major > 5:
@ -283,6 +341,9 @@ class KoboLibrary(object):
self.kobodir = os.path.join(self.kobodir, u"Kobo", u"Kobo Desktop Edition") self.kobodir = os.path.join(self.kobodir, u"Kobo", u"Kobo Desktop Edition")
elif sys.platform.startswith('darwin'): elif sys.platform.startswith('darwin'):
self.kobodir = os.path.join(os.environ['HOME'], u"Library", u"Application Support", u"Kobo", u"Kobo Desktop Edition") self.kobodir = os.path.join(os.environ['HOME'], u"Library", u"Application Support", u"Kobo", u"Kobo Desktop Edition")
elif linux_path != None:
# Probably Linux, let's get the wine prefix and path to Kobo.
self.kobodir = os.path.join(linux_path, u"Local Settings", u"Application Data", u"Kobo", u"Kobo Desktop Edition")
# desktop versions use Kobo.sqlite # desktop versions use Kobo.sqlite
kobodb = os.path.join(self.kobodir, u"Kobo.sqlite") kobodb = os.path.join(self.kobodir, u"Kobo.sqlite")
# check for existence of file # check for existence of file
@ -358,6 +419,13 @@ class KoboLibrary(object):
for m in matches: for m in matches:
# print u"m:{0}".format(m[0]) # print u"m:{0}".format(m[0])
macaddrs.append(m[0].upper()) macaddrs.append(m[0].upper())
else:
# probably linux, let's try ipconfig under wine
c = re.compile('\s(' + '[0-9a-f]{2}-' * 5 + '[0-9a-f]{2})(\s|$)', re.IGNORECASE)
for line in os.popen('ipconfig /all'):
m = c.search(line)
if m:
macaddrs.append(re.sub("-", ":", m.group(1)).upper())
# extend the list of macaddrs in any case with the serials # extend the list of macaddrs in any case with the serials
# cannot hurt ;-) # cannot hurt ;-)
@ -381,16 +449,11 @@ class KoboLibrary(object):
def __getuserkeys (self, macaddr): def __getuserkeys (self, macaddr):
userids = self.__getuserids() userids = self.__getuserids()
userkeys = [] userkeys = []
# This version is used for versions before 3.17.0. for hash in KOBO_HASH_KEYS:
deviceid = hashlib.sha256('NoCanLook' + macaddr).hexdigest() deviceid = hashlib.sha256(hash + macaddr).hexdigest()
for userid in userids: for userid in userids:
userkey = hashlib.sha256(deviceid + userid).hexdigest() userkey = hashlib.sha256(deviceid + userid).hexdigest()
userkeys.append(binascii.a2b_hex(userkey[32:])) userkeys.append(binascii.a2b_hex(userkey[32:]))
# This version is used for 3.17.0 and later.
deviceid = hashlib.sha256('XzUhGYdFp' + macaddr).hexdigest()
for userid in userids:
userkey = hashlib.sha256(deviceid + userid).hexdigest()
userkeys.append(binascii.a2b_hex(userkey[32:]))
return userkeys return userkeys
class KoboBook(object): class KoboBook(object):
@ -527,7 +590,17 @@ class KoboFile(object):
return contents return contents
def cli_main(): def cli_main():
lib = KoboLibrary() description = __about__
epilog = u"Parsing of arguments failed."
parser = argparse.ArgumentParser(prog=sys.argv[0], description=description, epilog=epilog)
parser.add_argument('--devicedir', default='/media/KOBOeReader', help="directory of connected Kobo device")
args = vars(parser.parse_args())
serials = []
devicedir = u""
if args['devicedir']:
devicedir = args['devicedir']
lib = KoboLibrary(serials, devicedir)
for i, book in enumerate(lib.books): for i, book in enumerate(lib.books):
print u"{0}: {1}".format(i + 1, book.title) print u"{0}: {1}".format(i + 1, book.title)

View File

@ -1,18 +1,4 @@
How-to: The latest Scuolabook tool can be found at Hex's own blog:
1) Make sure you can read all PDF files on Scuolabook Reader.
2) Run Scuolabook DRM Remover.
3) Decrypt your books.
Note:
It is recommended to use Scuolabook version 3.0.3 and refuse all updates
because the encryption algorithm may change making this tool useless.
Hex
For any further help or information, see Hex's own blog at
https://thisishex.wordpress.com/scuolabook-drm-remover/ https://thisishex.wordpress.com/scuolabook-drm-remover/
Harper. Harper.