Begin work on standalone version

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.
This commit is contained in:
NoDRM 2021-12-29 09:26:29 +01:00
parent 9c40b3ce5a
commit dbf4b54026
13 changed files with 379 additions and 149 deletions

View File

@ -97,11 +97,19 @@ import sys, os
import time import time
import traceback 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): class DeDRMError(Exception):
pass pass
from calibre.customize import FileTypePlugin try:
from calibre.customize import FileTypePlugin
except:
# Allow import without Calibre.
class FileTypePlugin:
pass
try: try:
from calibre.constants import iswindows, isosx from calibre.constants import iswindows, isosx
@ -109,7 +117,10 @@ except:
iswindows = sys.platform.startswith('win') iswindows = sys.platform.startswith('win')
isosx = sys.platform.startswith('darwin') 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 # Wrap a stream so that output gets flushed immediately
@ -150,6 +161,10 @@ class DeDRM(FileTypePlugin):
priority = 600 priority = 600
def cli_main(self, data):
from standalone import main
main(data)
def initialize(self): def initialize(self):
""" """
Dynamic modules can't be imported/loaded from a zipfile. Dynamic modules can't be imported/loaded from a zipfile.
@ -216,7 +231,7 @@ class DeDRM(FileTypePlugin):
postProcessStart = time.time() postProcessStart = time.time()
try: try:
import calibre_plugins.dedrm.prefs as prefs import prefs
dedrmprefs = prefs.DeDRM_Prefs() dedrmprefs = prefs.DeDRM_Prefs()
if dedrmprefs["deobfuscate_fonts"] is True: 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 path_to_ebook = self.checkFonts(path_to_ebook) or path_to_ebook
if dedrmprefs["remove_watermarks"] is True: if dedrmprefs["remove_watermarks"] is True:
import calibre_plugins.dedrm.epubwatermark as watermark import epubwatermark as watermark
# Remove Tolino's CDP watermark file # Remove Tolino's CDP watermark file
path_to_ebook = watermark.removeCDPwatermark(self, path_to_ebook) or path_to_ebook 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 # It checks if there's fonts that need to be deobfuscated
try: try:
import calibre_plugins.dedrm.epubfontdecrypt as epubfontdecrypt import epubfontdecrypt
output = self.temporary_file(".epub").name output = self.temporary_file(".epub").name
ret = epubfontdecrypt.decryptFontsBook(path_to_ebook, output) ret = epubfontdecrypt.decryptFontsBook(path_to_ebook, output)
@ -272,7 +287,7 @@ class DeDRM(FileTypePlugin):
def ePubDecrypt(self,path_to_ebook): def ePubDecrypt(self,path_to_ebook):
# Create a TemporaryPersistent file to work with. # Create a TemporaryPersistent file to work with.
# Check original epub archive for zip errors. # Check original epub archive for zip errors.
import calibre_plugins.dedrm.zipfix as zipfix import zipfix
inf = self.temporary_file(".epub") inf = self.temporary_file(".epub")
try: try:
@ -284,12 +299,12 @@ class DeDRM(FileTypePlugin):
raise raise
# import the decryption keys # import the decryption keys
import calibre_plugins.dedrm.prefs as prefs import prefs
dedrmprefs = prefs.DeDRM_Prefs() dedrmprefs = prefs.DeDRM_Prefs()
# import the LCP handler # import the LCP handler
import calibre_plugins.dedrm.lcpdedrm as lcpdedrm import lcpdedrm
if (lcpdedrm.isLCPbook(path_to_ebook)): if (lcpdedrm.isLCPbook(path_to_ebook)):
try: try:
@ -304,7 +319,7 @@ class DeDRM(FileTypePlugin):
# Not an LCP book, do the normal EPUB (Adobe) handling. # Not an LCP book, do the normal EPUB (Adobe) handling.
# import the Adobe ePub handler # import the Adobe ePub handler
import calibre_plugins.dedrm.ineptepub as ineptepub import ineptepub
if ineptepub.adeptBook(inf.name): if ineptepub.adeptBook(inf.name):
@ -345,11 +360,11 @@ class DeDRM(FileTypePlugin):
try: try:
if iswindows or isosx: if iswindows or isosx:
from calibre_plugins.dedrm.ignoblekeyNookStudy import nookkeys from ignoblekeyNookStudy import nookkeys
defaultkeys_study = nookkeys() defaultkeys_study = nookkeys()
else: # linux else: # linux
from .wineutils import WineGetKeys from wineutils import WineGetKeys
scriptpath = os.path.join(self.alfdir,"ignoblekeyNookStudy.py") scriptpath = os.path.join(self.alfdir,"ignoblekeyNookStudy.py")
defaultkeys_study = WineGetKeys(scriptpath, ".b64",dedrmprefs['adobewineprefix']) defaultkeys_study = WineGetKeys(scriptpath, ".b64",dedrmprefs['adobewineprefix'])
@ -365,7 +380,7 @@ class DeDRM(FileTypePlugin):
if iswindows: if iswindows:
# That's a Windows store app, it won't run on Linux or MacOS anyways. # That's a Windows store app, it won't run on Linux or MacOS anyways.
# No need to waste time running Wine. # 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) defaultkeys_store = dump_nook_keys(False)
except: except:
@ -377,7 +392,7 @@ class DeDRM(FileTypePlugin):
try: try:
if iswindows: if iswindows:
# Right now this is only implemented for Windows. MacOS support still needs to be added. # 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() defaultkeys_ade, names = passhash_keys()
if isosx: if isosx:
print("{0} v{1}: Dumping ADE PassHash data is not yet supported on MacOS.".format(PLUGIN_NAME, PLUGIN_VERSION)) 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: try:
if iswindows or isosx: if iswindows or isosx:
from calibre_plugins.dedrm.adobekey import adeptkeys from adobekey import adeptkeys
defaultkeys, defaultnames = adeptkeys() defaultkeys, defaultnames = adeptkeys()
else: # linux else: # linux
from .wineutils import WineGetKeys from wineutils import WineGetKeys
scriptpath = os.path.join(self.alfdir,"adobekey.py") scriptpath = os.path.join(self.alfdir,"adobekey.py")
defaultkeys, defaultnames = WineGetKeys(scriptpath, ".der",dedrmprefs['adobewineprefix']) defaultkeys, defaultnames = WineGetKeys(scriptpath, ".der",dedrmprefs['adobewineprefix'])
@ -546,7 +561,7 @@ class DeDRM(FileTypePlugin):
# Check for DeACSM keys: # Check for DeACSM keys:
try: try:
from calibre_plugins.dedrm.config import checkForDeACSMkeys from config import checkForDeACSMkeys
newkey, newname = checkForDeACSMkeys() newkey, newname = checkForDeACSMkeys()
@ -613,8 +628,8 @@ class DeDRM(FileTypePlugin):
def PDFIneptDecrypt(self, path_to_ebook): def PDFIneptDecrypt(self, path_to_ebook):
# Sub function to prevent PDFDecrypt from becoming too large ... # Sub function to prevent PDFDecrypt from becoming too large ...
import calibre_plugins.dedrm.prefs as prefs import prefs
import calibre_plugins.dedrm.ineptpdf as ineptpdf import ineptpdf
dedrmprefs = prefs.DeDRM_Prefs() dedrmprefs = prefs.DeDRM_Prefs()
book_uuid = None book_uuid = None
@ -688,11 +703,11 @@ class DeDRM(FileTypePlugin):
try: try:
if iswindows or isosx: if iswindows or isosx:
from calibre_plugins.dedrm.adobekey import adeptkeys from adobekey import adeptkeys
defaultkeys, defaultnames = adeptkeys() defaultkeys, defaultnames = adeptkeys()
else: # linux else: # linux
from .wineutils import WineGetKeys from wineutils import WineGetKeys
scriptpath = os.path.join(self.alfdir,"adobekey.py") scriptpath = os.path.join(self.alfdir,"adobekey.py")
defaultkeys, defaultnames = WineGetKeys(scriptpath, ".der",dedrmprefs['adobewineprefix']) defaultkeys, defaultnames = WineGetKeys(scriptpath, ".der",dedrmprefs['adobewineprefix'])
@ -712,7 +727,7 @@ class DeDRM(FileTypePlugin):
# Check for DeACSM keys: # Check for DeACSM keys:
try: try:
from calibre_plugins.dedrm.config import checkForDeACSMkeys from config import checkForDeACSMkeys
newkey, newname = checkForDeACSMkeys() newkey, newname = checkForDeACSMkeys()
@ -789,8 +804,8 @@ class DeDRM(FileTypePlugin):
def PDFStandardDecrypt(self, path_to_ebook): def PDFStandardDecrypt(self, path_to_ebook):
# Sub function to prevent PDFDecrypt from becoming too large ... # Sub function to prevent PDFDecrypt from becoming too large ...
import calibre_plugins.dedrm.prefs as prefs import prefs
import calibre_plugins.dedrm.ineptpdf as ineptpdf import ineptpdf
dedrmprefs = prefs.DeDRM_Prefs() dedrmprefs = prefs.DeDRM_Prefs()
# Attempt to decrypt PDF with each encryption key (generated or provided). # Attempt to decrypt PDF with each encryption key (generated or provided).
@ -836,9 +851,9 @@ class DeDRM(FileTypePlugin):
def PDFDecrypt(self,path_to_ebook): def PDFDecrypt(self,path_to_ebook):
import calibre_plugins.dedrm.prefs as prefs import prefs
import calibre_plugins.dedrm.ineptpdf as ineptpdf import ineptpdf
import calibre_plugins.dedrm.lcpdedrm as lcpdedrm import lcpdedrm
dedrmprefs = prefs.DeDRM_Prefs() dedrmprefs = prefs.DeDRM_Prefs()
if (lcpdedrm.isLCPbook(path_to_ebook)): 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 # Had to move this import here so the custom libs can be
# extracted to the appropriate places beforehand these routines # extracted to the appropriate places beforehand these routines
# look for them. # look for them.
import calibre_plugins.dedrm.prefs as prefs import prefs
import calibre_plugins.dedrm.k4mobidedrm as k4mobidedrm import k4mobidedrm
dedrmprefs = prefs.DeDRM_Prefs() dedrmprefs = prefs.DeDRM_Prefs()
pids = dedrmprefs['pids'] pids = dedrmprefs['pids']
@ -905,11 +920,11 @@ class DeDRM(FileTypePlugin):
try: try:
if iswindows or isosx: if iswindows or isosx:
from calibre_plugins.dedrm.kindlekey import kindlekeys from kindlekey import kindlekeys
defaultkeys = kindlekeys() defaultkeys = kindlekeys()
else: # linux else: # linux
from .wineutils import WineGetKeys from wineutils import WineGetKeys
scriptpath = os.path.join(self.alfdir,"kindlekey.py") scriptpath = os.path.join(self.alfdir,"kindlekey.py")
defaultkeys = WineGetKeys(scriptpath, ".k4i",dedrmprefs['kindlewineprefix']) defaultkeys = WineGetKeys(scriptpath, ".k4i",dedrmprefs['kindlewineprefix'])
@ -949,8 +964,8 @@ class DeDRM(FileTypePlugin):
def eReaderDecrypt(self,path_to_ebook): def eReaderDecrypt(self,path_to_ebook):
import calibre_plugins.dedrm.prefs as prefs import prefs
import calibre_plugins.dedrm.erdr2pml as erdr2pml import erdr2pml
dedrmprefs = prefs.DeDRM_Prefs() dedrmprefs = prefs.DeDRM_Prefs()
# Attempt to decrypt epub with each encryption key (generated or provided). # Attempt to decrypt epub with each encryption key (generated or provided).
@ -1011,7 +1026,7 @@ class DeDRM(FileTypePlugin):
return True return True
def config_widget(self): def config_widget(self):
import calibre_plugins.dedrm.config as config import config
return config.ConfigWidget(self.plugin_path, self.alfdir) return config.ConfigWidget(self.plugin_path, self.alfdir)
def save_settings(self, config_widget): def save_settings(self, config_widget):

