← Back to team overview

calibre-devs team mailing list archive

MobiDeDRM plugin

 

I bought a book yesterday from MobiPocket, intending to start reading it
in Calibre or FBReader, and then later on my BeBook with OpenInkpot when
that arrives. They took my money _before_ telling me that it would
actually be limited to working on certain devices. In order to get _any_
use out of the book I've purchased, I needed to remove the DRM.

I found a Calibre plugin which invoked MobiDeDRM as a separate process,
and which didn't do any error checking -- so if you tried to import a
non-DRMed file it would fail and end up importing a zero-length file.

I tweaked it a bit so that it uses the MobiDeDRM code directly in the
plugin, so it's more portable and can catch errors more easily. The
resulting patch against mobidedrm006.py is below (don't worry; none of
the DRM code is in this patch even in the context, so you won't catch
cooties from it even if you don't live in the Free World).

This version will at least allow you to import non-DRMed files without
errors, as well as stripping the DRM for files which match the single
configured PID. Anything which can't be decrypted will just be imported
as-is.

It would be nice to improve it a bit further -- so it can store and try
multiple PIDs, do the PID checksum check while you're entering the PID
rather than later, and show a dialog box asking for a new PID if you try
to import a file for which it doesn't have a valid PID. With 'abort
import' and 'import uncracked' options for that dialog box.

Any volunteers for that? It's mostly beyond my python capabilities.

That subprocess.call("echo foo > /dev/tty") obviously needs to die, but
I couldn't find a better way of giving any feedback.

--- f29c0eef0.txt	2009-11-24 12:48:23.000000000 +0000
+++ mobidedrm_plugin.py	2009-11-24 12:49:42.000000000 +0000
@@ -1,6 +1,6 @@
-# This is a python script. You need a Python interpreter to run it.
-# For example, ActiveState Python, which exists for windows.
-#
+import os, subprocess
+from calibre.customize import FileTypePlugin
+
 # Changelog
 #  0.01 - Initial version
 #  0.02 - Huffdic compressed books were not properly decrypted
@@ -169,17 +169,30 @@ class DrmStripper:
 	def getResult(self):
 		return self.data_file
 
-print "MobiDeDrm v0.06. Copyright (c) 2008 The Dark Reverser"
-if len(sys.argv)<4:
-	print "Removes protection from Mobipocket books"
-	print "Usage:"
-	print "  mobidedrm infile.mobi outfile.mobi PID"
-else:  
-	infile = sys.argv[1]
-	outfile = sys.argv[2]
-	pid = sys.argv[3]
-	data_file = file(infile, 'rb').read()
-	try:
-		file(outfile, 'wb').write(DrmStripper(data_file, pid).getResult())
-	except DrmException, e:
-		print "Error: %s" % e
\ No newline at end of file
+
+class MobiDeDRM(FileTypePlugin):
+
+	name                = 'MobiDeDRM' # Name of the plugin
+	description         = 'Removes DRM from secure Mobi files'
+	supported_platforms = ['linux', 'osx', 'windows'] # Platforms this plugin will run on
+	author              = 'Who Says' # The author of this plugin
+	version             = (0, 0, 6)   # The version number of this plugin
+	file_types          = set(['prc']) # The file types that this plugin will be applied to
+	on_import           = True # Run this plugin during the import
+
+	
+	def run(self, path_to_ebook):
+		of = self.temporary_file('.mobi')
+		PID = self.site_customization
+		data_file = file(path_to_ebook, 'rb').read()
+		try:
+			file(of.name, 'wb').write(DrmStripper(data_file, PID).getResult())
+		except Exception, e:
+			strexcept = 'echo exception: %s > /dev/tty' % e
+			subprocess.call(strexcept,shell=True)
+			raise e
+
+		return of.name
+		
+	def customization_help(self, gui=False):
+		return 'Enter PID'


-- 
dwmw2





Follow ups