Update of obok and change Scuolabook to a link
This commit is contained in:
parent
3e95168972
commit
72968d2124
|
@ -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)
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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.
|
Loading…
Reference in New Issue