tools v1.0

(With some additions)
Lots of authors, brought together by Apprentice Alf.
This commit is contained in:
Apprentice Alf 2009-02-13 20:59:59 +00:00
parent 71d66953d3
commit 93c2ccd2c2
26 changed files with 1923 additions and 129 deletions

View File

@ -21,7 +21,10 @@
# 0.07 - The extra data flags aren't present in MOBI header < 0xE8 in size # 0.07 - The extra data flags aren't present in MOBI header < 0xE8 in size
# 0.08 - ...and also not in Mobi header version < 6 # 0.08 - ...and also not in Mobi header version < 6
# 0.09 - ...but they are there with Mobi header version 6, header size 0xE4! # 0.09 - ...but they are there with Mobi header version 6, header size 0xE4!
# 0.10 - use autoflushed stdout and proper return values # 0.10 - Outputs unencrypted files as-is, so that when run as a Calibre
# import filter it works when importing unencrypted files.
# Also now handles encrypted files that don't need a specific PID.
# 0.11 - use autoflushed stdout and proper return values
class Unbuffered: class Unbuffered:
def __init__(self, stream): def __init__(self, stream):
@ -143,6 +146,17 @@ class DrmStripper:
if verification == ver and cksum == temp_key_sum and (flags & 0x1F) == 1: if verification == ver and cksum == temp_key_sum and (flags & 0x1F) == 1:
found_key = finalkey found_key = finalkey
break break
if not found_key:
# Then try the default encoding that doesn't require a PID
temp_key = keyvec1
temp_key_sum = sum(map(ord,temp_key)) & 0xff
for i in xrange(count):
verification, size, type, cksum, cookie = struct.unpack('>LLLBxxx32s', data[i*0x30:i*0x30+0x30])
cookie = PC1(temp_key, cookie)
ver,flags,finalkey,expiry,expiry2 = struct.unpack('>LL16sLL', cookie)
if verification == ver and cksum == temp_key_sum:
found_key = finalkey
break
return found_key return found_key
@ -178,34 +192,35 @@ class DrmStripper:
crypto_type, = struct.unpack('>H', sect[0xC:0xC+2]) crypto_type, = struct.unpack('>H', sect[0xC:0xC+2])
if crypto_type == 0: if crypto_type == 0:
raise DrmException("it seems that this book isn't encrypted") print "This book is not encrypted."
if crypto_type == 1: else:
raise DrmException("cannot decode Mobipocket encryption type 1") if crypto_type == 1:
if crypto_type != 2: raise DrmException("cannot decode Mobipocket encryption type 1")
raise DrmException("unknown encryption type: %d" % crypto_type) if crypto_type != 2:
raise DrmException("unknown encryption type: %d" % crypto_type)
# calculate the keys
drm_ptr, drm_count, drm_size, drm_flags = struct.unpack('>LLLL', sect[0xA8:0xA8+16]) # calculate the keys
if drm_count == 0: drm_ptr, drm_count, drm_size, drm_flags = struct.unpack('>LLLL', sect[0xA8:0xA8+16])
raise DrmException("no PIDs found in this file") if drm_count == 0:
found_key = self.parseDRM(sect[drm_ptr:drm_ptr+drm_size], drm_count, pid) raise DrmException("no PIDs found in this file")
if not found_key: found_key = self.parseDRM(sect[drm_ptr:drm_ptr+drm_size], drm_count, pid)
raise DrmException("no key found. maybe the PID is incorrect") if not found_key:
raise DrmException("no key found. maybe the PID is incorrect")
# kill the drm keys
self.patchSection(0, "\0" * drm_size, drm_ptr) # kill the drm keys
# kill the drm pointers self.patchSection(0, "\0" * drm_size, drm_ptr)
self.patchSection(0, "\xff" * 4 + "\0" * 12, 0xA8) # kill the drm pointers
# clear the crypto type self.patchSection(0, "\xff" * 4 + "\0" * 12, 0xA8)
self.patchSection(0, "\0" * 2, 0xC) # clear the crypto type
self.patchSection(0, "\0" * 2, 0xC)
# decrypt sections
print "Decrypting. Please wait...", # decrypt sections
for i in xrange(1, records+1): print "Decrypting. Please wait...",
data = self.loadSection(i) for i in xrange(1, records+1):
extra_size = getSizeOfTrailingDataEntries(data, len(data), extra_data_flags) data = self.loadSection(i)
# print "record %d, extra_size %d" %(i,extra_size) extra_size = getSizeOfTrailingDataEntries(data, len(data), extra_data_flags)
self.patchSection(i, PC1(found_key, data[0:len(data) - extra_size])) # print "record %d, extra_size %d" %(i,extra_size)
self.patchSection(i, PC1(found_key, data[0:len(data) - extra_size]))
print "done" print "done"
def getResult(self): def getResult(self):
return self.data_file return self.data_file
@ -219,7 +234,7 @@ if not __name__ == "__main__":
description = 'Removes DRM from secure Mobi files' description = 'Removes DRM from secure Mobi files'
supported_platforms = ['linux', 'osx', 'windows'] # Platforms this plugin will run on supported_platforms = ['linux', 'osx', 'windows'] # Platforms this plugin will run on
author = 'The Dark Reverser' # The author of this plugin author = 'The Dark Reverser' # The author of this plugin
version = (0, 0, 10) # The version number of this plugin version = (0, 1, 0) # The version number of this plugin
file_types = set(['prc','mobi','azw']) # The file types that this plugin will be applied to file_types = set(['prc','mobi','azw']) # The file types that this plugin will be applied to
on_import = True # Run this plugin during the import on_import = True # Run this plugin during the import
@ -245,25 +260,22 @@ if not __name__ == "__main__":
def customization_help(self, gui=False): def customization_help(self, gui=False):
return 'Enter PID (separate multiple PIDs with comma)' return 'Enter PID (separate multiple PIDs with comma)'
def main(argv=sys.argv): if __name__ == "__main__":
print "MobiDeDrm v0.10. Copyright (c) 2008 The Dark Reverser" print "MobiDeDrm v0.11. Copyright (c) 2008 The Dark Reverser"
if len(sys.argv)<4: if len(sys.argv)<4:
print "Removes protection from Mobipocket books" print "Removes protection from Mobipocket books"
print "Usage:" print "Usage:"
print " mobidedrm infile.mobi outfile.mobi PID" print " mobidedrm infile.mobi outfile.mobi (PID)"
return 1 sys.exit(1)
else: else:
infile = sys.argv[1] infile = sys.argv[1]
outfile = sys.argv[2] outfile = sys.argv[2]
pid = sys.argv[3] pid = sys.argv[3]
data_file = file(infile, 'rb').read() data_file = file(infile, 'rb').read()
try: try:
file(outfile, 'wb').write(DrmStripper(data_file, pid).getResult()) strippedFile = DrmStripper(data_file, pid)
file(outfile, 'wb').write(strippedFile.getResult())
except DrmException, e: except DrmException, e:
print "Error: %s" % e print "Error: %s" % e
return 1 sys.exit(1)
return 0 sys.exit(0)
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,193 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import sys
sys.path.append('lib')
import os, os.path, urllib
import subprocess
from subprocess import Popen, PIPE, STDOUT
import Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
import subasyncio
from subasyncio import Process
from scrolltextwidget import ScrolledText
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
self.status = Tkinter.Label(self, text='Extract Contents of Topaz eBook to a Directory')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text='Topaz eBook input file').grid(row=0, sticky=Tkconstants.E)
self.tpzpath = Tkinter.Entry(body, width=50)
self.tpzpath.grid(row=0, column=1, sticky=sticky)
self.tpzpath.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_tpzpath)
button.grid(row=0, column=2)
Tkinter.Label(body, text='Output Directory').grid(row=1, sticky=Tkconstants.E)
self.outpath = Tkinter.Entry(body, width=50)
self.outpath.grid(row=1, column=1, sticky=sticky)
self.outpath.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_outpath)
button.grid(row=1, column=2)
Tkinter.Label(body, text='First 8 char of PID (optional)').grid(row=3, sticky=Tkconstants.E)
self.pidnum = Tkinter.StringVar()
self.ccinfo = Tkinter.Entry(body, width=10, textvariable=self.pidnum)
self.ccinfo.grid(row=3, column=1, sticky=sticky)
msg1 = 'Conversion Log \n\n'
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE, height=15, width=60, wrap=Tkconstants.WORD)
self.stext.grid(row=4, column=0, columnspan=2,sticky=sticky)
self.stext.insert(Tkconstants.END,msg1)
buttons = Tkinter.Frame(self)
buttons.pack()
self.sbotton = Tkinter.Button(
buttons, text="Start", width=10, command=self.convertit)
self.sbotton.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
self.qbutton = Tkinter.Button(
buttons, text="Quit", width=10, command=self.quitting)
self.qbutton.pack(side=Tkconstants.RIGHT)
# 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):
poll = self.p2.wait('nowait')
if poll != None:
text = self.p2.readerr()
text += self.p2.read()
msg = text + '\n\n' + 'Files successfully extracted\n'
if poll != 0:
msg = text + '\n\n' + 'Error: File Extraction Failed\n'
self.showCmdOutput(msg)
self.p2 = None
self.sbotton.configure(state='normal')
return
text = self.p2.readerr()
text += self.p2.read()
self.showCmdOutput(text)
# make sure we get invoked again by event loop after interval
self.stext.after(self.interval,self.processPipe)
return
# post output from subprocess in scrolled text widget
def showCmdOutput(self, msg):
if msg and msg !='':
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run as a subprocess via pipes and collect stdout
def topazrdr(self, infile, outdir, pidnum):
# os.putenv('PYTHONUNBUFFERED', '1')
pidoption = ''
if pidnum and pidnum != '':
pidoption = ' -p "' + pidnum + '" '
outoption = ' -o "' + outdir + '" '
cmdline = 'python ./lib/cmbtc_dump.py -v -d ' + pidoption + outoption + '"' + infile + '"'
if sys.platform[0:3] == 'win':
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
cmdline = 'python lib\cmbtc_dump.py -v -d ' + pidoption + outoption + '"' + infile + '"'
else :
cmdline = 'lib\cmbtc_dump.py -v -d ' + pidoption + outoption + '"' + infile + '"'
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_tpzpath(self):
tpzpath = tkFileDialog.askopenfilename(
parent=None, title='Select Topaz File',
defaultextension='.prc', filetypes=[('Topaz azw1', '.azw1'), ('Topaz prc', '.prc'),
('All Files', '.*')])
if tpzpath:
tpzpath = os.path.normpath(tpzpath)
self.tpzpath.delete(0, Tkconstants.END)
self.tpzpath.insert(0, tpzpath)
return
def get_outpath(self):
outpath = tkFileDialog.askdirectory(
parent=None, title='Directory to Extract Files into',
initialdir=os.getcwd(), initialfile=None)
if outpath:
outpath = os.path.normpath(outpath)
self.outpath.delete(0, Tkconstants.END)
self.outpath.insert(0, outpath)
return
def quitting(self):
# kill any still running subprocess
if self.p2 != None:
if (self.p2.wait('nowait') == None):
self.p2.terminate()
self.root.destroy()
# actually ready to run the subprocess and get its output
def convertit(self):
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
tpzpath = self.tpzpath.get()
outpath = self.outpath.get()
if not tpzpath or not os.path.exists(tpzpath):
self.status['text'] = 'Specified Topaz eBook file does not exist'
self.sbotton.configure(state='normal')
return
if not outpath:
self.status['text'] = 'No output directory specified'
self.sbotton.configure(state='normal')
return
if not os.path.exists(outpath):
os.makedirs(outpath)
pidnum = self.pidnum.get()
# if not pidnum or pidnum == '':
# self.status['text'] = 'You have not entered a PID '
# self.sbotton.configure(state='normal')
# return
log = 'Command = "python cmbtc_dump.py"\n'
log += 'Topaz Path Path = "'+ tpzpath + '"\n'
log += 'Output Directory = "' + outpath + '"\n'
log += 'First 8 chars of PID = "' + pidnum + '"\n'
log += '\n\n'
log += 'Please Wait ...\n'
self.stext.insert(Tkconstants.END,log)
self.p2 = self.topazrdr(tpzpath, outpath, pidnum)
# python does not seem to allow you to create
# your own eventloop which every other gui does - strange
# so need to use the widget "after" command to force
# event loop to run non-gui events every interval
self.stext.after(self.interval,self.processPipe)
return
def main(argv=None):
root = Tkinter.Tk()
root.title('Topaz eBook File Extraction')
root.resizable(True, False)
root.minsize(300, 0)
MainDialog(root).pack(fill=Tkconstants.X, expand=1)
root.mainloop()
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,191 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import sys
sys.path.append('lib')
import os, os.path, urllib
import subprocess
from subprocess import Popen, PIPE, STDOUT
import Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
import subasyncio
from subasyncio import Process
from scrolltextwidget import ScrolledText
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
self.status = Tkinter.Label(self, text='Extract Contents of Topaz eBook to a Directory')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text='Topaz eBook input file').grid(row=0, sticky=Tkconstants.E)
self.tpzpath = Tkinter.Entry(body, width=50)
self.tpzpath.grid(row=0, column=1, sticky=sticky)
self.tpzpath.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_tpzpath)
button.grid(row=0, column=2)
Tkinter.Label(body, text='Output Directory').grid(row=1, sticky=Tkconstants.E)
self.outpath = Tkinter.Entry(body, width=50)
self.outpath.grid(row=1, column=1, sticky=sticky)
self.outpath.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_outpath)
button.grid(row=1, column=2)
Tkinter.Label(body, text='First 8 characters of PID').grid(row=3, sticky=Tkconstants.E)
self.pidnum = Tkinter.StringVar()
self.ccinfo = Tkinter.Entry(body, width=10, textvariable=self.pidnum)
self.ccinfo.grid(row=3, column=1, sticky=sticky)
msg1 = 'Conversion Log \n\n'
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE, height=15, width=60, wrap=Tkconstants.WORD)
self.stext.grid(row=4, column=0, columnspan=2,sticky=sticky)
self.stext.insert(Tkconstants.END,msg1)
buttons = Tkinter.Frame(self)
buttons.pack()
self.sbotton = Tkinter.Button(
buttons, text="Start", width=10, command=self.convertit)
self.sbotton.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
self.qbutton = Tkinter.Button(
buttons, text="Quit", width=10, command=self.quitting)
self.qbutton.pack(side=Tkconstants.RIGHT)
# 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):
poll = self.p2.wait('nowait')
if poll != None:
text = self.p2.readerr()
text += self.p2.read()
msg = text + '\n\n' + 'Files successfully extracted\n'
if poll != 0:
msg = text + '\n\n' + 'Error: File Extraction Failed\n'
self.showCmdOutput(msg)
self.p2 = None
self.sbotton.configure(state='normal')
return
text = self.p2.readerr()
text += self.p2.read()
self.showCmdOutput(text)
# make sure we get invoked again by event loop after interval
self.stext.after(self.interval,self.processPipe)
return
# post output from subprocess in scrolled text widget
def showCmdOutput(self, msg):
if msg and msg !='':
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run as a subprocess via pipes and collect stdout
def topazrdr(self, infile, outdir, pidnum):
# os.putenv('PYTHONUNBUFFERED', '1')
pidoption = ' -p "' + pidnum + '" '
outoption = ' -o "' + outdir + '" '
cmdline = 'python ./lib/cmbtc_dump_nonK4PC.py -v -d ' + pidoption + outoption + '"' + infile + '"'
if sys.platform[0:3] == 'win':
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
cmdline = 'python lib\cmbtc_dump_nonK4PC.py -v -d ' + pidoption + outoption + '"' + infile + '"'
else :
cmdline = 'lib\cmbtc_dump_nonK4PC.py -v -d ' + pidoption + outoption + '"' + infile + '"'
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_tpzpath(self):
tpzpath = tkFileDialog.askopenfilename(
parent=None, title='Select Topaz File',
defaultextension='.prc', filetypes=[('Topaz azw1', '.azw1'), ('Topaz prc', '.prc'),
('All Files', '.*')])
if tpzpath:
tpzpath = os.path.normpath(tpzpath)
self.tpzpath.delete(0, Tkconstants.END)
self.tpzpath.insert(0, tpzpath)
return
def get_outpath(self):
outpath = tkFileDialog.askdirectory(
parent=None, title='Directory to Extract Files into',
initialdir=os.getcwd(), initialfile=None)
if outpath:
outpath = os.path.normpath(outpath)
self.outpath.delete(0, Tkconstants.END)
self.outpath.insert(0, outpath)
return
def quitting(self):
# kill any still running subprocess
if self.p2 != None:
if (self.p2.wait('nowait') == None):
self.p2.terminate()
self.root.destroy()
# actually ready to run the subprocess and get its output
def convertit(self):
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
tpzpath = self.tpzpath.get()
outpath = self.outpath.get()
if not tpzpath or not os.path.exists(tpzpath):
self.status['text'] = 'Specified Topaz eBook file does not exist'
self.sbotton.configure(state='normal')
return
if not outpath:
self.status['text'] = 'No output directory specified'
self.sbotton.configure(state='normal')
return
if not os.path.exists(outpath):
os.makedirs(outpath)
pidnum = self.pidnum.get()
if not pidnum or pidnum == '':
self.status['text'] = 'You have not entered a PID '
self.sbotton.configure(state='normal')
return
log = 'Command = "python cmbtc_dump_nonK4PC.py"\n'
log += 'Topaz Path Path = "'+ tpzpath + '"\n'
log += 'Output Directory = "' + outpath + '"\n'
log += 'First 8 chars of PID = "' + pidnum + '"\n'
log += '\n\n'
log += 'Please Wait ...\n'
self.stext.insert(Tkconstants.END,log)
self.p2 = self.topazrdr(tpzpath, outpath, pidnum)
# python does not seem to allow you to create
# your own eventloop which every other gui does - strange
# so need to use the widget "after" command to force
# event loop to run non-gui events every interval
self.stext.after(self.interval,self.processPipe)
return
def main(argv=None):
root = Tkinter.Tk()
root.title('Topaz eBook File Extraction')
root.resizable(True, False)
root.minsize(300, 0)
MainDialog(root).pack(fill=Tkconstants.X, expand=1)
root.mainloop()
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,152 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import sys
sys.path.append('lib')
import os, os.path, urllib
import subprocess
from subprocess import Popen, PIPE, STDOUT
import Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
import subasyncio
from subasyncio import Process
from scrolltextwidget import ScrolledText
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
self.status = Tkinter.Label(self, text='Convert Files From Topaz eBook to HTML')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text='Directory you Extracted Topaz Files into').grid(row=0, sticky=Tkconstants.E)
self.bookdir = Tkinter.Entry(body, width=50)
self.bookdir.grid(row=0, column=1, sticky=sticky)
self.bookdir.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_bookdir)
button.grid(row=0, column=2)
msg1 = 'Conversion Log \n\n'
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE, height=15, width=60, wrap=Tkconstants.WORD)
self.stext.grid(row=4, column=0, columnspan=2,sticky=sticky)
self.stext.insert(Tkconstants.END,msg1)
buttons = Tkinter.Frame(self)
buttons.pack()
self.sbotton = Tkinter.Button(
buttons, text="Start", width=10, command=self.convertit)
self.sbotton.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
self.qbutton = Tkinter.Button(
buttons, text="Quit", width=10, command=self.quitting)
self.qbutton.pack(side=Tkconstants.RIGHT)
# 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):
poll = self.p2.wait('nowait')
if poll != None:
text = self.p2.readerr()
text += self.p2.read()
msg = text + '\n\n' + 'book.html successfully created in ' + self.bookdir.get() + '\n'
if poll != 0:
msg = text + '\n\n' + 'Error: HTML conversion Failed\n'
self.showCmdOutput(msg)
self.p2 = None
self.sbotton.configure(state='normal')
return
text = self.p2.readerr()
text += self.p2.read()
self.showCmdOutput(text)
# make sure we get invoked again by event loop after interval
self.stext.after(self.interval,self.processPipe)
return
# post output from subprocess in scrolled text widget
def showCmdOutput(self, msg):
if msg and msg !='':
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run as a subprocess via pipes and collect stdout
def topazrdr(self, bookdir):
# os.putenv('PYTHONUNBUFFERED', '1')
cmdline = 'python ./lib/genhtml.py "' + bookdir + '"'
if sys.platform[0:3] == 'win':
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
cmdline = 'python lib\genhtml.py "' + bookdir + '"'
else :
cmdline = 'lib\genhtml.py "' + bookdir + '"'
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_bookdir(self):
bookdir = tkFileDialog.askdirectory(
parent=None, title='Select the Directory you Extracted Topaz Files into',
initialdir=os.getcwd(), initialfile=None)
if bookdir:
bookdir = os.path.normpath(bookdir)
self.bookdir.delete(0, Tkconstants.END)
self.bookdir.insert(0, bookdir)
return
def quitting(self):
# kill any still running subprocess
if self.p2 != None:
if (self.p2.wait('nowait') == None):
self.p2.terminate()
self.root.destroy()
# actually ready to run the subprocess and get its output
def convertit(self):
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
bookdir = self.bookdir.get()
if not bookdir:
self.status['text'] = 'No directory specified'
self.sbotton.configure(state='normal')
return
log = 'Command = "python genhtml.py"\n'
log += 'Book Directory = "' + bookdir + '"\n'
log += '\n\n'
log += 'Please Wait ...\n'
self.stext.insert(Tkconstants.END,log)
self.p2 = self.topazrdr(bookdir)
# python does not seem to allow you to create
# your own eventloop which every other gui does - strange
# so need to use the widget "after" command to force
# event loop to run non-gui events every interval
self.stext.after(self.interval,self.processPipe)
return
def main(argv=None):
root = Tkinter.Tk()
root.title('Convert Topaz Files to SVG Files')
root.resizable(True, False)
root.minsize(300, 0)
MainDialog(root).pack(fill=Tkconstants.X, expand=1)
root.mainloop()
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,152 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import sys
sys.path.append('lib')
import os, os.path, urllib
import subprocess
from subprocess import Popen, PIPE, STDOUT
import Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
import subasyncio
from subasyncio import Process
from scrolltextwidget import ScrolledText
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
self.status = Tkinter.Label(self, text='Convert Files From Topaz eBook to SVG')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text='Directory you Extracted Topaz Files into').grid(row=0, sticky=Tkconstants.E)
self.bookdir = Tkinter.Entry(body, width=50)
self.bookdir.grid(row=0, column=1, sticky=sticky)
self.bookdir.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_bookdir)
button.grid(row=0, column=2)
msg1 = 'Conversion Log \n\n'
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE, height=15, width=60, wrap=Tkconstants.WORD)
self.stext.grid(row=4, column=0, columnspan=2,sticky=sticky)
self.stext.insert(Tkconstants.END,msg1)
buttons = Tkinter.Frame(self)
buttons.pack()
self.sbotton = Tkinter.Button(
buttons, text="Start", width=10, command=self.convertit)
self.sbotton.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
self.qbutton = Tkinter.Button(
buttons, text="Quit", width=10, command=self.quitting)
self.qbutton.pack(side=Tkconstants.RIGHT)
# 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):
poll = self.p2.wait('nowait')
if poll != None:
text = self.p2.readerr()
text += self.p2.read()
msg = text + '\n\n' + 'SVG embedded in XHTML files successfully created in the svg directory in ' + self.bookdir.get() + '\n'
if poll != 0:
msg = text + '\n\n' + 'Error: SVG conversion Failed\n'
self.showCmdOutput(msg)
self.p2 = None
self.sbotton.configure(state='normal')
return
text = self.p2.readerr()
text += self.p2.read()
self.showCmdOutput(text)
# make sure we get invoked again by event loop after interval
self.stext.after(self.interval,self.processPipe)
return
# post output from subprocess in scrolled text widget
def showCmdOutput(self, msg):
if msg and msg !='':
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run as a subprocess via pipes and collect stdout
def topazrdr(self, bookdir):
# os.putenv('PYTHONUNBUFFERED', '1')
cmdline = 'python ./lib/gensvg.py "' + bookdir + '"'
if sys.platform[0:3] == 'win':
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
cmdline = 'python lib\gensvg.py "' + bookdir + '"'
else :
cmdline = 'lib\gensvg.py "' + bookdir + '"'
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_bookdir(self):
bookdir = tkFileDialog.askdirectory(
parent=None, title='Select the Directory you Extracted Topaz Files into',
initialdir=os.getcwd(), initialfile=None)
if bookdir:
bookdir = os.path.normpath(bookdir)
self.bookdir.delete(0, Tkconstants.END)
self.bookdir.insert(0, bookdir)
return
def quitting(self):
# kill any still running subprocess
if self.p2 != None:
if (self.p2.wait('nowait') == None):
self.p2.terminate()
self.root.destroy()
# actually ready to run the subprocess and get its output
def convertit(self):
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
bookdir = self.bookdir.get()
if not bookdir:
self.status['text'] = 'No directory specified'
self.sbotton.configure(state='normal')
return
log = 'Command = "python gensvg.py"\n'
log += 'Book Directory = "' + bookdir + '"\n'
log += '\n\n'
log += 'Please Wait ...\n'
self.stext.insert(Tkconstants.END,log)
self.p2 = self.topazrdr(bookdir)
# python does not seem to allow you to create
# your own eventloop which every other gui does - strange
# so need to use the widget "after" command to force
# event loop to run non-gui events every interval
self.stext.after(self.interval,self.processPipe)
return
def main(argv=None):
root = Tkinter.Tk()
root.title('Convert Topaz Files to SVG Files')
root.resizable(True, False)
root.minsize(300, 0)
MainDialog(root).pack(fill=Tkconstants.X, expand=1)
root.mainloop()
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,152 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import sys
sys.path.append('lib')
import os, os.path, urllib
import subprocess
from subprocess import Popen, PIPE, STDOUT
import Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
import subasyncio
from subasyncio import Process
from scrolltextwidget import ScrolledText
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
self.status = Tkinter.Label(self, text='Convert Files From Topaz eBook to XML')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text='Directory you Extracted Topaz Files into').grid(row=0, sticky=Tkconstants.E)
self.bookdir = Tkinter.Entry(body, width=50)
self.bookdir.grid(row=0, column=1, sticky=sticky)
self.bookdir.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_bookdir)
button.grid(row=0, column=2)
msg1 = 'Conversion Log \n\n'
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE, height=15, width=60, wrap=Tkconstants.WORD)
self.stext.grid(row=4, column=0, columnspan=2,sticky=sticky)
self.stext.insert(Tkconstants.END,msg1)
buttons = Tkinter.Frame(self)
buttons.pack()
self.sbotton = Tkinter.Button(
buttons, text="Start", width=10, command=self.convertit)
self.sbotton.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
self.qbutton = Tkinter.Button(
buttons, text="Quit", width=10, command=self.quitting)
self.qbutton.pack(side=Tkconstants.RIGHT)
# 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):
poll = self.p2.wait('nowait')
if poll != None:
text = self.p2.readerr()
text += self.p2.read()
msg = text + '\n\n' + 'XML files successfully created in the xml directory in ' + self.bookdir.get() + '\n'
if poll != 0:
msg = text + '\n\n' + 'Error: XML conversion Failed\n'
self.showCmdOutput(msg)
self.p2 = None
self.sbotton.configure(state='normal')
return
text = self.p2.readerr()
text += self.p2.read()
self.showCmdOutput(text)
# make sure we get invoked again by event loop after interval
self.stext.after(self.interval,self.processPipe)
return
# post output from subprocess in scrolled text widget
def showCmdOutput(self, msg):
if msg and msg !='':
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run as a subprocess via pipes and collect stdout
def topazrdr(self, bookdir):
# os.putenv('PYTHONUNBUFFERED', '1')
cmdline = 'python ./lib/genxml.py "' + bookdir + '"'
if sys.platform[0:3] == 'win':
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
cmdline = 'python lib\genxml.py "' + bookdir + '"'
else :
cmdline = 'lib\genxml.py "' + bookdir + '"'
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_bookdir(self):
bookdir = tkFileDialog.askdirectory(
parent=None, title='Select the Directory you Extracted Topaz Files into',
initialdir=os.getcwd(), initialfile=None)
if bookdir:
bookdir = os.path.normpath(bookdir)
self.bookdir.delete(0, Tkconstants.END)
self.bookdir.insert(0, bookdir)
return
def quitting(self):
# kill any still running subprocess
if self.p2 != None:
if (self.p2.wait('nowait') == None):
self.p2.terminate()
self.root.destroy()
# actually ready to run the subprocess and get its output
def convertit(self):
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
bookdir = self.bookdir.get()
if not bookdir:
self.status['text'] = 'No directory specified'
self.sbotton.configure(state='normal')
return
log = 'Command = "python genxml.py"\n'
log += 'Book Directory = "' + bookdir + '"\n'
log += '\n\n'
log += 'Please Wait ...\n'
self.stext.insert(Tkconstants.END,log)
self.p2 = self.topazrdr(bookdir)
# python does not seem to allow you to create
# your own eventloop which every other gui does - strange
# so need to use the widget "after" command to force
# event loop to run non-gui events every interval
self.stext.after(self.interval,self.processPipe)
return
def main(argv=None):
root = Tkinter.Tk()
root.title('Convert Topaz Files to XML Files')
root.resizable(True, False)
root.minsize(300, 0)
MainDialog(root).pack(fill=Tkconstants.X, expand=1)
root.mainloop()
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,5 +1,5 @@
#! /usr/bin/python #! /usr/bin/python
# For use in Topaz Scripts version 2.0 # For use in Topaz Scripts version 2.2
""" """
@ -13,11 +13,22 @@ y2/pHuYme7U1TsgSjwIDAQAB
-----END PUBLIC KEY----- -----END PUBLIC KEY-----
""" """
from __future__ import with_statement from __future__ import with_statement
import csv 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 import sys
sys.stdout=Unbuffered(sys.stdout)
import csv
import os import os
import getopt import getopt
import zlib import zlib
@ -305,7 +316,10 @@ def encodeNumber(number):
byte += flag byte += flag
result += chr(byte) result += chr(byte)
flag = 0x80 flag = 0x80
if number == 0 : break if number == 0 :
if (byte == 0xFF and negative == False) :
result += chr(0x80)
break
if negative: if negative:
result += chr(0xFF) result += chr(0xFF)
@ -841,13 +855,12 @@ def main(argv=sys.argv):
if len(bookKeys) == 0 : if len(bookKeys) == 0 :
if verbose > 0 : if verbose > 0 :
print ("Book key could not be found. Maybe this book is not registered with this device.") print ("Book key could not be found. Maybe this book is not registered with this device.")
return 1
else : else :
bookKey = bookKeys[0] bookKey = bookKeys[0]
if verbose > 0: if verbose > 0:
print("Book key: " + bookKey.encode('hex')) print("Book key: " + bookKey.encode('hex'))
if command == "printRecord" : if command == "printRecord" :
extractBookPayloadRecord(recordName,int(recordIndex),outputFile) extractBookPayloadRecord(recordName,int(recordIndex),outputFile)
if outputFile != "" and verbose>0 : if outputFile != "" and verbose>0 :
@ -859,6 +872,7 @@ def main(argv=sys.argv):
print ("Decrypted book saved. Don't pirate!") print ("Decrypted book saved. Don't pirate!")
elif verbose > 0: elif verbose > 0:
print("Output directory name was not supplied.") print("Output directory name was not supplied.")
return 1
return 0 return 0

