Compare commits

...

15 Commits

Author SHA1 Message Date
apprenticeharper
cfc13db6c5 Merge branch 'master' of https://github.com/apprenticeharper/DeDRM_tools 2016-01-15 06:34:15 +00:00
apprenticeharper
8aa2157d55 Completely remove erroneous check 2016-01-15 06:33:05 +00:00
apprenticeharper
81b08dcf05 Completely remove erroneous check 2016-01-15 06:30:54 +00:00
apprenticeharper
ca42e028a7 Regression bug fixes 2016-01-14 17:15:43 +00:00
apprenticeharper
10963f6011 Update to DeDRM to try to fix Linux python problem, and improve Adobe logging 2016-01-11 06:44:44 +00:00
apprenticeharper
72968d2124 Update of obok and change Scuolabook to a link 2016-01-11 06:43:22 +00:00
apprenticeharper
3e95168972 Merge fixes for new Kobo version and Linux support, update version number 2016-01-11 06:40:15 +00:00
apprenticeharper
ecf1d76d90 Update to Scuolabooks tool 2016-01-07 06:20:00 +00:00
Apprentice Harper
e59f0f346d Merge pull request #51 from norbusan/master
update obok.py with new hashes - support obok cmd line usage
2016-01-06 17:45:13 +00:00
Norbert Preining
b6046d3f4b move serial detection into obok.py, cater for cmd usage 2015-12-28 09:53:13 +09:00
Norbert Preining
a863a4856a update obok.py with new hashes and code from minmax 2015-12-26 09:13:16 +09:00
apprenticeharper
a13d08c3bc Fix for crash when Arc or Vox is connected. 2015-10-29 07:47:49 +00:00
apprenticeharper
9434751a72 updated version number and script copy for obok changes 2015-10-13 08:05:34 +01:00
Apprentice Harper
fc156852a4 Merge pull request #41 from norbusan/fixes
obok: make sure that file exists before opening the db
2015-10-13 07:36:54 +01:00
Norbert Preining
0c67fd43a2 obok: make sure that file exists before opening the db 2015-10-08 10:59:34 +09:00
26 changed files with 348 additions and 123 deletions

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 AppleScript 6.3.4 Written 20102015 by Apprentice Alf et al.</string> <string>DeDRM AppleScript 6.3.6 Written 20102016 by Apprentice Alf et al.</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>DeDRM</string> <string>DeDRM</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@@ -36,7 +36,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>6.3.4</string> <string>6.3.6</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>dplt</string> <string>dplt</string>
<key>LSRequiresCarbon</key> <key>LSRequiresCarbon</key>

View File

@@ -46,6 +46,8 @@ __docformat__ = 'restructuredtext en'
# 6.3.2 - Fixed Kindle for Android help file # 6.3.2 - Fixed Kindle for Android help file
# 6.3.3 - Bug fix for Kindle for PC support # 6.3.3 - Bug fix for Kindle for PC support
# 6.3.4 - Fixes for Kindle for Android, Linux, and Kobo 3.17 # 6.3.4 - Fixes for Kindle for Android, Linux, and Kobo 3.17
# 6.3.5 - Fixes for Linux, and Kobo 3.19 and more logging
# 6.3.6 - Fixes for ADE ePub and PDF introduced in 6.3.5
""" """
@@ -53,7 +55,7 @@ Decrypt DRMed ebooks.
""" """
PLUGIN_NAME = u"DeDRM" PLUGIN_NAME = u"DeDRM"
PLUGIN_VERSION_TUPLE = (6, 3, 4) PLUGIN_VERSION_TUPLE = (6, 3, 6)
PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE]) PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE])
# Include an html helpfile in the plugin's zipfile with the following name. # Include an html helpfile in the plugin's zipfile with the following name.
RESOURCE_NAME = PLUGIN_NAME + '_Help.htm' RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
@@ -96,7 +98,7 @@ class DeDRM(FileTypePlugin):
supported_platforms = ['linux', 'osx', 'windows'] supported_platforms = ['linux', 'osx', 'windows']
author = u"Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages" author = u"Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages"
version = PLUGIN_VERSION_TUPLE version = PLUGIN_VERSION_TUPLE
minimum_calibre_version = (0, 7, 55) # Compiled python libraries cannot be imported in earlier versions. minimum_calibre_version = (1, 0, 0) # Compiled python libraries cannot be imported in earlier versions.
file_types = set(['epub','pdf','pdb','prc','mobi','pobi','azw','azw1','azw3','azw4','tpz']) file_types = set(['epub','pdf','pdb','prc','mobi','pobi','azw','azw1','azw3','azw4','tpz'])
on_import = True on_import = True
priority = 600 priority = 600
@@ -296,11 +298,15 @@ class DeDRM(FileTypePlugin):
traceback.print_exc() traceback.print_exc()
result = 1 result = 1
try:
of.close() of.close()
except:
print u"{0} v{1}: Exception closing temporary file after {2:.1f} seconds. Ignored.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
if result == 0: if result == 0:
# Decryption was successful. # Decryption was successful.
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
print u"{0} v{1}: Decrypted with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
return of.name return of.name
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime) print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
@@ -360,6 +366,7 @@ class DeDRM(FileTypePlugin):
except: except:
print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime) print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
traceback.print_exc() traceback.print_exc()
print u"{0} v{1}: Decrypted with new default key after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
return of.name return of.name

