]> xmof Git - DeDRM.git/commitdiff
Begin work on standalone version
authorNoDRM <no_drm123@protonmail.com>
Wed, 29 Dec 2021 08:26:29 +0000 (09:26 +0100)
committerNoDRM <no_drm123@protonmail.com>
Wed, 29 Dec 2021 08:26:29 +0000 (09:26 +0100)
Now the plugin ZIP file (DeDRM_plugin.zip) can be run with a normal
Python interpreter as if it were a Python file (try
`python3 DeDRM_plugin.zip --help`). This way I can begin building a
standalone version (that can run without Calibre) without having to
duplicate a ton of code.

13 files changed:
DeDRM_plugin/__init__.py
DeDRM_plugin/__main__.py [new file with mode: 0644]
DeDRM_plugin/config.py
DeDRM_plugin/erdr2pml.py
DeDRM_plugin/genbook.py
DeDRM_plugin/k4mobidedrm.py
DeDRM_plugin/kfxdedrm.py
DeDRM_plugin/prefs.py
DeDRM_plugin/scriptinterface.py
DeDRM_plugin/standalone/__init__.py [new file with mode: 0644]
DeDRM_plugin/topazextract.py
DeDRM_plugin/utilities.py
DeDRM_plugin/zipfix.py

index ab9bcf744732c22e037e4b8cbb4a2b460d4ae0ac..80f7f288ffe7327b9af9ae3e0ef631d28cf6632a 100644 (file)
@@ -97,11 +97,19 @@ import sys, os
 import time
 import traceback
 
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
 
 class DeDRMError(Exception):
     pass
 
-from calibre.customize import FileTypePlugin
+try: 
+    from calibre.customize import FileTypePlugin
+except: 
+    # Allow import without Calibre.
+    class FileTypePlugin:
+        pass
 
 try:
     from calibre.constants import iswindows, isosx
@@ -109,7 +117,10 @@ except:
     iswindows = sys.platform.startswith('win')
     isosx = sys.platform.startswith('darwin')
 
-from calibre.utils.config import config_dir
+try: 
+    from calibre.utils.config import config_dir
+except:
+    config_dir = ""
 
 
 # Wrap a stream so that output gets flushed immediately
@@ -150,6 +161,10 @@ class DeDRM(FileTypePlugin):
     priority                = 600
 
 
