]> xmof Git - DeDRM.git/commitdiff
tools v6.0.5
authorApprentice Alf <apprenticealf@gmail.com>
Wed, 24 Apr 2013 18:28:20 +0000 (19:28 +0100)
committerApprentice Alf <apprenticealf@gmail.com>
Sat, 7 Mar 2015 19:29:43 +0000 (19:29 +0000)
13 files changed:
DeDRM_Macintosh_Application/DeDRM.app/Contents/Info.plist
DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/__init__.py
DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py
DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/topazextract.py
DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_app.pyw
DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/__init__.py
DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/config.py
DeDRM_calibre_plugin/DeDRM_plugin.zip
DeDRM_calibre_plugin/DeDRM_plugin/__init__.py
DeDRM_calibre_plugin/DeDRM_plugin/config.py
DeDRM_calibre_plugin/DeDRM_plugin/plugin-import-name-dedrm.txt
Other_Tools/DRM_Key_Scripts/Kindle_for_iOS/kindleiospidgen.py [new file with mode: 0644]
ReadMe_First.txt

index d8c82fa59caffe4ddac6c6b0f75a359a7e479e4e..e2d40779959fa47f34a20a133e237cefa218cb85 100644 (file)
@@ -24,7 +24,7 @@
        <key>CFBundleExecutable</key>
        <string>droplet</string>
        <key>CFBundleGetInfoString</key>
-       <string>DeDRM AppleScript 6.0.4. Written 2010–2013 by Apprentice Alf and others.</string>
+       <string>DeDRM AppleScript 6.0.5. Written 2010–2013 by Apprentice Alf and others.</string>
        <key>CFBundleIconFile</key>
        <string>DeDRM</string>
        <key>CFBundleIdentifier</key>
@@ -36,7 +36,7 @@
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.0.4</string>
+       <string>6.0.5</string>
        <key>CFBundleSignature</key>
        <string>dplt</string>
        <key>LSRequiresCarbon</key>