View File

@@ -3,18 +3,19 @@
from __future__ import with_statement from __future__ import with_statement
# ineptepub.pyw, version 6.1 # ineptepub.pyw, version 6.5
# Copyright © 2009-2010 by i♥cabbages # Copyright © 2009-2010 by i♥cabbages
# Released under the terms of the GNU General Public Licence, version 3 # Released under the terms of the GNU General Public Licence, version 3
# <http://www.gnu.org/licenses/> # <http://www.gnu.org/licenses/>
# Modified 20102013 by some_updates, DiapDealer and Apprentice Alf # Modified 20102013 by some_updates, DiapDealer and Apprentice Alf
# Modified 20152016 by Apprentice Harper
# Windows users: Before running this program, you must first install Python 2.6 # Windows users: Before running this program, you must first install Python 2.7
# from <http://www.python.org/download/> and PyCrypto from # from <http://www.python.org/download/> and PyCrypto from
# <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to # <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to
# install the version for Python 2.6). Save this script file as # install the version for Python 2.7). Save this script file as
# ineptepub.pyw and double-click on it to run it. # ineptepub.pyw and double-click on it to run it.
# #
# Mac OS X users: Save this script file as ineptepub.pyw. You can run this # Mac OS X users: Save this script file as ineptepub.pyw. You can run this
@@ -38,13 +39,16 @@ from __future__ import with_statement
# 6.0 - moved unicode_argv call inside main for Windows DeDRM compatibility # 6.0 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 6.1 - Work if TkInter is missing # 6.1 - Work if TkInter is missing
# 6.2 - Handle UTF-8 file names inside an ePub, fix by Jose Luis # 6.2 - Handle UTF-8 file names inside an ePub, fix by Jose Luis
# 6.3 - Add additional check on DER file sanity
# 6.4 - Remove erroneous check on DER file sanity
# 6.5 - Completely remove erroneous check on DER file sanity
""" """
Decrypt Adobe Digital Editions encrypted ePub books. Decrypt Adobe Digital Editions encrypted ePub books.
""" """
__license__ = 'GPL v3' __license__ = 'GPL v3'
__version__ = "6.2" __version__ = "6.5"
import sys import sys
import os import os

View File

@@ -3,18 +3,19 @@
from __future__ import with_statement from __future__ import with_statement
# ineptpdf.pyw, version 7.11 # ineptpdf.pyw, version 8.0.4
# Copyright © 2009-2010 by i♥cabbages # Copyright © 2009-2010 by i♥cabbages
# Released under the terms of the GNU General Public Licence, version 3 # Released under the terms of the GNU General Public Licence, version 3
# <http://www.gnu.org/licenses/> # <http://www.gnu.org/licenses/>
# Modified 20102012 by some_updates, DiapDealer and Apprentice Alf # Modified 20102012 by some_updates, DiapDealer and Apprentice Alf
# Modified 2015-2016 by Apprentice Harper
# Windows users: Before running this program, you must first install Python 2.6 # Windows users: Before running this program, you must first install Python 2.7
# from <http://www.python.org/download/> and PyCrypto from # from <http://www.python.org/download/> and PyCrypto from
# <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to # <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to
# install the version for Python 2.6). Save this script file as # install the version for Python 2.7). Save this script file as
# ineptpdf.pyw and double-click on it to run it. # ineptpdf.pyw and double-click on it to run it.
# #
# Mac OS X users: Save this script file as ineptpdf.pyw. You can run this # Mac OS X users: Save this script file as ineptpdf.pyw. You can run this
@@ -53,13 +54,17 @@ from __future__ import with_statement
# 7.14 - moved unicode_argv call inside main for Windows DeDRM compatibility # 7.14 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 8.0 - Work if TkInter is missing # 8.0 - Work if TkInter is missing
# 8.0.1 - Broken Metadata fix. # 8.0.1 - Broken Metadata fix.
# 8.0.2 - Add additional check on DER file sanity
# 8.0.3 - Remove erroneous check on DER file sanity
# 8.0.4 - Completely remove erroneous check on DER file sanity
""" """
Decrypts Adobe ADEPT-encrypted PDF files. Decrypts Adobe ADEPT-encrypted PDF files.
""" """
__license__ = 'GPL v3' __license__ = 'GPL v3'
__version__ = "8.0.1" __version__ = "8.0.4"
import sys import sys
import os import os