View File

@ -1,10 +1,19 @@
#! /usr/bin/python #!/usr/bin/python
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
from __future__ import with_statement 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 csv import csv
import sys
import os import os
import getopt import getopt
import zlib import zlib
@ -90,7 +99,10 @@ def encodeNumber(number):
byte += flag byte += flag
result += chr(byte) result += chr(byte)
flag = 0x80 flag = 0x80
if number == 0 : break if number == 0 :
if (byte == 0xFF and negative == False) :
result += chr(0x80)
break
if negative: if negative:
result += chr(0xFF) result += chr(0xFF)
@ -480,12 +492,11 @@ def main(argv=sys.argv):
if len(bookKeys) == 0 : if len(bookKeys) == 0 :
if verbose > 0 : if verbose > 0 :
print ("Book key could not be found. Maybe this book is not registered with this device.") print ("Book key could not be found. Maybe this book is not registered with this device.")
return 1
else : else :
bookKey = bookKeys[0] bookKey = bookKeys[0]
if verbose > 0: if verbose > 0:
print("Book key: " + bookKey.encode('hex')) print("Book key: " + bookKey.encode('hex'))
if command == "printRecord" : if command == "printRecord" :
extractBookPayloadRecord(recordName,int(recordIndex),outputFile) extractBookPayloadRecord(recordName,int(recordIndex),outputFile)
@ -498,6 +509,7 @@ def main(argv=sys.argv):
print ("Decrypted book saved. Don't pirate!") print ("Decrypted book saved. Don't pirate!")
elif verbose > 0: elif verbose > 0:
print("Output directory name was not supplied.") print("Output directory name was not supplied.")
return 1
return 0 return 0

View File

@ -1,10 +1,20 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
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)
from __future__ import with_statement
import csv
import sys import sys
sys.stdout=Unbuffered(sys.stdout)
import csv
import os import os
import getopt import getopt
from struct import pack from struct import pack
@ -61,7 +71,10 @@ def encodeNumber(number):
byte += flag byte += flag
result += chr(byte) result += chr(byte)
flag = 0x80 flag = 0x80
if number == 0 : break if number == 0 :
if (byte == 0xFF and negative == False) :
result += chr(0x80)
break
if negative: if negative:
result += chr(0xFF) result += chr(0xFF)
@ -729,8 +742,6 @@ def main(argv):
if len(argv) == 0: if len(argv) == 0:
printOutput = True printOutput = True
argv = sys.argv argv = sys.argv
else :
argv = argv.split()
try: try:
opts, args = getopt.getopt(argv[1:], "hd", ["flat-xml"]) opts, args = getopt.getopt(argv[1:], "hd", ["flat-xml"])

View File

@ -1,8 +1,7 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
from __future__ import with_statement
import csv import csv
import sys import sys
import os import os
@ -61,8 +60,11 @@ def encodeNumber(number):
byte += flag byte += flag
result += chr(byte) result += chr(byte)
flag = 0x80 flag = 0x80
if number == 0 : break if number == 0 :
if (byte == 0xFF and negative == False) :
result += chr(0x80)
break
if negative: if negative:
result += chr(0xFF) result += chr(0xFF)

View File

@ -1,10 +1,9 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
from __future__ import with_statement
import csv
import sys import sys
import csv
import os import os
import math import math
import getopt import getopt

View File

@ -1,8 +1,21 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
import os, sys, getopt 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, getopt
# local routines # local routines
import convert2xml import convert2xml
@ -27,8 +40,6 @@ def main(argv):
if len(argv) == 0: if len(argv) == 0:
argv = sys.argv argv = sys.argv
else :
argv = argv.split()
try: try:
opts, args = getopt.getopt(argv[1:], "h:",["fixed-image"]) opts, args = getopt.getopt(argv[1:], "h:",["fixed-image"])
@ -36,11 +47,11 @@ def main(argv):
except getopt.GetoptError, err: except getopt.GetoptError, err:
print str(err) print str(err)
usage() usage()
sys.exit(2) sys.exit(1)
if len(opts) == 0 and len(args) == 0 : if len(opts) == 0 and len(args) == 0 :
usage() usage()
sys.exit(2) sys.exit(1)
for o, a in opts: for o, a in opts:
if o =="-h": if o =="-h":
@ -53,39 +64,39 @@ def main(argv):
if not os.path.exists(bookDir) : if not os.path.exists(bookDir) :
print "Can not find directory with unencrypted book" print "Can not find directory with unencrypted book"
sys.exit(-1) sys.exit(1)
dictFile = os.path.join(bookDir,'dict0000.dat') dictFile = os.path.join(bookDir,'dict0000.dat')
if not os.path.exists(dictFile) : if not os.path.exists(dictFile) :
print "Can not find dict0000.dat file" print "Can not find dict0000.dat file"
sys.exit(-1) sys.exit(1)
pageDir = os.path.join(bookDir,'page') pageDir = os.path.join(bookDir,'page')
if not os.path.exists(pageDir) : if not os.path.exists(pageDir) :
print "Can not find page directory in unencrypted book" print "Can not find page directory in unencrypted book"
sys.exit(-1) sys.exit(1)
imgDir = os.path.join(bookDir,'img') imgDir = os.path.join(bookDir,'img')
if not os.path.exists(imgDir) : if not os.path.exists(imgDir) :
print "Can not find image directory in unencrypted book" print "Can not find image directory in unencrypted book"
sys.exit(-1) sys.exit(1)
svgDir = os.path.join(bookDir,'svg') svgDir = os.path.join(bookDir,'svg')
if not os.path.exists(svgDir) : if not os.path.exists(svgDir) :
print "Can not find svg directory in unencrypted book" print "Can not find svg directory in unencrypted book"
print "please run gensvg.py before running genhtml.py" print "please run gensvg.py before running genhtml.py"
sys.exit(-1) sys.exit(1)
otherFile = os.path.join(bookDir,'other0000.dat') otherFile = os.path.join(bookDir,'other0000.dat')
if not os.path.exists(otherFile) : if not os.path.exists(otherFile) :
print "Can not find other0000.dat in unencrypted book" print "Can not find other0000.dat in unencrypted book"
sys.exit(-1) sys.exit(1)
metaFile = os.path.join(bookDir,'metadata0000.dat') metaFile = os.path.join(bookDir,'metadata0000.dat')
if not os.path.exists(metaFile) : if not os.path.exists(metaFile) :
print "Can not find metadata0000.dat in unencrypted book" print "Can not find metadata0000.dat in unencrypted book"
sys.exit(-1) sys.exit(1)
htmlFileName = "book.html" htmlFileName = "book.html"
htmlstr = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' htmlstr = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n'
@ -123,18 +134,28 @@ def main(argv):
pnum = int(spage) pnum = int(spage)
# get page height and width from first text page for use in stylesheet scaling # get page height and width from first text page for use in stylesheet scaling
pname = 'page%04d.dat' % pnum pname = 'page%04d.dat' % (pnum + 1)
fname = os.path.join(pageDir,pname) fname = os.path.join(pageDir,pname)
flat_xml = convert2xml.main('convert2xml.py --flat-xml ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append('--flat-xml')
pargv.append(dictFile)
pargv.append(fname)
flat_xml = convert2xml.main(pargv)
(ph, pw) = getpagedim.getPageDim(flat_xml) (ph, pw) = getpagedim.getPageDim(flat_xml)
if (ph == '-1') : ph = 11000 if (ph == '-1') or (ph == '0') : ph = '11000'
if (pw == '-1') : pw = 8500 if (pw == '-1') or (pw == '0') : pw = '8500'
# now build up the style sheet # now build up the style sheet
print ' ', 'other0000.dat' print ' ', 'other0000.dat'
fname = os.path.join(bookDir,'other0000.dat') fname = os.path.join(bookDir,'other0000.dat')
xname = os.path.join(bookDir, 'style.css') xname = os.path.join(bookDir, 'style.css')
xmlstr = convert2xml.main('convert2xml.py --flat-xml ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append('--flat-xml')
pargv.append(dictFile)
pargv.append(fname)
xmlstr = convert2xml.main(pargv)
cssstr , classlst = stylexml2css.convert2CSS(xmlstr, fontsize, ph, pw) cssstr , classlst = stylexml2css.convert2CSS(xmlstr, fontsize, ph, pw)
file(xname, 'wb').write(cssstr) file(xname, 'wb').write(cssstr)
htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n' htmlstr += '<link href="style.css" rel="stylesheet" type="text/css" />\n'
@ -143,7 +164,12 @@ def main(argv):
for filename in filenames: for filename in filenames:
print ' ', filename print ' ', filename
fname = os.path.join(pageDir,filename) fname = os.path.join(pageDir,filename)
flat_xml = convert2xml.main('convert2xml.py --flat-xml ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append('--flat-xml')
pargv.append(dictFile)
pargv.append(fname)
flat_xml = convert2xml.main(pargv)
htmlstr += flatxml2html.convert2HTML(flat_xml, classlst, fname, bookDir, fixedimage) htmlstr += flatxml2html.convert2HTML(flat_xml, classlst, fname, bookDir, fixedimage)
htmlstr += '</body>\n</html>\n' htmlstr += '</body>\n</html>\n'

View File

@ -1,8 +1,20 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
import os, sys, getopt 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, getopt
# local routines # local routines
import convert2xml import convert2xml
@ -190,8 +202,6 @@ def main(argv):
if len(argv) == 0: if len(argv) == 0:
argv = sys.argv argv = sys.argv
else :
argv = argv.split()
try: try:
opts, args = getopt.getopt(argv[1:], "xrh") opts, args = getopt.getopt(argv[1:], "xrh")
@ -199,11 +209,11 @@ def main(argv):
except getopt.GetoptError, err: except getopt.GetoptError, err:
print str(err) print str(err)
usage() usage()
sys.exit(2) sys.exit(1)
if len(opts) == 0 and len(args) == 0 : if len(opts) == 0 and len(args) == 0 :
usage() usage()
sys.exit(2) sys.exit(1)
raw = 0 raw = 0
for o, a in opts: for o, a in opts:
@ -219,33 +229,33 @@ def main(argv):
if not os.path.exists(bookDir) : if not os.path.exists(bookDir) :
print "Can not find directory with unencrypted book" print "Can not find directory with unencrypted book"
sys.exit(-1) sys.exit(1)
dictFile = os.path.join(bookDir,'dict0000.dat') dictFile = os.path.join(bookDir,'dict0000.dat')
if not os.path.exists(dictFile) : if not os.path.exists(dictFile) :
print "Can not find dict0000.dat file" print "Can not find dict0000.dat file"
sys.exit(-1) sys.exit(1)
pageDir = os.path.join(bookDir,'page') pageDir = os.path.join(bookDir,'page')
if not os.path.exists(pageDir) : if not os.path.exists(pageDir) :
print "Can not find page directory in unencrypted book" print "Can not find page directory in unencrypted book"
sys.exit(-1) sys.exit(1)
imgDir = os.path.join(bookDir,'img') imgDir = os.path.join(bookDir,'img')
if not os.path.exists(imgDir) : if not os.path.exists(imgDir) :
print "Can not find image directory in unencrypted book" print "Can not find image directory in unencrypted book"
sys.exit(-1) sys.exit(1)
glyphsDir = os.path.join(bookDir,'glyphs') glyphsDir = os.path.join(bookDir,'glyphs')
if not os.path.exists(glyphsDir) : if not os.path.exists(glyphsDir) :
print "Can not find glyphs directory in unencrypted book" print "Can not find glyphs directory in unencrypted book"
sys.exit(-1) sys.exit(1)
metaFile = os.path.join(bookDir,'metadata0000.dat') metaFile = os.path.join(bookDir,'metadata0000.dat')
if not os.path.exists(metaFile) : if not os.path.exists(metaFile) :
print "Can not find metadata0000.dat in unencrypted book" print "Can not find metadata0000.dat in unencrypted book"
sys.exit(-1) sys.exit(1)
svgDir = os.path.join(bookDir,'svg') svgDir = os.path.join(bookDir,'svg')
if not os.path.exists(svgDir) : if not os.path.exists(svgDir) :
@ -274,7 +284,12 @@ def main(argv):
for filename in filenames: for filename in filenames:
print ' ', filename print ' ', filename
fname = os.path.join(glyphsDir,filename) fname = os.path.join(glyphsDir,filename)
flat_xml = convert2xml.main('convert2xml.py --flat-xml ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append('--flat-xml')
pargv.append(dictFile)
pargv.append(fname)
flat_xml = convert2xml.main(pargv)
gp = GParser(flat_xml) gp = GParser(flat_xml)
for i in xrange(0, gp.count): for i in xrange(0, gp.count):
path = gp.getPath(i) path = gp.getPath(i)
@ -297,7 +312,12 @@ def main(argv):
for filename in filenames: for filename in filenames:
print ' ', filename print ' ', filename
fname = os.path.join(pageDir,filename) fname = os.path.join(pageDir,filename)
flat_xml = convert2xml.main('convert2xml.py --flat-xml ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append('--flat-xml')
pargv.append(dictFile)
pargv.append(fname)
flat_xml = convert2xml.main(pargv)
pp = PParser(flat_xml) pp = PParser(flat_xml)
if (raw) : if (raw) :
pfile = open(os.path.join(svgDir,filename.replace('.dat','.svg')), 'w') pfile = open(os.path.join(svgDir,filename.replace('.dat','.svg')), 'w')

View File

@ -1,8 +1,21 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
import os, sys, getopt 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, getopt
# local routines # local routines
import convert2xml import convert2xml
@ -23,8 +36,6 @@ def main(argv):
if len(argv) == 0: if len(argv) == 0:
argv = sys.argv argv = sys.argv
else :
argv = argv.split()
try: try:
opts, args = getopt.getopt(argv[1:], "h:") opts, args = getopt.getopt(argv[1:], "h:")
@ -32,11 +43,11 @@ def main(argv):
except getopt.GetoptError, err: except getopt.GetoptError, err:
print str(err) print str(err)
usage() usage()
sys.exit(2) sys.exit(1)
if len(opts) == 0 and len(args) == 0 : if len(opts) == 0 and len(args) == 0 :
usage() usage()
sys.exit(2) sys.exit(1)
for o, a in opts: for o, a in opts:
if o =="-h": if o =="-h":
@ -47,32 +58,32 @@ def main(argv):
if not os.path.exists(bookDir) : if not os.path.exists(bookDir) :
print "Can not find directory with unencrypted book" print "Can not find directory with unencrypted book"
sys.exit(-1) sys.exit(1)
dictFile = os.path.join(bookDir,'dict0000.dat') dictFile = os.path.join(bookDir,'dict0000.dat')
if not os.path.exists(dictFile) : if not os.path.exists(dictFile) :
print "Can not find dict0000.dat file" print "Can not find dict0000.dat file"
sys.exit(-1) sys.exit(1)
pageDir = os.path.join(bookDir,'page') pageDir = os.path.join(bookDir,'page')
if not os.path.exists(pageDir) : if not os.path.exists(pageDir) :
print "Can not find page directory in unencrypted book" print "Can not find page directory in unencrypted book"
sys.exit(-1) sys.exit(1)
glyphsDir = os.path.join(bookDir,'glyphs') glyphsDir = os.path.join(bookDir,'glyphs')
if not os.path.exists(glyphsDir) : if not os.path.exists(glyphsDir) :
print "Can not find glyphs directory in unencrypted book" print "Can not find glyphs directory in unencrypted book"
sys.exit(-1) sys.exit(1)
otherFile = os.path.join(bookDir,'other0000.dat') otherFile = os.path.join(bookDir,'other0000.dat')
if not os.path.exists(otherFile) : if not os.path.exists(otherFile) :
print "Can not find other0000.dat in unencrypted book" print "Can not find other0000.dat in unencrypted book"
sys.exit(-1) sys.exit(1)
metaFile = os.path.join(bookDir,'metadata0000.dat') metaFile = os.path.join(bookDir,'metadata0000.dat')
if not os.path.exists(metaFile) : if not os.path.exists(metaFile) :
print "Can not find metadata0000.dat in unencrypted book" print "Can not find metadata0000.dat in unencrypted book"
sys.exit(-1) sys.exit(1)
xmlDir = os.path.join(bookDir,'xml') xmlDir = os.path.join(bookDir,'xml')
if not os.path.exists(xmlDir): if not os.path.exists(xmlDir):
@ -90,7 +101,11 @@ def main(argv):
print ' ', 'other0000.dat' print ' ', 'other0000.dat'
fname = os.path.join(bookDir,'other0000.dat') fname = os.path.join(bookDir,'other0000.dat')
xname = os.path.join(xmlDir, 'stylesheet.xml') xname = os.path.join(xmlDir, 'stylesheet.xml')
xmlstr = convert2xml.main('convert2xml.py ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append(dictFile)
pargv.append(fname)
xmlstr = convert2xml.main(pargv)
file(xname, 'wb').write(xmlstr) file(xname, 'wb').write(xmlstr)
filenames = os.listdir(pageDir) filenames = os.listdir(pageDir)
@ -100,7 +115,11 @@ def main(argv):
print ' ', filename print ' ', filename
fname = os.path.join(pageDir,filename) fname = os.path.join(pageDir,filename)
xname = os.path.join(xmlDir, filename.replace('.dat','.xml')) xname = os.path.join(xmlDir, filename.replace('.dat','.xml'))
xmlstr = convert2xml.main('convert2xml.py ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append(dictFile)
pargv.append(fname)
xmlstr = convert2xml.main(pargv)
file(xname, 'wb').write(xmlstr) file(xname, 'wb').write(xmlstr)
filenames = os.listdir(glyphsDir) filenames = os.listdir(glyphsDir)
@ -110,7 +129,11 @@ def main(argv):
print ' ', filename print ' ', filename
fname = os.path.join(glyphsDir,filename) fname = os.path.join(glyphsDir,filename)
xname = os.path.join(xmlDir, filename.replace('.dat','.xml')) xname = os.path.join(xmlDir, filename.replace('.dat','.xml'))
xmlstr = convert2xml.main('convert2xml.py ' + dictFile + ' ' + fname) pargv=[]
pargv.append('convert2xml.py')
pargv.append(dictFile)
pargv.append(fname)
xmlstr = convert2xml.main(pargv)
file(xname, 'wb').write(xmlstr) file(xname, 'wb').write(xmlstr)

View File

@ -1,8 +1,7 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
from __future__ import with_statement
import csv import csv
import sys import sys
import os import os

View File

@ -0,0 +1,27 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import Tkinter
import Tkconstants
# basic scrolled text widget
class ScrolledText(Tkinter.Text):
def __init__(self, master=None, **kw):
self.frame = Tkinter.Frame(master)
self.vbar = Tkinter.Scrollbar(self.frame)
self.vbar.pack(side=Tkconstants.RIGHT, fill=Tkconstants.Y)
kw.update({'yscrollcommand': self.vbar.set})
Tkinter.Text.__init__(self, self.frame, **kw)
self.pack(side=Tkconstants.LEFT, fill=Tkconstants.BOTH, expand=True)
self.vbar['command'] = self.yview
# Copy geometry methods of self.frame without overriding Text
# methods = hack!
text_meths = vars(Tkinter.Text).keys()
methods = vars(Tkinter.Pack).keys() + vars(Tkinter.Grid).keys() + vars(Tkinter.Place).keys()
methods = set(methods).difference(text_meths)
for m in methods:
if m[0] != '_' and m != 'config' and m != 'configure':
setattr(self, m, getattr(self.frame, m))
def __str__(self):
return str(self.frame)

View File

@ -1,8 +1,7 @@
#! /usr/bin/python #! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.0 # For use with Topaz Scripts Version 2.2
from __future__ import with_statement
import csv import csv
import sys import sys
import os import os

View File

@ -0,0 +1,149 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import os, sys
import signal
import threading
import subprocess
from subprocess import Popen, PIPE, STDOUT
# **heavily** chopped up and modfied version of asyncproc.py
# to make it actually work on Windows as well as Mac/Linux
# For the original see:
# "http://www.lysator.liu.se/~bellman/download/"
# author is "Thomas Bellman <bellman@lysator.liu.se>"
# available under GPL version 3 or Later
# create an asynchronous subprocess whose output can be collected in
# a non-blocking manner
# What a mess! Have to use threads just to get non-blocking io
# in a cross-platform manner
# luckily all thread use is hidden within this class
class Process(object):
def __init__(self, *params, **kwparams):
if len(params) <= 3:
kwparams.setdefault('stdin', subprocess.PIPE)
if len(params) <= 4:
kwparams.setdefault('stdout', subprocess.PIPE)
if len(params) <= 5:
kwparams.setdefault('stderr', subprocess.PIPE)
self.__pending_input = []
self.__collected_outdata = []
self.__collected_errdata = []
self.__exitstatus = None
self.__lock = threading.Lock()
self.__inputsem = threading.Semaphore(0)
self.__quit = False
self.__process = subprocess.Popen(*params, **kwparams)
if self.__process.stdin:
self.__stdin_thread = threading.Thread(
name="stdin-thread",
target=self.__feeder, args=(self.__pending_input,
self.__process.stdin))
self.__stdin_thread.setDaemon(True)
self.__stdin_thread.start()
if self.__process.stdout:
self.__stdout_thread = threading.Thread(
name="stdout-thread",
target=self.__reader, args=(self.__collected_outdata,
self.__process.stdout))
self.__stdout_thread.setDaemon(True)
self.__stdout_thread.start()
if self.__process.stderr:
self.__stderr_thread = threading.Thread(
name="stderr-thread",
target=self.__reader, args=(self.__collected_errdata,
self.__process.stderr))
self.__stderr_thread.setDaemon(True)
self.__stderr_thread.start()
def pid(self):
return self.__process.pid
def kill(self, signal):
self.__process.send_signal(signal)
# check on subprocess (pass in 'nowait') to act like poll
def wait(self, flag):
if flag.lower() == 'nowait':
rc = self.__process.poll()
else:
rc = self.__process.wait()
if rc != None:
if self.__process.stdin:
self.closeinput()
if self.__process.stdout:
self.__stdout_thread.join()
if self.__process.stderr:
self.__stderr_thread.join()
return self.__process.returncode
def terminate(self):
if self.__process.stdin:
self.closeinput()
self.__process.terminate()
# thread gets data from subprocess stdout
def __reader(self, collector, source):
while True:
data = os.read(source.fileno(), 65536)
self.__lock.acquire()
collector.append(data)
self.__lock.release()
if data == "":
source.close()
break
return
# thread feeds data to subprocess stdin
def __feeder(self, pending, drain):
while True:
self.__inputsem.acquire()
self.__lock.acquire()
if not pending and self.__quit:
drain.close()
self.__lock.release()
break
data = pending.pop(0)
self.__lock.release()
drain.write(data)
# non-blocking read of data from subprocess stdout
def read(self):
self.__lock.acquire()
outdata = "".join(self.__collected_outdata)
del self.__collected_outdata[:]
self.__lock.release()
return outdata
# non-blocking read of data from subprocess stderr
def readerr(self):
self.__lock.acquire()
errdata = "".join(self.__collected_errdata)
del self.__collected_errdata[:]
self.__lock.release()
return errdata
# non-blocking write to stdin of subprocess
def write(self, data):
if self.__process.stdin is None:
raise ValueError("Writing to process with stdin not a pipe")
self.__lock.acquire()
self.__pending_input.append(data)
self.__inputsem.release()
self.__lock.release()
# close stdinput of subprocess
def closeinput(self):
self.__lock.acquire()
self.__quit = True
self.__inputsem.release()
self.__lock.release()

View File

@ -0,0 +1,75 @@
Changes in 2.2
- fix for minor bug in encode_Number from clark nova
- more fixes to handle paths with spaces in them
- updates to work better with the gui front end
Changes in 2.1
- extremely minor changes to support a gui frontend
- no changes to functionality
Changes in version 2.0
- gensvg.py now accepts two options
-x : output browseable XHTML+SVG pages (default)
-r : output raw SVG images (useful for later conversion to pdf)
- flatxml2html.py now understands page.groups of type graphic
and handles vertical regions as svg images
- genhtml.py now accepts an option
--fixed-image : which will force the conversion
of all fixed regions to svg images
- minor bug fixes and html conversion improvements
Changes in version 1.8
- gensvg.py now builds wonderful xhtml pages with embedded svg
that can be easily paged through as if reading a book!
(tested in Safari for Mac and Win and Firefox)
(requires javascript to be enabled)
- genhtml.py now REQUIRES that gensvg.py be run FIRST
this allows create of images on the fly from glyphs
- genhtml.py now automatically makes tables of words into svg
based images and will handle glyph based ornate first
letters of words
- cmbtc_dump_mac_linux.py has been renamed to be
cmbtc_dump_nonK4PC.py to make it clearer
when it needs to be used
Changes in version 1.7
- gensvg.py has been improved so that the glyphs render exactly (ClarkNova)
- gensvg.py has fixed a render order "bug" that allowed some images to cover or hide text. (ClarkNova)
- change generated html to use external stylesheet via a link to "style.css"
- add missing <title> tag
- make xhtml compliant doctype and minor changes to write correct xhtml
- make divs that act as anchors be hidden visually and to take up 0 height and 0 width to prevent any impact on layout
Changes in version 1.6
- support for books whose paragraphs have no styles
- support to run cmbtc_dump on Linux and Mac OSX provided you know your PID of your ipod or standalone Kindle
(contributed by DiapDealer)
Changes in version 1.5
- completely reworked generation of styles to use actual page heights and widths
- added new script getpagedim.py to support the above
- style names with underscores in them are now properly paired with their base class
- fixed hanging indents that did not ever set a left margin
- added support for a number of not previously known region types
- added support for a previously unknown snippet - <empty></empty>
- corrected a bug that caused unknown regions to abort the program
- added code to make the handling of unknown regions better in general
- corrected a bug that caused the last link on a page to be missing (if it was the last thing on the page)
Changes in version 1.3
- font generation by gensvg.py is now greatly improved with support for contour points added
- support for more region types
- support for inline images in paragraphs or text fields (ie. initial graphics for the first letter of a word)
- greatly improved dtd information used for the xml to prevent parsing mistakes
Version 1.0
- initial release

181
eReader_Tools/Pml2HTML.pyw Normal file
View File

@ -0,0 +1,181 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import sys
sys.path.append('lib')
import os, os.path, urllib
import subprocess
from subprocess import Popen, PIPE, STDOUT
import subasyncio
from subasyncio import Process
import Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
from scrolltextwidget import ScrolledText
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
self.status = Tkinter.Label(self, text='Pml to HTML Conversion')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text='eBook Pml input file').grid(row=0, sticky=Tkconstants.E)
self.pmlpath = Tkinter.Entry(body, width=50)
self.pmlpath.grid(row=0, column=1, sticky=sticky)
self.pmlpath.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_pmlpath)
button.grid(row=0, column=2)
Tkinter.Label(body, text='Name for HTML Output File').grid(row=1, sticky=Tkconstants.E)
self.outpath = Tkinter.Entry(body, width=50)
self.outpath.grid(row=1, column=1, sticky=sticky)
self.outpath.insert(0, '')
button = Tkinter.Button(body, text="...", command=self.get_outpath)
button.grid(row=1, column=2)
msg1 = 'Conversion Log \n\n'
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE, height=15, width=60, wrap=Tkconstants.WORD)
self.stext.grid(row=2, column=0, columnspan=2,sticky=sticky)
self.stext.insert(Tkconstants.END,msg1)
buttons = Tkinter.Frame(self)
buttons.pack()
self.sbotton = Tkinter.Button(
buttons, text="Start", width=10, command=self.convertit)
self.sbotton.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
self.qbutton = Tkinter.Button(
buttons, text="Quit", width=10, command=self.quitting)
self.qbutton.pack(side=Tkconstants.RIGHT)
# 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):
poll = self.p2.wait('nowait')
if poll != None:
text = self.p2.readerr()
text += self.p2.read()
msg = text + '\n\n' + 'File successfully converted\n'
if poll != 0:
msg = text + '\n\n' + 'Error: Conversion Failed\n'
self.showCmdOutput(msg)
self.p2 = None
self.sbotton.configure(state='normal')
return
text = self.p2.readerr()
text += self.p2.read()
self.showCmdOutput(text)
# make sure we get invoked again by event loop after interval
self.stext.after(self.interval,self.processPipe)
return
# post output from subprocess in scrolled text widget
def showCmdOutput(self, msg):
if msg and msg !='':
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run xpml2hxtml.py as a subprocess via pipes and collect stdout
def pmlhtml(self, infile, outfile):
# os.putenv('PYTHONUNBUFFERED', '1')
cmdline = 'python ./lib/xpml2xhtml.py "' + infile + '" "' + outfile + '"'
if sys.platform[0:3] == 'win':
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
cmdline = 'python lib\\xpml2xhtml.py "' + infile + '" "' + outfile + '"'
else :
cmdline = 'lib\\xpml2xhtml.py "' + infile + '" "' + outfile + '"'
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_pmlpath(self):
pmlpath = tkFileDialog.askopenfilename(
parent=None, title='Select eBook Pml File',
defaultextension='.pml', filetypes=[('eBook Pml File', '.pml'),
('All Files', '.*')])
if pmlpath:
pmlpath = os.path.normpath(pmlpath)
self.pmlpath.delete(0, Tkconstants.END)
self.pmlpath.insert(0, pmlpath)
return
def get_outpath(self):
pmlpath = self.pmlpath.get()
initname = os.path.basename(pmlpath)
p = initname.find('.')
if p >= 0: initname = initname[0:p]
initname += '.html'
outpath = tkFileDialog.asksaveasfilename(
parent=None, title='Select HTML file to produce',
defaultextension='.html', initialfile=initname,
filetypes=[('HTML files', '.html'), ('All files', '.*')])
if outpath:
outpath = os.path.normpath(outpath)
self.outpath.delete(0, Tkconstants.END)
self.outpath.insert(0, outpath)
return
def quitting(self):
# kill any still running subprocess
if self.p2 != None:
if (self.p2.wait('nowait') == None):
self.p2.terminate()
self.root.destroy()
# actually ready to run the subprocess and get its output
def convertit(self):
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
pmlpath = self.pmlpath.get()
outpath = self.outpath.get()
if not pmlpath or not os.path.exists(pmlpath):
self.status['text'] = 'Specified eBook pml file does not exist'
self.sbotton.configure(state='normal')
return
if not outpath:
self.status['text'] = 'No output file specified'
self.sbotton.configure(state='normal')
return
log = 'Command = "python xpml2xhtml.py"\n'
log += 'PDB Path = "'+ pmlpath + '"\n'
log += 'HTML Output File = "' + outpath + '"\n'
log += '\n\n'
log += 'Please Wait ...\n\n'
self.stext.insert(Tkconstants.END,log)
self.p2 = self.pmlhtml(pmlpath, outpath)
# python does not seem to allow you to create
# your own eventloop which every other gui does - strange
# so need to use the widget "after" command to force
# event loop to run non-gui events every interval
self.stext.after(self.interval,self.processPipe)
return
def main(argv=None):
root = Tkinter.Tk()
root.title('eBook Pml to HTML Conversion')
root.resizable(True, False)
root.minsize(300, 0)
MainDialog(root).pack(fill=Tkconstants.X, expand=1)
root.mainloop()
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,200 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import sys
sys.path.append('lib')
import os, os.path, urllib
import subprocess
from subprocess import Popen, PIPE, STDOUT
import Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
import subasyncio
from subasyncio import Process
from scrolltextwidget import ScrolledText
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
self.status = Tkinter.Label(self, text='eReader eBook Conversion')
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text='eBook PDB input file').grid(row=0, sticky=Tkconstants.E)
self.pdbpath = Tkinter.Entry(body, width=50)
self.pdbpath.grid(row=0, column=1, sticky=sticky)
self.pdbpath.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_pdbpath)
button.grid(row=0, column=2)
Tkinter.Label(body, text='Output Directory').grid(row=1, sticky=Tkconstants.E)
self.outpath = Tkinter.Entry(body, width=50)
self.outpath.grid(row=1, column=1, sticky=sticky)
self.outpath.insert(0, os.getcwd())
button = Tkinter.Button(body, text="...", command=self.get_outpath)
button.grid(row=1, column=2)
Tkinter.Label(body, text='Name on CC').grid(row=2, sticky=Tkconstants.E)
self.name = Tkinter.StringVar()
self.nameinfo = Tkinter.Entry(body, width=40, textvariable=self.name)
self.nameinfo.grid(row=2, column=1, sticky=sticky)
Tkinter.Label(body, text='Last 8 digits of CC Number').grid(row=3, sticky=Tkconstants.E)
self.ccnum = Tkinter.StringVar()
self.ccinfo = Tkinter.Entry(body, width=10, textvariable=self.ccnum)
self.ccinfo.grid(row=3, column=1, sticky=sticky)
msg1 = 'Conversion Log \n\n'
self.stext = ScrolledText(body, bd=5, relief=Tkconstants.RIDGE, height=15, width=60, wrap=Tkconstants.WORD)
self.stext.grid(row=4, column=0, columnspan=2,sticky=sticky)
self.stext.insert(Tkconstants.END,msg1)
buttons = Tkinter.Frame(self)
buttons.pack()
self.sbotton = Tkinter.Button(
buttons, text="Start", width=10, command=self.convertit)
self.sbotton.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
self.qbutton = Tkinter.Button(
buttons, text="Quit", width=10, command=self.quitting)
self.qbutton.pack(side=Tkconstants.RIGHT)
# 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):
poll = self.p2.wait('nowait')
if poll != None:
text = self.p2.readerr()
text += self.p2.read()
msg = text + '\n\n' + 'File successfully converted\n'
if poll != 0:
msg = text + '\n\n' + 'Error: Conversion Failed\n'
self.showCmdOutput(msg)
self.p2 = None
self.sbotton.configure(state='normal')
return
text = self.p2.readerr()
text += self.p2.read()
self.showCmdOutput(text)
# make sure we get invoked again by event loop after interval
self.stext.after(self.interval,self.processPipe)
return
# post output from subprocess in scrolled text widget
def showCmdOutput(self, msg):
if msg and msg !='':
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run erdr2pml.py as a subprocess via pipes and collect stdout
def erdr(self, infile, outdir, name, ccnum):
# os.putenv('PYTHONUNBUFFERED', '1')
cmdline = 'python ./lib/erdr2pml.py "' + infile + '" "' + outdir + '" "' + name + '" ' + ccnum
if sys.platform[0:3] == 'win':
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
cmdline = 'python lib\erdr2pml.py "' + infile + '" "' + outdir + '" "' + name + '" ' + ccnum
else :
cmdline = 'lib\erdr2pml.py "' + infile + '" "' + outdir + '" "' + name + '" ' + ccnum
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_pdbpath(self):
pdbpath = tkFileDialog.askopenfilename(
parent=None, title='Select eReader PDB File',
defaultextension='.pdb', filetypes=[('eReader eBooks', '.pdb'),
('All Files', '.*')])
if pdbpath:
pdbpath = os.path.normpath(pdbpath)
self.pdbpath.delete(0, Tkconstants.END)
self.pdbpath.insert(0, pdbpath)
return
def get_outpath(self):
outpath = tkFileDialog.askdirectory(
parent=None, title='Directory to Store Output into',
initialdir=os.getcwd(), initialfile=None)
if outpath:
outpath = os.path.normpath(outpath)
self.outpath.delete(0, Tkconstants.END)
self.outpath.insert(0, outpath)
return
def quitting(self):
# kill any still running subprocess
if self.p2 != None:
if (self.p2.wait('nowait') == None):
self.p2.terminate()
self.root.destroy()
# actually ready to run the subprocess and get its output
def convertit(self):
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
pdbpath = self.pdbpath.get()
outpath = self.outpath.get()
if not pdbpath or not os.path.exists(pdbpath):
self.status['text'] = 'Specified eBook file does not exist'
self.sbotton.configure(state='normal')
return
if not outpath:
self.status['text'] = 'No output directory specified'
self.sbotton.configure(state='normal')
return
if not os.path.exists(outpath):
os.makedirs(outpath)
name = self.name.get()
if not name or name == '':
self.status['text'] = 'Your forgot to enter the Name on the CC'
self.sbotton.configure(state='normal')
return
ccnum = self.ccnum.get()
if not ccnum or ccnum == '':
self.status['text'] = 'Your forgot to enter the last 8 digits on the CC'
self.sbotton.configure(state='normal')
return
log = 'Command = "python erdr2pml.py"\n'
log += 'PDB Path = "'+ pdbpath + '"\n'
log += 'Output Directory = "' + outpath + '"\n'
log += 'Name = "' + name + '"\n'
log += 'Last 8 of CC = "' + ccnum + '"\n'
log += '\n\n'
log += 'Please Wait ...\n'
self.stext.insert(Tkconstants.END,log)
self.p2 = self.erdr(pdbpath, outpath, name, ccnum)
# python does not seem to allow you to create
# your own eventloop which every other gui does - strange
# so need to use the widget "after" command to force
# event loop to run non-gui events every interval
self.stext.after(self.interval,self.processPipe)
return
def main(argv=None):
root = Tkinter.Tk()
root.title('eReader PDB to PML Conversion')
root.resizable(True, False)
root.minsize(300, 0)
MainDialog(root).pack(fill=Tkconstants.X, expand=1)
root.mainloop()
return 0
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab # vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# #
# eRdr2Pml.py # erdr2pml.py
# #
# This is a python script. You need a Python interpreter to run it. # This is a python script. You need a Python interpreter to run it.
# For example, ActiveState Python, which exists for windows. # For example, ActiveState Python, which exists for windows.
@ -50,9 +50,10 @@
# 0.09 - fixed typos in first_pages to first_page to again support older formats # 0.09 - fixed typos in first_pages to first_page to again support older formats
# 0.10 - minor cleanups # 0.10 - minor cleanups
# 0.11 - fixups for using correct xml for footnotes and sidebars for use with Dropbook # 0.11 - fixups for using correct xml for footnotes and sidebars for use with Dropbook
# 0.12 - fixup for file name cleaning - no longer converts to lower case # 0.12 - Fix added to prevent lowercasing of image names when the pml code itself uses a different case in the link name.
# 0.13 - change to unbuffered stdout for use with gui front ends
__version__='0.12' __version__='0.13'
# Import Psyco if available # Import Psyco if available
try: try:
@ -72,7 +73,20 @@ try:
except ImportError: except ImportError:
pass pass
import struct, binascii, zlib, os, sys, os.path, urllib 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 struct, binascii, zlib, os, os.path, urllib
try: try:
from hashlib import sha1 from hashlib import sha1
except ImportError: except ImportError:
@ -85,7 +99,6 @@ import logging
logging.basicConfig() logging.basicConfig()
#logging.basicConfig(level=logging.DEBUG) #logging.basicConfig(level=logging.DEBUG)
ECB = 0 ECB = 0
CBC = 1 CBC = 1
class Des(object): class Des(object):
@ -593,6 +606,7 @@ def main(argv=None):
print "Note:" print "Note:"
print " if ommitted, outdir defaults based on 'infile.pdb'" print " if ommitted, outdir defaults based on 'infile.pdb'"
print " It's enough to enter the last 8 digits of the credit card number" print " It's enough to enter the last 8 digits of the credit card number"
return 1
else: else:
if len(argv)==4: if len(argv)==4:
infile, name, cc = argv[1], argv[2], argv[3] infile, name, cc = argv[1], argv[2], argv[3]
@ -613,6 +627,8 @@ def main(argv=None):
print "done" print "done"
except ValueError, e: except ValueError, e:
print "Error: %s" % e print "Error: %s" % e
return 1
return 0
if __name__ == "__main__": if __name__ == "__main__":
#import cProfile #import cProfile

View File

@ -0,0 +1,27 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import Tkinter
import Tkconstants
# basic scrolled text widget
class ScrolledText(Tkinter.Text):
def __init__(self, master=None, **kw):
self.frame = Tkinter.Frame(master)
self.vbar = Tkinter.Scrollbar(self.frame)
self.vbar.pack(side=Tkconstants.RIGHT, fill=Tkconstants.Y)
kw.update({'yscrollcommand': self.vbar.set})
Tkinter.Text.__init__(self, self.frame, **kw)
self.pack(side=Tkconstants.LEFT, fill=Tkconstants.BOTH, expand=True)
self.vbar['command'] = self.yview
# Copy geometry methods of self.frame without overriding Text
# methods = hack!
text_meths = vars(Tkinter.Text).keys()
methods = vars(Tkinter.Pack).keys() + vars(Tkinter.Grid).keys() + vars(Tkinter.Place).keys()
methods = set(methods).difference(text_meths)
for m in methods:
if m[0] != '_' and m != 'config' and m != 'configure':
setattr(self, m, getattr(self.frame, m))
def __str__(self):
return str(self.frame)

View File

@ -0,0 +1,149 @@
#!/usr/bin/env python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
import os, sys
import signal
import threading
import subprocess
from subprocess import Popen, PIPE, STDOUT
# **heavily** chopped up and modfied version of asyncproc.py
# to make it actually work on Windows as well as Mac/Linux
# For the original see:
# "http://www.lysator.liu.se/~bellman/download/"
# author is "Thomas Bellman <bellman@lysator.liu.se>"
# available under GPL version 3 or Later
# create an asynchronous subprocess whose output can be collected in
# a non-blocking manner
# What a mess! Have to use threads just to get non-blocking io
# in a cross-platform manner
# luckily all thread use is hidden within this class
class Process(object):
def __init__(self, *params, **kwparams):
if len(params) <= 3:
kwparams.setdefault('stdin', subprocess.PIPE)
if len(params) <= 4:
kwparams.setdefault('stdout', subprocess.PIPE)
if len(params) <= 5:
kwparams.setdefault('stderr', subprocess.PIPE)
self.__pending_input = []
self.__collected_outdata = []
self.__collected_errdata = []
self.__exitstatus = None
self.__lock = threading.Lock()
self.__inputsem = threading.Semaphore(0)
self.__quit = False
self.__process = subprocess.Popen(*params, **kwparams)
if self.__process.stdin:
self.__stdin_thread = threading.Thread(
name="stdin-thread",
target=self.__feeder, args=(self.__pending_input,
self.__process.stdin))
self.__stdin_thread.setDaemon(True)
self.__stdin_thread.start()
if self.__process.stdout:
self.__stdout_thread = threading.Thread(
name="stdout-thread",
target=self.__reader, args=(self.__collected_outdata,
self.__process.stdout))
self.__stdout_thread.setDaemon(True)
self.__stdout_thread.start()
if self.__process.stderr:
self.__stderr_thread = threading.Thread(
name="stderr-thread",
target=self.__reader, args=(self.__collected_errdata,
self.__process.stderr))
self.__stderr_thread.setDaemon(True)
self.__stderr_thread.start()
def pid(self):
return self.__process.pid
def kill(self, signal):
self.__process.send_signal(signal)
# check on subprocess (pass in 'nowait') to act like poll
def wait(self, flag):
if flag.lower() == 'nowait':
rc = self.__process.poll()
else:
rc = self.__process.wait()
if rc != None:
if self.__process.stdin:
self.closeinput()
if self.__process.stdout:
self.__stdout_thread.join()
if self.__process.stderr:
self.__stderr_thread.join()
return self.__process.returncode
def terminate(self):
if self.__process.stdin:
self.closeinput()
self.__process.terminate()
# thread gets data from subprocess stdout
def __reader(self, collector, source):
while True:
data = os.read(source.fileno(), 65536)
self.__lock.acquire()
collector.append(data)
self.__lock.release()
if data == "":
source.close()
break
return
# thread feeds data to subprocess stdin
def __feeder(self, pending, drain):
while True:
self.__inputsem.acquire()
self.__lock.acquire()
if not pending and self.__quit:
drain.close()
self.__lock.release()
break
data = pending.pop(0)
self.__lock.release()
drain.write(data)
# non-blocking read of data from subprocess stdout
def read(self):
self.__lock.acquire()
outdata = "".join(self.__collected_outdata)
del self.__collected_outdata[:]
self.__lock.release()
return outdata
# non-blocking read of data from subprocess stderr
def readerr(self):
self.__lock.acquire()
errdata = "".join(self.__collected_errdata)
del self.__collected_errdata[:]
self.__lock.release()
return errdata
# non-blocking write to stdin of subprocess
def write(self, data):
if self.__process.stdin is None:
raise ValueError("Writing to process with stdin not a pipe")
self.__lock.acquire()
self.__pending_input.append(data)
self.__inputsem.release()
self.__lock.release()
# close stdinput of subprocess
def closeinput(self):
self.__lock.acquire()
self.__quit = True
self.__inputsem.release()
self.__lock.release()

View File

@ -29,10 +29,23 @@
# 0.16 - use proper and safe temporary file when passing things to tidy # 0.16 - use proper and safe temporary file when passing things to tidy
# 0.17 - add support for tidy.exe under windows # 0.17 - add support for tidy.exe under windows
# 0.18 - fix corner case of lines that start with \axxx or \Uxxxx tags # 0.18 - fix corner case of lines that start with \axxx or \Uxxxx tags
# 0.19 - change to use auto flushed stdout, and use proper return values
__version__='0.18' __version__='0.19'
import struct, binascii, zlib, os, getopt, sys, os.path, urllib, re, tempfile 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 struct, binascii, zlib, os, getopt, os.path, urllib, re, tempfile
import logging import logging
from subprocess import Popen, PIPE, STDOUT from subprocess import Popen, PIPE, STDOUT
@ -790,10 +803,10 @@ def main(argv=None):
except getopt.GetoptError, err: except getopt.GetoptError, err:
print str(err) print str(err)
usage() usage()
return 2 return 1
if len(args) != 2: if len(args) != 2:
usage() usage()
return 2 return 1
sigil_breaks = False sigil_breaks = False
use_tidy = False use_tidy = False
for o, a in opts: for o, a in opts:
@ -832,7 +845,7 @@ def main(argv=None):
print "Finished Processing" print "Finished Processing"
except ValueError, e: except ValueError, e:
print "Error: %s" % e print "Error: %s" % e
return 2 return 1
return 0 return 0
if __name__ == "__main__": if __name__ == "__main__":