index ce72c8de4882bfc7fc5eca5b8334b09cd00a2181..35c37d7b0287eca68a7eff5038cf7d675c7e00b2 100644 (file)
@@ -34,7 +34,7 @@ Decrypt DRMed ebooks.
 """
 
 PLUGIN_NAME = u"DeDRM"
-PLUGIN_VERSION_TUPLE = (6, 0, 2)
+PLUGIN_VERSION_TUPLE = (6, 0, 5)
 PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE])
 # Include an html helpfile in the plugin's zipfile with the following name.
 RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
index f2cd00525e8999dc284fb8574f95cb332a199463..1e584768b04e559e852b2cf347b61b9ee10b0f26 100644 (file)
@@ -6,7 +6,7 @@ from __future__ import with_statement
 __license__ = 'GPL v3'
 
 # Standard Python modules.
-import os, traceback
+import os, traceback, json
 
 # PyQT4 modules (part of calibre).
 from PyQt4.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
@@ -178,8 +178,8 @@ class ManageKeysDialog(QDialog):
         self.create_key = create_key
         self.keyfile_ext = keyfile_ext
         self.import_key = (keyfile_ext != u"")
-        self.binary_file = (keyfile_ext == u".der")
-        self.json_file = (keyfile_ext == u".k4i")
+        self.binary_file = (keyfile_ext == u"der")
+        self.json_file = (keyfile_ext == u"k4i")
         self.wineprefix = wineprefix
 
         self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))
@@ -676,7 +676,7 @@ class AddAdeptDialog(QDialog):
                 from calibre_plugins.dedrm.adobekey import adeptkeys
 
                 defaultkeys = adeptkeys()
-            else: # linux
+            else:  # linux
                 from wineutils import WineGetKeys
 
                 scriptpath = os.path.join(parent.parent.alfdir,u"adobekey.py")
index 97f658304d857a3cb547e8a8cb305a83b596c7d5..72f8797f7ee623b88246952041f448757bd260d5 100644 (file)
@@ -71,7 +71,7 @@ def unicode_argv():
         argvencoding = sys.stdin.encoding
         if argvencoding == None:
             argvencoding = 'utf-8'
-        return [arg if (type(arg) == unicode) else unicode(arg,argvencoding) for arg in sys.argv]
+        return [arg if (type(arg) == unicode) else unicode(arg, argvencoding) for arg in sys.argv]
 
 #global switch
 debug = False
@@ -92,12 +92,12 @@ class DrmException(Exception):
 def zipUpDir(myzip, tdir, localname):
     currentdir = tdir
     if localname != u"":
-        currentdir = os.path.join(currentdir,localname)
+        currentdir = os.path.join(currentdir, localname)
     list = os.listdir(currentdir)
     for file in list:
         afilename = file
         localfilePath = os.path.join(localname, afilename)
-        realfilePath = os.path.join(currentdir,file)
+        realfilePath = os.path.join(currentdir, file)
         if os.path.isfile(realfilePath):
             myzip.write(realfilePath, localfilePath)
         elif os.path.isdir(realfilePath):
@@ -116,7 +116,7 @@ def bookReadEncodedNumber(fo):
         data = ord(fo.read(1))
     if data >= 0x80:
         datax = (data & 0x7F)
-        while data >= 0x80 :
+        while data >= 0x80:
             data = ord(fo.read(1))
             datax = (datax <<7) + (data & 0x7F)
         data = datax
index f00b934bda2e0134a842d9430a18cc37c7802090..26eb06e597c72607466110d16af22095f9a0e672 100644 (file)
@@ -10,8 +10,9 @@
 #   6.0.2 - Fixed problem with spaces in paths and the bat file
 #   6.0.3 - Fix for Windows non-ascii user names
 #   6.0.4 - Fix for other potential unicode problems
+#   6.0.5 - Fix typo
 
-__version__ = '6.0.4'
+__version__ = '6.0.5'
 
 import sys
 import os, os.path
index ce72c8de4882bfc7fc5eca5b8334b09cd00a2181..830b66df27789b7feb2570da2aea3c4ce1688113 100644 (file)
@@ -27,14 +27,17 @@ __docformat__ = 'restructuredtext en'
 # Revision history:
 #   6.0.0 - Initial release
 #   6.0.1 - Bug Fixes for Windows App, Kindle for Mac and Windows Adobe Digital Editions
-#   6.0.2 - Restored call to Wine to get Kindle for PC keys
+#   6.0.2 - Restored call to Wine to get Kindle for PC keys, added for ADE
+#   6.0.3 - Fixes for Kindle for Mac and Windows non-ascii user names
+#   6.0.4 - Fixes for stand-alone scripts and applications
+#           and pdb files in plugin and initial conversion of prefs.
 
 """
 Decrypt DRMed ebooks.
 """
 
 PLUGIN_NAME = u"DeDRM"
-PLUGIN_VERSION_TUPLE = (6, 0, 2)
+PLUGIN_VERSION_TUPLE = (6, 0, 5)
 PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE])
 # Include an html helpfile in the plugin's zipfile with the following name.
 RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
@@ -426,7 +429,7 @@ class DeDRM(FileTypePlugin):
         import calibre_plugins.dedrm.prefs as prefs
         import calibre_plugins.dedrm.erdr2pml
 
-        dedrmrefs = prefs.DeDRM_Prefs()
+        dedrmprefs = prefs.DeDRM_Prefs()
         # Attempt to decrypt epub with each encryption key (generated or provided).
         for keyname, userkey in dedrmprefs['ereaderkeys'].items():
             keyname_masked = u"".join((u'X' if (x.isdigit()) else x) for x in keyname)
index f2cd00525e8999dc284fb8574f95cb332a199463..1e584768b04e559e852b2cf347b61b9ee10b0f26 100644 (file)
@@ -6,7 +6,7 @@ from __future__ import with_statement
 __license__ = 'GPL v3'
 
 # Standard Python modules.
-import os, traceback
+import os, traceback, json
 
 # PyQT4 modules (part of calibre).
 from PyQt4.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
@@ -178,8 +178,8 @@ class ManageKeysDialog(QDialog):
         self.create_key = create_key
         self.keyfile_ext = keyfile_ext
         self.import_key = (keyfile_ext != u"")
-        self.binary_file = (keyfile_ext == u".der")
-        self.json_file = (keyfile_ext == u".k4i")
+        self.binary_file = (keyfile_ext == u"der")
+        self.json_file = (keyfile_ext == u"k4i")
         self.wineprefix = wineprefix
 
         self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))
@@ -676,7 +676,7 @@ class AddAdeptDialog(QDialog):
                 from calibre_plugins.dedrm.adobekey import adeptkeys
 
                 defaultkeys = adeptkeys()
-            else: # linux
+            else:  # linux
                 from wineutils import WineGetKeys
 
                 scriptpath = os.path.join(parent.parent.alfdir,u"adobekey.py")
index 0420378f190b0c16a98b742f5a499030f406c913..d3b1b9157c4d63910b2c0f72e43b46257fbc5c15 100644 (file)
Binary files a/DeDRM_calibre_plugin/DeDRM_plugin.zip and b/DeDRM_calibre_plugin/DeDRM_plugin.zip differ
index fe7e223cfd586f5d5c1ed034bcca340d1e3ce489..830b66df27789b7feb2570da2aea3c4ce1688113 100644 (file)
@@ -37,7 +37,7 @@ Decrypt DRMed ebooks.
 """
 
 PLUGIN_NAME = u"DeDRM"