+    def cli_main(self, data):
+        from standalone import main
+        main(data)
+    
     def initialize(self):
         """
         Dynamic modules can't be imported/loaded from a zipfile.
@@ -216,7 +231,7 @@ class DeDRM(FileTypePlugin):
         postProcessStart = time.time()
 
         try: 
-            import calibre_plugins.dedrm.prefs as prefs
+            import prefs
             dedrmprefs = prefs.DeDRM_Prefs()
 
             if dedrmprefs["deobfuscate_fonts"] is True:
@@ -224,7 +239,7 @@ class DeDRM(FileTypePlugin):
                 path_to_ebook = self.checkFonts(path_to_ebook) or path_to_ebook
 
             if dedrmprefs["remove_watermarks"] is True:
-                import calibre_plugins.dedrm.epubwatermark as watermark
+                import epubwatermark as watermark
 
                 # Remove Tolino's CDP watermark file
                 path_to_ebook = watermark.removeCDPwatermark(self, path_to_ebook) or path_to_ebook
@@ -251,7 +266,7 @@ class DeDRM(FileTypePlugin):
         # It checks if there's fonts that need to be deobfuscated
 
         try: 
-            import calibre_plugins.dedrm.epubfontdecrypt as epubfontdecrypt
+            import epubfontdecrypt
 
             output = self.temporary_file(".epub").name
             ret = epubfontdecrypt.decryptFontsBook(path_to_ebook, output)
@@ -272,7 +287,7 @@ class DeDRM(FileTypePlugin):
     def ePubDecrypt(self,path_to_ebook):
         # Create a TemporaryPersistent file to work with.
         # Check original epub archive for zip errors.
-        import calibre_plugins.dedrm.zipfix as zipfix
+        import zipfix
 
         inf = self.temporary_file(".epub")
         try:
@@ -284,12 +299,12 @@ class DeDRM(FileTypePlugin):
             raise
 
         # import the decryption keys
-        import calibre_plugins.dedrm.prefs as prefs
+        import prefs
         dedrmprefs = prefs.DeDRM_Prefs()
 
 
         # import the LCP handler
-        import calibre_plugins.dedrm.lcpdedrm as lcpdedrm
+        import lcpdedrm
 
         if (lcpdedrm.isLCPbook(path_to_ebook)):
             try: 
@@ -304,7 +319,7 @@ class DeDRM(FileTypePlugin):
         # Not an LCP book, do the normal EPUB (Adobe) handling.
 
         # import the Adobe ePub handler
-        import calibre_plugins.dedrm.ineptepub as ineptepub
+        import ineptepub
 
         if ineptepub.adeptBook(inf.name):
 
@@ -345,11 +360,11 @@ class DeDRM(FileTypePlugin):
 
                 try:
                     if iswindows or isosx:
-                        from calibre_plugins.dedrm.ignoblekeyNookStudy import nookkeys
+                        from ignoblekeyNookStudy import nookkeys
 
                         defaultkeys_study = nookkeys()
                     else: # linux
-                        from .wineutils import WineGetKeys
+                        from wineutils import WineGetKeys
 
                         scriptpath = os.path.join(self.alfdir,"ignoblekeyNookStudy.py")
                         defaultkeys_study = WineGetKeys(scriptpath, ".b64",dedrmprefs['adobewineprefix'])
@@ -365,7 +380,7 @@ class DeDRM(FileTypePlugin):
                     if iswindows:
                         # That's a Windows store app, it won't run on Linux or MacOS anyways.
                         # No need to waste time running Wine.
-                        from calibre_plugins.dedrm.ignoblekeyWindowsStore import dump_keys as dump_nook_keys
+                        from ignoblekeyWindowsStore import dump_keys as dump_nook_keys
                         defaultkeys_store = dump_nook_keys(False)
 
                 except:
@@ -377,7 +392,7 @@ class DeDRM(FileTypePlugin):
                 try: 
                     if iswindows:
                         # Right now this is only implemented for Windows. MacOS support still needs to be added.
-                        from calibre_plugins.dedrm.adobekey_get_passhash import passhash_keys
+                        from adobekey_get_passhash import passhash_keys
                         defaultkeys_ade, names = passhash_keys()
                     if isosx:
                         print("{0} v{1}: Dumping ADE PassHash data is not yet supported on MacOS.".format(PLUGIN_NAME, PLUGIN_VERSION))
@@ -522,11 +537,11 @@ class DeDRM(FileTypePlugin):
 
                 try:
                     if iswindows or isosx:
-                        from calibre_plugins.dedrm.adobekey import adeptkeys
+                        from adobekey import adeptkeys
 
                         defaultkeys, defaultnames = adeptkeys()
                     else: # linux
-                        from .wineutils import WineGetKeys
+                        from wineutils import WineGetKeys
 
                         scriptpath = os.path.join(self.alfdir,"adobekey.py")
                         defaultkeys, defaultnames = WineGetKeys(scriptpath, ".der",dedrmprefs['adobewineprefix'])
@@ -546,7 +561,7 @@ class DeDRM(FileTypePlugin):
 
                 # Check for DeACSM keys:
                 try: 
-                    from calibre_plugins.dedrm.config import checkForDeACSMkeys
+                    from config import checkForDeACSMkeys
 
                     newkey, newname = checkForDeACSMkeys()
 
@@ -613,8 +628,8 @@ class DeDRM(FileTypePlugin):
     
     def PDFIneptDecrypt(self, path_to_ebook):
         # Sub function to prevent PDFDecrypt from becoming too large ...
-        import calibre_plugins.dedrm.prefs as prefs
-        import calibre_plugins.dedrm.ineptpdf as ineptpdf
+        import prefs
+        import ineptpdf
         dedrmprefs = prefs.DeDRM_Prefs()
 
         book_uuid = None
@@ -688,11 +703,11 @@ class DeDRM(FileTypePlugin):
 
         try:
             if iswindows or isosx:
-                from calibre_plugins.dedrm.adobekey import adeptkeys
+                from adobekey import adeptkeys
 
                 defaultkeys, defaultnames = adeptkeys()
             else: # linux
-                from .wineutils import WineGetKeys
+                from wineutils import WineGetKeys
 
                 scriptpath = os.path.join(self.alfdir,"adobekey.py")
                 defaultkeys, defaultnames = WineGetKeys(scriptpath, ".der",dedrmprefs['adobewineprefix'])
@@ -712,7 +727,7 @@ class DeDRM(FileTypePlugin):
 
         # Check for DeACSM keys:
         try: 
-            from calibre_plugins.dedrm.config import checkForDeACSMkeys
+            from config import checkForDeACSMkeys
 
             newkey, newname = checkForDeACSMkeys()
 
@@ -789,8 +804,8 @@ class DeDRM(FileTypePlugin):
 
     def PDFStandardDecrypt(self, path_to_ebook):
         # Sub function to prevent PDFDecrypt from becoming too large ...
-        import calibre_plugins.dedrm.prefs as prefs
-        import calibre_plugins.dedrm.ineptpdf as ineptpdf
+        import prefs
+        import ineptpdf
         dedrmprefs = prefs.DeDRM_Prefs()
 
         # Attempt to decrypt PDF with each encryption key (generated or provided).  
@@ -836,9 +851,9 @@ class DeDRM(FileTypePlugin):
         
     
     def PDFDecrypt(self,path_to_ebook):
-        import calibre_plugins.dedrm.prefs as prefs
-        import calibre_plugins.dedrm.ineptpdf as ineptpdf
-        import calibre_plugins.dedrm.lcpdedrm as lcpdedrm
+        import prefs
+        import ineptpdf
+        import lcpdedrm
         dedrmprefs = prefs.DeDRM_Prefs()
 
         if (lcpdedrm.isLCPbook(path_to_ebook)):
@@ -881,8 +896,8 @@ class DeDRM(FileTypePlugin):
         # Had to move this import here so the custom libs can be
         # extracted to the appropriate places beforehand these routines
         # look for them.
-        import calibre_plugins.dedrm.prefs as prefs
-        import calibre_plugins.dedrm.k4mobidedrm as k4mobidedrm
+        import prefs
+        import k4mobidedrm
 
         dedrmprefs = prefs.DeDRM_Prefs()
         pids = dedrmprefs['pids']
@@ -905,11 +920,11 @@ class DeDRM(FileTypePlugin):
 
             try:
                 if iswindows or isosx:
-                    from calibre_plugins.dedrm.kindlekey import kindlekeys
+                    from kindlekey import kindlekeys
 
                     defaultkeys = kindlekeys()
                 else: # linux
-                    from .wineutils import WineGetKeys
+                    from wineutils import WineGetKeys
 
                     scriptpath = os.path.join(self.alfdir,"kindlekey.py")
                     defaultkeys = WineGetKeys(scriptpath, ".k4i",dedrmprefs['kindlewineprefix'])
@@ -949,8 +964,8 @@ class DeDRM(FileTypePlugin):
 
     def eReaderDecrypt(self,path_to_ebook):
 
-        import calibre_plugins.dedrm.prefs as prefs
-        import calibre_plugins.dedrm.erdr2pml as erdr2pml
+        import prefs
+        import erdr2pml
 
         dedrmprefs = prefs.DeDRM_Prefs()
         # Attempt to decrypt epub with each encryption key (generated or provided).
@@ -1011,7 +1026,7 @@ class DeDRM(FileTypePlugin):
         return True
 
     def config_widget(self):
-        import calibre_plugins.dedrm.config as config
+        import config
         return config.ConfigWidget(self.plugin_path, self.alfdir)
 
     def save_settings(self, config_widget):
diff --git a/DeDRM_plugin/__main__.py b/DeDRM_plugin/__main__.py
new file mode 100644 (file)
index 0000000..96b4217
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# __main__.py for DeDRM_plugin
+# (CLI interface without Calibre)
+# Copyright © 2021 NoDRM
+
+__license__   = 'GPL v3'
+__docformat__ = 'restructuredtext en'
+
+# For revision history see __init__.py
+
+"""
+Run DeDRM plugin without Calibre.
+"""
+
+# Import __init__.py from the standalone folder so we can have all the 
+# standalone / non-Calibre code in that subfolder.
+
+import standalone.__init__ as mdata
+import sys
+
+mdata.main(sys.argv)
\ No newline at end of file
index 9a7c493420bc4ecf07db3d05073f1ddf5efd8193..4cdb2eabf282a60e0df458ff6004030bf3dc02ef 100755 (executable)
@@ -16,19 +16,23 @@ from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
 from PyQt5 import Qt as QtGui
 from zipfile import ZipFile
 
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+
 # calibre modules and constants.
 from calibre.gui2 import (error_dialog, question_dialog, info_dialog, open_url,
                             choose_dir, choose_files, choose_save_file)
 from calibre.utils.config import dynamic, config_dir, JSONConfig
 from calibre.constants import iswindows, isosx
 
-# modules from this plugin's zipfile.
-from calibre_plugins.dedrm.__init__ import PLUGIN_NAME, PLUGIN_VERSION
-from calibre_plugins.dedrm.__init__ import RESOURCE_NAME as help_file_name
-from calibre_plugins.dedrm.utilities import uStrCmp
 
-import calibre_plugins.dedrm.prefs as prefs
-import calibre_plugins.dedrm.androidkindlekey as androidkindlekey
+from __init__ import PLUGIN_NAME, PLUGIN_VERSION
+from __init__ import RESOURCE_NAME as help_file_name
+from utilities import uStrCmp
+
+import prefs
+import androidkindlekey
 
 def checkForDeACSMkeys(): 
         try: 
@@ -868,7 +872,7 @@ class AddBandNKeyDialog(QDialog):
             errmsg = "This isn't the correct path, or the data is invalid."
             return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
 
-        from calibre_plugins.dedrm.ignoblekeyAndroid import dump_keys
+        from ignoblekeyAndroid import dump_keys
         store_result = dump_keys(path_to_ade_data)
 
         if len(store_result) == 0:
@@ -899,7 +903,7 @@ class AddBandNKeyDialog(QDialog):
     def accept_ade_dump_passhash(self):
         
         try: 
-            from calibre_plugins.dedrm.adobekey_get_passhash import passhash_keys
+            from adobekey_get_passhash import passhash_keys
             keys, names = passhash_keys()
         except:
             errmsg = "Failed to grab PassHash keys from ADE."
@@ -940,7 +944,7 @@ class AddBandNKeyDialog(QDialog):
             return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
 
         try: 
-            from calibre_plugins.dedrm.ignoblekeyWindowsStore import dump_keys
+            from ignoblekeyWindowsStore import dump_keys
             store_result = dump_keys(False)
         except:
             errmsg = "Failed to import from Nook Microsoft Store app."
@@ -948,7 +952,7 @@ class AddBandNKeyDialog(QDialog):
 
         try: 
             # Try the Nook Study app
-            from calibre_plugins.dedrm.ignoblekeyNookStudy import nookkeys
+            from ignoblekeyNookStudy import nookkeys
             study_result = nookkeys()
         except:
             errmsg = "Failed to import from Nook Study app."
@@ -1009,7 +1013,7 @@ class AddBandNKeyDialog(QDialog):
             return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
 
         try: 
-            from calibre_plugins.dedrm.ignoblekeyGenPassHash import generate_key
+            from ignoblekeyGenPassHash import generate_key
             self.result_data = generate_key(self.user_name, self.cc_number)
         except: 
             errmsg = "Key generation failed."
@@ -1077,7 +1081,7 @@ class AddEReaderDialog(QDialog):
 
     @property
     def key_value(self):
-        from calibre_plugins.dedrm.erdr2pml import getuser_key as generate_ereader_key
+        from erdr2pml import getuser_key as generate_ereader_key
         return codecs.encode(generate_ereader_key(self.user_name, self.cc_number),'hex')
 
     @property
@@ -1124,7 +1128,7 @@ class AddAdeptDialog():
 
         try:
             if iswindows or isosx:
-                from calibre_plugins.dedrm.adobekey import adeptkeys
+                from adobekey import adeptkeys
 
                 defaultkeys, defaultnames = adeptkeys()
             else:  # linux
@@ -1220,7 +1224,7 @@ class AddKindleDialog(QDialog):
 
         try:
             if iswindows or isosx:
-                from calibre_plugins.dedrm.kindlekey import kindlekeys
+                from kindlekey import kindlekeys
 
                 defaultkeys = kindlekeys()
             else: # linux
index c32431a6b655102fdba899980b91b18c5b53d138..70d7b46924b46699ac585df6d0042de13d1aea6b 100755 (executable)
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # erdr2pml.py
-# Copyright © 2008-2020 The Dark Reverser, Apprentice Harper et al.
+# Copyright © 2008-2021 The Dark Reverser, Apprentice Harper, noDRM et al.
 #
 # Changelog
 #
 #  0.22 - Unicode and plugin support, different image folders for PMLZ and source
 #  0.23 - moved unicode_argv call inside main for Windows DeDRM compatibility
 #  1.00 - Added Python 3 compatibility for calibre 5.0
+#  1.01 - Bugfixes for standalone version.
 
 __version__='1.00'
 
 import sys, re
 import struct, binascii, getopt, zlib, os, os.path, urllib, tempfile, traceback
 
-if 'calibre' in sys.modules:
-    inCalibre = True
-else:
-    inCalibre = False
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
 
 # Wrap a stream so that output gets flushed immediately
 # and also make sure that any unicode strings get
@@ -141,40 +141,25 @@ def unicode_argv():
 Des = None
 if iswindows:
     # first try with pycrypto
-    if inCalibre:
-        from calibre_plugins.dedrm import pycrypto_des
-    else:
-        import pycrypto_des
+    import pycrypto_des
     Des = pycrypto_des.load_pycrypto()
     if Des == None:
         # they try with openssl
-        if inCalibre:
-            from calibre_plugins.dedrm import openssl_des
-        else:
-            import openssl_des
+        import openssl_des
         Des = openssl_des.load_libcrypto()
 else:
     # first try with openssl
-    if inCalibre:
-        from calibre_plugins.dedrm import openssl_des
-    else:
-        import openssl_des
+    import openssl_des
     Des = openssl_des.load_libcrypto()
     if Des == None:
         # then try with pycrypto
-        if inCalibre:
-            from calibre_plugins.dedrm import pycrypto_des
-        else:
-            import pycrypto_des
+        import pycrypto_des
         Des = pycrypto_des.load_pycrypto()
 
 # if that did not work then use pure python implementation
 # of DES and try to speed it up with Psycho
 if Des == None:
-    if inCalibre:
-        from calibre_plugins.dedrm import python_des
-    else:
-        import python_des
+    import python_des
     Des = python_des.Des
     # Import Psyco if available
     try:
index 6f3f57d19f5cce07a72ead8932ef67f488ac8cb0..a0e0d0d6d7a6181510568b32f8bbe3708fb1d42b 100644 (file)
@@ -35,25 +35,18 @@ import getopt
 from struct import pack
 from struct import unpack
 
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+
 class TpzDRMError(Exception):
     pass
 
 # local support routines
-if 'calibre' in sys.modules:
-    inCalibre = True
-else:
-    inCalibre = False
-
-if inCalibre :
-    from calibre_plugins.dedrm import convert2xml
-    from calibre_plugins.dedrm import flatxml2html
-    from calibre_plugins.dedrm import flatxml2svg
-    from calibre_plugins.dedrm import stylexml2css
-else :
-    import convert2xml
-    import flatxml2html
-    import flatxml2svg
-    import stylexml2css
+import convert2xml
+import flatxml2html
+import flatxml2svg
+import stylexml2css
 
 # global switch
 buildXML = False
index 4a305359f50e8f3d235251339446d4998a3afc72..1a6465bbf2eceea60209f6006f1eac158ac5e4ac 100644 (file)
@@ -72,26 +72,18 @@ import time
 import html.entities
 import json
 
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+
 class DrmException(Exception):
     pass
 
-if 'calibre' in sys.modules:
-    inCalibre = True
-else:
-    inCalibre = False
-
-if inCalibre:
-    from calibre_plugins.dedrm import mobidedrm
-    from calibre_plugins.dedrm import topazextract
-    from calibre_plugins.dedrm import kgenpids
-    from calibre_plugins.dedrm import androidkindlekey
-    from calibre_plugins.dedrm import kfxdedrm
-else:
-    import mobidedrm
-    import topazextract
-    import kgenpids
-    import androidkindlekey
-    import kfxdedrm
+import mobidedrm
+import topazextract
+import kgenpids
+import androidkindlekey
+import kfxdedrm
 
 # Wrap a stream so that output gets flushed immediately
 # and also make sure that any unicode strings get
@@ -243,7 +235,7 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime
     try:
         mb.processBook(totalpids)
     except:
-        mb.cleanup
+        mb.cleanup()
         raise
 
     print("Decryption succeeded after {0:.1f} seconds".format(time.time()-starttime))
index 23e46dc77b2a84597dce571bacf1dca9c316687e..0674d630ea2732ac75b2821f5081a699300a9584 100644 (file)
@@ -8,16 +8,18 @@
 #  2.1.1 - Whitespace!
 
 
-import os
+import os, sys
 import shutil
 import traceback
 import zipfile
 
 from io import BytesIO
-try:
-    from ion import DrmIon, DrmIonVoucher
-except:
-    from calibre_plugins.dedrm.ion import DrmIon, DrmIonVoucher
+
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+from ion import DrmIon, DrmIonVoucher
+
 
 
 __license__ = 'GPL v3'
index aee4846decad44c2bfd152fcb93770f7c8840b09..ae44213282f1f8cdd6e8694cd217bc9efa5be40d 100755 (executable)
@@ -5,15 +5,15 @@
 __license__ = 'GPL v3'
 
 # Standard Python modules.
-import os
+import os, sys
 import traceback
 
-from calibre.utils.config import JSONConfig
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
 
-try: 
-    from calibre_plugins.dedrm.__init__ import PLUGIN_NAME
-except: 
-    PLUGIN_NAME = "DeDRM"
+from calibre.utils.config import JSONConfig
+from __init__ import PLUGIN_NAME
 
 class DeDRM_Prefs():
     def __init__(self):
index 1810237e7f4b65c70f86c97992eea190d0bf3519..3351ee724f7d80d45ebf7d03526200b8fe89ac9d 100644 (file)
@@ -5,15 +5,19 @@
 
 import sys
 import os
+
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+
 import re
 import traceback
-import calibre_plugins.dedrm.ineptepub
-import calibre_plugins.dedrm.ignobleepub
-import calibre_plugins.dedrm.epubtest
-import calibre_plugins.dedrm.zipfix
-import calibre_plugins.dedrm.ineptpdf
-import calibre_plugins.dedrm.erdr2pml
-import calibre_plugins.dedrm.k4mobidedrm
+import ineptepub
+import epubtest
+import zipfix
+import ineptpdf
+import erdr2pml
+import k4mobidedrm
 
 def decryptepub(infile, outdir, rscpath):
     errlog = ''
diff --git a/DeDRM_plugin/standalone/__init__.py b/DeDRM_plugin/standalone/__init__.py
new file mode 100644 (file)
index 0000000..fceda3b
--- /dev/null
@@ -0,0 +1,217 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# CLI interface for the DeDRM plugin (useable without Calibre, too)
+
+# Copyright © 2021 NoDRM
+
+OPT_SHORT_TO_LONG = [
+    ["h", "help"], 
+    ["t", "test"], 
+    ["v", "verbose"],
+    ["q", "quiet"],
+    ["u", "username"],
+    ["p", "password"],
+    ["d", "dest"],
+    ["f", "force"]
+]
+
+import sys, os
+IS_CALIBRE = False
+if "calibre" in sys.modules:
+    IS_CALIBRE = True
+
+# Explicitly allow importing the parent folder
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+# Explicitly set the package identifier so we are allowed to import stuff ...
+__package__ = "DeDRM_plugin"
+
+
+global _additional_data
+global _additional_params
+global _function
+_additional_data = []
+_additional_params = []
+_function = None
+
+def print_err_header():
+    from __init__ import PLUGIN_NAME, PLUGIN_VERSION # type: ignore
+
+    print(PLUGIN_NAME + " v" + PLUGIN_VERSION + " - DRM removal plugin by noDRM")
+    print()
+
+def print_help():
+    from __init__ import PLUGIN_NAME, PLUGIN_VERSION
+    print(PLUGIN_NAME + " v" + PLUGIN_VERSION + " - DRM removal plugin by noDRM")
+    print("Based on DeDRM Calibre plugin by Apprentice Harper, Apprentice Alf and others.")
+    print("See https://github.com/noDRM/DeDRM_tools for more information.")
+    print()
+    if IS_CALIBRE:
+        print("This plugin can be run through Calibre - like you are doing right now - ")
+        print("but it can also be executed with a standalone Python interpreter.")
+    else:
+        print("This plugin can either be imported into Calibre, or be executed directly")
+        print("through Python like you are doing right now.")
+    print()
+    print("TODO: Parameters here ...")
+
+def print_credits():
+    from __init__ import PLUGIN_NAME, PLUGIN_VERSION
+    print(PLUGIN_NAME + " v" + PLUGIN_VERSION + " - Calibre DRM removal plugin by noDRM")
+    print("Based on DeDRM Calibre plugin by Apprentice Harper, Apprentice Alf and others.")
+    print("See https://github.com/noDRM/DeDRM_tools for more information.")
+    print()
+    print("Credits:")
+    print(" - noDRM for the current release of the DeDRM plugin")
+    print(" - Apprentice Alf and Apprentice Harper for the previous versions of the DeDRM plugin")
+    print(" - The Dark Reverser for the Mobipocket and eReader script")
+    print(" - i ♥ cabbages for the Adobe Digital Editions scripts")
+    print(" - Skindle aka Bart Simpson for the Amazon Kindle for PC script")
+    print(" - CMBDTC for Amazon Topaz DRM removal script")
+    print(" - some_updates, clarknova and Bart Simpson for Amazon Topaz conversion scripts")
+    print(" - DiapDealer for the first calibre plugin versions of the tools")
+    print(" - some_updates, DiapDealer, Apprentice Alf and mdlnx for Amazon Kindle/Mobipocket tools")
+    print(" - some_updates for the DeDRM all-in-one Python tool")
+    print(" - Apprentice Alf for the DeDRM all-in-one AppleScript tool")
+
+
+def handle_single_argument(arg, next):
+    used_up = 0
+    global _additional_params
+    
+    if arg == "--help":
+        print_help()
+        exit(0)
+
+    elif arg == "--credits":
+        print_credits()
+        exit(0)
+
+    elif arg in ["--username", "--password"]: 
+        used_up = 1
+        _additional_params.append(arg)
+        if next is None: 
+            print_err_header()
+            print("Missing parameter for argument " + arg)
+            exit(1)
+        else:
+            _additional_params.append(next[0])
+
+    elif arg in ["--verbose", "--quiet"]:
+        _additional_params.append(arg)
+
+        
+    else:
+        print_err_header()
+        print("Unknown argument: " + arg)
+        exit(1)
+    
+    
+    # Used up 0 additional arguments
+    return used_up
+
+
+
+def handle_data(data):
+    global _function
+    global _additional_data
+
+    if _function is None: 
+        _function = str(data)
+    else:
+        _additional_data.append(str(data))
+
+def execute_action(action, filenames, params):
+    print("Executing '{0}' on file(s) {1} with parameters {2}".format(action, str(filenames), str(params)))
+
+    print("ERROR: This feature is still in development. Right now it can't be used yet.")
+
+
+def main(argv):
+    arguments = argv
+    skip_opts = False
+
+    # First element is always the ZIP name, remove that. 
+    if not arguments[0].lower().endswith(".zip") and not IS_CALIBRE:
+        print("Warning: File name does not end in .zip ...")
+        print(arguments)
+    arguments.pop(0)
+
+    while len(arguments) > 0:
+        arg = arguments.pop(0)
+
+        if arg == "--":
+            skip_opts = True
+            continue
+
+        if not skip_opts:
+            if arg.startswith("--"):
+                # Give the current arg, plus all remaining ones. 
+                # Return the number of additional args we used.
+                used = handle_single_argument(arg, arguments)
+                for _ in range(used):
+                    # Function returns number of additional arguments that were
+                    # "used up" by that argument. 
+                    # Remove that amount of arguments from the list.
+                    try: 
+                        arguments.pop(0)
+                    except:
+                        pass
+                continue
+            elif arg.startswith("-"):
+                single_args = list(arg[1:])
+                # single_args is now a list of single chars, for when you call the program like "ls -alR"
+                # with multiple single-letter options combined.
+                while len(single_args) > 0:
+                    c = single_args.pop(0)
+                
+                    # See if we have a long name for that option.
+                    for wrapper in OPT_SHORT_TO_LONG:
+                        if wrapper[0] == c:
+                            c = "--" + wrapper[1]
+                            break
+                    else: 
+                        c = "-" + c
+                    # c is now the long term (unless there is no long version, then it's the short version).
+
+                    if len(single_args) > 0:
+                        # If we have more short arguments, the argument for this one must be None.
+                        handle_single_argument(c, None)
+                        used = 0
+                    else: 
+                        # If not, then there might be parameters for this short argument.
+                        used = handle_single_argument(c, arguments)
+
+                    for _ in range(used):
+                        # Function returns number of additional arguments that were
+                        # "used up" by that argument. 
+                        # Remove that amount of arguments from the list.
+                        try: 
+                            arguments.pop(0)
+                        except: 
+                            pass
+                
+                continue
+        
+        handle_data(arg)
+        
+
+    if _function is None:
+        print_help()
+        return(1)
+    
+    # Okay, now actually begin doing stuff.
+    # This function gets told what to do and gets additional data (filenames).
+    # It also receives additional parameters.
+    # The rest of the code will be in different Python files.
+    execute_action(_function, _additional_data, _additional_params)
+        
+
+    
+
+
+if __name__ == "__main__":
+    # NOTE: This MUST not do anything else other than calling main()
+    # All the code must be in main(), not in here.
+    import sys
+    main(sys.argv)
\ No newline at end of file
index 55fa2ffc1dabecb96107115f7ebb55644061387d..4db507234c15499b50f43aa97e2127aa01287be8 100644 (file)
@@ -13,14 +13,16 @@ __version__ = '6.0'
 
 import sys
 import os, csv, getopt
+
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
 import zlib, zipfile, tempfile, shutil
 import traceback
 from struct import pack
 from struct import unpack
-try:
-    from calibre_plugins.dedrm.alfcrypto import Topaz_Cipher
-except:
-    from alfcrypto import Topaz_Cipher
+
+from alfcrypto import Topaz_Cipher
 
 # Wrap a stream so that output gets flushed immediately
 # and also make sure that any unicode strings get
@@ -88,12 +90,7 @@ def unicode_argv():
 #global switch
 debug = False
 
-if 'calibre' in sys.modules:
-    inCalibre = True
-    from calibre_plugins.dedrm import kgenpids
-else:
-    inCalibre = False
-    import kgenpids
+import kgenpids
 
 
 class DrmException(Exception):
@@ -336,10 +333,7 @@ class TopazBook:
             self.createBookDirectory()
             self.extractFiles()
             print("Successfully Extracted Topaz contents")
-            if inCalibre:
-                from calibre_plugins.dedrm import genbook
-            else:
-                import genbook
+            import genbook
 
             rv = genbook.generateBook(self.outdir, raw, fixedimage)
             if rv == 0:
@@ -370,10 +364,7 @@ class TopazBook:
         self.createBookDirectory()
         self.extractFiles()
         print("Successfully Extracted Topaz contents")
-        if inCalibre:
-            from calibre_plugins.dedrm import genbook
-        else:
-            import genbook
+        import genbook
 
         rv = genbook.generateBook(self.outdir, raw, fixedimage)
         if rv == 0:
index 47d6106bbf727c610ec54c6e6e4f9b8f5f9f901b..1efd8ce5a4442c6ff520c9a715ee709ac67480ce 100644 (file)
@@ -1,7 +1,12 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
-from calibre_plugins.dedrm.ignoblekeyGenPassHash import generate_key
+import sys, os
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
+
+from ignoblekeyGenPassHash import generate_key
 
 __license__ = 'GPL v3'
 
index 54469d8867dfd22b9e4dc0952b01490bfe6148fa..079e49acb82cac1685533bffb2dc49bbf0c94373 100644 (file)
@@ -20,14 +20,13 @@ Re-write zip (or ePub) fixing problems with file names (and mimetype entry).
 __license__ = 'GPL v3'
 __version__ = "1.1"
 
-import sys
+import sys, os
+
+# Calibre stuff - so we can import from our ZIP without absolute module name
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+
 import zlib
-try:
-    import zipfilerugged
-except:
-    import calibre_plugins.dedrm.zipfilerugged as zipfilerugged
-import os
-import os.path
+import zipfilerugged
 import getopt
 from struct import unpack