DeDRM_tools/Kindle_Mobi_Tools/K4_Mobi_DeDRM_Combined_Tool/K4MobiDeDRM.pyw

243 lines
9.8 KiB
Python
Raw Normal View History

#!/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 Tkinter
import Tkconstants
import tkFileDialog
import tkMessageBox
from scrolltextwidget import ScrolledText
2010-10-26 23:18:46 +06:00
import subprocess
from subprocess import Popen, PIPE, STDOUT
import subasyncio
from subasyncio import Process
class MainDialog(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.root = root
self.interval = 2000
self.p2 = None
2010-10-26 23:18:46 +06:00
self.status = Tkinter.Label(self, text='Remove Encryption from a K4PC, K4M, or Mobi eBook')
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)
2010-10-26 23:18:46 +06:00
Tkinter.Label(body, text='K4 or Mobi eBook input file').grid(row=0, sticky=Tkconstants.E)
self.mobipath = Tkinter.Entry(body, width=50)
self.mobipath.grid(row=0, column=1, sticky=sticky)
2010-02-19 01:35:12 +06:00
cwd = os.getcwdu()
cwd = cwd.encode('utf-8')
self.mobipath.insert(0, cwd)
button = Tkinter.Button(body, text="...", command=self.get_mobipath)
button.grid(row=0, column=2)
2010-10-26 23:18:46 +06:00
Tkinter.Label(body, text='Directory for the Unencrypted Output File').grid(row=1, sticky=Tkconstants.E)
self.outpath = Tkinter.Entry(body, width=50)
self.outpath.grid(row=1, column=1, sticky=sticky)
2010-10-26 23:18:46 +06:00
cwd = os.getcwdu()
cwd = cwd.encode('utf-8')
outname = cwd
self.outpath.insert(0, outname)
button = Tkinter.Button(body, text="...", command=self.get_outpath)
button.grid(row=1, column=2)
2010-11-12 04:11:36 +06:00
Tkinter.Label(body, text='Kindle.info file (optional)').grid(row=2, sticky=Tkconstants.E)
self.altinfopath = Tkinter.Entry(body, width=50)
self.altinfopath.grid(row=2, column=1, sticky=sticky)
#cwd = os.getcwdu()
#cwd = cwd.encode('utf-8')
#self.altinfopath.insert(0, cwd)
button = Tkinter.Button(body, text="...", command=self.get_altinfopath)
button.grid(row=2, column=2)
Tkinter.Label(body, text='Comma Separated List of 10 Character PIDs (no spaces)').grid(row=3, sticky=Tkconstants.E)
2010-10-26 23:18:46 +06:00
self.pidnums = Tkinter.StringVar()
self.pidinfo = Tkinter.Entry(body, width=50, textvariable=self.pidnums)
2010-11-12 04:11:36 +06:00
self.pidinfo.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)
2010-10-26 23:18:46 +06:00
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' + 'Encryption successfully removed\n'
2010-10-26 23:18:46 +06:00
if poll == 1:
msg = text + '\n\n' + 'Error: Encryption Removal Failed\n'
2010-10-26 23:18:46 +06:00
if poll == 2:
msg = text + '\n\n' + 'Input File was Not Encrypted - No Output File Needed\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 !='':
2010-02-19 01:35:12 +06:00
msg = msg.encode('utf-8')
self.stext.insert(Tkconstants.END,msg)
self.stext.yview_pickplace(Tkconstants.END)
return
# run as a subprocess via pipes and collect stdout
2010-11-12 04:11:36 +06:00
def mobirdr(self, infile, outfile, altinfopath, pidnums):
# os.putenv('PYTHONUNBUFFERED', '1')
2010-11-12 04:11:36 +06:00
pidoption = ''
if pidnums and pidnums != '':
pidoption = ' -p "' + pidnums + '" '
infooption = ''
if altinfopath and altinfopath != '':
infooption = ' -k "' + altinfopath + '" '
cmdline = 'python ./lib/k4mobidedrm.py ' + pidoption + infooption + '"' + infile + '" "' + outfile + '"'
print cmdline
2010-10-26 23:18:46 +06:00
if sys.platform.startswith('win'):
search_path = os.environ['PATH']
search_path = search_path.lower()
if search_path.find('python') >= 0:
2010-11-12 04:11:36 +06:00
cmdline = 'python lib\k4mobidedrm.py ' + pidoption + infooption + '"' + infile + '" "' + outfile + '"'
else :
2010-11-12 04:11:36 +06:00
cmdline = 'lib\k4mobidedrm.py ' + pidoption + infooption + '"' + infile + '" "' + outfile + '"'
2010-02-19 01:35:12 +06:00
cmdline = cmdline.encode(sys.getfilesystemencoding())
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=PIPE, stderr=PIPE, close_fds=False)
return p2
def get_mobipath(self):
2010-10-26 23:18:46 +06:00
cpath = self.mobipath.get()
mobipath = tkFileDialog.askopenfilename(
2010-10-26 23:18:46 +06:00
initialdir = cpath,
parent=None, title='Select K4PC, K4M or Mobi eBook File',
2010-07-24 17:55:24 +06:00
defaultextension='.prc', filetypes=[('Mobi eBook File', '.prc'), ('Mobi eBook File', '.azw'),('Mobi eBook File', '.mobi'),
('All Files', '.*')])
if mobipath:
mobipath = os.path.normpath(mobipath)
self.mobipath.delete(0, Tkconstants.END)
self.mobipath.insert(0, mobipath)
return
def get_outpath(self):
2010-10-26 23:18:46 +06:00
cwd = os.getcwdu()
cwd = cwd.encode('utf-8')
outpath = tkFileDialog.askdirectory(
parent=None, title='Directory to Store Unencrypted file into',
initialdir=cwd, initialfile=None)
if outpath:
outpath = os.path.normpath(outpath)
self.outpath.delete(0, Tkconstants.END)
self.outpath.insert(0, outpath)
return
2010-11-12 04:11:36 +06:00
def get_altinfopath(self):
cwd = os.getcwdu()
cwd = cwd.encode('utf-8')
altinfopath = tkFileDialog.askopenfilename(
parent=None, title='Select kindle.info File',
defaultextension='.prc', filetypes=[('Kindle Info', '.info'),
('All Files', '.*')],
initialdir=cwd)
if altinfopath:
altinfopath = os.path.normpath(altinfopath)
self.altinfopath.delete(0, Tkconstants.END)
self.altinfopath.insert(0, altinfopath)
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):
self.status['text'] = ''
# now disable the button to prevent multiple launches
self.sbotton.configure(state='disabled')
mobipath = self.mobipath.get()
outpath = self.outpath.get()
2010-11-12 04:11:36 +06:00
altinfopath = self.altinfopath.get()
2010-10-26 23:18:46 +06:00
pidnums = self.pidinfo.get()
if not mobipath or not os.path.exists(mobipath) or not os.path.isfile(mobipath):
2010-10-26 23:18:46 +06:00
self.status['text'] = 'Specified K4PC, K4M or Mobi eBook file does not exist'
self.sbotton.configure(state='normal')
return
if not outpath:
2010-10-26 23:18:46 +06:00
self.status['text'] = 'No output directory specified'
self.sbotton.configure(state='normal')
return
2010-10-26 23:18:46 +06:00
if not os.path.isdir(outpath):
self.status['text'] = 'Error specified output directory does not exist'
self.sbotton.configure(state='normal')
return
2010-11-12 04:11:36 +06:00
if altinfopath and not os.path.exists(altinfopath):
self.status['text'] = 'Specified kindle.info file does not exist'
self.sbotton.configure(state='normal')
return
2010-10-26 23:18:46 +06:00
# default output file name to be input file name + '_nodrm.mobi'
initname = os.path.splitext(os.path.basename(mobipath))[0]
initname += '_nodrm.mobi'
outpath += os.sep + initname
2010-10-26 23:18:46 +06:00
log = 'Command = "python k4mobidedrm.py"\n'
log += 'K4PC, K4M or Mobi Path = "'+ mobipath + '"\n'
log += 'Output File = "' + outpath + '"\n'
2010-11-12 04:11:36 +06:00
log += 'Kindle.info file = "' + altinfopath + '"\n'
2010-10-26 23:18:46 +06:00
log += 'PID list = "' + pidnums + '"\n'
log += '\n\n'
log += 'Please Wait ...\n\n'
2010-02-19 01:35:12 +06:00
log = log.encode('utf-8')
self.stext.insert(Tkconstants.END,log)
2010-11-12 04:11:36 +06:00
self.p2 = self.mobirdr(mobipath, outpath, altinfopath, pidnums)
# 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()
2010-10-26 23:18:46 +06:00
root.title('K4PC/K4M/Mobi eBook Encryption Removal')
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())