-PLUGIN_VERSION_TUPLE = (6, 0, 4)
+PLUGIN_VERSION_TUPLE = (6, 0, 5)
 PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE])
 # Include an html helpfile in the plugin's zipfile with the following name.
 RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
index f2cd00525e8999dc284fb8574f95cb332a199463..1e584768b04e559e852b2cf347b61b9ee10b0f26 100644 (file)
@@ -6,7 +6,7 @@ from __future__ import with_statement
 __license__ = 'GPL v3'
 
 # Standard Python modules.
-import os, traceback
+import os, traceback, json
 
 # PyQT4 modules (part of calibre).
 from PyQt4.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
@@ -178,8 +178,8 @@ class ManageKeysDialog(QDialog):
         self.create_key = create_key
         self.keyfile_ext = keyfile_ext
         self.import_key = (keyfile_ext != u"")
-        self.binary_file = (keyfile_ext == u".der")
-        self.json_file = (keyfile_ext == u".k4i")
+        self.binary_file = (keyfile_ext == u"der")
+        self.json_file = (keyfile_ext == u"k4i")
         self.wineprefix = wineprefix
 
         self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))
@@ -676,7 +676,7 @@ class AddAdeptDialog(QDialog):
                 from calibre_plugins.dedrm.adobekey import adeptkeys
 
                 defaultkeys = adeptkeys()
-            else: # linux
+            else:  # linux
                 from wineutils import WineGetKeys
 
                 scriptpath = os.path.join(parent.parent.alfdir,u"adobekey.py")
index 478372e9164edfa699287563c550f0843e221c2f..05065acd336eb14733026c862e788c6ff036672a 100644 (file)
@@ -114,7 +114,7 @@ def convertprefs(always = False):
                 # Generate eReader user key from name and credit card number.
                 keyname = u"{0}_{1}".format(name.strip(),cc.strip()[-4:])
                 keyvalue = getuser_key(name,cc).encode('hex')
-                userkeysappend([keyname,keyvalue])
+                userkeys.append([keyname,keyvalue])
             except Exception, e:
                 traceback.print_exc()
                 print e.args[0]