23
DeDRM_plugin/__main__.py Normal file
View File

@ -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)

View File

@ -16,19 +16,23 @@ from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
from PyQt5 import Qt as QtGui from PyQt5 import Qt as QtGui
from zipfile import ZipFile 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. # calibre modules and constants.
from calibre.gui2 import (error_dialog, question_dialog, info_dialog, open_url, from calibre.gui2 import (error_dialog, question_dialog, info_dialog, open_url,
choose_dir, choose_files, choose_save_file) choose_dir, choose_files, choose_save_file)
from calibre.utils.config import dynamic, config_dir, JSONConfig from calibre.utils.config import dynamic, config_dir, JSONConfig
from calibre.constants import iswindows, isosx 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 from __init__ import PLUGIN_NAME, PLUGIN_VERSION
import calibre_plugins.dedrm.androidkindlekey as androidkindlekey from __init__ import RESOURCE_NAME as help_file_name
from utilities import uStrCmp
import prefs
import androidkindlekey
def checkForDeACSMkeys(): def checkForDeACSMkeys():
try: try:
@ -868,7 +872,7 @@ class AddBandNKeyDialog(QDialog):
errmsg = "This isn't the correct path, or the data is invalid." 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) 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) store_result = dump_keys(path_to_ade_data)
if len(store_result) == 0: if len(store_result) == 0:
@ -899,7 +903,7 @@ class AddBandNKeyDialog(QDialog):
def accept_ade_dump_passhash(self): def accept_ade_dump_passhash(self):
try: try:
from calibre_plugins.dedrm.adobekey_get_passhash import passhash_keys from adobekey_get_passhash import passhash_keys
keys, names = passhash_keys() keys, names = passhash_keys()
except: except:
errmsg = "Failed to grab PassHash keys from ADE." 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) return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
try: try:
from calibre_plugins.dedrm.ignoblekeyWindowsStore import dump_keys from ignoblekeyWindowsStore import dump_keys
store_result = dump_keys(False) store_result = dump_keys(False)
except: except:
errmsg = "Failed to import from Nook Microsoft Store app." errmsg = "Failed to import from Nook Microsoft Store app."
@ -948,7 +952,7 @@ class AddBandNKeyDialog(QDialog):
try: try:
# Try the Nook Study app # Try the Nook Study app
from calibre_plugins.dedrm.ignoblekeyNookStudy import nookkeys from ignoblekeyNookStudy import nookkeys
study_result = nookkeys() study_result = nookkeys()
except: except:
errmsg = "Failed to import from Nook Study app." 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) return error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
try: 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) self.result_data = generate_key(self.user_name, self.cc_number)
except: except:
errmsg = "Key generation failed." errmsg = "Key generation failed."
@ -1077,7 +1081,7 @@ class AddEReaderDialog(QDialog):
@property @property
def key_value(self): 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') return codecs.encode(generate_ereader_key(self.user_name, self.cc_number),'hex')
@property @property
@ -1124,7 +1128,7 @@ class AddAdeptDialog():
try: try:
if iswindows or isosx: if iswindows or isosx:
from calibre_plugins.dedrm.adobekey import adeptkeys from adobekey import adeptkeys
defaultkeys, defaultnames = adeptkeys() defaultkeys, defaultnames = adeptkeys()
else: # linux else: # linux
@ -1220,7 +1224,7 @@ class AddKindleDialog(QDialog):
try: try:
if iswindows or isosx: if iswindows or isosx:
from calibre_plugins.dedrm.kindlekey import kindlekeys from kindlekey import kindlekeys
defaultkeys = kindlekeys() defaultkeys = kindlekeys()
else: # linux else: # linux

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# erdr2pml.py # erdr2pml.py
# Copyright © 2008-2020 The Dark Reverser, Apprentice Harper et al. # Copyright © 2008-2021 The Dark Reverser, Apprentice Harper, noDRM et al.
# #
# Changelog # Changelog
# #
@ -64,16 +64,16 @@
# 0.22 - Unicode and plugin support, different image folders for PMLZ and source # 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 # 0.23 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 1.00 - Added Python 3 compatibility for calibre 5.0 # 1.00 - Added Python 3 compatibility for calibre 5.0
# 1.01 - Bugfixes for standalone version.
__version__='1.00' __version__='1.00'
import sys, re import sys, re
import struct, binascii, getopt, zlib, os, os.path, urllib, tempfile, traceback import struct, binascii, getopt, zlib, os, os.path, urllib, tempfile, traceback
if 'calibre' in sys.modules: # Calibre stuff - so we can import from our ZIP without absolute module name
inCalibre = True sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
else:
inCalibre = False
# Wrap a stream so that output gets flushed immediately # Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get # and also make sure that any unicode strings get
@ -141,40 +141,25 @@ def unicode_argv():
Des = None Des = None
if iswindows: if iswindows:
# first try with pycrypto # first try with pycrypto
if inCalibre: import pycrypto_des
from calibre_plugins.dedrm import pycrypto_des
else:
import pycrypto_des
Des = pycrypto_des.load_pycrypto() Des = pycrypto_des.load_pycrypto()
if Des == None: if Des == None:
# they try with openssl # they try with openssl
if inCalibre: import openssl_des
from calibre_plugins.dedrm import openssl_des
else:
import openssl_des
Des = openssl_des.load_libcrypto() Des = openssl_des.load_libcrypto()
else: else:
# first try with openssl # first try with openssl
if inCalibre: import openssl_des
from calibre_plugins.dedrm import openssl_des
else:
import openssl_des
Des = openssl_des.load_libcrypto() Des = openssl_des.load_libcrypto()
if Des == None: if Des == None:
# then try with pycrypto # then try with pycrypto
if inCalibre: import pycrypto_des
from calibre_plugins.dedrm import pycrypto_des
else:
import pycrypto_des
Des = pycrypto_des.load_pycrypto() Des = pycrypto_des.load_pycrypto()
# if that did not work then use pure python implementation # if that did not work then use pure python implementation
# of DES and try to speed it up with Psycho # of DES and try to speed it up with Psycho
if Des == None: if Des == None:
if inCalibre: import python_des
from calibre_plugins.dedrm import python_des
else:
import python_des
Des = python_des.Des Des = python_des.Des
# Import Psyco if available # Import Psyco if available
try: try:

View File

@ -35,25 +35,18 @@ import getopt
from struct import pack from struct import pack
from struct import unpack 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): class TpzDRMError(Exception):
pass pass
# local support routines # local support routines
if 'calibre' in sys.modules: import convert2xml
inCalibre = True import flatxml2html
else: import flatxml2svg
inCalibre = False import stylexml2css
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
# global switch # global switch
buildXML = False buildXML = False

View File

@ -72,26 +72,18 @@ import time
import html.entities import html.entities
import json 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): class DrmException(Exception):
pass pass
if 'calibre' in sys.modules: import mobidedrm
inCalibre = True import topazextract
else: import kgenpids
inCalibre = False import androidkindlekey
import kfxdedrm
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
# Wrap a stream so that output gets flushed immediately # Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get # and also make sure that any unicode strings get
@ -243,7 +235,7 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime
try: try:
mb.processBook(totalpids) mb.processBook(totalpids)
except: except:
mb.cleanup mb.cleanup()
raise raise
print("Decryption succeeded after {0:.1f} seconds".format(time.time()-starttime)) print("Decryption succeeded after {0:.1f} seconds".format(time.time()-starttime))

View File

@ -8,16 +8,18 @@
# 2.1.1 - Whitespace! # 2.1.1 - Whitespace!
import os import os, sys
import shutil import shutil
import traceback import traceback
import zipfile import zipfile
from io import BytesIO from io import BytesIO
try:
from ion import DrmIon, DrmIonVoucher # Calibre stuff - so we can import from our ZIP without absolute module name
except: sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from calibre_plugins.dedrm.ion import DrmIon, DrmIonVoucher
from ion import DrmIon, DrmIonVoucher
__license__ = 'GPL v3' __license__ = 'GPL v3'

View File

@ -5,15 +5,15 @@
__license__ = 'GPL v3' __license__ = 'GPL v3'
# Standard Python modules. # Standard Python modules.
import os import os, sys
import traceback 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 from calibre.utils.config import JSONConfig
except: from __init__ import PLUGIN_NAME
PLUGIN_NAME = "DeDRM"
class DeDRM_Prefs(): class DeDRM_Prefs():
def __init__(self): def __init__(self):

View File

@ -5,15 +5,19 @@
import sys import sys
import os 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 re
import traceback import traceback
import calibre_plugins.dedrm.ineptepub import ineptepub
import calibre_plugins.dedrm.ignobleepub import epubtest
import calibre_plugins.dedrm.epubtest import zipfix
import calibre_plugins.dedrm.zipfix import ineptpdf
import calibre_plugins.dedrm.ineptpdf import erdr2pml
import calibre_plugins.dedrm.erdr2pml import k4mobidedrm
import calibre_plugins.dedrm.k4mobidedrm
def decryptepub(infile, outdir, rscpath): def decryptepub(infile, outdir, rscpath):
errlog = '' errlog = ''

View File

@ -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)

View File

@ -13,14 +13,16 @@ __version__ = '6.0'
import sys import sys
import os, csv, getopt 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 zlib, zipfile, tempfile, shutil
import traceback import traceback
from struct import pack from struct import pack
from struct import unpack from struct import unpack
try:
from calibre_plugins.dedrm.alfcrypto import Topaz_Cipher from alfcrypto import Topaz_Cipher
except:
from alfcrypto import Topaz_Cipher
# Wrap a stream so that output gets flushed immediately # Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get # and also make sure that any unicode strings get
@ -88,12 +90,7 @@ def unicode_argv():
#global switch #global switch
debug = False debug = False
if 'calibre' in sys.modules: import kgenpids
inCalibre = True
from calibre_plugins.dedrm import kgenpids
else:
inCalibre = False
import kgenpids
class DrmException(Exception): class DrmException(Exception):
@ -336,10 +333,7 @@ class TopazBook:
self.createBookDirectory() self.createBookDirectory()
self.extractFiles() self.extractFiles()
print("Successfully Extracted Topaz contents") print("Successfully Extracted Topaz contents")
if inCalibre: import genbook
from calibre_plugins.dedrm import genbook
else:
import genbook
rv = genbook.generateBook(self.outdir, raw, fixedimage) rv = genbook.generateBook(self.outdir, raw, fixedimage)
if rv == 0: if rv == 0:
@ -370,10 +364,7 @@ class TopazBook:
self.createBookDirectory() self.createBookDirectory()
self.extractFiles() self.extractFiles()
print("Successfully Extracted Topaz contents") print("Successfully Extracted Topaz contents")
if inCalibre: import genbook
from calibre_plugins.dedrm import genbook
else:
import genbook
rv = genbook.generateBook(self.outdir, raw, fixedimage) rv = genbook.generateBook(self.outdir, raw, fixedimage)
if rv == 0: if rv == 0:

View File

@ -1,7 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- 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' __license__ = 'GPL v3'

View File

@ -20,14 +20,13 @@ Re-write zip (or ePub) fixing problems with file names (and mimetype entry).
__license__ = 'GPL v3' __license__ = 'GPL v3'
__version__ = "1.1" __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 import zlib
try: import zipfilerugged
import zipfilerugged
except:
import calibre_plugins.dedrm.zipfilerugged as zipfilerugged
import os
import os.path
import getopt import getopt
from struct import unpack from struct import unpack