View File

@@ -26,6 +26,7 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
if not os.path.exists(outdirpath): if not os.path.exists(outdirpath):
os.makedirs(outdirpath) os.makedirs(outdirpath)
wineprefix = os.path.abspath(os.path.expanduser(os.path.expandvars(wineprefix)))
if wineprefix != "" and os.path.exists(wineprefix): if wineprefix != "" and os.path.exists(wineprefix):
cmdline = u"WINEPREFIX=\"{2}\" wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix) cmdline = u"WINEPREFIX=\"{2}\" wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
else: else:
@@ -38,8 +39,20 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
result = p2.wait("wait") result = p2.wait("wait")
except Exception, e: except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]) print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
return [] if wineprefix != "" and os.path.exists(wineprefix):
cmdline = u"WINEPREFIX=\"{2}\" wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
else:
cmdline = u"wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
print u"{0} v{1}: Command line: “{2}".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline)
try:
cmdline = cmdline.encode(sys.getfilesystemencoding())
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
result = p2.wait("wait")
except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
# try finding winekeys anyway, even if above code errored
winekeys = [] winekeys = []
# get any files with extension in the output dir # get any files with extension in the output dir
files = [f for f in os.listdir(outdirpath) if f.endswith(extension)] files = [f for f in os.listdir(outdirpath) if f.endswith(extension)]

View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# DeDRM.pyw # DeDRM.pyw
# Copyright 2010-2015 some_updates, Apprentice Alf and Apprentice Harper # Copyright 2010-2016 some_updates, Apprentice Alf and Apprentice Harper
# Revision history: # Revision history:
# 6.0.0 - Release along with unified plugin # 6.0.0 - Release along with unified plugin
@@ -19,8 +19,10 @@
# 6.3.2 - Version bump to match plugin # 6.3.2 - Version bump to match plugin
# 6.3.3 - Version bump to match plugin # 6.3.3 - Version bump to match plugin
# 6.3.4 - Version bump to match plugin # 6.3.4 - Version bump to match plugin
# 6.3.5 - Version bump to match plugin
# 6.3.6 - Version bump to match plugin
__version__ = '6.3.4' __version__ = '6.3.6'
import sys import sys
import os, os.path import os, os.path

View File

@@ -46,6 +46,8 @@ __docformat__ = 'restructuredtext en'
# 6.3.2 - Fixed Kindle for Android help file # 6.3.2 - Fixed Kindle for Android help file
# 6.3.3 - Bug fix for Kindle for PC support # 6.3.3 - Bug fix for Kindle for PC support
# 6.3.4 - Fixes for Kindle for Android, Linux, and Kobo 3.17 # 6.3.4 - Fixes for Kindle for Android, Linux, and Kobo 3.17
# 6.3.5 - Fixes for Linux, and Kobo 3.19 and more logging
# 6.3.6 - Fixes for ADE ePub and PDF introduced in 6.3.5
""" """
@@ -53,7 +55,7 @@ Decrypt DRMed ebooks.
""" """
PLUGIN_NAME = u"DeDRM" PLUGIN_NAME = u"DeDRM"
PLUGIN_VERSION_TUPLE = (6, 3, 4) PLUGIN_VERSION_TUPLE = (6, 3, 6)
PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE]) PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE])
# Include an html helpfile in the plugin's zipfile with the following name. # Include an html helpfile in the plugin's zipfile with the following name.
RESOURCE_NAME = PLUGIN_NAME + '_Help.htm' RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
@@ -96,7 +98,7 @@ class DeDRM(FileTypePlugin):
supported_platforms = ['linux', 'osx', 'windows'] supported_platforms = ['linux', 'osx', 'windows']
author = u"Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages" author = u"Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages"
version = PLUGIN_VERSION_TUPLE version = PLUGIN_VERSION_TUPLE
minimum_calibre_version = (0, 7, 55) # Compiled python libraries cannot be imported in earlier versions. minimum_calibre_version = (1, 0, 0) # Compiled python libraries cannot be imported in earlier versions.
file_types = set(['epub','pdf','pdb','prc','mobi','pobi','azw','azw1','azw3','azw4','tpz']) file_types = set(['epub','pdf','pdb','prc','mobi','pobi','azw','azw1','azw3','azw4','tpz'])
on_import = True on_import = True
priority = 600 priority = 600
@@ -296,11 +298,15 @@ class DeDRM(FileTypePlugin):
traceback.print_exc() traceback.print_exc()
result = 1 result = 1
try:
of.close() of.close()
except:
print u"{0} v{1}: Exception closing temporary file after {2:.1f} seconds. Ignored.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
if result == 0: if result == 0:
# Decryption was successful. # Decryption was successful.
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
print u"{0} v{1}: Decrypted with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
return of.name return of.name
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime) print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
@@ -360,6 +366,7 @@ class DeDRM(FileTypePlugin):
except: except:
print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime) print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
traceback.print_exc() traceback.print_exc()
print u"{0} v{1}: Decrypted with new default key after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
return of.name return of.name

View File

@@ -3,18 +3,19 @@
from __future__ import with_statement from __future__ import with_statement
# ineptepub.pyw, version 6.1 # ineptepub.pyw, version 6.5
# Copyright © 2009-2010 by i♥cabbages # Copyright © 2009-2010 by i♥cabbages
# Released under the terms of the GNU General Public Licence, version 3 # Released under the terms of the GNU General Public Licence, version 3
# <http://www.gnu.org/licenses/> # <http://www.gnu.org/licenses/>
# Modified 20102013 by some_updates, DiapDealer and Apprentice Alf # Modified 20102013 by some_updates, DiapDealer and Apprentice Alf
# Modified 20152016 by Apprentice Harper
# Windows users: Before running this program, you must first install Python 2.6 # Windows users: Before running this program, you must first install Python 2.7
# from <http://www.python.org/download/> and PyCrypto from # from <http://www.python.org/download/> and PyCrypto from
# <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to # <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to
# install the version for Python 2.6). Save this script file as # install the version for Python 2.7). Save this script file as
# ineptepub.pyw and double-click on it to run it. # ineptepub.pyw and double-click on it to run it.
# #
# Mac OS X users: Save this script file as ineptepub.pyw. You can run this # Mac OS X users: Save this script file as ineptepub.pyw. You can run this
@@ -38,13 +39,16 @@ from __future__ import with_statement
# 6.0 - moved unicode_argv call inside main for Windows DeDRM compatibility # 6.0 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 6.1 - Work if TkInter is missing # 6.1 - Work if TkInter is missing
# 6.2 - Handle UTF-8 file names inside an ePub, fix by Jose Luis # 6.2 - Handle UTF-8 file names inside an ePub, fix by Jose Luis
# 6.3 - Add additional check on DER file sanity
# 6.4 - Remove erroneous check on DER file sanity
# 6.5 - Completely remove erroneous check on DER file sanity
""" """
Decrypt Adobe Digital Editions encrypted ePub books. Decrypt Adobe Digital Editions encrypted ePub books.
""" """
__license__ = 'GPL v3' __license__ = 'GPL v3'
__version__ = "6.2" __version__ = "6.5"
import sys import sys
import os import os

View File

@@ -3,18 +3,19 @@
from __future__ import with_statement from __future__ import with_statement
# ineptpdf.pyw, version 7.11 # ineptpdf.pyw, version 8.0.4
# Copyright © 2009-2010 by i♥cabbages # Copyright © 2009-2010 by i♥cabbages
# Released under the terms of the GNU General Public Licence, version 3 # Released under the terms of the GNU General Public Licence, version 3
# <http://www.gnu.org/licenses/> # <http://www.gnu.org/licenses/>
# Modified 20102012 by some_updates, DiapDealer and Apprentice Alf # Modified 20102012 by some_updates, DiapDealer and Apprentice Alf
# Modified 2015-2016 by Apprentice Harper
# Windows users: Before running this program, you must first install Python 2.6 # Windows users: Before running this program, you must first install Python 2.7
# from <http://www.python.org/download/> and PyCrypto from # from <http://www.python.org/download/> and PyCrypto from
# <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to # <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to
# install the version for Python 2.6). Save this script file as # install the version for Python 2.7). Save this script file as
# ineptpdf.pyw and double-click on it to run it. # ineptpdf.pyw and double-click on it to run it.
# #
# Mac OS X users: Save this script file as ineptpdf.pyw. You can run this # Mac OS X users: Save this script file as ineptpdf.pyw. You can run this
@@ -53,13 +54,17 @@ from __future__ import with_statement
# 7.14 - moved unicode_argv call inside main for Windows DeDRM compatibility # 7.14 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 8.0 - Work if TkInter is missing # 8.0 - Work if TkInter is missing
# 8.0.1 - Broken Metadata fix. # 8.0.1 - Broken Metadata fix.
# 8.0.2 - Add additional check on DER file sanity
# 8.0.3 - Remove erroneous check on DER file sanity
# 8.0.4 - Completely remove erroneous check on DER file sanity
""" """
Decrypts Adobe ADEPT-encrypted PDF files. Decrypts Adobe ADEPT-encrypted PDF files.
""" """
__license__ = 'GPL v3' __license__ = 'GPL v3'
__version__ = "8.0.1" __version__ = "8.0.4"
import sys import sys
import os import os

View File

@@ -26,6 +26,7 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
if not os.path.exists(outdirpath): if not os.path.exists(outdirpath):
os.makedirs(outdirpath) os.makedirs(outdirpath)
wineprefix = os.path.abspath(os.path.expanduser(os.path.expandvars(wineprefix)))
if wineprefix != "" and os.path.exists(wineprefix): if wineprefix != "" and os.path.exists(wineprefix):
cmdline = u"WINEPREFIX=\"{2}\" wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix) cmdline = u"WINEPREFIX=\"{2}\" wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
else: else:
@@ -38,8 +39,20 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
result = p2.wait("wait") result = p2.wait("wait")
except Exception, e: except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]) print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
return [] if wineprefix != "" and os.path.exists(wineprefix):
cmdline = u"WINEPREFIX=\"{2}\" wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
else:
cmdline = u"wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
print u"{0} v{1}: Command line: “{2}".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline)
try:
cmdline = cmdline.encode(sys.getfilesystemencoding())
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
result = p2.wait("wait")
except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
# try finding winekeys anyway, even if above code errored
winekeys = [] winekeys = []
# get any files with extension in the output dir # get any files with extension in the output dir
files = [f for f in os.listdir(outdirpath) if f.endswith(extension)] files = [f for f in os.listdir(outdirpath) if f.endswith(extension)]

View File

@@ -46,6 +46,8 @@ __docformat__ = 'restructuredtext en'
# 6.3.2 - Fixed Kindle for Android help file # 6.3.2 - Fixed Kindle for Android help file
# 6.3.3 - Bug fix for Kindle for PC support # 6.3.3 - Bug fix for Kindle for PC support
# 6.3.4 - Fixes for Kindle for Android, Linux, and Kobo 3.17 # 6.3.4 - Fixes for Kindle for Android, Linux, and Kobo 3.17
# 6.3.5 - Fixes for Linux, and Kobo 3.19 and more logging
# 6.3.6 - Fixes for ADE ePub and PDF introduced in 6.3.5
""" """
@@ -53,7 +55,7 @@ Decrypt DRMed ebooks.
""" """
PLUGIN_NAME = u"DeDRM" PLUGIN_NAME = u"DeDRM"
PLUGIN_VERSION_TUPLE = (6, 3, 4) PLUGIN_VERSION_TUPLE = (6, 3, 6)
PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE]) PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE])
# Include an html helpfile in the plugin's zipfile with the following name. # Include an html helpfile in the plugin's zipfile with the following name.
RESOURCE_NAME = PLUGIN_NAME + '_Help.htm' RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
@@ -96,7 +98,7 @@ class DeDRM(FileTypePlugin):
supported_platforms = ['linux', 'osx', 'windows'] supported_platforms = ['linux', 'osx', 'windows']
author = u"Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages" author = u"Apprentice Alf, Aprentice Harper, The Dark Reverser and i♥cabbages"
version = PLUGIN_VERSION_TUPLE version = PLUGIN_VERSION_TUPLE
minimum_calibre_version = (0, 7, 55) # Compiled python libraries cannot be imported in earlier versions. minimum_calibre_version = (1, 0, 0) # Compiled python libraries cannot be imported in earlier versions.
file_types = set(['epub','pdf','pdb','prc','mobi','pobi','azw','azw1','azw3','azw4','tpz']) file_types = set(['epub','pdf','pdb','prc','mobi','pobi','azw','azw1','azw3','azw4','tpz'])
on_import = True on_import = True
priority = 600 priority = 600
@@ -296,11 +298,15 @@ class DeDRM(FileTypePlugin):
traceback.print_exc() traceback.print_exc()
result = 1 result = 1
try:
of.close() of.close()
except:
print u"{0} v{1}: Exception closing temporary file after {2:.1f} seconds. Ignored.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
if result == 0: if result == 0:
# Decryption was successful. # Decryption was successful.
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
print u"{0} v{1}: Decrypted with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
return of.name return of.name
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime) print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname,time.time()-self.starttime)
@@ -360,6 +366,7 @@ class DeDRM(FileTypePlugin):
except: except:
print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime) print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
traceback.print_exc() traceback.print_exc()
print u"{0} v{1}: Decrypted with new default key after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
return of.name return of.name

View File

@@ -3,18 +3,19 @@
from __future__ import with_statement from __future__ import with_statement
# ineptepub.pyw, version 6.1 # ineptepub.pyw, version 6.5
# Copyright © 2009-2010 by i♥cabbages # Copyright © 2009-2010 by i♥cabbages
# Released under the terms of the GNU General Public Licence, version 3 # Released under the terms of the GNU General Public Licence, version 3
# <http://www.gnu.org/licenses/> # <http://www.gnu.org/licenses/>
# Modified 20102013 by some_updates, DiapDealer and Apprentice Alf # Modified 20102013 by some_updates, DiapDealer and Apprentice Alf
# Modified 20152016 by Apprentice Harper
# Windows users: Before running this program, you must first install Python 2.6 # Windows users: Before running this program, you must first install Python 2.7
# from <http://www.python.org/download/> and PyCrypto from # from <http://www.python.org/download/> and PyCrypto from
# <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to # <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to
# install the version for Python 2.6). Save this script file as # install the version for Python 2.7). Save this script file as
# ineptepub.pyw and double-click on it to run it. # ineptepub.pyw and double-click on it to run it.
# #
# Mac OS X users: Save this script file as ineptepub.pyw. You can run this # Mac OS X users: Save this script file as ineptepub.pyw. You can run this
@@ -38,13 +39,16 @@ from __future__ import with_statement
# 6.0 - moved unicode_argv call inside main for Windows DeDRM compatibility # 6.0 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 6.1 - Work if TkInter is missing # 6.1 - Work if TkInter is missing
# 6.2 - Handle UTF-8 file names inside an ePub, fix by Jose Luis # 6.2 - Handle UTF-8 file names inside an ePub, fix by Jose Luis
# 6.3 - Add additional check on DER file sanity
# 6.4 - Remove erroneous check on DER file sanity
# 6.5 - Completely remove erroneous check on DER file sanity
""" """
Decrypt Adobe Digital Editions encrypted ePub books. Decrypt Adobe Digital Editions encrypted ePub books.
""" """
__license__ = 'GPL v3' __license__ = 'GPL v3'
__version__ = "6.2" __version__ = "6.5"
import sys import sys
import os import os

View File

@@ -3,18 +3,19 @@
from __future__ import with_statement from __future__ import with_statement
# ineptpdf.pyw, version 7.11 # ineptpdf.pyw, version 8.0.4
# Copyright © 2009-2010 by i♥cabbages # Copyright © 2009-2010 by i♥cabbages
# Released under the terms of the GNU General Public Licence, version 3 # Released under the terms of the GNU General Public Licence, version 3
# <http://www.gnu.org/licenses/> # <http://www.gnu.org/licenses/>
# Modified 20102012 by some_updates, DiapDealer and Apprentice Alf # Modified 20102012 by some_updates, DiapDealer and Apprentice Alf
# Modified 2015-2016 by Apprentice Harper
# Windows users: Before running this program, you must first install Python 2.6 # Windows users: Before running this program, you must first install Python 2.7
# from <http://www.python.org/download/> and PyCrypto from # from <http://www.python.org/download/> and PyCrypto from
# <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to # <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make sure to
# install the version for Python 2.6). Save this script file as # install the version for Python 2.7). Save this script file as
# ineptpdf.pyw and double-click on it to run it. # ineptpdf.pyw and double-click on it to run it.
# #
# Mac OS X users: Save this script file as ineptpdf.pyw. You can run this # Mac OS X users: Save this script file as ineptpdf.pyw. You can run this
@@ -53,13 +54,17 @@ from __future__ import with_statement
# 7.14 - moved unicode_argv call inside main for Windows DeDRM compatibility # 7.14 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 8.0 - Work if TkInter is missing # 8.0 - Work if TkInter is missing
# 8.0.1 - Broken Metadata fix. # 8.0.1 - Broken Metadata fix.
# 8.0.2 - Add additional check on DER file sanity
# 8.0.3 - Remove erroneous check on DER file sanity
# 8.0.4 - Completely remove erroneous check on DER file sanity
""" """
Decrypts Adobe ADEPT-encrypted PDF files. Decrypts Adobe ADEPT-encrypted PDF files.
""" """
__license__ = 'GPL v3' __license__ = 'GPL v3'
__version__ = "8.0.1" __version__ = "8.0.4"
import sys import sys
import os import os

View File

@@ -39,8 +39,20 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
result = p2.wait("wait") result = p2.wait("wait")
except Exception, e: except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]) print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
return [] if wineprefix != "" and os.path.exists(wineprefix):
cmdline = u"WINEPREFIX=\"{2}\" wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
else:
cmdline = u"wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
print u"{0} v{1}: Command line: “{2}".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline)
try:
cmdline = cmdline.encode(sys.getfilesystemencoding())
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
result = p2.wait("wait")
except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
# try finding winekeys anyway, even if above code errored
winekeys = [] winekeys = []
# get any files with extension in the output dir # get any files with extension in the output dir
files = [f for f in os.listdir(outdirpath) if f.endswith(extension)] files = [f for f in os.listdir(outdirpath) if f.endswith(extension)]

Binary file not shown.

View File

@@ -19,7 +19,7 @@ except NameError:
PLUGIN_NAME = 'Obok DeDRM' PLUGIN_NAME = 'Obok DeDRM'
PLUGIN_SAFE_NAME = PLUGIN_NAME.strip().lower().replace(' ', '_') PLUGIN_SAFE_NAME = PLUGIN_NAME.strip().lower().replace(' ', '_')
PLUGIN_DESCRIPTION = _('Removes DRM from Kobo kepubs and adds them to the library.') PLUGIN_DESCRIPTION = _('Removes DRM from Kobo kepubs and adds them to the library.')
PLUGIN_VERSION_TUPLE = (3, 1, 6) PLUGIN_VERSION_TUPLE = (6, 3, 6)
PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE]) PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE])
HELPFILE_NAME = PLUGIN_SAFE_NAME + '_Help.htm' HELPFILE_NAME = PLUGIN_SAFE_NAME + '_Help.htm'
PLUGIN_AUTHORS = 'Anon' PLUGIN_AUTHORS = 'Anon'

View File

@@ -34,15 +34,6 @@ from calibre_plugins.obok_dedrm.utilities import (
from calibre_plugins.obok_dedrm.obok.obok import KoboLibrary from calibre_plugins.obok_dedrm.obok.obok import KoboLibrary
from calibre_plugins.obok_dedrm.obok.legacy_obok import legacy_obok from calibre_plugins.obok_dedrm.obok.legacy_obok import legacy_obok
can_parse_xml = True
try:
from xml.etree import ElementTree as ET
debug_print("using xml.etree for xml parsing")
except ImportError:
can_parse_xml = False
debug_print("Cannot find xml.etree, disabling extraction of serial numbers")
PLUGIN_ICONS = ['images/obok.png'] PLUGIN_ICONS = ['images/obok.png']
try: try:
@@ -90,28 +81,16 @@ class InterfacePluginAction(InterfaceAction):
# #
# search for connected device in case serials are saved # search for connected device in case serials are saved
tmpserials = cfg['kobo_serials'] tmpserials = cfg['kobo_serials']
device = self.parent().device_manager.connected_device
device_path = None device_path = None
try:
device = self.parent().device_manager.connected_device
if (device): if (device):
device_path = device._main_prefix device_path = device._main_prefix
debug_print("get_device_settings - device_path=", device_path) debug_print("get_device_settings - device_path=", 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')
debug_print("trying to load %s" % devicexml)
if (os.path.exists(devicexml)):
debug_print("trying to parse %s" % devicexml)
xmltree = ET.parse(devicexml)
for node in xmltree.iter():
if "deviceSerial" in node.tag:
serial = node.text
debug_print ("found serial %s" % serial)
tmpserials.append(serial)
break
else: else:
debug_print("didn't find device") debug_print("didn't find device")
except:
debug_print("Exception getting device path. Probably not an E-Ink Kobo device")
# Get the Kobo Library object (obok v3.01) # Get the Kobo Library object (obok v3.01)
self.library = KoboLibrary(tmpserials, device_path) self.library = KoboLibrary(tmpserials, device_path)

View File

@@ -1,6 +1,19 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Version 3.2.0 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
# Handle the case of no device or database more gracefully.
#
# Version 3.1.6 September 2015 # Version 3.1.6 September 2015
# Enable support for Kobo devices # Enable support for Kobo devices
# More character encoding fixes (unicode strings) # More character encoding fixes (unicode strings)
@@ -123,7 +136,8 @@
# #
"""Manage all Kobo books, either encrypted or DRM-free.""" """Manage all Kobo books, either encrypted or DRM-free."""
__version__ = '3.1.6' __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
@@ -137,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
@@ -249,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.exists(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""
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"" self.kobodir = u""
kobodb = 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:
@@ -280,8 +341,17 @@ 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
if (not(os.path.isfile(kobodb))):
# give up here, we haven't found anything useful
self.kobodir = u""
kobodb = u""
if (self.kobodir != u""): if (self.kobodir != u""):
self.bookdir = os.path.join(self.kobodir, u"kepub") self.bookdir = os.path.join(self.kobodir, u"kepub")
@@ -349,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 ;-)
@@ -372,13 +449,8 @@ 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:
userkey = hashlib.sha256(deviceid + userid).hexdigest()
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: 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:]))
@@ -518,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,7 +1,7 @@
obok_plugin.zip obok_plugin.zip
================ ================
This plugin will remove the DRM from Kobo ebooks download on Mac or Windows using the Kobo desktop application, or from Kobo ebooks on an attached Kobo reader. If both are available, ebooks will be read from the attached Kobo reader. To import from the desktop application, unplug the Kobo reader. This plugin will remove the DRM from Kobo ebooks download on Mac or Windows using the Kobo desktop application, or from Kobo ebooks on an attached E-Ink Kobo reader (but not a Kobo Arc or Kobo Vox). If both are available, ebooks will be read from the attached E-Ink Kobo reader. To import from the desktop application, unplug the Kobo reader.
Installation Installation