diff --git a/Other_Tools/DRM_Key_Scripts/Kindle_for_iOS/kindleiospidgen.py b/Other_Tools/DRM_Key_Scripts/Kindle_for_iOS/kindleiospidgen.py
new file mode 100644 (file)
index 0000000..0c0b11b
--- /dev/null
@@ -0,0 +1,275 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+# kindleforios4key.py
+# Copyright © 2013 by Apprentice Alf
+# Portions Copyright © 2007, 2009 Igor Skochinsky <skochinsky@mail.ru>
+
+# Revision history:
+#  1.0   - Generates fixed PID for Kindle for iOS 3.1.1 running on iOS 4.x
+
+
+"""
+Generate fixed PID for Kindle for iOS 3.1.1
+"""
+
+__license__ = 'GPL v3'
+__version__ = '1.0'
+
+import sys, os
+import getopt
+import binascii
+
+# Wrap a stream so that output gets flushed immediately
+# and also make sure that any unicode strings get
+# encoded using "replace" before writing them.
+class SafeUnbuffered:
+    def __init__(self, stream):
+        self.stream = stream
+        self.encoding = stream.encoding
+        if self.encoding == None:
+            self.encoding = "utf-8"
+    def write(self, data):
+        if isinstance(data,unicode):
+            data = data.encode(self.encoding,"replace")
+        self.stream.write(data)
+        self.stream.flush()
+    def __getattr__(self, attr):
+        return getattr(self.stream, attr)
+
+iswindows = sys.platform.startswith('win')
+isosx = sys.platform.startswith('darwin')
+
+def unicode_argv():
+    if iswindows:
+        # Uses shell32.GetCommandLineArgvW to get sys.argv as a list of Unicode
+        # strings.
+
+        # Versions 2.x of Python don't support Unicode in sys.argv on
+        # Windows, with the underlying Windows API instead replacing multi-byte
+        # characters with '?'.
+
+
+        from ctypes import POINTER, byref, cdll, c_int, windll
+        from ctypes.wintypes import LPCWSTR, LPWSTR
+
+        GetCommandLineW = cdll.kernel32.GetCommandLineW
+        GetCommandLineW.argtypes = []
+        GetCommandLineW.restype = LPCWSTR
+
+        CommandLineToArgvW = windll.shell32.CommandLineToArgvW
+        CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)]
+        CommandLineToArgvW.restype = POINTER(LPWSTR)
+
+        cmd = GetCommandLineW()
+        argc = c_int(0)
+        argv = CommandLineToArgvW(cmd, byref(argc))
+        if argc.value > 0:
+            # Remove Python executable and commands if present
+            start = argc.value - len(sys.argv)
+            return [argv[i] for i in
+                    xrange(start, argc.value)]
+        # if we don't have any arguments at all, just pass back script name
+        # this should never happen
+        return [u"mobidedrm.py"]
+    else:
+        argvencoding = sys.stdin.encoding
+        if argvencoding == None:
+            argvencoding = "utf-8"
+        return [arg if (type(arg) == unicode) else unicode(arg,argvencoding) for arg in sys.argv]
+
+import hashlib
+
+def SHA256(message):
+    ctx = hashlib.sha256()
+    ctx.update(message)
+    return ctx.digest()
+
+def crc32(s):
+    return (~binascii.crc32(s,-1))&0xFFFFFFFF
+
+letters = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789'
+
+def checksumPid(s):
+    crc = crc32(s)
+    crc = crc ^ (crc >> 16)
+    res = s
+    l = len(letters)
+    for i in (0,1):
+        b = crc & 0xff
+        pos = (b // l) ^ (b % l)
+        res += letters[pos%l]
+        crc >>= 8
+
+    return res
+
+def pidFromSerial(s, l):
+    crc = crc32(s)
+
+    arr1 = [0]*l
+    for i in xrange(len(s)):
+        arr1[i%l] ^= ord(s[i])
+
+    crc_bytes = [crc >> 24 & 0xff, crc >> 16 & 0xff, crc >> 8 & 0xff, crc & 0xff]
+    for i in xrange(l):
+        arr1[i] ^= crc_bytes[i&3]
+
+    pid = ''
+    for i in xrange(l):
+        b = arr1[i] & 0xff
+        pid+=letters[(b >> 7) + ((b >> 5 & 3) ^ (b & 0x1f))]
+
+    return pid
+
+def generatekeys(email, mac):
+    keys = []
+    email = email.encode('utf-8').lower()
+    mac = mac.encode('utf-8').lower()
+    cleanmac = "".join(c if (c in "0123456789abcdef") else "" for c in mac)
+    lowermac = cleanmac.lower()
+    #print lowermac
+    keyseed = lowermac + email.encode('utf-8')
+    #print keyseed
+    keysha256 = SHA256(keyseed)
+    keybase64 = keysha256.encode('base64')
+    #print keybase64
+    cleankeybase64 = "".join(c if (c in "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") else "0" for c in keybase64)
+    #print cleankeybase64
+    pseudoudid = cleankeybase64[:40]
+    #print pseudoudid
+    keys.append(pidFromSerial(pseudoudid.encode("utf-8"),8))
+    return keys
+
+# interface for Python DeDRM
+# returns single key or multiple keys, depending on path or file passed in
+def getkey(email, mac, outpath):
+    keys = generatekeys(email,mac)
+    if len(keys) > 0:
+        if not os.path.isdir(outpath):
+            outfile = outpath
+            with file(outfile, 'w') as keyfileout:
+                keyfileout.write(keys[0])
+            print u"Saved a key to {0}".format(outfile)
+        else:
+            keycount = 0
+            for key in keys:
+                while True:
+                    keycount += 1
+                    outfile = os.path.join(outpath,u"kindleios{0:d}.pid".format(keycount))
+                    if not os.path.exists(outfile):
+                        break
+                with file(outfile, 'w') as keyfileout:
+                    keyfileout.write(key)
+                print u"Saved a key to {0}".format(outfile)
+        return True
+    return False
+
+def usage(progname):
+    print u"Generates the key for Kindle for iOS 3.1.1"
+    print u"Requires email address of Amazon acccount"
+    print u"And MAC address for iOS device’s wifi"
+    print u"Outputs to a file or to stdout"
+    print u"Usage:"
+    print u"    {0:s} [-h] <email address> <MAC address> [<outfile>]".format(progname)
+
+
+def cli_main():
+    sys.stdout=SafeUnbuffered(sys.stdout)
+    sys.stderr=SafeUnbuffered(sys.stderr)
+    argv=unicode_argv()
+    progname = os.path.basename(argv[0])
+    print u"{0} v{1}\nCopyright © 2013 Apprentice Alf".format(progname,__version__)
+
+    try:
+        opts, args = getopt.getopt(argv[1:], "h")
+    except getopt.GetoptError, err:
+        print u"Error in options or arguments: {0}".format(err.args[0])
+        usage(progname)
+        sys.exit(2)
+
+    for o, a in opts:
+        if o == "-h":
+            usage(progname)
+            sys.exit(0)
+
+
+    if len(args) < 2 or len(args) > 3:
+        usage(progname)
+        sys.exit(2)
+
+    if len(args) == 3:
+        # save to the specified file or folder
+        getkey(args[0],args[1],args[2])
+    else:
+        keys = generatekeys(args[0],args[1])
+        for key in keys:
+            print key
+
+    return 0
+
+
+def gui_main():
+    try:
+        import Tkinter
+        import Tkconstants
+        import tkMessageBox
+    except:
+        print "Tkinter not installed"
+        return cli_main()
+
+    class DecryptionDialog(Tkinter.Frame):
+        def __init__(self, root):
+            Tkinter.Frame.__init__(self, root, border=5)
+            self.status = Tkinter.Label(self, text=u"Enter parameters")
+            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=u"Amazon email address").grid(row=0)
+            self.email = Tkinter.Entry(body, width=40)
+            self.email.grid(row=0, column=1, sticky=sticky)
+            Tkinter.Label(body, text=u"iOS  MAC address").grid(row=1)
+            self.mac = Tkinter.Entry(body, width=40)
+            self.mac.grid(row=1, column=1, sticky=sticky)
+            buttons = Tkinter.Frame(self)
+            buttons.pack()
+            button = Tkinter.Button(
+                buttons, text=u"Generate", width=10, command=self.generate)
+            button.pack(side=Tkconstants.LEFT)
+            Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
+            button = Tkinter.Button(
+                buttons, text=u"Quit", width=10, command=self.quit)
+            button.pack(side=Tkconstants.RIGHT)
+
+        def generate(self):
+            email = self.email.get()
+            mac = self.mac.get()
+            if not email:
+                self.status['text'] = u"Email not specified"
+                return
+            if not mac:
+                self.status['text'] = u"MAC not specified"
+                return
+            self.status['text'] = u"Generating..."
+            try:
+                keys = generatekeys(email, mac)
+            except Exception, e:
+                self.status['text'] = u"Error: (0}".format(e.args[0])
+                return
+            self.status['text'] = ", ".join(key for key in keys)
+
+    root = Tkinter.Tk()
+    root.title(u"Kindle for iOS PID Generator v.{0}".format(__version__))
+    root.resizable(True, False)
+    root.minsize(300, 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())
index 5143509ce9622cc4faeaa2358dadd22e36e18e82..b08fd6cc7891ae46d429d7632422b426d5279b3e 100644 (file)
@@ -1,7 +1,7 @@
 Welcome to the tools!
 =====================
 
-This ReadMe_First.txt is meant to give users a quick overview of what is available and how to get started. This document is part of the Tools v6.0.4 archive from Apprentice Alf's Blog: http://apprenticealf.wordpress.com/
+This ReadMe_First.txt is meant to give users a quick overview of what is available and how to get started. This document is part of the Tools v6.0.5 archive from Apprentice Alf's Blog: http://apprenticealf.wordpress.com/
 
 The is archive includes tools to remove DRM from: