parent
694dfafd39
commit
00ac669f76
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,216 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# This is a simple tool to identify all Amazon Topaz ebooks in a specific directory.
|
||||||
|
# There always seems to be confusion since Topaz books downloaded to K4PC/Mac can have
|
||||||
|
# almost any extension (.azw, .azw1, .prc, tpz). While the .azw1 and .tpz extensions
|
||||||
|
# are fairly easy to indentify, the others are not (without opening the files in an editor).
|
||||||
|
|
||||||
|
# To run the tool with the GUI frontend, just double-click on the 'FindTopazFiles.pyw' file
|
||||||
|
# and select the folder where all of the ebooks in question are located. Then click 'Search'.
|
||||||
|
# The program will list the file names of the ebooks that are indentified as being Topaz.
|
||||||
|
# You can then isolate those books and use the Topaz tools to decrypt and convert them.
|
||||||
|
|
||||||
|
# You can also run the script from a command line... supplying the folder to search
|
||||||
|
# as a parameter: python FindTopazEbooks.pyw "C:\My Folder" (change appropriately for
|
||||||
|
# your particular O.S.)
|
||||||
|
|
||||||
|
# ** NOTE: This program does NOT decrypt or modify Topaz files in any way. It simply identifies them.
|
||||||
|
|
||||||
|
# PLEASE DO NOT PIRATE EBOOKS!
|
||||||
|
|
||||||
|
# We want all authors and publishers, and eBook stores to live
|
||||||
|
# long and prosperous lives but at the same time we just want to
|
||||||
|
# be able to read OUR books on whatever device we want and to keep
|
||||||
|
# readable for a long, long time
|
||||||
|
|
||||||
|
# This borrows very heavily from works by CMBDTC, IHeartCabbages, skindle,
|
||||||
|
# unswindle, DarkReverser, ApprenticeAlf, DiapDealer, some_updates
|
||||||
|
# and many many others
|
||||||
|
|
||||||
|
# Revision history:
|
||||||
|
# 1 - Initial release.
|
||||||
|
|
||||||
|
from __future__ import with_statement
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import Tkinter
|
||||||
|
import Tkconstants
|
||||||
|
import tkFileDialog
|
||||||
|
import tkMessageBox
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
def cli_main(argv=sys.argv, obj=None):
|
||||||
|
progname = os.path.basename(argv[0])
|
||||||
|
if len(argv) != 2:
|
||||||
|
print "usage: %s DIRECTORY" % (progname,)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if obj == None:
|
||||||
|
print "\nTopaz search results:\n"
|
||||||
|
else:
|
||||||
|
obj.stext.insert(Tkconstants.END,"Topaz search results:\n\n")
|
||||||
|
|
||||||
|
inpath = argv[1]
|
||||||
|
files = os.listdir(inpath)
|
||||||
|
filefilter = re.compile("(\.azw$)|(\.azw1$)|(\.prc$)|(\.tpz$)", re.IGNORECASE)
|
||||||
|
files = filter(filefilter.search, files)
|
||||||
|
|
||||||
|
if files:
|
||||||
|
topazcount = 0
|
||||||
|
totalcount = 0
|
||||||
|
for filename in files:
|
||||||
|
with open(os.path.join(inpath, filename), 'rb') as f:
|
||||||
|
try:
|
||||||
|
if f.read().startswith('TPZ'):
|
||||||
|
f.close()
|
||||||
|
basename, extension = os.path.splitext(filename)
|
||||||
|
if obj == None:
|
||||||
|
print " %s is a Topaz formatted ebook." % filename
|
||||||
|
"""
|
||||||
|
if extension == '.azw' or extension == '.prc':
|
||||||
|
print " renaming to %s" % (basename + '.tpz')
|
||||||
|
shutil.move(os.path.join(inpath, filename),
|
||||||
|
os.path.join(inpath, basename + '.tpz'))
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
msg1 = " %s is a Topaz formatted ebook.\n" % filename
|
||||||
|
obj.stext.insert(Tkconstants.END,msg1)
|
||||||
|
"""
|
||||||
|
if extension == '.azw' or extension == '.prc':
|
||||||
|
msg2 = " renaming to %s\n" % (basename + '.tpz')
|
||||||
|
obj.stext.insert(Tkconstants.END,msg2)
|
||||||
|
shutil.move(os.path.join(inpath, filename),
|
||||||
|
os.path.join(inpath, basename + '.tpz'))
|
||||||
|
"""
|
||||||
|
topazcount += 1
|
||||||
|
except:
|
||||||
|
if obj == None:
|
||||||
|
print " Error reading %s." % filename
|
||||||
|
else:
|
||||||
|
msg = " Error reading or %s.\n" % filename
|
||||||
|
obj.stext.insert(Tkconstants.END,msg)
|
||||||
|
pass
|
||||||
|
totalcount += 1
|
||||||
|
if topazcount == 0:
|
||||||
|
if obj == None:
|
||||||
|
print "\nNo Topaz books found in %s." % inpath
|
||||||
|
else:
|
||||||
|
msg = "\nNo Topaz books found in %s.\n\n" % inpath
|
||||||
|
obj.stext.insert(Tkconstants.END,msg)
|
||||||
|
else:
|
||||||
|
if obj == None:
|
||||||
|
print "\n%i Topaz books found in %s\n%i total books checked.\n" % (topazcount, inpath, totalcount)
|
||||||
|
else:
|
||||||
|
msg = "\n%i Topaz books found in %s\n%i total books checked.\n\n" %(topazcount, inpath, totalcount)
|
||||||
|
obj.stext.insert(Tkconstants.END,msg)
|
||||||
|
else:
|
||||||
|
if obj == None:
|
||||||
|
print "No typical Topaz file extensions found in %s.\n" % inpath
|
||||||
|
else:
|
||||||
|
msg = "No typical Topaz file extensions found in %s.\n\n" % inpath
|
||||||
|
obj.stext.insert(Tkconstants.END,msg)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
class DecryptionDialog(Tkinter.Frame):
|
||||||
|
def __init__(self, root):
|
||||||
|
Tkinter.Frame.__init__(self, root, border=5)
|
||||||
|
ltext='Search a directory for Topaz eBooks\n'
|
||||||
|
self.status = Tkinter.Label(self, text=ltext)
|
||||||
|
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 to Search').grid(row=1)
|
||||||
|
self.inpath = Tkinter.Entry(body, width=30)
|
||||||
|
self.inpath.grid(row=1, column=1, sticky=sticky)
|
||||||
|
button = Tkinter.Button(body, text="...", command=self.get_inpath)
|
||||||
|
button.grid(row=1, column=2)
|
||||||
|
msg1 = 'Topaz search results \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.botton = Tkinter.Button(
|
||||||
|
buttons, text="Search", width=10, command=self.search)
|
||||||
|
self.botton.pack(side=Tkconstants.LEFT)
|
||||||
|
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
|
||||||
|
self.button = Tkinter.Button(
|
||||||
|
buttons, text="Quit", width=10, command=self.quit)
|
||||||
|
self.button.pack(side=Tkconstants.RIGHT)
|
||||||
|
|
||||||
|
def get_inpath(self):
|
||||||
|
cwd = os.getcwdu()
|
||||||
|
cwd = cwd.encode('utf-8')
|
||||||
|
inpath = tkFileDialog.askdirectory(
|
||||||
|
parent=None, title='Directory to search',
|
||||||
|
initialdir=cwd, initialfile=None)
|
||||||
|
if inpath:
|
||||||
|
inpath = os.path.normpath(inpath)
|
||||||
|
self.inpath.delete(0, Tkconstants.END)
|
||||||
|
self.inpath.insert(0, inpath)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def search(self):
|
||||||
|
inpath = self.inpath.get()
|
||||||
|
if not inpath or not os.path.exists(inpath):
|
||||||
|
self.status['text'] = 'Specified directory does not exist'
|
||||||
|
return
|
||||||
|
argv = [sys.argv[0], inpath]
|
||||||
|
self.status['text'] = 'Searching...'
|
||||||
|
self.botton.configure(state='disabled')
|
||||||
|
cli_main(argv, self)
|
||||||
|
self.status['text'] = 'Search a directory for Topaz files'
|
||||||
|
self.botton.configure(state='normal')
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def gui_main():
|
||||||
|
root = Tkinter.Tk()
|
||||||
|
root.title('Topaz eBook Finder')
|
||||||
|
root.resizable(True, False)
|
||||||
|
root.minsize(370, 0)
|
||||||
|
DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1)
|
||||||
|
root.mainloop()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
sys.exit(cli_main())
|
||||||
|
sys.exit(gui_main())
|
@ -0,0 +1,199 @@
|
|||||||
|
#!/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='Remove Encryption from a 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)
|
||||||
|
|
||||||
|
Tkinter.Label(body, text='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)
|
||||||
|
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)
|
||||||
|
|
||||||
|
Tkinter.Label(body, text='Name for 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)
|
||||||
|
self.outpath.insert(0, '')
|
||||||
|
button = Tkinter.Button(body, text="...", command=self.get_outpath)
|
||||||
|
button.grid(row=1, column=2)
|
||||||
|
|
||||||
|
Tkinter.Label(body, text='10 Character PID').grid(row=2, sticky=Tkconstants.E)
|
||||||
|
self.pidnum = Tkinter.StringVar()
|
||||||
|
self.pidinfo = Tkinter.Entry(body, width=12, textvariable=self.pidnum)
|
||||||
|
self.pidinfo.grid(row=2, 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=3, 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'
|
||||||
|
if poll != 0:
|
||||||
|
msg = text + '\n\n' + 'Error: Encryption Removal 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 !='':
|
||||||
|
msg = msg.encode('utf-8')
|
||||||
|
if sys.platform.startswith('win'):
|
||||||
|
msg = msg.replace('\r\n','\n')
|
||||||
|
self.stext.insert(Tkconstants.END,msg)
|
||||||
|
self.stext.yview_pickplace(Tkconstants.END)
|
||||||
|
return
|
||||||
|
|
||||||
|
# run as a subprocess via pipes and collect stdout
|
||||||
|
def mobirdr(self, infile, outfile, pidnum):
|
||||||
|
# os.putenv('PYTHONUNBUFFERED', '1')
|
||||||
|
cmdline = 'python ./lib/mobidedrm.py "' + infile + '" "' + outfile + '" "' + pidnum + '"'
|
||||||
|
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\mobidedrm.py "' + infile + '" "' + outfile + '" "' + pidnum + '"'
|
||||||
|
else :
|
||||||
|
cmdline = 'lib\mobidedrm.py "' + infile + '" "' + outfile + '" "' + pidnum + '"'
|
||||||
|
|
||||||
|
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):
|
||||||
|
mobipath = tkFileDialog.askopenfilename(
|
||||||
|
parent=None, title='Select Mobi eBook File',
|
||||||
|
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):
|
||||||
|
mobipath = self.mobipath.get()
|
||||||
|
initname = os.path.basename(mobipath)
|
||||||
|
p = initname.find('.')
|
||||||
|
if p >= 0: initname = initname[0:p]
|
||||||
|
initname += '_nodrm.mobi'
|
||||||
|
outpath = tkFileDialog.asksaveasfilename(
|
||||||
|
parent=None, title='Select Unencrypted Mobi File to produce',
|
||||||
|
defaultextension='.mobi', initialfile=initname,
|
||||||
|
filetypes=[('Mobi files', '.mobi'), ('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')
|
||||||
|
mobipath = self.mobipath.get()
|
||||||
|
outpath = self.outpath.get()
|
||||||
|
pidnum = self.pidinfo.get()
|
||||||
|
if not mobipath or not os.path.exists(mobipath):
|
||||||
|
self.status['text'] = 'Specified Mobi eBook 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
|
||||||
|
if not pidnum or pidnum == '':
|
||||||
|
self.status['text'] = 'No PID specified'
|
||||||
|
self.sbotton.configure(state='normal')
|
||||||
|
return
|
||||||
|
|
||||||
|
log = 'Command = "python mobidedrm.py"\n'
|
||||||
|
log += 'Mobi Path = "'+ mobipath + '"\n'
|
||||||
|
log += 'Output File = "' + outpath + '"\n'
|
||||||
|
log += 'PID = "' + pidnum + '"\n'
|
||||||
|
log += '\n\n'
|
||||||
|
log += 'Please Wait ...\n\n'
|
||||||
|
log = log.encode('utf-8')
|
||||||
|
self.stext.insert(Tkconstants.END,log)
|
||||||
|
self.p2 = self.mobirdr(mobipath, 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('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())
|
@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
|
||||||
|
Welcome to the tools!
|
||||||
|
|
||||||
|
The set includes tools to remove DRM from eReader PDB books, Barnes and Noble ePubs, Adobe ePubs, Adobe PDFs, and Kindle/Mobi ebooks (including Topaz).
|
||||||
|
|
||||||
|
|
||||||
|
This ReadMe_First.txt is meant to give users a quick overview of what is available and how to get started.
|
||||||
|
|
||||||
|
|
||||||
|
Calibre Users (Mac OS X, Linux, Windows)
|
||||||
|
-------------
|
||||||
|
If you are a calibre user, the quickest and easiest way to remove DRM form your ebooks is to open the Calibre_Plugins folder and install each of the plugins following the instructions and configuration directions provided in each plugins README file.
|
||||||
|
|
||||||
|
Once installed and configured, you can simply import a DRM book into Calibre and end up with the DeDRM version in the Calibre database.
|
||||||
|
|
||||||
|
These plugins work for Windows, Mac OS X, and Linux
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Mac OS X Users (Mac OS X 10.5 and 10.6)
|
||||||
|
--------------
|
||||||
|
Drag the DeDRM X.X.app droplet to your Desktop. Double-click on it once and it will guide you through collecting the data it needs to remove the DRM.
|
||||||
|
|
||||||
|
To use it simply drag a book onto the droplet, and a DeDRM version will appear. This tools supports dragging and dropping of folders of ebooks as well.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Not a Calibre or a Mac OS X DeDRM User?
|
||||||
|
----------------------------------------
|
||||||
|
There are a number of python based tools that have graphical user interfaces to make them easy to use. To use any of these tools, you need to have Python 2.5, 2.6, or 2.7 for 32 bits installed on your machine as well as a matching PyCrypto or OpenSSL for some tools.
|
||||||
|
|
||||||
|
On Mac OS X (10.5 and 10.6) and Linux (recent versions), your systems already have the proper Python and OpenSSL installed. So nothing need be done, you can already run these tools by double-clicking on the .pyw python scripts.
|
||||||
|
|
||||||
|
Users of Mac OS X 10.3 and 10.4, need to download and install the "32-bit Mac Installer disk Image (2.7.X) for OS X 10.3 and later from http://www.python.org/download/releases/2.7.1/
|
||||||
|
|
||||||
|
On Windows, you need to install a 32 bit version of Python (even on Windows 64) plus a matching 32 bit version of PyCrypto *OR* OpenSSL. See the end of this document for details.
|
||||||
|
|
||||||
|
The scripts are organized by type of ebook you need to remove the DRM from. Choose from among:
|
||||||
|
|
||||||
|
"Adobe_ePub_Tools"
|
||||||
|
"Adobe_PDF_Tools"
|
||||||
|
"Barnes_and_Noble_ePub_Tools"
|
||||||
|
"eReader_PDB_Tools"
|
||||||
|
"KindleBooks_Tools"
|
||||||
|
|
||||||
|
by simply opening that folder.
|
||||||
|
|
||||||
|
In the "KindleBooks_Tools" folder the primary tool is in the "KindleBooks" folder.
|
||||||
|
|
||||||
|
If you are a Windows user, or a Linux platform using Wine, or Mac OS X or have trouble running the KindleBooks tools, there are two other tools provided. These are called "Kindle_4_Mac_Unswindle" and "Kindle_4_PC_Unswindle".
|
||||||
|
|
||||||
|
Look for a README inside of the relevant folder to get you started.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Additional Tools
|
||||||
|
----------------------
|
||||||
|
Some additional tools are also provided in the "Mobi_Additional_Tools" folder. There are tools for working with "Kindle for iPhone/iPod_Touch/iPad", finding Topaz ebooks, unpacking Mobi ebooks (without DRM) to get to the Mobi markup language inside, and etc.
|
||||||
|
|
||||||
|
There is also an "ePub_Fixer" folder that can be used to fix broken DRM epubs that sometimes provided by Adobe and Barnes and Noble that actually violate the zip standard.
|
||||||
|
|
||||||
|
Check out their readmes for more info.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Windows and Python Tools
|
||||||
|
------------------------
|
||||||
|
We strongly recommend ActiveState's Active Python 2.6 or 2.7 Community Edition for Windows (x86) 32 bits. This can be downloaded for free from:
|
||||||
|
|
||||||
|
http://www.activestate.com/activepython/downloads
|
||||||
|
|
||||||
|
|
||||||
|
In addition, Windows Users need one of PyCrypto OR OpenSSL.
|
||||||
|
|
||||||
|
For OpenSSL:
|
||||||
|
|
||||||
|
Win32 OpenSSL v0.9.8o (8Mb)
|
||||||
|
http://www.slproweb.com/download/Win32OpenSSL-0_9_8o.exe
|
||||||
|
(if you get an error message about missing Visual C++
|
||||||
|
redistributables... cancel the install and install the
|
||||||
|
below support program from Microsoft, THEN install OpenSSL)
|
||||||
|
|
||||||
|
Visual C++ 2008 Redistributables (1.7Mb)
|
||||||
|
http://www.microsoft.com/downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF
|
||||||
|
|
||||||
|
For PyCrypto:
|
||||||
|
|
||||||
|
There are many places to get PyCrypto installers for Windows. One such place is:
|
||||||
|
|
||||||
|
http://www.voidspace.org.uk/python/modules.shtml
|
||||||
|
|
||||||
|
Please get the latest PyCrypto meant for Windows 32 bit that matches the version of Python you installed (2.7, or 2.6)
|
||||||
|
|
||||||
|
Once Windows users have installed Python 2.X for 32 bits, and the matching OpenSSL OR PyCrypto pieces, they too are ready to run the scripts.
|
||||||
|
|
Loading…
Reference in New Issue