View File

@@ -1,6 +1,19 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Version 3.2.0 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
# Handle the case of no device or database more gracefully.
#
# Version 3.1.6 September 2015 # Version 3.1.6 September 2015
# Enable support for Kobo devices # Enable support for Kobo devices
# More character encoding fixes (unicode strings) # More character encoding fixes (unicode strings)
@@ -123,7 +136,8 @@
# #
"""Manage all Kobo books, either encrypted or DRM-free.""" """Manage all Kobo books, either encrypted or DRM-free."""
__version__ = '3.1.6' __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
@@ -137,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
@@ -249,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.exists(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""
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"" self.kobodir = u""
kobodb = 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:
@@ -280,8 +341,17 @@ 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
if (not(os.path.isfile(kobodb))):
# give up here, we haven't found anything useful
self.kobodir = u""
kobodb = u""
if (self.kobodir != u""): if (self.kobodir != u""):
self.bookdir = os.path.join(self.kobodir, u"kepub") self.bookdir = os.path.join(self.kobodir, u"kepub")
@@ -349,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 ;-)
@@ -372,13 +449,8 @@ 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:
userkey = hashlib.sha256(deviceid + userid).hexdigest()
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: 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:]))
@@ -518,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,10 +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. https://thisishex.wordpress.com/scuolabook-drm-remover/
2) Run Scuolabook DRM Remover.
3) Get your free books from the directory where you started the program.
Note: Harper.
It is recommended to use Scuolabook version 2.0.1 and refuse all updates
because the encryption algorithm may change making this tool useless.
Hex

View File

@@ -12,7 +12,7 @@ The is archive includes tools to remove DRM from:
- Adobe Digital Editions PDFs - Adobe Digital Editions PDFs
- Mobipocket ebooks - Mobipocket ebooks
- eReader PDB books - eReader PDB books
- Scuolabooks (Windows only solution by Hex) - Scuolabooks (Link to solution by Hex)
These tools do NOT work with Apple's iBooks FairPlay DRM (see end of this file.) These tools do NOT work with Apple's iBooks FairPlay DRM (see end of this file.)
@@ -78,7 +78,7 @@ Rocket_ebooks
Information about the now-obsolete Rocket ebook format and DRM, along with source for a tool to remove the DRM. Information about the now-obsolete Rocket ebook format and DRM, along with source for a tool to remove the DRM.
Scuolabook_DRM Scuolabook_DRM
A windows-only application (including source code) for removing DRM from ScuolaBooks PDFs, created by "Hex" and included with permission. A link to the tool for removing DRM from ScuolaBooks PDFs, created by "Hex".
Windows and Python Windows and Python