mirror of
https://github.com/noDRM/DeDRM_tools.git
synced 2026-03-20 13:08:55 +00:00
Compare commits
8 Commits
7eb8f07a33
...
v10.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
077e8f5c2a | ||
|
|
fed8bb716b | ||
|
|
c12d214b59 | ||
|
|
012ff533ab | ||
|
|
dcbb377566 | ||
|
|
76ce6d9c5c | ||
|
|
726d72217e | ||
|
|
2d51005cf1 |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -35,7 +35,7 @@ List of changes since the fork of Apprentice Harper's repository:
|
||||
- Fix small issue with elibri watermark removal.
|
||||
- Adobe key name will now contain account email.
|
||||
|
||||
## Fixes on master (not yet released):
|
||||
## Fixes in v10.0.3 (2022-07-13):
|
||||
|
||||
- Fix issue where importing a key from Adobe Digital Editions would fail in Python2 (Calibre < 5) if there were non-ASCII characters in the username.
|
||||
- Add code to support importing multiple decryption keys from ADE.
|
||||
@@ -56,9 +56,17 @@ List of changes since the fork of Apprentice Harper's repository:
|
||||
- Drop support for importing key data from the ancient, pre "DeDRM" Calibre plugins ("Ignoble Epub DeDRM", "eReader PDB 2 PML" and "K4MobiDeDRM"). These are from 2011, I doubt anyone still has these installed, I can't even find a working link for these to test them. If you still have encryption keys in one of these plugins, you will need to update to DeDRM v10.0.2 or older (to convert the keys) before updating to DeDRM v10.0.3 or newer.
|
||||
- Some Python3 bugfixes for Amazon books (merged #10 by ableeker).
|
||||
- Fix a bug where extracting an Adobe key from ADE on Linux through Wine did fail when using the OpenSSL backend (instead of PyCrypto). See #13 and #14 for details, thanks acaloiaro for the bugfix.
|
||||
- Make the plugin work on Calibre 6 (Qt 6). If you're running the Calibre 6 beta and you notice any issues, please open a bug report.
|
||||
- Fix IndexError when DeDRMing some Amazon eBooks.
|
||||
- Add support for books with the new ADE3.0+ DRM by merging #48 by a980e066a01. Thanks a lot!
|
||||
- Add support for books with the new ADE3.0+ DRM by merging #48 by a980e066a01. Thanks a lot! (Also fixes #96 on MacOS)
|
||||
- Remove OpenSSL support, now the plugin will always use the Python crypto libraries.
|
||||
- Obok: Fix issues with invalid UTF-8 characters by merging #26 by baby-bell.
|
||||
- Try to fix PDF files with V3 key obfuscation algorithm.
|
||||
- ineptpdf: Fix broken V=3 key obfuscation algorithm.
|
||||
- ineptpdf: (Hopefully) fix issues with some B&N PDF files.
|
||||
- Fix broken Amazon K4PC key retrieval (fixes #38)
|
||||
- Fix bug that corrupts output file for Print-Replica Amazon books (fixes #30).
|
||||
- Fix Nook Study key retrieval code (partially fixes #50).
|
||||
- Make the plugin work on Calibre 6 (Qt 6). (fixes #54 and #98) If you're running Calibre 6 and you notice any issues, please open a bug report.
|
||||
|
||||
## Fixes on master (not yet released):
|
||||
|
||||
- (None)
|
||||
@@ -17,7 +17,7 @@ p {margin-top: 0}
|
||||
|
||||
<body>
|
||||
|
||||
<h1>DeDRM Plugin <span class="version">(v10.0.2)</span></h1>
|
||||
<h1>DeDRM Plugin <span class="version">(v10.0.3)</span></h1>
|
||||
|
||||
<p>This plugin removes DRM from ebooks when they are imported into calibre. If you already have DRMed ebooks in your calibre library, you will need to remove them and import them again.</p>
|
||||
|
||||
@@ -39,14 +39,14 @@ p {margin-top: 0}
|
||||
|
||||
<h3>Troubleshooting:</h3>
|
||||
|
||||
<p >If you find that it’s not working for you , you can save a lot of time by trying to add the ebook to Calibre in debug mode. This will print out a lot of helpful info that can be copied into any online help requests.</p>
|
||||
<p>If you find that it’s not working for you , you can save a lot of time by trying to add the ebook to Calibre in debug mode. This will print out a lot of helpful info that can be copied into any online help requests.</p>
|
||||
|
||||
<p>Open a command prompt (terminal window) and type "calibre-debug -g" (without the quotes). Calibre will launch, and you can can add the problem ebook the usual way. The debug info will be output to the original command prompt (terminal window). Copy the resulting output and paste it into the comment you make at my blog.</p>
|
||||
<p><span class="bold">Note:</span> The Mac version of Calibre doesn’t install the command line tools by default. If you go to the ‘Preferences’ page and click on the miscellaneous button, you’ll find the option to install the command line tools.</p>
|
||||
|
||||
<h3>Credits:</h3>
|
||||
<ul>
|
||||
<li>NoDRM for a bunch of updates and maintenance since November 2021, and the Readium LCP support</li>
|
||||
<li>NoDRM for a bunch of updates and maintenance since November 2021<s>, and the Readium LCP support</s></li>
|
||||
<li>The Dark Reverser for the Mobipocket and eReader scripts</li>
|
||||
<li>i♥cabbages for the Adobe Digital Editions scripts</li>
|
||||
<li>Skindle aka Bart Simpson for the Amazon Kindle for PC script</li>
|
||||
|
||||
@@ -959,30 +959,28 @@ class DeDRM(FileTypePlugin):
|
||||
traceback.print_exc()
|
||||
pass
|
||||
|
||||
newkeys = []
|
||||
newkeys = {}
|
||||
newnames = []
|
||||
|
||||
for i,keyvalue in enumerate(defaultkeys):
|
||||
try:
|
||||
keyname = "default_key_" + defaultnames[i]
|
||||
except:
|
||||
keyname = "default_key_{0:d}".format(i+1)
|
||||
|
||||
if keyvalue not in dedrmprefs['kindlekeys'].values():
|
||||
newkeys.append(keyvalue)
|
||||
newnames.append(keyname)
|
||||
newkeys["key_{0:d}".format(i)] = keyvalue
|
||||
|
||||
if len(newkeys) > 0:
|
||||
print("{0} v{1}: Found {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), "key" if len(newkeys)==1 else "keys"))
|
||||
try:
|
||||
book = k4mobidedrm.GetDecryptedBook(path_to_ebook,list(newkeys.items()),[],[],[],self.starttime)
|
||||
book = k4mobidedrm.GetDecryptedBook(path_to_ebook,newkeys.items(),[],[],[],self.starttime)
|
||||
decoded = True
|
||||
# store the new successful keys in the defaults
|
||||
print("{0} v{1}: Saving {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), "key" if len(newkeys)==1 else "keys"))
|
||||
for i,keyvalue in enumerate(newkeys):
|
||||
dedrmprefs.addnamedvaluetoprefs('kindlekeys',newnames[i],keyvalue)
|
||||
i = 1
|
||||
for keyvalue in newkeys.values():
|
||||
while "kindle_key_{0:d}_{1:d}".format(int(time.time()), i) in dedrmprefs['kindlekeys']:
|
||||
i = i + 1
|
||||
dedrmprefs.addnamedvaluetoprefs('kindlekeys',"kindle_key_{0:d}_{1:d}".format(int(time.time()), i),keyvalue)
|
||||
dedrmprefs.writeprefs()
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
pass
|
||||
if not decoded:
|
||||
#if you reached here then no luck raise and exception
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#@@CALIBRE_COMPAT_CODE@@
|
||||
|
||||
PLUGIN_NAME = "DeDRM"
|
||||
__version__ = '10.0.2'
|
||||
__version__ = '10.0.3'
|
||||
|
||||
PLUGIN_VERSION_TUPLE = tuple([int(x) for x in __version__.split(".")])
|
||||
PLUGIN_VERSION = ".".join([str(x)for x in PLUGIN_VERSION_TUPLE])
|
||||
|
||||
@@ -6,7 +6,7 @@ __license__ = 'GPL v3'
|
||||
# Python 3, September 2020
|
||||
|
||||
# Standard Python modules.
|
||||
import sys, os, traceback, json, codecs, base64
|
||||
import sys, os, traceback, json, codecs, base64, time
|
||||
|
||||
from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
|
||||
QGroupBox, QPushButton, QListWidget, QListWidgetItem, QCheckBox,
|
||||
@@ -1237,7 +1237,7 @@ class AddKindleDialog(QDialog):
|
||||
from wineutils import WineGetKeys
|
||||
|
||||
scriptpath = os.path.join(parent.parent.alfdir,"kindlekey.py")
|
||||
defaultkeys = WineGetKeys(scriptpath, ".k4i",parent.getwineprefix())
|
||||
defaultkeys, defaultnames = WineGetKeys(scriptpath, ".k4i",parent.getwineprefix())
|
||||
|
||||
self.default_key = defaultkeys[0]
|
||||
except:
|
||||
@@ -1255,7 +1255,7 @@ class AddKindleDialog(QDialog):
|
||||
key_group = QHBoxLayout()
|
||||
data_group_box_layout.addLayout(key_group)
|
||||
key_group.addWidget(QLabel("Unique Key Name:", self))
|
||||
self.key_ledit = QLineEdit("default_key", self)
|
||||
self.key_ledit = QLineEdit("default_key_" + str(int(time.time())), self)
|
||||
self.key_ledit.setToolTip("<p>Enter an identifying name for the current default Kindle for Mac/PC key.")
|
||||
key_group.addWidget(self.key_ledit)
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ def getNookLogFiles():
|
||||
logpath = path +'\\Barnes & Noble\\NOOKstudy\\logs\\BNClientLog.txt'
|
||||
if os.path.isfile(logpath):
|
||||
found = True
|
||||
print('Found nookStudy log file: ' + logpath.encode('ascii','ignore'), file=sys.stderr)
|
||||
print('Found nookStudy log file: ' + logpath, file=sys.stderr)
|
||||
logFiles.append(logpath)
|
||||
else:
|
||||
home = os.getenv('HOME')
|
||||
|
||||
@@ -50,13 +50,14 @@
|
||||
# 9.1.0 - Support for decrypting with owner password, support for V=5, R=5 and R=6 PDF files, support for AES256-encrypted PDFs.
|
||||
# 9.1.1 - Only support PyCryptodome; clean up the code
|
||||
# 10.0.0 - Add support for "hardened" Adobe DRM (RMSDK >= 10)
|
||||
# 10.0.2 - Fix some Python2 stuff
|
||||
|
||||
"""
|
||||
Decrypts Adobe ADEPT-encrypted PDF files.
|
||||
"""
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__version__ = "10.0.0"
|
||||
__version__ = "10.0.2"
|
||||
|
||||
import codecs
|
||||
import hashlib
|
||||
@@ -65,6 +66,8 @@ import os
|
||||
import re
|
||||
import zlib
|
||||
import struct
|
||||
import binascii
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from decimal import Decimal
|
||||
import itertools
|
||||
@@ -1369,7 +1372,7 @@ class PDFDocument(object):
|
||||
return file_key
|
||||
|
||||
|
||||
def process_with_aes(self, key: bytes, encrypt: bool, data: bytes, repetitions: int = 1, iv: bytes = None):
|
||||
def process_with_aes(self, key, encrypt, data, repetitions = 1, iv = None):
|
||||
if iv is None:
|
||||
keylen = len(key)
|
||||
iv = bytes([0x00]*keylen)
|
||||
@@ -1601,19 +1604,17 @@ class PDFDocument(object):
|
||||
|
||||
def initialize_ebx_ignoble(self, keyb64, docid, param):
|
||||
self.is_printable = self.is_modifiable = self.is_extractable = True
|
||||
try:
|
||||
key = keyb64.decode('base64')[:16]
|
||||
# This will probably always error, but I'm not 100% sure, so lets leave the old code in.
|
||||
except AttributeError:
|
||||
key = codecs.decode(keyb64.encode("ascii"), 'base64')[:16]
|
||||
key = keyb64.decode('base64')[:16]
|
||||
|
||||
length = int_value(param.get('Length', 0)) / 8
|
||||
rights = str_value(param.get('ADEPT_LICENSE')).decode('base64')
|
||||
rights = codecs.decode(str_value(param.get('ADEPT_LICENSE')), "base64")
|
||||
rights = zlib.decompress(rights, -15)
|
||||
rights = etree.fromstring(rights)
|
||||
expr = './/{http://ns.adobe.com/adept}encryptedKey'
|
||||
bookkey = ''.join(rights.findtext(expr)).decode('base64')
|
||||
bookkey = unpad(AES.new(key, AES.MODE_CBC, b'\x00'*16).decrypt(bookkey), 16) # PKCS#7
|
||||
bookkey = ''.join(rights.findtext(expr))
|
||||
bookkey = base64.b64decode(bookkey)
|
||||
bookkey = AES.new(key, AES.MODE_CBC, b'\x00'*16).decrypt(bookkey)
|
||||
bookkey = unpad(bookkey, 16) # PKCS#7
|
||||
if len(bookkey) > 16:
|
||||
bookkey = bookkey[-16:]
|
||||
ebx_V = int_value(param.get('V', 4))
|
||||
|
||||
@@ -275,7 +275,7 @@ def decryptBook(infile, outdir, kDatabaseFiles, androidFiles, serials, pids):
|
||||
orig_fn_root = os.path.splitext(os.path.basename(infile))[0]
|
||||
if (
|
||||
re.match('^B[A-Z0-9]{9}(_EBOK|_EBSP|_sample)?$', orig_fn_root) or
|
||||
re.match('^{0-9A-F-}{36}$', orig_fn_root)
|
||||
re.match('^[0-9A-F-]{36}$', orig_fn_root)
|
||||
): # Kindle for PC / Mac / Android / Fire / iOS
|
||||
clean_title = cleanup_name(book.getBookTitle())
|
||||
outfilename = "{}_{}".format(orig_fn_root, clean_title)
|
||||
|
||||
@@ -453,7 +453,7 @@ class MobiBook:
|
||||
if crypto_type == 0:
|
||||
print("This book is not encrypted.")
|
||||
# we must still check for Print Replica
|
||||
self.print_replica = (self.loadSection(1)[0:4] == '%MOP')
|
||||
self.print_replica = (self.loadSection(1)[0:4] == b'%MOP')
|
||||
self.mobi_data = self.data_file
|
||||
return
|
||||
if crypto_type != 2 and crypto_type != 1:
|
||||
@@ -524,7 +524,7 @@ class MobiBook:
|
||||
# print "record %d, extra_size %d" %(i,extra_size)
|
||||
decoded_data = PC1(found_key, data[0:len(data) - extra_size])
|
||||
if i==1:
|
||||
self.print_replica = (decoded_data[0:4] == '%MOP')
|
||||
self.print_replica = (decoded_data[0:4] == b'%MOP')
|
||||
mobidataList.append(decoded_data)
|
||||
if extra_size > 0:
|
||||
mobidataList.append(data[-extra_size:])
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#@@CALIBRE_COMPAT_CODE@@
|
||||
|
||||
from ignoblekeyGenPassHash import generate_key
|
||||
import sys
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
|
||||
@@ -21,8 +22,13 @@ DETAILED_MESSAGE = \
|
||||
|
||||
def uStrCmp (s1, s2, caseless=False):
|
||||
import unicodedata as ud
|
||||
str1 = s1 if isinstance(s1, str) else str(s1)
|
||||
str2 = s2 if isinstance(s2, str) else str(s2)
|
||||
if sys.version_info[0] == 2:
|
||||
str1 = s1 if isinstance(s1, unicode) else unicode(s1)
|
||||
str2 = s2 if isinstance(s2, unicode) else unicode(s2)
|
||||
else:
|
||||
str1 = s1 if isinstance(s1, str) else str(s1)
|
||||
str2 = s2 if isinstance(s2, str) else str(s2)
|
||||
|
||||
if caseless:
|
||||
return ud.normalize('NFC', str1.lower()) == ud.normalize('NFC', str2.lower())
|
||||
else:
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__version__ = '10.0.0'
|
||||
__version__ = '10.0.3'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
#####################################################################
|
||||
@@ -20,7 +20,7 @@ except NameError:
|
||||
PLUGIN_NAME = 'Obok DeDRM'
|
||||
PLUGIN_SAFE_NAME = PLUGIN_NAME.strip().lower().replace(' ', '_')
|
||||
PLUGIN_DESCRIPTION = _('Removes DRM from Kobo kepubs and adds them to the library.')
|
||||
PLUGIN_VERSION_TUPLE = (10, 0, 0)
|
||||
PLUGIN_VERSION_TUPLE = (10, 0, 3)
|
||||
PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE])
|
||||
HELPFILE_NAME = PLUGIN_SAFE_NAME + '_Help.htm'
|
||||
PLUGIN_AUTHORS = 'Anon'
|
||||
|
||||
@@ -62,7 +62,7 @@ class ConfigWidget(QWidget):
|
||||
|
||||
|
||||
def edit_kobo_directory(self):
|
||||
tmpkobodirectory = QFileDialog.getExistingDirectory(self, "Select Kobo directory", self.kobodirectory or "/home", QFileDialog.ShowDirsOnly)
|
||||
tmpkobodirectory = QFileDialog.getExistingDirectory(self, "Select Kobo directory", self.kobodirectory or "/home", QFileDialog.Option.ShowDirsOnly)
|
||||
|
||||
if tmpkobodirectory != u"" and tmpkobodirectory is not None:
|
||||
self.kobodirectory = tmpkobodirectory
|
||||
|
||||
@@ -409,7 +409,7 @@ class ReadOnlyTableWidgetItem(QTableWidgetItem):
|
||||
def __init__(self, text):
|
||||
if text is None:
|
||||
text = ''
|
||||
QTableWidgetItem.__init__(self, text, QTableWidgetItem.UserType)
|
||||
QTableWidgetItem.__init__(self, text, QTableWidgetItem.ItemType.UserType)
|
||||
self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
|
||||
|
||||
class AuthorTableWidgetItem(ReadOnlyTableWidgetItem):
|
||||
@@ -448,7 +448,7 @@ class IconWidgetItem(ReadOnlyTableWidgetItem):
|
||||
class NumericTableWidgetItem(QTableWidgetItem):
|
||||
|
||||
def __init__(self, number, is_read_only=False):
|
||||
QTableWidgetItem.__init__(self, '', QTableWidgetItem.UserType)
|
||||
QTableWidgetItem.__init__(self, '', QTableWidgetItem.ItemType.UserType)
|
||||
self.setData(Qt.DisplayRole, number)
|
||||
if is_read_only:
|
||||
self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Version 10.0.3 July 2022
|
||||
# Fix Calibre 6
|
||||
#
|
||||
# Version 10.0.1 February 2022
|
||||
# Remove OpenSSL support to only support PyCryptodome; clean up the code.
|
||||
#
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<body>
|
||||
|
||||
<h1>Obok DeDRM Plugin</h1>
|
||||
<h3>(version 10.0.0)</h3>
|
||||
<h3>(version 10.0.2)</h3>
|
||||
|
||||
<h3>Installation:</h3>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user