summaryrefslogtreecommitdiffstats
path: root/DeDRM_Windows_Application
diff options
context:
space:
mode:
authorApprentice Alf <[email protected]>2013-01-19 14:50:57 +0000
committerApprentice Alf <[email protected]>2015-03-07 14:21:18 +0000
commitc23b9034209b8c9448dc298bdc3807fa6933779b (patch)
treec0043d43ce4f3cec695786a9e9c2b5f7ebd5192c /DeDRM_Windows_Application
parent602ff30b3af38ff3ad2ecb80010afe2aff131f1d (diff)
tools v5.6
Diffstat (limited to 'DeDRM_Windows_Application')
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_app.pyw236
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/alfcrypto.py8
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/argv_utils.py92
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/convert2xml.py17
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptepub.py88
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdb.py45
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdf.py54
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/flatxml2html.py12
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/genbook.py2
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ignobleepub.py39
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ineptepub.py4
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py7
-rw-r--r--DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/scriptinterface.py153
-rw-r--r--DeDRM_Windows_Application/DeDRM_ReadMe.txt8
14 files changed, 433 insertions, 332 deletions
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_app.pyw b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_app.pyw
index 23cc30a..8e9290e 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_app.pyw
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_app.pyw
@@ -1,13 +1,19 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# DeDRM.pyw, version 5.5.3
+# DeDRM.pyw, version 5.6
# By some_updates and Apprentice Alf
import sys
import os, os.path
sys.path.append(os.path.join(sys.path[0],"lib"))
-os.environ['PYTHONIOENCODING'] = "utf-8"
+import sys, os
+import codecs
+
+from argv_utils import add_cp65001_codec, set_utf8_default_encoding, utf8_argv
+add_cp65001_codec()
+set_utf8_default_encoding()
+
import shutil
import Tkinter
@@ -16,15 +22,35 @@ import Tkconstants
import tkFileDialog
from scrolltextwidget import ScrolledText
from activitybar import ActivityBar
-import subprocess
-from subprocess import Popen, PIPE, STDOUT
-import subasyncio
-from subasyncio import Process
import re
import simpleprefs
-
-__version__ = '5.5.3'
+from Queue import Full
+from Queue import Empty
+from multiprocessing import Process, Queue
+
+from scriptinterface import decryptepub, decryptpdb, decryptpdf, decryptk4mobi
+
+
+# Wrap a stream so that output gets flushed immediately
+# and appended to shared queue
+class QueuedStream:
+ def __init__(self, stream, q):
+ self.stream = stream
+ self.encoding = stream.encoding
+ self.q = q
+ if self.encoding == None:
+ self.encoding = "utf-8"
+ def write(self, data):
+ if isinstance(data,unicode):
+ data = data.encode(self.encoding,"replace")
+ self.q.put(data)
+ # self.stream.write(data)
+ # self.stream.flush()
+ def __getattr__(self, attr):
+ return getattr(self.stream, attr)
+
+__version__ = '5.6'
class DrmException(Exception):
pass
@@ -35,6 +61,7 @@ class MainApp(Tk):
self.withdraw()
self.dnd = dnd
self.apphome = apphome
+
# preference settings
# [dictionary key, file in preferences directory where info is stored]
description = [ ['pids' , 'pidlist.txt' ],
@@ -152,7 +179,7 @@ class PrefsDialog(Toplevel):
self.pidnums.set(self.prefs_array['pids'])
self.pidinfo.grid(row=3, column=1, sticky=sticky)
- Tkinter.Label(body, text='eInk Kindle Serial Number list\n(16 characters, first character B, comma separated)').grid(row=4, sticky=Tkconstants.E)
+ Tkinter.Label(body, text='eInk Kindle Serial Number list\n(16 characters, comma separated)').grid(row=4, sticky=Tkconstants.E)
self.sernums = Tkinter.StringVar()
self.serinfo = Tkinter.Entry(body, width=50, textvariable=self.sernums)
if 'serials' in self.prefs_array:
@@ -327,10 +354,11 @@ class ConvDialog(Toplevel):
self.filenames = filenames
self.interval = 50
self.p2 = None
+ self.q = Queue()
self.running = 'inactive'
self.numgood = 0
self.numbad = 0
- self.log = u""
+ self.log = ''
self.status = Tkinter.Label(self, text='DeDRM processing...')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
@@ -378,16 +406,18 @@ class ConvDialog(Toplevel):
if len(self.filenames) > 0:
filename = self.filenames.pop(0)
if filename == None:
- msg = u"\nComplete: Successes: {0}, Failures: {1}\n".format(self.numgood,self.numbad)
+ msg = '\nComplete: '
+ msg += 'Successes: %d, ' % self.numgood
+ msg += 'Failures: %d\n' % self.numbad
self.showCmdOutput(msg)
if self.numbad == 0:
self.after(2000,self.conversion_done())
logfile = os.path.join(rscpath,'dedrm.log')
- file(logfile,'w').write(self.log.encode('utf8'))
+ file(logfile,'wb').write(self.log)
return
infile = filename
bname = os.path.basename(infile)
- msg = u"Processing: {0} ... ".format(bname)
+ msg = 'Processing: ' + bname + ' ... '
self.log += msg
self.showCmdOutput(msg)
outdir = os.path.dirname(filename)
@@ -399,9 +429,9 @@ class ConvDialog(Toplevel):
if rv == 0:
self.bar.start()
self.running = 'active'
- self.processPipe()
+ self.processQueue()
else:
- msg = u"Unknown File: {0}\n".format(bname)
+ msg = 'Unknown File: ' + bname + '\n'
self.log += msg
self.showCmdOutput(msg)
self.numbad += 1
@@ -410,7 +440,7 @@ class ConvDialog(Toplevel):
# kill any still running subprocess
self.running = 'stopped'
if self.p2 != None:
- if (self.p2.wait('nowait') == None):
+ if (self.p2.exitcode == None):
self.p2.terminate()
self.conversion_done()
@@ -426,130 +456,127 @@ class ConvDialog(Toplevel):
# read from subprocess pipe without blocking
# invoked every interval via the widget "after"
# option being used, so need to reset it for the next time
- def processPipe(self):
+ def processQueue(self):
if self.p2 == None:
# nothing to wait for so just return
return
- poll = self.p2.wait('nowait')
+ poll = self.p2.exitcode
if poll != None:
self.bar.stop()
if poll == 0:
- msg = u"\nSuccess\n"
+ msg = 'Success\n'
self.numgood += 1
- text = self.p2.read().decode('utf8')
- text += self.p2.readerr().decode('utf8')
+ done = False
+ text = ''
+ while not done:
+ try:
+ data = self.q.get_nowait()
+ text += data
+ except Empty:
+ done = True
+ pass
self.log += text
self.log += msg
- else:
- msg = u"\nFailed\n"
- text = self.p2.read().decode('utf8')
- text += self.p2.readerr().decode('utf8')
- msg += text
- self.numbad += 1
+ if poll != 0:
+ msg = 'Failed\n'
+ done = False
+ text = ''
+ while not done:
+ try:
+ data = self.q.get_nowait()
+ text += data
+ except Empty:
+ done = True
+ pass
+ msg += '\n'
+ self.log += text
self.log += msg
+ self.numbad += 1
+ self.p2.join()
self.showCmdOutput(msg)
self.p2 = None
self.running = 'inactive'
self.after(50,self.processBooks)
return
+ try:
+ text = self.q.get_nowait()
+ except Empty:
+ text = ''
+ pass
+ if text != '':
+ self.log += text
# make sure we get invoked again by event loop after interval
- self.stext.after(self.interval,self.processPipe)
+ self.stext.after(self.interval,self.processQueue)
return
def decrypt_ebook(self, infile, outdir, rscpath):
- apphome = self.apphome
+ q = self.q
rv = 1
name, ext = os.path.splitext(os.path.basename(infile))
ext = ext.lower()
if ext == '.epub':
- self.p2 = processEPUB(apphome, infile, outdir, rscpath)
+ self.p2 = Process(target=processEPUB, args=(q, infile, outdir, rscpath))
+ self.p2.start()
return 0
if ext == '.pdb':
- self.p2 = processPDB(apphome, infile, outdir, rscpath)
+ self.p2 = Process(target=processPDB, args=(q, infile, outdir, rscpath))
+ self.p2.start()
return 0
if ext in ['.azw', '.azw1', '.azw3', '.azw4', '.prc', '.mobi', '.tpz']:
- self.p2 = processK4MOBI(apphome, infile, outdir, rscpath)
+ self.p2 = Process(target=processK4MOBI,args=(q, infile, outdir, rscpath))
+ self.p2.start()
return 0
if ext == '.pdf':
- self.p2 = processPDF(apphome, infile, outdir, rscpath)
+ self.p2 = Process(target=processPDF, args=(q, infile, outdir, rscpath))
+ self.p2.start()
return 0
return rv
-# run as a subprocess via pipes and collect stdout, stderr, and return value
-def runit(apphome, ncmd, nparms):
- pengine = sys.executable
- if pengine is None or pengine == '':
- pengine = 'python'
- pengine = os.path.normpath(pengine)
- cmdline = pengine + ' "' + os.path.join(apphome, ncmd) + '" '
- # if sys.platform.startswith('win'):
- # search_path = os.environ['PATH']
- # search_path = search_path.lower()
- # if search_path.find('python') < 0:
- # # if no python hope that win registry finds what is associated with py extension
- # cmdline = pengine + ' "' + os.path.join(apphome, ncmd) + '" '
- cmdline += nparms
- cmdline = cmdline.encode(sys.getfilesystemencoding())
- p2 = subasyncio.Process(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False, env = os.environ)
- return p2
-
-def processK4MOBI(apphome, infile, outdir, rscpath):
- cmd = os.path.join('lib','k4mobidedrm.py')
- parms = ''
- pidnums = ''
- pidspath = os.path.join(rscpath,'pidlist.txt')
- if os.path.exists(pidspath):
- pidnums = file(pidspath,'r').read()
- pidnums = pidnums.rstrip(os.linesep)
- if pidnums != '':
- parms += '-p "' + pidnums + '" '
- serialnums = ''
- serialnumspath = os.path.join(rscpath,'seriallist.txt')
- if os.path.exists(serialnumspath):
- serialnums = file(serialnumspath,'r').read()
- serialnums = serialnums.rstrip(os.linesep)
- if serialnums != '':
- parms += '-s "' + serialnums + '" '
-
- files = os.listdir(rscpath)
- filefilter = re.compile("\.info$|\.kinf$", re.IGNORECASE)
- files = filter(filefilter.search, files)
- if files:
- for filename in files:
- dpath = os.path.join(rscpath,filename)
- parms += '-k "' + dpath + '" '
- parms += '"' + infile +'" "' + outdir + '"'
- p2 = runit(apphome, cmd, parms)
- return p2
-
-def processPDF(apphome, infile, outdir, rscpath):
- cmd = os.path.join('lib','decryptpdf.py')
- parms = '"' + infile + '" "' + outdir + '" "' + rscpath + '"'
- p2 = runit(apphome, cmd, parms)
- return p2
-
-def processEPUB(apphome, infile, outdir, rscpath):
- # invoke routine to check both Adept and Barnes and Noble
- cmd = os.path.join('lib','decryptepub.py')
- parms = '"' + infile + '" "' + outdir + '" "' + rscpath + '"'
- p2 = runit(apphome, cmd, parms)
- return p2
-
-def processPDB(apphome, infile, outdir, rscpath):
- cmd = os.path.join('lib','decryptpdb.py')
- parms = '"' + infile + '" "' + outdir + '" "' + rscpath + '"'
- p2 = runit(apphome, cmd, parms)
- return p2
-
-
-def main(argv=sys.argv):
- apphome = os.path.dirname(sys.argv[0])
+# child process starts here
+def processK4MOBI(q, infile, outdir, rscpath):
+ add_cp65001_codec()
+ set_utf8_default_encoding()
+ sys.stdout = QueuedStream(sys.stdout, q)
+ sys.stderr = QueuedStream(sys.stderr, q)
+ rv = decryptk4mobi(infile, outdir, rscpath)
+ sys.exit(rv)
+
+# child process starts here
+def processPDF(q, infile, outdir, rscpath):
+ add_cp65001_codec()
+ set_utf8_default_encoding()
+ sys.stdout = QueuedStream(sys.stdout, q)
+ sys.stderr = QueuedStream(sys.stderr, q)
+ rv = decryptpdf(infile, outdir, rscpath)
+ sys.exit(rv)
+
+# child process starts here
+def processEPUB(q, infile, outdir, rscpath):
+ add_cp65001_codec()
+ set_utf8_default_encoding()
+ sys.stdout = QueuedStream(sys.stdout, q)
+ sys.stderr = QueuedStream(sys.stderr, q)
+ rv = decryptepub(infile, outdir, rscpath)
+ sys.exit(rv)
+
+# child process starts here
+def processPDB(q, infile, outdir, rscpath):
+ add_cp65001_codec()
+ set_utf8_default_encoding()
+ sys.stdout = QueuedStream(sys.stdout, q)
+ sys.stderr = QueuedStream(sys.stderr, q)
+ rv = decryptpdb(infile, outdir, rscpath)
+ sys.exit(rv)
+
+
+def main(argv=utf8_argv()):
+ apphome = os.path.dirname(argv[0])
apphome = os.path.abspath(apphome)
# windows may pass a spurious quoted null string as argv[1] from bat file
# simply work around this until we can figure out a better way to handle things
- if len(argv) == 2:
+ if sys.platform.startswith('win') and len(argv) == 2:
temp = argv[1]
temp = temp.strip('"')
temp = temp.strip()
@@ -563,11 +590,10 @@ def main(argv=sys.argv):
else : # processing books via drag and drop
dnd = True
# build a list of the files to be processed
+ # note all filenames and paths have been utf-8 encoded
infilelst = argv[1:]
filenames = []
for infile in infilelst:
- infile = infile.decode(sys.getfilesystemencoding())
- print infile
infile = infile.replace('"','')
infile = os.path.abspath(infile)
if os.path.isdir(infile):
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/alfcrypto.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/alfcrypto.py
index b1b0606..036ba10 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/alfcrypto.py
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/alfcrypto.py
@@ -34,10 +34,14 @@ def _load_libalfcrypto():
else:
name_of_lib = 'libalfcrypto64.so'
+ # hard code to local location for libalfcrypto
libalfcrypto = os.path.join(sys.path[0],name_of_lib)
-
if not os.path.isfile(libalfcrypto):
- raise Exception('libalfcrypto not found')
+ libalfcrypto = os.path.join(sys.path[0], 'lib', name_of_lib)
+ if not os.path.isfile(libalfcrypto):
+ libalfcrypto = os.path.join('.',name_of_lib)
+ if not os.path.isfile(libalfcrypto):
+ raise Exception('libalfcrypto not found at %s' % libalfcrypto)
libalfcrypto = CDLL(libalfcrypto)
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/argv_utils.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/argv_utils.py
new file mode 100644
index 0000000..717387a
--- /dev/null
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/argv_utils.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys, os
+import locale
+import codecs
+
+# get sys.argv arguments and encode them into utf-8
+def utf8_argv():
+ if sys.platform.startswith('win'):
+ # Versions 2.x of Python don't support Unicode in sys.argv on
+ # Windows, with the underlying Windows API instead replacing multi-byte
+ # characters with '?'. So use shell32.GetCommandLineArgvW to get sys.argv
+ # as a list of Unicode strings and encode them as utf-8
+
+ from ctypes import POINTER, byref, cdll, c_int, windll
+ from ctypes.wintypes import LPCWSTR, LPWSTR
+
+ GetCommandLineW = cdll.kernel32.GetCommandLineW
+ GetCommandLineW.argtypes = []
+ GetCommandLineW.restype = LPCWSTR
+
+ CommandLineToArgvW = windll.shell32.CommandLineToArgvW
+ CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)]
+ CommandLineToArgvW.restype = POINTER(LPWSTR)
+
+ cmd = GetCommandLineW()
+ argc = c_int(0)
+ argv = CommandLineToArgvW(cmd, byref(argc))
+ if argc.value > 0:
+ # Remove Python executable and commands if present
+ start = argc.value - len(sys.argv)
+ return [argv[i].encode('utf-8') for i in
+ xrange(start, argc.value)]
+ # this should never happen
+ return None
+ else:
+ argv = []
+ argvencoding = sys.stdin.encoding
+ if argvencoding == None:
+ argvencoding = sys.getfilesystemencoding()
+ if argvencoding == None:
+ argvencoding = 'utf-8'
+ for arg in sys.argv:
+ if type(arg) == unicode:
+ argv.append(arg.encode('utf-8'))
+ else:
+ argv.append(arg.decode(argvencoding).encode('utf-8'))
+ return argv
+
+
+def add_cp65001_codec():
+ try:
+ codecs.lookup('cp65001')
+ except LookupError:
+ codecs.register(
+ lambda name: name == 'cp65001' and codecs.lookup('utf-8') or None)
+ return
+
+
+def set_utf8_default_encoding():
+ if sys.getdefaultencoding() == 'utf-8':
+ return
+
+ # Regenerate setdefaultencoding.
+ reload(sys)
+ sys.setdefaultencoding('utf-8')
+
+ for attr in dir(locale):
+ if attr[0:3] != 'LC_':
+ continue
+ aref = getattr(locale, attr)
+ try:
+ locale.setlocale(aref, '')
+ except locale.Error:
+ continue
+ try:
+ lang = locale.getlocale(aref)[0]
+ except (TypeError, ValueError):
+ continue
+ if lang:
+ try:
+ locale.setlocale(aref, (lang, 'UTF-8'))
+ except locale.Error:
+ os.environ[attr] = lang + '.UTF-8'
+ try:
+ locale.setlocale(locale.LC_ALL, '')
+ except locale.Error:
+ pass
+ return
+
+
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/convert2xml.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/convert2xml.py
index 6c8fa83..c4e23b7 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/convert2xml.py
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/convert2xml.py
@@ -255,13 +255,15 @@ class PageParser(object):
'empty_text_region' : (1, 'snippets', 1, 0),
- 'img' : (1, 'snippets', 1, 0),
- 'img.x' : (1, 'scalar_number', 0, 0),
- 'img.y' : (1, 'scalar_number', 0, 0),
- 'img.h' : (1, 'scalar_number', 0, 0),
- 'img.w' : (1, 'scalar_number', 0, 0),
- 'img.src' : (1, 'scalar_number', 0, 0),
- 'img.color_src' : (1, 'scalar_number', 0, 0),
+ 'img' : (1, 'snippets', 1, 0),
+ 'img.x' : (1, 'scalar_number', 0, 0),
+ 'img.y' : (1, 'scalar_number', 0, 0),
+ 'img.h' : (1, 'scalar_number', 0, 0),
+ 'img.w' : (1, 'scalar_number', 0, 0),
+ 'img.src' : (1, 'scalar_number', 0, 0),
+ 'img.color_src' : (1, 'scalar_number', 0, 0),
+ 'img.gridBeginCenter' : (1, 'scalar_number', 0, 0),
+ 'img.gridEndCenter' : (1, 'scalar_number', 0, 0),
'paragraph' : (1, 'snippets', 1, 0),
'paragraph.class' : (1, 'scalar_text', 0, 0),
@@ -307,6 +309,7 @@ class PageParser(object):
'span.gridEndCenter' : (1, 'scalar_number', 0, 0),
'extratokens' : (1, 'snippets', 1, 0),
+ 'extratokens.class' : (1, 'scalar_text', 0, 0),
'extratokens.type' : (1, 'scalar_text', 0, 0),
'extratokens.firstGlyph' : (1, 'scalar_number', 0, 0),
'extratokens.lastGlyph' : (1, 'scalar_number', 0, 0),
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptepub.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptepub.py
deleted file mode 100644
index e64c860..0000000
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptepub.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python
-# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
-
-class Unbuffered:
- def __init__(self, stream):
- self.stream = stream
- def write(self, data):
- self.stream.write(data)
- self.stream.flush()
- def __getattr__(self, attr):
- return getattr(self.stream, attr)
-
-import sys
-sys.stdout=Unbuffered(sys.stdout)
-import os
-
-import ineptepub
-import ignobleepub
-import zipfix
-import re
-
-def main(argv=sys.argv):
- args = argv[1:]
- if len(args) != 3:
- return -1
- infile = args[0]
- outdir = args[1]
- rscpath = args[2]
- errlog = ''
-
- # first fix the epub to make sure we do not get errors
- name, ext = os.path.splitext(os.path.basename(infile))
- bpath = os.path.dirname(infile)
- zippath = os.path.join(bpath,name + '_temp.zip')
- rv = zipfix.repairBook(infile, zippath)
- if rv != 0:
- print "Error while trying to fix epub"
- return rv
-
- # determine a good name for the output file
- outfile = os.path.join(outdir, name + '_nodrm.epub')
-
- rv = 1
- # first try with the Adobe adept epub
- # try with any keyfiles (*.der) in the rscpath
- files = os.listdir(rscpath)
- filefilter = re.compile("\.der$", re.IGNORECASE)
- files = filter(filefilter.search, files)
- if files:
- for filename in files:
- keypath = os.path.join(rscpath, filename)
- try:
- rv = ineptepub.decryptBook(keypath, zippath, outfile)
- if rv == 0:
- break
- except Exception, e:
- errlog += str(e)
- rv = 1
- pass
- if rv == 0:
- os.remove(zippath)
- return 0
-
- # still no luck
- # now try with ignoble epub
- # try with any keyfiles (*.b64) in the rscpath
- files = os.listdir(rscpath)
- filefilter = re.compile("\.b64$", re.IGNORECASE)
- files = filter(filefilter.search, files)
- if files:
- for filename in files:
- keypath = os.path.join(rscpath, filename)
- try:
- rv = ignobleepub.decryptBook(keypath, zippath, outfile)
- if rv == 0:
- break
- except Exception, e:
- errlog += str(e)
- rv = 1
- pass
- os.remove(zippath)
- if rv != 0:
- print errlog
- return rv
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdb.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdb.py
deleted file mode 100644
index f0775c1..0000000
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdb.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
-
-class Unbuffered:
- def __init__(self, stream):
- self.stream = stream
- def write(self, data):
- self.stream.write(data)
- self.stream.flush()
- def __getattr__(self, attr):
- return getattr(self.stream, attr)
-
-import sys
-sys.stdout=Unbuffered(sys.stdout)
-import os
-
-import erdr2pml
-
-def main(argv=sys.argv):
- args = argv[1:]
- if len(args) != 3:
- return -1
- infile = args[0]
- outdir = args[1]
- rscpath = args[2]
- rv = 1
- socialpath = os.path.join(rscpath,'sdrmlist.txt')
- if os.path.exists(socialpath):
- keydata = file(socialpath,'r').read()
- keydata = keydata.rstrip(os.linesep)
- ar = keydata.split(',')
- for i in ar:
- try:
- name, cc8 = i.split(':')
- except ValueError:
- print ' Error parsing user supplied social drm data.'
- return 1
- rv = erdr2pml.decryptBook(infile, outdir, True, erdr2pml.getuser_key(name, cc8) )
- if rv == 0:
- break
- return rv
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdf.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdf.py
deleted file mode 100644
index ddaeacd..0000000
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/decryptpdf.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
-
-class Unbuffered:
- def __init__(self, stream):
- self.stream = stream
- def write(self, data):
- self.stream.write(data)
- self.stream.flush()
- def __getattr__(self, attr):
- return getattr(self.stream, attr)
-
-import sys
-sys.stdout=Unbuffered(sys.stdout)
-import os
-import re
-import ineptpdf
-
-def main(argv=sys.argv):
- args = argv[1:]
- if len(args) != 3:
- return -1
- infile = args[0]
- outdir = args[1]
- rscpath = args[2]
- errlog = ''
- rv = 1
-
- # determine a good name for the output file
- name, ext = os.path.splitext(os.path.basename(infile))
- outfile = os.path.join(outdir, name + '_nodrm.pdf')
-
- # try with any keyfiles (*.der) in the rscpath
- files = os.listdir(rscpath)
- filefilter = re.compile("\.der$", re.IGNORECASE)
- files = filter(filefilter.search, files)
- if files:
- for filename in files:
- keypath = os.path.join(rscpath, filename)
- try:
- rv = ineptpdf.decryptBook(keypath, infile, outfile)
- if rv == 0:
- break
- except Exception, e:
- errlog += str(e)
- rv = 1
- pass
- if rv != 0:
- print errlog
- return rv
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/flatxml2html.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/flatxml2html.py
index e5647f4..4d83368 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/flatxml2html.py
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/flatxml2html.py
@@ -387,10 +387,14 @@ class DocParser(object):
ws_last = int(argres)
elif name.endswith('word.class'):
- (cname, space) = argres.split('-',1)
- if space == '' : space = '0'
- if (cname == 'spaceafter') and (int(space) > 0) :
- word_class = 'sa'
+ # we only handle spaceafter word class
+ try:
+ (cname, space) = argres.split('-',1)
+ if space == '' : space = '0'
+ if (cname == 'spaceafter') and (int(space) > 0) :
+ word_class = 'sa'
+ except:
+ pass
elif name.endswith('word.img.src'):
result.append(('img' + word_class, int(argres)))
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/genbook.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/genbook.py
index 9733887..746178f 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/genbook.py
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/genbook.py
@@ -117,7 +117,7 @@ class Dictionary(object):
self.pos = val
return self.stable[self.pos]
else:
- print "Error - %d outside of string table limits" % val
+ print "Error: %d outside of string table limits" % val
raise TpzDRMError('outside or string table limits')
# sys.exit(-1)
def getSize(self):
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ignobleepub.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ignobleepub.py
index 2e0bd06..b7cbdc5 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ignobleepub.py
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ignobleepub.py
@@ -3,7 +3,7 @@
from __future__ import with_statement
-# ignobleepub.pyw, version 3.6
+# ignobleepub.pyw, version 3.7
# Copyright © 2009-2010 by i♥cabbages
# Released under the terms of the GNU General Public Licence, version 3
@@ -26,18 +26,19 @@ from __future__ import with_statement
# 2 - Added OS X support by using OpenSSL when available
# 3 - screen out improper key lengths to prevent segfaults on Linux
# 3.1 - Allow Windows versions of libcrypto to be found
-# 3.2 - add support for encoding to 'utf-8' when building up list of files to cecrypt from encryption.xml
-# 3.3 - On Windows try PyCrypto first and OpenSSL next
-# 3.4 - Modify interace to allow use with import
+# 3.2 - add support for encoding to 'utf-8' when building up list of files to decrypt from encryption.xml
+# 3.3 - On Windows try PyCrypto first, OpenSSL next
+# 3.4 - Modify interface to allow use with import
# 3.5 - Fix for potential problem with PyCrypto
# 3.6 - Revised to allow use in calibre plugins to eliminate need for duplicate code
+# 3.7 - Tweaked to match ineptepub more closely
"""
Decrypt Barnes & Noble encrypted ePub books.
"""
__license__ = 'GPL v3'
-__version__ = "3.6"
+__version__ = "3.7"
import sys
import os
@@ -254,18 +255,17 @@ def ignobleBook(inpath):
return True
return False
-# return error code and error message duple
def decryptBook(keyb64, inpath, outpath):
if AES is None:
- # 1 means don't try again
- return (1, u"PyCrypto or OpenSSL must be installed.")
+ raise IGNOBLEError(u"PyCrypto or OpenSSL must be installed.")
key = keyb64.decode('base64')[:16]
aes = AES(key)
with closing(ZipFile(open(inpath, 'rb'))) as inf:
namelist = set(inf.namelist())
if 'META-INF/rights.xml' not in namelist or \
'META-INF/encryption.xml' not in namelist:
- return (1, u"Not a secure Barnes & Noble ePub.")
+ print u"{0:s} is DRM-free.".format(os.path.basename(inpath))
+ return 1
for name in META_NAMES:
namelist.remove(name)
try:
@@ -274,7 +274,8 @@ def decryptBook(keyb64, inpath, outpath):
expr = './/%s' % (adept('encryptedKey'),)
bookkey = ''.join(rights.findtext(expr))
if len(bookkey) != 64:
- return (1, u"Not a secure Barnes & Noble ePub.")
+ print u"{0:s} is not a secure Barnes & Noble ePub.".format(os.path.basename(inpath))
+ return 1
bookkey = aes.decrypt(bookkey.decode('base64'))
bookkey = bookkey[:-ord(bookkey[-1])]
encryption = inf.read('META-INF/encryption.xml')
@@ -286,21 +287,23 @@ def decryptBook(keyb64, inpath, outpath):
for path in namelist:
data = inf.read(path)
outf.writestr(path, decryptor.decrypt(path, data))
- except Exception, e:
- return (2, u"{0}.".format(e.args[0]))
- return (0, u"Success")
+ except:
+ print u"Could not decrypt {0:s} because of an exception:\n{1:s}".format(os.path.basename(inpath), traceback.format_exc())
+ return 2
+ return 0
def cli_main(argv=unicode_argv()):
progname = os.path.basename(argv[0])
if len(argv) != 4:
- print u"usage: {0} <keyfile.der> <inbook.epub> <outbook.epub>".format(progname)
+ print u"usage: {0} <keyfile.b64> <inbook.epub> <outbook.epub>".format(progname)
return 1
keypath, inpath, outpath = argv[1:]
userkey = open(keypath,'rb').read()
result = decryptBook(userkey, inpath, outpath)
- print result[1]
- return result[0]
+ if result == 0:
+ print u"Successfully decrypted {0:s} as {1:s}".format(os.path.basename(inpath),os.path.basename(outpath))
+ return result
def gui_main():
import Tkinter
@@ -399,10 +402,10 @@ def gui_main():
except Exception, e:
self.status['text'] = u"Error: {0}".format(e.args[0])
return
- if decrypt_status[0] == 0:
+ if decrypt_status == 0:
self.status['text'] = u"File successfully decrypted"
else:
- self.status['text'] = decrypt_status[1]
+ self.status['text'] = u"The was an error decrypting the file."
root = Tkinter.Tk()
root.title(u"Barnes & Noble ePub Decrypter v.{0}".format(__version__))
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ineptepub.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ineptepub.py
index 4b5a296..48b7727 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ineptepub.py
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/ineptepub.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
@@ -542,7 +542,7 @@ def gui_main():
try:
decrypt_status = decryptBook(userkey, inpath, outpath)
except Exception, e:
- self.status['text'] = u"Error; {0}".format(e)
+ self.status['text'] = u"Error: {0}".format(e.args[0])
return
if decrypt_status == 0:
self.status['text'] = u"File successfully decrypted"
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py
index 8adb107..70ed898 100644
--- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py
@@ -50,8 +50,9 @@ from __future__ import with_statement
# 4.7 - Added timing reports, and changed search for Mac key files
# 4.8 - Much better unicode handling, matching the updated inept and ignoble scripts
# - Moved back into plugin, __init__ in plugin now only contains plugin code.
+# 4.9 - Missed some invalid characters in cleanup_name
-__version__ = '4.8'
+__version__ = '4.9'
import sys, os, re
@@ -144,7 +145,7 @@ def unicode_argv():
# and with some (heavily edited) code from Paul Durrant's kindlenamer.py
def cleanup_name(name):
# substitute filename unfriendly characters
- name = name.replace(u"<",u"[").replace(u">",u"]").replace(u" : ",u" – ").replace(u": ",u" – ").replace(u":",u"—").replace(u"/",u"_").replace(u"\\",u"_").replace(u"|",u"_").replace(u"\"",u"\'")
+ name = name.replace(u"<",u"[").replace(u">",u"]").replace(u" : ",u" – ").replace(u": ",u" – ").replace(u":",u"—").replace(u"/",u"_").replace(u"\\",u"_").replace(u"|",u"_").replace(u"\"",u"\'").replace(u"*",u"_").replace(u"?",u"")
# delete control characters
name = u"".join(char for char in name if ord(char)>=32)
# white space to single space, delete leading and trailing while space
@@ -220,6 +221,7 @@ def decryptBook(infile, outdir, kInfoFiles, serials, pids):
book = GetDecryptedBook(infile, kInfoFiles, serials, pids, starttime)
except Exception, e:
print u"Error decrypting book after {1:.1f} seconds: {0}".format(e.args[0],time.time()-starttime)
+ traceback.print_exc()
return 1
# if we're saving to the same folder as the original, use file name_
@@ -246,6 +248,7 @@ def decryptBook(infile, outdir, kInfoFiles, serials, pids):
# remove internal temporary directory of Topaz pieces
book.cleanup()
+ return 0
def usage(progname):
diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/scriptinterface.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/scriptinterface.py
new file mode 100644
index 0000000..b8f1cff
--- /dev/null
+++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/scriptinterface.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
+
+import sys
+import os
+import re
+import ineptepub
+import ignobleepub
+import zipfix
+import ineptpdf
+import erdr2pml
+import k4mobidedrm
+
+def decryptepub(infile, outdir, rscpath):
+ errlog = ''
+
+ # first fix the epub to make sure we do not get errors
+ name, ext = os.path.splitext(os.path.basename(infile))
+ bpath = os.path.dirname(infile)
+ zippath = os.path.join(bpath,name + '_temp.zip')
+ rv = zipfix.repairBook(infile, zippath)
+ if rv != 0:
+ print "Error while trying to fix epub"
+ return rv
+
+ # determine a good name for the output file
+ outfile = os.path.join(outdir, name + '_nodrm.epub')
+
+ rv = 1
+ # first try with the Adobe adept epub
+ # try with any keyfiles (*.der) in the rscpath
+ files = os.listdir(rscpath)
+ filefilter = re.compile("\.der$", re.IGNORECASE)
+ files = filter(filefilter.search, files)
+ if files:
+ for filename in files:
+ keypath = os.path.join(rscpath, filename)
+ userkey = open(keypath,'rb').read()
+ try:
+ rv = ineptepub.decryptBook(userkey, zippath, outfile)
+ if rv == 0:
+ break
+ except Exception, e:
+ errlog += str(e)
+ rv = 1
+ pass
+ if rv == 0:
+ os.remove(zippath)
+ return 0
+
+ # still no luck
+ # now try with ignoble epub
+ # try with any keyfiles (*.b64) in the rscpath
+ files = os.listdir(rscpath)
+ filefilter = re.compile("\.b64$", re.IGNORECASE)
+ files = filter(filefilter.search, files)
+ if files:
+ for filename in files:
+ keypath = os.path.join(rscpath, filename)
+ userkey = open(keypath,'rb').read()
+ try:
+ rv = ignobleepub.decryptBook(userkey, zippath, outfile)
+ if rv == 0:
+ break
+ except Exception, e:
+ errlog += str(e)
+ rv = 1
+ pass
+ os.remove(zippath)
+ if rv != 0:
+ print errlog
+ return rv
+
+
+def decryptpdf(infile, outdir, rscpath):
+ errlog = ''
+ rv = 1
+
+ # determine a good name for the output file
+ name, ext = os.path.splitext(os.path.basename(infile))
+ outfile = os.path.join(outdir, name + '_nodrm.pdf')
+
+ # try with any keyfiles (*.der) in the rscpath
+ files = os.listdir(rscpath)
+ filefilter = re.compile("\.der$", re.IGNORECASE)
+ files = filter(filefilter.search, files)
+ if files:
+ for filename in files:
+ keypath = os.path.join(rscpath, filename)
+ userkey = open(keypath,'rb').read()
+ try:
+ rv = ineptpdf.decryptBook(userkey, infile, outfile)
+ if rv == 0:
+ break
+ except Exception, e:
+ errlog += str(e)
+ rv = 1
+ pass
+ if rv != 0:
+ print errlog
+ return rv
+
+
+def decryptpdb(infile, outdir, rscpath):
+ outname = os.path.splitext(os.path.basename(infile))[0] + ".pmlz"
+ outpath = os.path.join(outdir, outname)
+ rv = 1
+ socialpath = os.path.join(rscpath,'sdrmlist.txt')
+ if os.path.exists(socialpath):
+ keydata = file(socialpath,'r').read()
+ keydata = keydata.rstrip(os.linesep)
+ ar = keydata.split(',')
+ for i in ar:
+ try:
+ name, cc8 = i.split(':')
+ except ValueError:
+ print ' Error parsing user supplied social drm data.'
+ return 1
+ rv = erdr2pml.decryptBook(infile, outpath, True, erdr2pml.getuser_key(name, cc8))
+ if rv == 0:
+ break
+ return rv
+
+
+def decryptk4mobi(infile, outdir, rscpath):
+ rv = 1
+ pidnums = []
+ pidspath = os.path.join(rscpath,'pidlist.txt')
+ if os.path.exists(pidspath):
+ pidstr = file(pidspath,'r').read()
+ pidstr = pidstr.rstrip(os.linesep)
+ pidstr = pidstr.strip()
+ if pidstr != '':
+ pidnums = pidstr.split(',')
+ serialnums = []
+ serialnumspath = os.path.join(rscpath,'seriallist.txt')
+ if os.path.exists(serialnumspath):
+ serialstr = file(serialnumspath,'r').read()
+ serialstr = serialstr.rstrip(os.linesep)
+ serialstr = serialstr.strip()
+ if serialstr != '':
+ serialnums = serialstr.split(',')
+ kInfoFiles = []
+ files = os.listdir(rscpath)
+ filefilter = re.compile("\.info$|\.kinf$", re.IGNORECASE)
+ files = filter(filefilter.search, files)
+ if files:
+ for filename in files:
+ dpath = os.path.join(rscpath,filename)
+ kInfoFiles.append(dpath)
+ rv = k4mobidedrm.decryptBook(infile, outdir, kInfoFiles, serialnums, pidnums)
+ return rv
diff --git a/DeDRM_Windows_Application/DeDRM_ReadMe.txt b/DeDRM_Windows_Application/DeDRM_ReadMe.txt
index ad52d33..2650a19 100644
--- a/DeDRM_Windows_Application/DeDRM_ReadMe.txt
+++ b/DeDRM_Windows_Application/DeDRM_ReadMe.txt
@@ -1,7 +1,7 @@
-ReadMe_DeDRM_v5.5.3_WinApp
+ReadMe_DeDRM_v5.6_WinApp
========================
-DeDRM_v5.5.3_WinApp is a pure python drag and drop application that allows users to drag and drop ebooks or folders of ebooks onto the DeDRM_Drop_Target to have the DRM removed. It repackages all the "tools" python software in one easy to use program that remembers preferences and settings.
+DeDRM_v5.6_WinApp is a pure python drag and drop application that allows users to drag and drop ebooks or folders of ebooks onto the DeDRM_Drop_Target to have the DRM removed. It repackages all the "tools" python software in one easy to use program that remembers preferences and settings.
It will work without manual configuration for Kindle for PC ebooks and Adobe Adept epub and pdf ebooks.
@@ -23,9 +23,9 @@ Installation
0. If you don't already have a correct version of Python and PyCrypto installed, follow the "Installing Python on Windows" and "Installing PyCrypto on Windows" sections below before continuing.
-1. Drag the DeDRM_5.5.3 folder from tools_v5.5.3/DeDRM_Applications/Windows to your "My Documents" folder.
+1. Drag the DeDRM_5.6 folder from tools_v5.6/DeDRM_Applications/Windows to your "My Documents" folder.
-2. Open the DeDRM_5.5.3 folder you've just dragged, and make a short-cut of the DeDRM_Drop_Target.bat file (right-click/Create Shortcut). Drag the shortcut file onto your Desktop.
+2. Open the DeDRM_5.6 folder you've just dragged, and make a short-cut of the DeDRM_Drop_Target.bat file (right-click/Create Shortcut). Drag the shortcut file onto your Desktop.
3. To set the preferences simply double-click on your just created short-cut.