Compare commits

...

83 Commits

Author SHA1 Message Date
Apprentice Harper
2bb73584f2 merge of translations 2020-02-17 12:07:35 +00:00
Apprentice Harper
8495ebe36d Merge branch 'master' of https://github.com/apprenticeharper/DeDRM_tools 2020-02-17 12:06:23 +00:00
Apprentice Harper
92bf51bc8f Remove stand-alone apps. Only support the two plugins. 2020-02-16 10:12:25 +00:00
Apprentice Harper
e15ff385ca Merge pull request #989 from jony0008/master
New translation for obok plug-in: Swedish
2020-02-06 12:01:44 +00:00
Apprentice Harper
d48f4b86cf Merge pull request #988 from ZolaLa9/Update-FAQs-for-Kindle-for-Mac-and-Catalina
Update FAQs.md for K4Mac and Catalina
2020-02-06 11:59:15 +00:00
Jony
2ef5c59ebe New translation: Swedish
I have finished the Swedish translation. Please merge it.
2020-02-02 09:20:52 +01:00
ZolaLa
d2995539f0 Update FAQs.md 2020-02-01 05:22:56 +00:00
Apprentice Harper
ef3c7f261c Merge pull request #859 from HansChua/linux_handling
Allow users to specify Kobo directory and add 'ip' command for linux
2020-01-30 12:08:45 +00:00
Apprentice Harper
778ce4782e Merge branch 'master' into linux_handling 2020-01-30 12:06:38 +00:00
Apprentice Harper
69ac9b7399 Merge pull request #848 from sretlawd/kfx_dsn_fix
Allow decryption with DSN only.
2020-01-30 12:04:00 +00:00
Apprentice Harper
423dec0309 Merge pull request #847 from aplaice/linux_documentation
Improve documentation for using Kindle for PC with Linux in Wine
2020-01-30 12:03:08 +00:00
Apprentice Harper
582479c1f4 Merge pull request #845 from aplaice/fix_default_winepath
Fix automatic import of decryption keys on Linux with wine
2020-01-30 12:02:15 +00:00
Apprentice Harper
c1ece2f288 Merge pull request #850 from cclauss/modernize-Python-2-codes
Use print() function in both Python 2 and Python 3
2020-01-30 12:00:02 +00:00
Apprentice Harper
f5dd758b1b Merge branch 'master' into modernize-Python-2-codes 2020-01-30 11:58:50 +00:00
Apprentice Harper
a107742191 Merge pull request #983 from cclauss/patch-1
GitHub Action: There is no requirements.txt
2020-01-30 11:57:21 +00:00
Christian Clauss
ce8538a2ca Remove the unused rename_key() method 2020-01-23 13:24:45 +01:00
Apprentice Harper
2cf5960511 Merge pull request #863 from taroxd/patch-2
Fix typos - thanks.
2020-01-23 12:11:24 +00:00
Apprentice Harper
ef687eb057 Merge pull request #895 from adrw/patch-1
Update link - thanks.
2020-01-23 12:10:34 +00:00
Apprentice Harper
7d5352fdf3 Merge pull request #910 from corysolovewicz/patch-2
Update FAQs.md
2020-01-23 12:09:31 +00:00
Apprentice Harper
795f413ecb Allow Kindle serial numbers to have spaces, allowing copy/paste from Amazon web site (thanks to jakemarsden) 2020-01-23 12:14:19 +00:00
Christian Clauss
b35f777580 Focus only on legacy Python for now 2020-01-20 15:23:19 +01:00
Christian Clauss
0895aeb323 Undefined name: from ignoblekeygen import generate_key 2020-01-20 15:17:06 +01:00
Christian Clauss
eddbefcf91 Undefined name: strip(uuidnum) --> uuidnum.strip() 2020-01-20 15:11:14 +01:00
Christian Clauss
0955713cd6 Undefined name: errlog = '' 2020-01-20 14:58:03 +01:00
Christian Clauss
4e26b9d4e7 Undefined name: errlog = '' 2020-01-20 14:55:42 +01:00
Christian Clauss
8c08c67aa8 Undefined name: import zipfix 2020-01-20 14:47:04 +01:00
Christian Clauss
90335bb925 Undefined name: Define RegError 2020-01-20 14:41:29 +01:00
Christian Clauss
a10d9a617f Undefined name: Error() --> ValueError() 2020-01-20 14:34:56 +01:00
Christian Clauss
7edebeef0d import erdr2pml, ineptpdf, k4mobidedrm 2020-01-20 14:33:16 +01:00
Christian Clauss
e35b37c4f4 Undefined name: from .convert2xml import encodeNumber 2020-01-20 14:29:03 +01:00
Christian Clauss
1fd972ee17 Identity is not the same thing as equality in Python 2020-01-20 13:54:20 +01:00
Christian Clauss
616548a9a8 Undefined name: import traceback for line 70 2020-01-20 13:52:54 +01:00
Christian Clauss
e4c1a09d45 Undefined name: import traceback 2020-01-20 13:49:02 +01:00
Christian Clauss
89cf29cb78 flake8 . --builtins=_,I 2020-01-20 13:46:20 +01:00
Christian Clauss
c74f4b20d3 Undefined name: from datetime import datetime 2020-01-20 13:45:36 +01:00
Christian Clauss
ae703e523c flake8 . --builtins=_ 2020-01-20 13:41:14 +01:00
Christian Clauss
48dac14218 builtins=_ 2020-01-20 13:39:27 +01:00
Christian Clauss
798a7f9c8e GitHub Action: There is no requirements.txt 2020-01-20 13:35:10 +01:00
Apprentice Harper
43f80b767a Merge pull request #957 from cclauss/patch-1
GitHub Actions: Lint and test our Python code
2020-01-20 12:32:28 +00:00
Apprentice Harper
e07bb6523b Merge pull request #965 from jakemarsden/patch-1
Fix very minor typo in contrib README
2020-01-20 12:28:26 +00:00
Apprentice Harper
5d8dc595ce Merge pull request #971 from cgaspar/master
Update lzma import to include calibre >= 4.6.0
2020-01-19 14:48:20 +00:00
Carson Gaspar
fc6f830088 Update lzma import to include calibre >= 4.6.0 2020-01-04 05:20:16 -08:00
Jake Marsden
ff51ee8227 Fix very minor typo in contrib README 2019-12-29 23:30:29 +13:00
Christian Clauss
952b7fa7c0 GitHub Actions: Lint and test our Python code 2019-12-17 08:51:25 +01:00
Cory Solovewicz
0e9e3cf7ca Update FAQs.md
Update formatting: Wrap all filenames, file paths, and terminal commands in code quotes and cleaned up the file hashes by putting them in an unordered ist.
2019-10-05 12:03:59 -07:00
Andrew (Paradi) Alexander
57702b7d17 Update link 2019-09-05 12:04:40 -04:00
taroxd
666af55404 Update DeDRM_plugin_ReadMe.txt 2019-07-15 20:27:00 +08:00
taroxd
60f1865b53 Fix typo 2019-07-15 20:19:40 +08:00
snah
488cc540cd Allow users to specify Kobo directory and add 'ip' command for linux 2019-07-06 11:01:28 +08:00
cclauss
5bb6b58bc1 Use print() function in both Python 2 and Python 3
Legacy __print__ statements are syntax errors in Python 3 but __print()__ function works as expected in both Python 2 and Python 3.
2019-06-24 18:49:38 +02:00
Dan Walters
3f591ce66f Allow decryption with DSN only. 2019-06-14 14:20:56 -05:00
Adam Plaice
8bd53cd998 Improve documentation for using Kindle for PC with Linux in Wine
I've tested this on Ubuntu 18.04, with wine installed from the default
package repos (no PPAs) with Kindle for PC version 1.17.
2019-06-12 22:36:14 +02:00
Adam Plaice
4bd89fa4aa Fix automatic import of decryption keys on Linux with wine
By default, the wineprefix passed to WineGetKeys is "". Unfortunately,

    os.path.abspath(os.path.expanduser(os.path.expandvars("")))

returns the path to the working directory, which depends on the
directory from which calibre was invoked.  Hence under current
behaviour the wineprefix becomes that path, no longer being the empty
string.  This means that the `cmdline` that's run is always
`WINEPREFIX=/some/path/ wine python.exe [...]`, rather than `wine
python.exe [...]` even under default conditions, when the wineprefix
hasn't been changed.  Unless the user is improbably lucky and invokes
calibre from ~/.wine/ (the default wineprefix), this causes automatic
retrieval of the keys to always fail.

The bug was introduced in f2190a6755.

Checking for "" allows for correct behaviour in the default case,
while keeping the nice behaviour of expanding `~`.
2019-06-12 21:13:25 +02:00
Apprentice Harper
b71ed3887e Update README.md
added three very FAQs
2019-05-18 18:42:56 +01:00
Apprentice Harper
d152586edc Update FAQs.md 2019-04-22 15:03:09 +01:00
Apprentice Harper
aca8043174 Update FAQs.md
better pycrypto install instructions for Mac
2019-04-22 15:01:43 +01:00
Apprentice Harper
8165ad3ebb Fix silly version number error 2019-03-30 16:13:05 +00:00
Apprentice Harper
3d0aa17b2e Version to 6.6.3 with update for kindle book name cleanup and .kinf2018 support (initial) 2019-03-30 15:02:40 +00:00
Apprentice Harper
b17b913839 Update FAQs.md
confirmed that it's Kindle for Mac and PC 1.25 that's incompatible at present.
2019-02-23 16:45:16 +00:00
Apprentice Harper
d73cd15090 Update for Mac application - 64 bit and no splash screen 2019-02-23 16:13:22 +00:00
Apprentice Harper
e4f44604d7 Merge branch 'master' of https://github.com/apprenticeharper/DeDRM_tools 2019-01-19 15:43:46 +00:00
Apprentice Harper
6ab4f633f1 Merge branch 'master' of https://github.com/apprenticeharper/DeDRM_tools 2019-01-19 15:36:09 +00:00
Apprentice Harper
feae07c502 Update FAQs.md
better version info for Kindle for Mac and KIndle for PC
2019-01-19 15:30:06 +00:00
Apprentice Harper
c8aaabcbca Merge pull request #613 from jonahweissman/cli-instructions
Create Calibre CLI instructions
2019-01-19 15:17:06 +00:00
Apprentice Harper
588d06e846 Merge pull request #685 from mvastola/master
Fix "UnicodeEncodeError" in k4mobidedrm.py with titles containing UTF-8 chars
2019-01-19 15:16:07 +00:00
Apprentice Harper
ca4bab45ec 64-bit Macintosh Application, executable bit set on droplet, Updated release script, Version set to 6.6.2 2018-12-02 12:37:52 +00:00
Apprentice Harper
3f21bd9f5a Move to new positions 2018-12-02 11:37:07 +00:00
Mike Vastola
454286b08b Small fix to bug in K4/Mobi DeDRM with unicode filenames.
Fixes #658
2018-11-14 18:01:25 -05:00
Jonah Weissman
63c8b28efd Clarify CLI instructions are for Calibre plugin 2018-10-13 14:34:47 -04:00
Apprentice Harper
9b001bfaf3 Merge pull request #421 from drzraf/patch-1
obok.py: support fetching mac address on linux
2018-10-13 18:58:46 +01:00
Apprentice Harper
a76adf0ee1 Merge pull request #641 from adericbourg/patch-1
Fix typo
2018-10-13 18:48:54 +01:00
Apprentice Harper
49b064efa4 Merge pull request #623 from shhivam/master
Drastically simplified and corrected primes() in src/kindlekey.py
2018-10-13 18:44:23 +01:00
Apprentice Harper
8f23bf2b30 Merge pull request #546 from felixonmars/patch-1
Fix some typos in ReadMe_First.txt
2018-10-13 18:41:20 +01:00
Alban Dericbourg
1a38cdaf21 Fix typo
s/ooo/oo
2018-09-25 21:42:30 +02:00
shhivam
c20089676d shifted the comment to docstring 2018-09-08 23:33:54 +05:30
shhivam
f688bee0aa optimised and corrected primes func drastically 2018-09-08 23:30:00 +05:30
Jonah Weissman
114c4988c0 Create CLI instructions 2018-08-29 15:01:13 -04:00
Apprentice Harper
0b206e3fc5 Update FAQs.md 2018-08-29 08:07:02 +01:00
Apprentice Harper
ed306a8488 Update FAQs.md 2018-08-29 08:03:47 +01:00
Felix Yan
34b533363a Fix some typos in ReadMe_First.txt 2018-06-15 00:38:30 +08:00
Apprentice Harper
b1d13f2b23 Update FAQs.md
Updated KFX info
2018-06-02 17:07:35 +01:00
Apprentice Harper
613450f84d Update README.md 2018-06-02 17:00:10 +01:00
Raphaël Droz
20d445acb7 support fetching mac address on linux
support fetching mac address on linux
2018-01-01 14:46:03 -03:00
118 changed files with 1108 additions and 1893 deletions

17
.gitattributes vendored
View File

@@ -1,17 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

35
.github/workflows/Python_tests.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Python_tests
on: [push, pull_request]
jobs:
Python_tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest]
python-version: [2.7] # , 3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest # -r requirements.txt
#- name: Check formatting with black
# if: matrix.python-version == '3.8'
# run: |
# pip install black
# black --check .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --builtins=_,I --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --builtins=_,I --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
#- name: Test with pytest
# run: pytest
#- name: Run doctests with pytest
# run: pytest --doctest-modules

96
.gitignore vendored
View File

@@ -1,96 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.pyc
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk

View File

@@ -0,0 +1,47 @@
# Using the DeDRM plugin with the Calibre command line interface
If you prefer the Calibre CLI instead of the GUI, follow this guide to
install and use the DeDRM plugin.
This guide assumes you are on Linux, but it may very well work on other
platforms.
## Step-by-step Tutorial
#### Install Calibre
- Follow [Calibre's installation instructions](https://calibre-ebook.com/download_linux)
#### Install plugins
- Download the DeDRM `.zip` archive from DeDRM_tools'
[latest release](https://github.com/apprenticeharper/DeDRM_tools/releases/latest).
Then unzip it.
- Add the DeDRM plugin to Calibre:
```
cd *the unzipped DeDRM_tools folder*
calibre-customize --add DeDRM_calibre_plugin/DeDRM_plugin.zip
```
- Add the Obok plugin:
```
calibre-customize --add Obok_calibre_plugin/obok_plugin.zip
```
#### Enter your keys
- Figure out what format DeDRM wants your key in by looking in
[the code that handles that](dedrm_src/prefs.py).
- For Kindle eInk devices, DeDRM expects you to put a list of serial
numbers in the `serials` field: `"serials": ["012345689abcdef"]` or
`"serials": ["1111111111111111", "2222222222222222"]`.
- Now add your keys to `$CALIBRE_CONFIG_DIRECTORY/plugins/dedrm.json`.
#### Import your books
- Make a library folder
```
mkdir library
```
- Add your book(s) with this command:
```
calibredb add /path/to/book.format --with-library=library
```
The DRM should be removed from your book, which you can find in the `library`
folder.

View File

@@ -17,12 +17,12 @@ p {margin-top: 0}
<body>
<h1>DeDRM Plugin <span class="version">(v6.3.0)</span></h1>
<h1>DeDRM Plugin <span class="version">(v6.7.0)</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>
<h3>Installation</h3>
<p>You have obviously managed to install the plugin, as otherwise you wouldnt be reading this help file. However, you should also delete any older DeDRM plugins, as this DeDRM plugin replaces the five older plugins: Kindle and Mobipocket DeDRM (K4MobiDeDRM), Ignoble Epub DeDRM (ignobleepub), Inept Epub DeDRM (ineptepub), Inept PDF DeDRM (ineptepub) and eReader PDB 2 PML (eReaderPDB2PML).</p>
<p>You have obviously managed to install the plugin, as otherwise you wouldnt be reading this help file. However, you should also delete any older DRM removal plugins, as this DeDRM plugin replaces the five older plugins: Kindle and Mobipocket DeDRM (K4MobiDeDRM), Ignoble Epub DeDRM (ignobleepub), Inept Epub DeDRM (ineptepub), Inept PDF DeDRM (ineptepub) and eReader PDB 2 PML (eReaderPDB2PML).</p>
<h3>Configuration</h3>
<p>On Windows and Mac, the keys for ebooks downloaded for Kindle for Mac/PC and Adobe Digital Editions are automatically generated. If all your DRMed ebooks can be opened and read in Kindle for Mac/PC and/or Adobe Digital Editions on the same computer on which you are running calibre, you do not need to do any configuration of this plugin. On Linux, keys for Kindle for PC and Adobe Digital Editions need to be generated separately (see the Linux section below)</p>

View File

@@ -4,9 +4,10 @@
from __future__ import with_statement
# __init__.py for DeDRM_plugin
# Copyright © 2008-2018 Apprentice Harper et al.
# Copyright © 2008-2019 Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '6.7.0'
__docformat__ = 'restructuredtext en'
@@ -66,6 +67,9 @@ __docformat__ = 'restructuredtext en'
# 6.6.0 - Add kfx and kfx-zip as supported file types (also invoke this plugin if the original
# imported format was azw8 since that may be converted to kfx)
# 6.6.1 - Thanks to wzyboy for a fix for stand-alone tools, and the new folder structure.
# 6.6.2 - revamp of folders to get Mac OS X app working. Updated to 64-bit app. Various fixes.
# 6.6.3 - More cleanup of kindle book names and start of support for .kinf2018
# 6.7.0 - Handle new library in calibre.
"""
@@ -73,7 +77,7 @@ Decrypt DRMed ebooks.
"""
PLUGIN_NAME = u"DeDRM"
PLUGIN_VERSION_TUPLE = (6, 6, 1)
PLUGIN_VERSION_TUPLE = (6, 7, 0)
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'

View File

@@ -52,6 +52,7 @@ from __future__ import with_statement
"""
Retrieve Adobe ADEPT user key.
"""
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = '6.0'
@@ -407,7 +408,7 @@ if iswindows:
keys.append(userkey)
if len(keys) == 0:
raise ADEPTError('Could not locate privateLicenseKey')
print u"Found {0:d} keys".format(len(keys))
print(u"Found {0:d} keys".format(len(keys)))
return keys
@@ -465,7 +466,7 @@ def getkey(outpath):
outfile = outpath
with file(outfile, 'wb') as keyfileout:
keyfileout.write(keys[0])
print u"Saved a key to {0}".format(outfile)
print(u"Saved a key to {0}".format(outfile))
else:
keycount = 0
for key in keys:
@@ -476,28 +477,28 @@ def getkey(outpath):
break
with file(outfile, 'wb') as keyfileout:
keyfileout.write(key)
print u"Saved a key to {0}".format(outfile)
print(u"Saved a key to {0}".format(outfile))
return True
return False
def usage(progname):
print u"Finds, decrypts and saves the default Adobe Adept encryption key(s)."
print u"Keys are saved to the current directory, or a specified output directory."
print u"If a file name is passed instead of a directory, only the first key is saved, in that file."
print u"Usage:"
print u" {0:s} [-h] [<outpath>]".format(progname)
print(u"Finds, decrypts and saves the default Adobe Adept encryption key(s).")
print(u"Keys are saved to the current directory, or a specified output directory.")
print(u"If a file name is passed instead of a directory, only the first key is saved, in that file.")
print(u"Usage:")
print(u" {0:s} [-h] [<outpath>]".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 © 2009-2013 i♥cabbages and Apprentice Alf".format(progname,__version__)
print(u"{0} v{1}\nCopyright © 2009-2013 i♥cabbages and 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])
print(u"Error in options or arguments: {0}".format(err.args[0]))
usage(progname)
sys.exit(2)
@@ -528,7 +529,7 @@ def cli_main():
outfile = outpath
with file(outfile, 'wb') as keyfileout:
keyfileout.write(keys[0])
print u"Saved a key to {0}".format(outfile)
print(u"Saved a key to {0}".format(outfile))
else:
keycount = 0
for key in keys:
@@ -539,9 +540,9 @@ def cli_main():
break
with file(outfile, 'wb') as keyfileout:
keyfileout.write(key)
print u"Saved a key to {0}".format(outfile)
print(u"Saved a key to {0}".format(outfile))
else:
print u"Could not retrieve Adobe Adept key."
print(u"Could not retrieve Adobe Adept key.")
return 0

View File

@@ -8,6 +8,7 @@
# pbkdf2.py Copyright © 2009 Daniel Holth <dholth@fastmail.fm>
# pbkdf2.py This code may be freely used and modified for any purpose.
from __future__ import print_function
import sys, os
import hmac
from struct import pack
@@ -158,7 +159,7 @@ def _load_libalfcrypto():
topazCryptoDecrypt(ctx, data, out, len(data))
return out.raw
print u"Using Library AlfCrypto DLL/DYLIB/SO"
print(u"Using Library AlfCrypto DLL/DYLIB/SO")
return (AES_CBC, Pukall_Cipher, Topaz_Cipher)
@@ -244,7 +245,7 @@ def _load_python_alfcrypto():
cleartext = self.aes.decrypt(iv + data)
return cleartext
print u"Using Library AlfCrypto Python"
print(u"Using Library AlfCrypto Python")
return (AES_CBC, Pukall_Cipher, Topaz_Cipher)

View File

@@ -21,6 +21,7 @@ from __future__ import with_statement
"""
Retrieve Kindle for Android Serial Number.
"""
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = '1.5'
@@ -228,7 +229,7 @@ def get_serials2(path=STORAGE2):
if len(userdata_utf8) > 0:
dsns.append(userdata_utf8)
except:
print "Error getting one of the device serial name keys"
print("Error getting one of the device serial name keys")
traceback.print_exc()
pass
dsns = list(set(dsns))
@@ -243,7 +244,7 @@ def get_serials2(path=STORAGE2):
if len(userdata_utf8) > 0:
tokens.append(userdata_utf8)
except:
print "Error getting one of the account token keys"
print("Error getting one of the account token keys")
traceback.print_exc()
pass
tokens = list(set(tokens))
@@ -321,13 +322,13 @@ def getkey(outfile, inpath):
def usage(progname):
print u"Decrypts the serial number(s) of Kindle For Android from Android backup or file"
print u"Get backup.ab file using adb backup com.amazon.kindle for Android 4.0+."
print u"Otherwise extract AmazonSecureStorage.xml from /data/data/com.amazon.kindle/shared_prefs/AmazonSecureStorage.xml"
print u"Or map_data_storage.db from /data/data/com.amazon.kindle/databases/map_data_storage.db"
print u""
print u"Usage:"
print u" {0:s} [-h] [-b <backup.ab>] [<outfile.k4a>]".format(progname)
print(u"Decrypts the serial number(s) of Kindle For Android from Android backup or file")
print(u"Get backup.ab file using adb backup com.amazon.kindle for Android 4.0+.")
print(u"Otherwise extract AmazonSecureStorage.xml from /data/data/com.amazon.kindle/shared_prefs/AmazonSecureStorage.xml")
print(u"Or map_data_storage.db from /data/data/com.amazon.kindle/databases/map_data_storage.db")
print(u"")
print(u"Usage:")
print(u" {0:s} [-h] [-b <backup.ab>] [<outfile.k4a>]".format(progname))
def cli_main():
@@ -335,13 +336,13 @@ def cli_main():
sys.stderr=SafeUnbuffered(sys.stderr)
argv=unicode_argv()
progname = os.path.basename(argv[0])
print u"{0} v{1}\nCopyright © 2010-2015 Thom, some_updates, Apprentice Alf and Apprentice Harper".format(progname,__version__)
print(u"{0} v{1}\nCopyright © 2010-2015 Thom, some_updates, Apprentice Alf and Apprentice Harper".format(progname,__version__))
try:
opts, args = getopt.getopt(argv[1:], "hb:")
except getopt.GetoptError, err:
usage(progname)
print u"\nError in options or arguments: {0}".format(err.args[0])
print(u"\nError in options or arguments: {0}".format(err.args[0]))
return 2
inpath = ""
@@ -373,13 +374,13 @@ def cli_main():
if not os.path.isfile(inpath):
usage(progname)
print u"\n{0:s} file not found".format(inpath)
print(u"\n{0:s} file not found".format(inpath))
return 2
if getkey(outfile, inpath):
print u"\nSaved Kindle for Android key to {0}".format(outfile)
print(u"\nSaved Kindle for Android key to {0}".format(outfile))
else:
print u"\nCould not retrieve Kindle for Android key."
print(u"\nCould not retrieve Kindle for Android key.")
return 0
@@ -390,7 +391,7 @@ def gui_main():
import tkMessageBox
import tkFileDialog
except:
print "Tkinter not installed"
print("Tkinter not installed")
return cli_main()
class DecryptionDialog(Tkinter.Frame):

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from __future__ import print_function
__license__ = 'GPL v3'
@@ -457,7 +458,7 @@ class ManageKeysDialog(QDialog):
class RenameKeyDialog(QDialog):
def __init__(self, parent=None,):
print repr(self), repr(parent)
print(repr(self), repr(parent))
QDialog.__init__(self, parent)
self.parent = parent
self.setWindowTitle("{0} {1}: Rename {0}".format(PLUGIN_NAME, PLUGIN_VERSION, parent.key_type_name))
@@ -879,7 +880,7 @@ class AddSerialDialog(QDialog):
@property
def key_value(self):
return unicode(self.key_ledit.text()).strip()
return unicode(self.key_ledit.text()).replace(' ', '')
def accept(self):
if len(self.key_name) == 0 or self.key_name.isspace():

View File

@@ -2,6 +2,7 @@
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.6
from __future__ import print_function
class Unbuffered:
def __init__(self, stream):
self.stream = stream
@@ -139,7 +140,7 @@ class Dictionary(object):
self.pos = val
return self.stable[self.pos]
else:
print "Error - %d outside of string table limits" % val
print("Error - %d outside of string table limits" % val)
raise TpzDRMError('outside of string table limits')
# sys.exit(-1)
@@ -151,7 +152,7 @@ class Dictionary(object):
def dumpDict(self):
for i in xrange(self.size):
print "%d %s %s" % (i, convert(i), self.stable[i])
print("%d %s %s" % (i, convert(i), self.stable[i]))
return
# parses the xml snippets that are represented by each page*.dat file.
@@ -457,7 +458,7 @@ class PageParser(object):
elif (argtype == 'snippets') :
result = arg
else :
print "Error Unknown argtype %s" % argtype
print("Error Unknown argtype %s" % argtype)
sys.exit(-2)
return result
@@ -469,7 +470,7 @@ class PageParser(object):
known_token = False
self.tag_push(token)
if self.debug : print 'Processing: ', self.get_tagpath(0)
if self.debug : print('Processing: ', self.get_tagpath(0))
cnt = self.tagpath_len()
for j in xrange(cnt):
tkn = self.get_tagpath(j)
@@ -495,7 +496,7 @@ class PageParser(object):
if (subtags == 1):
ntags = readEncodedNumber(self.fo)
if self.debug : print 'subtags: ' + token + ' has ' + str(ntags)
if self.debug : print('subtags: ' + token + ' has ' + str(ntags))
for j in xrange(ntags):
val = readEncodedNumber(self.fo)
subtagres.append(self.procToken(self.dict.lookup(val)))
@@ -529,7 +530,7 @@ class PageParser(object):
else:
result = []
if (self.debug or self.first_unknown):
print 'Unknown Token:', token
print('Unknown Token:', token)
self.first_unknown = False
self.tag_pop()
return result
@@ -544,9 +545,9 @@ class PageParser(object):
result = 'Set of '+ str(cnt) + ' xml snippets. The overall structure \n'
result += 'of the document is indicated by snippet number sets at the\n'
result += 'end of each snippet. \n'
print result
print(result)
for i in xrange(cnt):
if self.debug: print 'Snippet:',str(i)
if self.debug: print('Snippet:',str(i))
snippet = []
snippet.append(i)
val = readEncodedNumber(self.fo)
@@ -588,10 +589,10 @@ class PageParser(object):
cnt = readEncodedNumber(self.fo)
mode = readEncodedNumber(self.fo)
if self.debug : print 'Loop for', cnt, 'with mode', mode, ': '
if self.debug : print('Loop for', cnt, 'with mode', mode, ': ')
return self.doLoop76Mode(argtype, cnt, mode)
if self.dbug: print "Unknown command", cmd
if self.dbug: print("Unknown command", cmd)
result = []
return result
@@ -720,7 +721,7 @@ class PageParser(object):
else:
rlst.append(self.formatTag(j))
result = "".join(rlst)
if self.debug : print result
if self.debug : print(result)
return result
@@ -775,7 +776,7 @@ class PageParser(object):
self.doc.append(tag)
else:
if self.debug:
print "Main Loop: Unknown value: %x" % v
print("Main Loop: Unknown value: %x" % v)
if (v == 0):
if (self.peek(1) == 0x5f):
skip = self.fo.read(1)
@@ -783,11 +784,11 @@ class PageParser(object):
# now do snippet injection
if len(self.snippetList) > 0 :
if self.debug : print 'Injecting Snippets:'
if self.debug : print('Injecting Snippets:')
snippet = self.injectSnippets(self.snippetList[0])
snipno = snippet[0]
tag_add = snippet[1]
if self.debug : print self.formatTag(tag_add)
if self.debug : print(self.formatTag(tag_add))
if len(tag_add) > 0:
self.doc.append(tag_add)
@@ -812,19 +813,19 @@ def getXML(dict, fname):
return xmlpage
def usage():
print 'Usage: '
print ' convert2xml.py dict0000.dat infile.dat '
print ' '
print ' Options:'
print ' -h print this usage help message '
print ' -d turn on debug output to check for potential errors '
print ' --flat-xml output the flattened xml page description only '
print ' '
print ' This program will attempt to convert a page*.dat file or '
print ' glyphs*.dat file, using the dict0000.dat file, to its xml description. '
print ' '
print ' Use "cmbtc_dump.py" first to unencrypt, uncompress, and dump '
print ' the *.dat files from a Topaz format e-book.'
print('Usage: ')
print(' convert2xml.py dict0000.dat infile.dat ')
print(' ')
print(' Options:')
print(' -h print this usage help message ')
print(' -d turn on debug output to check for potential errors ')
print(' --flat-xml output the flattened xml page description only ')
print(' ')
print(' This program will attempt to convert a page*.dat file or ')
print(' glyphs*.dat file, using the dict0000.dat file, to its xml description. ')
print(' ')
print(' Use "cmbtc_dump.py" first to unencrypt, uncompress, and dump ')
print(' the *.dat files from a Topaz format e-book.')
#
# Main
@@ -846,7 +847,7 @@ def main(argv):
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
print(str(err)) # will print something like "option -a not recognized"
usage()
sys.exit(2)
@@ -875,7 +876,7 @@ def main(argv):
xmlpage = pp.process()
if printOutput:
print xmlpage
print(xmlpage)
return 0
return xmlpage

View File

@@ -15,6 +15,7 @@ Provide base64 encoding.
"""
from __future__ import with_statement
from __future__ import print_function
__license__ = 'GPL v3'
@@ -23,9 +24,9 @@ import os
import base64
def usage(progname):
print "Applies base64 encoding to the supplied file, sending to standard output"
print "Usage:"
print " %s <infile>" % progname
print("Applies base64 encoding to the supplied file, sending to standard output")
print("Usage:")
print(" %s <infile>" % progname)
def cli_main(argv=sys.argv):
progname = os.path.basename(argv[0])
@@ -37,7 +38,7 @@ def cli_main(argv=sys.argv):
keypath = argv[1]
with open(keypath, 'rb') as f:
keyder = f.read()
print keyder.encode('base64')
print(keyder.encode('base64'))
return 0

View File

@@ -45,10 +45,11 @@
#
from __future__ import with_statement
from __future__ import print_function
__version__ = '1.01'
import sys, struct, os
import sys, struct, os, traceback
import zlib
import zipfile
import xml.etree.ElementTree as etree
@@ -199,7 +200,7 @@ def encryption(infile):
def main():
argv=unicode_argv()
print encryption(argv[1])
print(encryption(argv[1]))
return 0
if __name__ == "__main__":

View File

@@ -2,6 +2,7 @@
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.6
from __future__ import print_function
import sys
import csv
import os
@@ -750,11 +751,11 @@ class DocParser(object):
hlst.append('<div class="graphic"><img src="img/img%04d.jpg" alt="" /></div>' % int(simgsrc))
else :
print ' Making region type', regtype,
print(' Making region type', regtype, end=' ')
(pos, temp) = self.findinDoc('paragraph',start,end)
(pos2, temp) = self.findinDoc('span',start,end)
if pos != -1 or pos2 != -1:
print ' a "text" region'
print(' a "text" region')
orig_regtype = regtype
regtype = 'fixed'
ptype = 'full'
@@ -779,7 +780,7 @@ class DocParser(object):
else :
hlst.append(self.buildParagraph(pclass, pdesc, ptype, regtype))
else :
print ' a "graphic" region'
print(' a "graphic" region')
(pos, simgsrc) = self.findinDoc('img.src',start,end)
if simgsrc:
hlst.append('<div class="graphic"><img src="img/img%04d.jpg" alt="" /></div>' % int(simgsrc))

View File

@@ -1,6 +1,9 @@
#! /usr/bin/python
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
from __future__ import print_function
from .convert2xml import encodeNumber
class Unbuffered:
def __init__(self, stream):
self.stream = stream
@@ -117,7 +120,7 @@ class Dictionary(object):
self.pos = val
return self.stable[self.pos]
else:
print "Error: %d outside of string table limits" % val
print("Error: %d outside of string table limits" % val)
raise TpzDRMError('outside or string table limits')
# sys.exit(-1)
def getSize(self):
@@ -268,32 +271,32 @@ class GlyphDict(object):
def generateBook(bookDir, raw, fixedimage):
# sanity check Topaz file extraction
if not os.path.exists(bookDir) :
print "Can not find directory with unencrypted book"
print("Can not find directory with unencrypted book")
return 1
dictFile = os.path.join(bookDir,'dict0000.dat')
if not os.path.exists(dictFile) :
print "Can not find dict0000.dat file"
print("Can not find dict0000.dat file")
return 1
pageDir = os.path.join(bookDir,'page')
if not os.path.exists(pageDir) :
print "Can not find page directory in unencrypted book"
print("Can not find page directory in unencrypted book")
return 1
imgDir = os.path.join(bookDir,'img')
if not os.path.exists(imgDir) :
print "Can not find image directory in unencrypted book"
print("Can not find image directory in unencrypted book")
return 1
glyphsDir = os.path.join(bookDir,'glyphs')
if not os.path.exists(glyphsDir) :
print "Can not find glyphs directory in unencrypted book"
print("Can not find glyphs directory in unencrypted book")
return 1
metaFile = os.path.join(bookDir,'metadata0000.dat')
if not os.path.exists(metaFile) :
print "Can not find metadata0000.dat in unencrypted book"
print("Can not find metadata0000.dat in unencrypted book")
return 1
svgDir = os.path.join(bookDir,'svg')
@@ -307,10 +310,10 @@ def generateBook(bookDir, raw, fixedimage):
otherFile = os.path.join(bookDir,'other0000.dat')
if not os.path.exists(otherFile) :
print "Can not find other0000.dat in unencrypted book"
print("Can not find other0000.dat in unencrypted book")
return 1
print "Updating to color images if available"
print("Updating to color images if available")
spath = os.path.join(bookDir,'color_img')
dpath = os.path.join(bookDir,'img')
filenames = os.listdir(spath)
@@ -322,7 +325,7 @@ def generateBook(bookDir, raw, fixedimage):
imgdata = file(sfile,'rb').read()
file(dfile,'wb').write(imgdata)
print "Creating cover.jpg"
print("Creating cover.jpg")
isCover = False
cpath = os.path.join(bookDir,'img')
cpath = os.path.join(cpath,'img0000.jpg')
@@ -333,10 +336,10 @@ def generateBook(bookDir, raw, fixedimage):
isCover = True
print 'Processing Dictionary'
print('Processing Dictionary')
dict = Dictionary(dictFile)
print 'Processing Meta Data and creating OPF'
print('Processing Meta Data and creating OPF')
meta_array = getMetaArray(metaFile)
# replace special chars in title and authors like & < >
@@ -360,7 +363,7 @@ def generateBook(bookDir, raw, fixedimage):
mlst = None
file(xname, 'wb').write(metastr)
print 'Processing StyleSheet'
print('Processing StyleSheet')
# get some scaling info from metadata to use while processing styles
# and first page info
@@ -426,7 +429,7 @@ def generateBook(bookDir, raw, fixedimage):
xname = os.path.join(xmlDir, 'other0000.xml')
file(xname, 'wb').write(convert2xml.getXML(dict, otherFile))
print 'Processing Glyphs'
print('Processing Glyphs')
gd = GlyphDict()
filenames = os.listdir(glyphsDir)
filenames = sorted(filenames)
@@ -440,7 +443,7 @@ def generateBook(bookDir, raw, fixedimage):
counter = 0
for filename in filenames:
# print ' ', filename
print '.',
print('.', end=' ')
fname = os.path.join(glyphsDir,filename)
flat_xml = convert2xml.fromData(dict, fname)
@@ -459,7 +462,7 @@ def generateBook(bookDir, raw, fixedimage):
glyfile.write('</defs>\n')
glyfile.write('</svg>\n')
glyfile.close()
print " "
print(" ")
# start up the html
@@ -481,7 +484,7 @@ def generateBook(bookDir, raw, fixedimage):
hlst.append('<link href="style.css" rel="stylesheet" type="text/css" />\n')
hlst.append('</head>\n<body>\n')
print 'Processing Pages'
print('Processing Pages')
# Books are at 1440 DPI. This is rendering at twice that size for
# readability when rendering to the screen.
scaledpi = 1440.0
@@ -495,7 +498,7 @@ def generateBook(bookDir, raw, fixedimage):
for filename in filenames:
# print ' ', filename
print ".",
print(".", end=' ')
fname = os.path.join(pageDir,filename)
flat_xml = convert2xml.fromData(dict, fname)
@@ -517,8 +520,8 @@ def generateBook(bookDir, raw, fixedimage):
hlst = None
file(os.path.join(bookDir, htmlFileName), 'wb').write(htmlstr)
print " "
print 'Extracting Table of Contents from Amazon OCR'
print(" ")
print('Extracting Table of Contents from Amazon OCR')
# first create a table of contents file for the svg images
tlst = []
@@ -550,7 +553,7 @@ def generateBook(bookDir, raw, fixedimage):
toclst = tocentries.split('\n')
toclst.pop()
for entry in toclst:
print entry
print(entry)
title, pagenum = entry.split('|')
id = pageidnums[int(pagenum)]
if (raw):
@@ -580,7 +583,7 @@ def generateBook(bookDir, raw, fixedimage):
slst.append('</head>\n')
slst.append('<body>\n')
print "Building svg images of each book page"
print("Building svg images of each book page")
slst.append('<h2>List of Pages</h2>\n')
slst.append('<div>\n')
idlst = sorted(pageIDMap.keys())
@@ -593,7 +596,7 @@ def generateBook(bookDir, raw, fixedimage):
nextid = idlst[j+1]
else:
nextid = None
print '.',
print('.', end=' ')
pagelst = pageIDMap[pageid]
flst = []
for page in pagelst:
@@ -618,7 +621,7 @@ def generateBook(bookDir, raw, fixedimage):
slst = None
file(os.path.join(bookDir, 'index_svg.xhtml'), 'wb').write(svgindex)
print " "
print(" ")
# build the opf file
opfname = os.path.join(bookDir, 'book.opf')
@@ -667,20 +670,20 @@ def generateBook(bookDir, raw, fixedimage):
olst = None
file(opfname, 'wb').write(opfstr)
print 'Processing Complete'
print('Processing Complete')
return 0
def usage():
print "genbook.py generates a book from the extract Topaz Files"
print "Usage:"
print " genbook.py [-r] [-h [--fixed-image] <bookDir> "
print " "
print "Options:"
print " -h : help - print this usage message"
print " -r : generate raw svg files (not wrapped in xhtml)"
print " --fixed-image : genearate any Fixed Area as an svg image in the html"
print " "
print("genbook.py generates a book from the extract Topaz Files")
print("Usage:")
print(" genbook.py [-r] [-h [--fixed-image] <bookDir> ")
print(" ")
print("Options:")
print(" -h : help - print this usage message")
print(" -r : generate raw svg files (not wrapped in xhtml)")
print(" --fixed-image : genearate any Fixed Area as an svg image in the html")
print(" ")
def main(argv):
@@ -692,7 +695,7 @@ def main(argv):
opts, args = getopt.getopt(argv[1:], "rh:",["fixed-image"])
except getopt.GetoptError, err:
print str(err)
print(str(err))
usage()
return 1

View File

@@ -41,6 +41,7 @@ from __future__ import with_statement
"""
Decrypt Barnes & Noble encrypted ePub books.
"""
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = "4.1"
@@ -262,7 +263,7 @@ def decryptBook(keyb64, inpath, outpath):
namelist = set(inf.namelist())
if 'META-INF/rights.xml' not in namelist or \
'META-INF/encryption.xml' not in namelist:
print u"{0:s} is DRM-free.".format(os.path.basename(inpath))
print(u"{0:s} is DRM-free.".format(os.path.basename(inpath)))
return 1
for name in META_NAMES:
namelist.remove(name)
@@ -272,7 +273,7 @@ def decryptBook(keyb64, inpath, outpath):
expr = './/%s' % (adept('encryptedKey'),)
bookkey = ''.join(rights.findtext(expr))
if len(bookkey) != 64:
print u"{0:s} is not a secure Barnes & Noble ePub.".format(os.path.basename(inpath))
print(u"{0:s} is not a secure Barnes & Noble ePub.".format(os.path.basename(inpath)))
return 1
bookkey = aes.decrypt(bookkey.decode('base64'))
bookkey = bookkey[:-ord(bookkey[-1])]
@@ -315,7 +316,7 @@ def decryptBook(keyb64, inpath, outpath):
pass
outf.writestr(zi, decryptor.decrypt(path, data))
except:
print u"Could not decrypt {0:s} because of an exception:\n{1:s}".format(os.path.basename(inpath), traceback.format_exc())
print(u"Could not decrypt {0:s} because of an exception:\n{1:s}".format(os.path.basename(inpath), traceback.format_exc()))
return 2
return 0
@@ -326,13 +327,13 @@ def cli_main():
argv=unicode_argv()
progname = os.path.basename(argv[0])
if len(argv) != 4:
print u"usage: {0} <keyfile.b64> <inbook.epub> <outbook.epub>".format(progname)
print(u"usage: {0} <keyfile.b64> <inbook.epub> <outbook.epub>".format(progname))
return 1
keypath, inpath, outpath = argv[1:]
userkey = open(keypath,'rb').read()
result = decryptBook(userkey, inpath, outpath)
if result == 0:
print u"Successfully decrypted {0:s} as {1:s}".format(os.path.basename(inpath),os.path.basename(outpath))
print(u"Successfully decrypted {0:s} as {1:s}".format(os.path.basename(inpath),os.path.basename(outpath)))
return result
def gui_main():

View File

@@ -18,6 +18,7 @@ from __future__ import with_statement
"""
Get Barnes & Noble EPUB user key from nook Studio log file
"""
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = "1.1"
@@ -198,7 +199,7 @@ def nookkeys(files = []):
for file in files:
fileKeys = getKeysFromLog(file)
if fileKeys:
print u"Found {0} keys in the Nook Study log files".format(len(fileKeys))
print(u"Found {0} keys in the Nook Study log files".format(len(fileKeys)))
keys.extend(fileKeys)
return list(set(keys))
@@ -211,7 +212,7 @@ def getkey(outpath, files=[]):
outfile = outpath
with file(outfile, 'w') as keyfileout:
keyfileout.write(keys[-1])
print u"Saved a key to {0}".format(outfile)
print(u"Saved a key to {0}".format(outfile))
else:
keycount = 0
for key in keys:
@@ -222,16 +223,16 @@ def getkey(outpath, files=[]):
break
with file(outfile, 'w') as keyfileout:
keyfileout.write(key)
print u"Saved a key to {0}".format(outfile)
print(u"Saved a key to {0}".format(outfile))
return True
return False
def usage(progname):
print u"Finds the nook Study encryption keys."
print u"Keys are saved to the current directory, or a specified output directory."
print u"If a file name is passed instead of a directory, only the first key is saved, in that file."
print u"Usage:"
print u" {0:s} [-h] [-k <logFile>] [<outpath>]".format(progname)
print(u"Finds the nook Study encryption keys.")
print(u"Keys are saved to the current directory, or a specified output directory.")
print(u"If a file name is passed instead of a directory, only the first key is saved, in that file.")
print(u"Usage:")
print(u" {0:s} [-h] [-k <logFile>] [<outpath>]".format(progname))
def cli_main():
@@ -239,12 +240,12 @@ def cli_main():
sys.stderr=SafeUnbuffered(sys.stderr)
argv=unicode_argv()
progname = os.path.basename(argv[0])
print u"{0} v{1}\nCopyright © 2015 Apprentice Alf".format(progname,__version__)
print(u"{0} v{1}\nCopyright © 2015 Apprentice Alf".format(progname,__version__))
try:
opts, args = getopt.getopt(argv[1:], "hk:")
except getopt.GetoptError, err:
print u"Error in options or arguments: {0}".format(err.args[0])
print(u"Error in options or arguments: {0}".format(err.args[0]))
usage(progname)
sys.exit(2)
@@ -273,7 +274,7 @@ def cli_main():
outpath = os.path.realpath(os.path.normpath(outpath))
if not getkey(outpath, files):
print u"Could not retrieve nook Study key."
print(u"Could not retrieve nook Study key.")
return 0
@@ -307,7 +308,7 @@ def gui_main():
keys = nookkeys()
keycount = 0
for key in keys:
print key
print(key)
while True:
keycount += 1
outfile = os.path.join(progpath,u"nookkey{0:d}.b64".format(keycount))

View File

@@ -28,6 +28,7 @@ from __future__ import with_statement
"""
Fetch Barnes & Noble EPUB user key from B&N servers using email and password
"""
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = "1.1"
@@ -155,14 +156,14 @@ def cli_main():
argv=unicode_argv()
progname = os.path.basename(argv[0])
if len(argv) != 4:
print u"usage: {0} <email> <password> <keyfileout.b64>".format(progname)
print(u"usage: {0} <email> <password> <keyfileout.b64>".format(progname))
return 1
email, password, keypath = argv[1:]
userkey = fetch_key(email, password)
if len(userkey) == 28:
open(keypath,'wb').write(userkey)
return 0
print u"Failed to fetch key."
print(u"Failed to fetch key.")
return 1

View File

@@ -38,6 +38,7 @@ from __future__ import with_statement
"""
Generate Barnes & Noble EPUB user key from name and credit card number.
"""
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = "2.8"
@@ -223,12 +224,12 @@ def cli_main():
argv=unicode_argv()
progname = os.path.basename(argv[0])
if AES is None:
print "%s: This script requires OpenSSL or PyCrypto, which must be installed " \
print("%s: This script requires OpenSSL or PyCrypto, which must be installed " \
"separately. Read the top-of-script comment for details." % \
(progname,)
(progname,))
return 1
if len(argv) != 4:
print u"usage: {0} <Name> <CC#> <keyfileout.b64>".format(progname)
print(u"usage: {0} <Name> <CC#> <keyfileout.b64>".format(progname))
return 1
name, ccn, keypath = argv[1:]
userkey = generate_key(name, ccn)

View File

@@ -21,19 +21,24 @@ from Crypto.Cipher import AES
from Crypto.Util.py3compat import bchr, bord
try:
# lzma library from calibre 2.35.0 or later
import lzma.lzma1 as calibre_lzma
# lzma library from calibre 4.6.0 or later
import calibre_lzma.lzma1 as calibre_lzma
except ImportError:
calibre_lzma = None
# lzma library from calibre 2.35.0 or later
try:
import lzma
import lzma.lzma1 as calibre_lzma
except ImportError:
# Need pip backports.lzma on Python <3.3
calibre_lzma = None
try:
from backports import lzma
import lzma
except ImportError:
# Windows-friendly choice: pylzma wheels
import pylzma as lzma
# Need pip backports.lzma on Python <3.3
try:
from backports import lzma
except ImportError:
# Windows-friendly choice: pylzma wheels
import pylzma as lzma
TID_NULL = 0

View File

@@ -4,10 +4,10 @@
from __future__ import with_statement
# k4mobidedrm.py
# Copyright © 2008-2017 by Apprentice Harper et al.
# Copyright © 2008-2019 by Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '5.5'
__version__ = '5.7'
# Engine to remove drm from Kindle and Mobipocket ebooks
# for personal use for archiving and converting your ebooks
@@ -60,7 +60,8 @@ __version__ = '5.5'
# 5.3 - Changed Android support to allow passing of backup .ab files
# 5.4 - Recognise KFX files masquerading as azw, even if we can't decrypt them yet.
# 5.5 - Added GPL v3 licence explicitly.
# 5.x - Invoke KFXZipBook to handle zipped KFX files
# 5.6 - Invoke KFXZipBook to handle zipped KFX files
# 5.7 - Revamp cleanup_name
import sys, os, re
import csv
@@ -155,19 +156,24 @@ def unicode_argv():
# added in removal of control (<32) chars
# and removal of . at start and end
# and with some (heavily edited) code from Paul Durrant's kindlenamer.py
# and some improvements suggested by jhaisley
def cleanup_name(name):
# substitute filename unfriendly characters
name = name.replace(u"<",u"[").replace(u">",u"]").replace(u" : ",u" ").replace(u": ",u" ").replace(u":",u"").replace(u"/",u"_").replace(u"\\",u"_").replace(u"|",u"_").replace(u"\"",u"\'").replace(u"*",u"_").replace(u"?",u"")
# delete control characters
name = u"".join(char for char in name if ord(char)>=32)
# white space to single space, delete leading and trailing while space
name = re.sub(ur"\s", u" ", name).strip()
# delete control characters
name = u"".join(char for char in name if ord(char)>=32)
# delete non-ascii characters
name = u"".join(char for char in name if ord(char)<=126)
# remove leading dots
while len(name)>0 and name[0] == u".":
name = name[1:]
# remove trailing dots (Windows doesn't like them)
if name.endswith(u'.'):
while name.endswith(u'.'):
name = name[:-1]
if len(name)==0:
name=u"DecryptedBook"
return name
# must be passed unicode
@@ -269,7 +275,7 @@ def decryptBook(infile, outdir, kDatabaseFiles, androidFiles, serials, pids):
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)
outfilename = u'{}_{}'.format(orig_fn_root, clean_title)
else: # E Ink Kindle, which already uses a reasonable name
outfilename = orig_fn_root

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from __future__ import print_function
# Engine to remove drm from Kindle KFX ebooks
@@ -43,7 +44,7 @@ class KFXZipBook:
data += fh.read()
if self.voucher is None:
self.decrypt_voucher(totalpids)
print u'Decrypting KFX DRMION: {0}'.format(filename)
print(u'Decrypting KFX DRMION: {0}'.format(filename))
outfile = StringIO()
ion.DrmIon(StringIO(data[8:-8]), lambda name: self.voucher).parse(outfile)
self.decrypted[filename] = outfile.getvalue()
@@ -65,10 +66,10 @@ class KFXZipBook:
else:
raise Exception(u'The .kfx-zip archive contains an encrypted DRMION file without a DRM voucher')
print u'Decrypting KFX DRM voucher: {0}'.format(info.filename)
print(u'Decrypting KFX DRM voucher: {0}'.format(info.filename))
for pid in [''] + totalpids:
for dsn_len,secret_len in [(0,0), (16,0), (16,40), (32,40), (40,40)]:
for dsn_len,secret_len in [(0,0), (16,0), (16,40), (32,40), (40,0), (40,40)]:
if len(pid) == dsn_len + secret_len:
break # split pid into DSN and account secret
else:
@@ -84,7 +85,7 @@ class KFXZipBook:
else:
raise Exception(u'Failed to decrypt KFX DRM voucher with any key')
print u'KFX DRM voucher successfully decrypted'
print(u'KFX DRM voucher successfully decrypted')
license_type = voucher.getlicensetype()
if license_type != "Purchase":

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from __future__ import print_function
# kgenpids.py
# Copyright © 2008-2017 Apprentice Harper et al.
@@ -214,7 +215,7 @@ def getK4Pids(rec209, token, kindleDatabase):
try:
# Get the DSN token, if present
DSN = (kindleDatabase[1])['DSN'].decode('hex')
print u"Got DSN key from database {0}".format(kindleDatabase[0])
print(u"Got DSN key from database {0}".format(kindleDatabase[0]))
except KeyError:
# See if we have the info to generate the DSN
try:
@@ -225,7 +226,7 @@ def getK4Pids(rec209, token, kindleDatabase):
try:
# Get the SerialNumber token, if present
IDString = (kindleDatabase[1])['SerialNumber'].decode('hex')
print u"Got SerialNumber from database {0}".format(kindleDatabase[0])
print(u"Got SerialNumber from database {0}".format(kindleDatabase[0]))
except KeyError:
# Get the IDString we added
IDString = (kindleDatabase[1])['IDString'].decode('hex')
@@ -233,7 +234,7 @@ def getK4Pids(rec209, token, kindleDatabase):
try:
# Get the UsernameHash token, if present
encodedUsername = (kindleDatabase[1])['UsernameHash'].decode('hex')
print u"Got UsernameHash from database {0}".format(kindleDatabase[0])
print(u"Got UsernameHash from database {0}".format(kindleDatabase[0]))
except KeyError:
# Get the UserName we added
UserName = (kindleDatabase[1])['UserName'].decode('hex')
@@ -241,7 +242,7 @@ def getK4Pids(rec209, token, kindleDatabase):
encodedUsername = encodeHash(UserName,charMap1)
#print u"encodedUsername",encodedUsername.encode('hex')
except KeyError:
print u"Keys not found in the database {0}.".format(kindleDatabase[0])
print(u"Keys not found in the database {0}.".format(kindleDatabase[0]))
return pids
# Get the ID string used
@@ -297,14 +298,14 @@ def getPidList(md1, md2, serials=[], kDatabases=[]):
try:
pidlst.extend(getK4Pids(md1, md2, kDatabase))
except Exception, e:
print u"Error getting PIDs from database {0}: {1}".format(kDatabase[0],e.args[0])
print(u"Error getting PIDs from database {0}: {1}".format(kDatabase[0],e.args[0]))
traceback.print_exc()
for serialnum in serials:
try:
pidlst.extend(getKindlePids(md1, md2, serialnum))
except Exception, e:
print u"Error getting PIDs from serial number {0}: {1}".format(serialnum ,e.args[0])
print(u"Error getting PIDs from serial number {0}: {1}".format(serialnum ,e.args[0]))
traceback.print_exc()
return pidlst

View File

@@ -7,7 +7,7 @@ from __future__ import with_statement
# Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '2.5'
__version__ = '2.6'
# Revision history:
# 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc.
@@ -28,6 +28,7 @@ __version__ = '2.5'
# 2.3 - Added more field names thanks to concavegit's KFX code.
# 2.4 - Fix for complex Mac disk setups, thanks to Tibs
# 2.5 - Final Fix for Windows user names with non-ascii characters, thanks to oneofusoneofus
# 2.6 - Start adding support for Kindle 1.25+ .kinf2018 file
"""
@@ -39,6 +40,12 @@ from struct import pack, unpack, unpack_from
import json
import getopt
try:
RegError
except NameError:
class RegError(Exception):
pass
# Routines common to Mac and PC
# Wrap a stream so that output gets flushed immediately
@@ -124,25 +131,27 @@ def SHA256(message):
return ctx.digest()
# For K4M/PC 1.6.X and later
# generate table of prime number less than or equal to int n
def primes(n):
if n==2: return [2]
elif n<2: return []
s=range(3,n+1,2)
mroot = n ** 0.5
half=(n+1)/2-1
i=0
m=3
while m <= mroot:
if s[i]:
j=(m*m-3)/2
s[j]=0
while j<half:
s[j]=0
j+=m
i=i+1
m=2*i+3
return [2]+[x for x in s if x]
"""
Return a list of prime integers smaller than or equal to n
:param n: int
:return: list->int
"""
if n == 2:
return [2]
elif n < 2:
return []
primeList = [2]
for potentialPrime in range(3, n + 1, 2):
isItPrime = True
for prime in primeList:
if potentialPrime % prime == 0:
isItPrime = False
if isItPrime is True:
primeList.append(potentialPrime)
return primeList
# Encode the bytes in data with the characters in map
def encode(data, map):
@@ -971,6 +980,13 @@ if iswindows:
# Probably not the best. To Fix (shouldn't ignore in encoding) or use utf-8
print(u'searching for kinfoFiles in ' + path.encode('ascii', 'ignore'))
# look for (K4PC 1.25.1 and later) .kinf2018 file
kinfopath = path +'\\Amazon\\Kindle\\storage\\.kinf2018'
if os.path.isfile(kinfopath):
found = True
print('Found K4PC 1.25+ kinf2018 file: ' + kinfopath.encode('ascii','ignore'))
kInfoFiles.append(kinfopath)
# look for (K4PC 1.9.0 and later) .kinf2011 file
kinfopath = path +'\\Amazon\\Kindle\\storage\\.kinf2011'
if os.path.isfile(kinfopath):
@@ -1292,7 +1308,7 @@ elif isosx:
uuids = []
uuidnum = os.getenv('MYUUIDNUMBER')
if uuidnum != None:
uuids.append(strip(uuidnum))
uuids.append(uuidnum.strip())
cmdline = '/usr/sbin/ioreg -l -S -w 0 -r -c AppleAHCIDiskDriver'
cmdline = cmdline.encode(sys.getfilesystemencoding())
p = subprocess.Popen(cmdline, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False)

View File

@@ -11,6 +11,7 @@
# 0.4 Added support for serial numbers starting with '9', fixed unicode bugs.
# 0.5 moved unicode_argv call inside main for Windows DeDRM compatibility
from __future__ import print_function
import sys
import binascii
@@ -73,7 +74,7 @@ def unicode_argv():
return [arg if (type(arg) == unicode) else unicode(arg,argvencoding) for arg in sys.argv]
if sys.hexversion >= 0x3000000:
print 'This script is incompatible with Python 3.x. Please install Python 2.7.x.'
print('This script is incompatible with Python 3.x. Please install Python 2.7.x.')
sys.exit(2)
letters = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789'
@@ -113,28 +114,28 @@ def pidFromSerial(s, l):
return pid
def cli_main():
print u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky"
print(u"Mobipocket PID calculator for Amazon Kindle. Copyright © 2007, 2009 Igor Skochinsky")
argv=unicode_argv()
if len(argv)==2:
serial = argv[1]
else:
print u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>"
print(u"Usage: kindlepid.py <Kindle Serial Number>/<iPhone/iPod Touch UDID>")
return 1
if len(serial)==16:
if serial.startswith("B") or serial.startswith("9"):
print u"Kindle serial number detected"
print(u"Kindle serial number detected")
else:
print u"Warning: unrecognized serial number. Please recheck input."
print(u"Warning: unrecognized serial number. Please recheck input.")
return 1
pid = pidFromSerial(serial.encode("utf-8"),7)+'*'
print u"Mobipocket PID for Kindle serial#{0} is {1}".format(serial,checksumPid(pid))
print(u"Mobipocket PID for Kindle serial#{0} is {1}".format(serial,checksumPid(pid)))
return 0
elif len(serial)==40:
print u"iPhone serial number (UDID) detected"
print(u"iPhone serial number (UDID) detected")
pid = pidFromSerial(serial.encode("utf-8"),8)
print u"Mobipocket PID for iPhone serial#{0} is {1}".format(serial,checksumPid(pid))
print(u"Mobipocket PID for iPhone serial#{0} is {1}".format(serial,checksumPid(pid)))
return 0
print u"Warning: unrecognized serial number. Please recheck input."
print(u"Warning: unrecognized serial number. Please recheck input.")
return 1

View File

@@ -5,6 +5,7 @@
# Copyright © 2008 The Dark Reverser
# Portions © 20082017 Apprentice Harper et al.
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = u"0.42"
@@ -80,7 +81,7 @@ import binascii
try:
from alfcrypto import Pukall_Cipher
except:
print u"AlfCrypto not found. Using python PC1 implementation."
print(u"AlfCrypto not found. Using python PC1 implementation.")
# Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get
@@ -244,12 +245,12 @@ class MobiBook:
pass
def __init__(self, infile):
print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
print(u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__))
try:
from alfcrypto import Pukall_Cipher
except:
print u"AlfCrypto not found. Using python PC1 implementation."
print(u"AlfCrypto not found. Using python PC1 implementation.")
# initial sanity check on file
self.data_file = file(infile, 'rb').read()
@@ -282,7 +283,7 @@ class MobiBook:
self.mobi_version = -1
if self.magic == 'TEXtREAd':
print u"PalmDoc format book detected."
print(u"PalmDoc format book detected.")
return
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
@@ -424,10 +425,10 @@ class MobiBook:
def processBook(self, pidlist):
crypto_type, = struct.unpack('>H', self.sect[0xC:0xC+2])
print u"Crypto Type is: {0:d}".format(crypto_type)
print(u"Crypto Type is: {0:d}".format(crypto_type))
self.crypto_type = crypto_type
if crypto_type == 0:
print u"This book is not encrypted."
print(u"This book is not encrypted.")
# we must still check for Print Replica
self.print_replica = (self.loadSection(1)[0:4] == '%MOP')
self.mobi_data = self.data_file
@@ -444,12 +445,12 @@ class MobiBook:
for pid in pidlist:
if len(pid)==10:
if checksumPid(pid[0:-2]) != pid:
print u"Warning: PID {0} has incorrect checksum, should have been {1}".format(pid,checksumPid(pid[0:-2]))
print(u"Warning: PID {0} has incorrect checksum, should have been {1}".format(pid,checksumPid(pid[0:-2])))
goodpids.append(pid[0:-2])
elif len(pid)==8:
goodpids.append(pid)
else:
print u"Warning: PID {0} has wrong number of digits".format(pid)
print(u"Warning: PID {0} has wrong number of digits".format(pid))
if self.crypto_type == 1:
t1_keyvec = 'QDCVEPMU675RUBSZ'
@@ -475,22 +476,22 @@ class MobiBook:
self.patchSection(0, '\xff' * 4 + '\0' * 12, 0xA8)
if pid=='00000000':
print u"File has default encryption, no specific key needed."
print(u"File has default encryption, no specific key needed.")
else:
print u"File is encoded with PID {0}.".format(checksumPid(pid))
print(u"File is encoded with PID {0}.".format(checksumPid(pid)))
# clear the crypto type
self.patchSection(0, "\0" * 2, 0xC)
# decrypt sections
print u"Decrypting. Please wait . . .",
print(u"Decrypting. Please wait . . .", end=' ')
mobidataList = []
mobidataList.append(self.data_file[:self.sections[1][0]])
for i in xrange(1, self.records+1):
data = self.loadSection(i)
extra_size = getSizeOfTrailingDataEntries(data, len(data), self.extra_data_flags)
if i%100 == 0:
print u".",
print(u".", end=' ')
# print "record %d, extra_size %d" %(i,extra_size)
decoded_data = PC1(found_key, data[0:len(data) - extra_size])
if i==1:
@@ -501,7 +502,7 @@ class MobiBook:
if self.num_sections > self.records+1:
mobidataList.append(self.data_file[self.sections[self.records+1][0]:])
self.mobi_data = "".join(mobidataList)
print u"done"
print(u"done")
return
def getUnencryptedBook(infile,pidlist):
@@ -516,15 +517,15 @@ def cli_main():
argv=unicode_argv()
progname = os.path.basename(argv[0])
if len(argv)<3 or len(argv)>4:
print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
print u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks"
print u"Usage:"
print u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname)
print(u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__))
print(u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks")
print(u"Usage:")
print(u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname))
return 1
else:
infile = argv[1]
outfile = argv[2]
if len(argv) is 4:
if len(argv) == 4:
pidlist = argv[3].split(',')
else:
pidlist = []
@@ -532,7 +533,7 @@ def cli_main():
stripped_file = getUnencryptedBook(infile, pidlist)
file(outfile, 'wb').write(stripped_file)
except DrmException, e:
print u"MobiDeDRM v{0} Error: {1:s}".format(__version__,e.args[0])
print(u"MobiDeDRM v{0} Error: {1:s}".format(__version__,e.args[0]))
return 1
return 0

View File

@@ -11,7 +11,7 @@ def load_pycrypto():
class DES(object):
def __init__(self, key):
if len(key) != 8 :
raise Error('DES improper key used')
raise ValueError('DES improper key used')
self.key = key
self._des = _DES.new(key,_DES.MODE_ECB)
def desdecrypt(self, data):

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
from __future__ import print_function
import sys
import os
import re
@@ -23,7 +24,7 @@ def decryptepub(infile, outdir, rscpath):
zippath = os.path.join(bpath,name + '_temp.zip')
rv = zipfix.repairBook(infile, zippath)
if rv != 0:
print "Error while trying to fix epub"
print("Error while trying to fix epub")
return rv
# determine a good name for the output file
@@ -43,7 +44,7 @@ def decryptepub(infile, outdir, rscpath):
try:
rv = ineptepub.decryptBook(userkey, zippath, outfile)
if rv == 0:
print "Decrypted Adobe ePub with key file {0}".format(filename)
print("Decrypted Adobe ePub with key file {0}".format(filename))
break
except Exception, e:
errlog += traceback.format_exc()
@@ -63,7 +64,7 @@ def decryptepub(infile, outdir, rscpath):
try:
rv = ignobleepub.decryptBook(userkey, zippath, outfile)
if rv == 0:
print "Decrypted B&N ePub with key file {0}".format(filename)
print("Decrypted B&N ePub with key file {0}".format(filename))
break
except Exception, e:
errlog += traceback.format_exc()
@@ -72,14 +73,14 @@ def decryptepub(infile, outdir, rscpath):
else:
encryption = epubtest.encryption(zippath)
if encryption == "Unencrypted":
print "{0} is not DRMed.".format(name)
print("{0} is not DRMed.".format(name))
rv = 0
else:
print "{0} has an unknown encryption.".format(name)
print("{0} has an unknown encryption.".format(name))
os.remove(zippath)
if rv != 0:
print errlog
print(errlog)
return rv
@@ -109,11 +110,12 @@ def decryptpdf(infile, outdir, rscpath):
rv = 1
if rv != 0:
print errlog
print(errlog)
return rv
def decryptpdb(infile, outdir, rscpath):
errlog = ''
outname = os.path.splitext(os.path.basename(infile))[0] + ".pmlz"
outpath = os.path.join(outdir, outname)
rv = 1
@@ -126,7 +128,7 @@ def decryptpdb(infile, outdir, rscpath):
try:
name, cc8 = i.split(':')
except ValueError:
print ' Error parsing user supplied social drm data.'
print(' Error parsing user supplied social drm data.')
return 1
try:
rv = erdr2pml.decryptBook(infile, outpath, True, erdr2pml.getuser_key(name, cc8))
@@ -141,6 +143,7 @@ def decryptpdb(infile, outdir, rscpath):
def decryptk4mobi(infile, outdir, rscpath):
errlog = ''
rv = 1
pidnums = []
pidspath = os.path.join(rscpath,'pidlist.txt')

View File

@@ -2,6 +2,7 @@
# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab
# For use with Topaz Scripts Version 2.6
from __future__ import print_function
import csv
import sys
import os
@@ -114,9 +115,9 @@ class DocParser(object):
# process each style converting what you can
if debug: print ' ', 'Processing styles.'
if debug: print(' ', 'Processing styles.')
for j in xrange(stylecnt):
if debug: print ' ', 'Processing style %d' %(j)
if debug: print(' ', 'Processing style %d' %(j))
start = styleList[j]
end = styleList[j+1]
@@ -135,7 +136,7 @@ class DocParser(object):
else :
sclass = ''
if debug: print 'sclass', sclass
if debug: print('sclass', sclass)
# check for any "after class" specifiers
(pos, aftclass) = self.findinDoc('style._after_class',start,end)
@@ -145,7 +146,7 @@ class DocParser(object):
else :
aftclass = ''
if debug: print 'aftclass', aftclass
if debug: print('aftclass', aftclass)
cssargs = {}
@@ -154,8 +155,8 @@ class DocParser(object):
(pos1, attr) = self.findinDoc('style.rule.attr', start, end)
(pos2, val) = self.findinDoc('style.rule.value', start, end)
if debug: print 'attr', attr
if debug: print 'val', val
if debug: print('attr', attr)
if debug: print('val', val)
if attr == None : break
@@ -182,7 +183,7 @@ class DocParser(object):
try:
f = float(val)
except:
print "Warning: unrecognised val, ignoring"
print("Warning: unrecognised val, ignoring")
val = 0
pv = float(val)/scale
cssargs[attr] = (self.attr_val_map[attr], pv)
@@ -194,7 +195,7 @@ class DocParser(object):
if aftclass != "" : keep = False
if keep :
if debug: print 'keeping style'
if debug: print('keeping style')
# make sure line-space does not go below 100% or above 300% since
# it can be wacky in some styles
if 'line-space' in cssargs:
@@ -266,15 +267,15 @@ class DocParser(object):
def convert2CSS(flatxml, fontsize, ph, pw):
print ' ', 'Using font size:',fontsize
print ' ', 'Using page height:', ph
print ' ', 'Using page width:', pw
print(' ', 'Using font size:',fontsize)
print(' ', 'Using page height:', ph)
print(' ', 'Using page width:', pw)
# create a document parser
dp = DocParser(flatxml, fontsize, ph, pw)
if debug: print ' ', 'Created DocParser.'
if debug: print(' ', 'Created DocParser.')
csspage = dp.process()
if debug: print ' ', 'Processed DocParser.'
if debug: print(' ', 'Processed DocParser.')
return csspage

View File

@@ -8,6 +8,7 @@
# 4.9 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 5.0 - Fixed potential unicode problem with command line interface
from __future__ import print_function
__version__ = '5.0'
import sys
@@ -213,7 +214,7 @@ class TopazBook:
# Read and return the data of one header record at the current book file position
# [[offset,decompressedLength,compressedLength],...]
nbValues = bookReadEncodedNumber(self.fo)
if debug: print "%d records in header " % nbValues,
if debug: print("%d records in header " % nbValues, end=' ')
values = []
for i in range (0,nbValues):
values.append([bookReadEncodedNumber(self.fo),bookReadEncodedNumber(self.fo),bookReadEncodedNumber(self.fo)])
@@ -227,10 +228,10 @@ class TopazBook:
record = bookReadHeaderRecordData()
return [tag,record]
nbRecords = bookReadEncodedNumber(self.fo)
if debug: print "Headers: %d" % nbRecords
if debug: print("Headers: %d" % nbRecords)
for i in range (0,nbRecords):
result = parseTopazHeaderRecord()
if debug: print result[0], ": ", result[1]
if debug: print(result[0], ": ", result[1])
self.bookHeaderRecords[result[0]] = result[1]
if ord(self.fo.read(1)) != 0x64 :
raise DrmException(u"Parse Error : Invalid Header")
@@ -244,12 +245,12 @@ class TopazBook:
raise DrmException(u"Parse Error : Record Names Don't Match")
flags = ord(self.fo.read(1))
nbRecords = ord(self.fo.read(1))
if debug: print "Metadata Records: %d" % nbRecords
if debug: print("Metadata Records: %d" % nbRecords)
for i in range (0,nbRecords) :
keyval = bookReadString(self.fo)
content = bookReadString(self.fo)
if debug: print keyval
if debug: print content
if debug: print(keyval)
if debug: print(content)
self.bookMetadata[keyval] = content
return self.bookMetadata
@@ -319,11 +320,11 @@ class TopazBook:
try:
keydata = self.getBookPayloadRecord('dkey', 0)
except DrmException, e:
print u"no dkey record found, book may not be encrypted"
print u"attempting to extrct files without a book key"
print(u"no dkey record found, book may not be encrypted")
print(u"attempting to extrct files without a book key")
self.createBookDirectory()
self.extractFiles()
print u"Successfully Extracted Topaz contents"
print(u"Successfully Extracted Topaz contents")
if inCalibre:
from calibre_plugins.dedrm import genbook
else:
@@ -331,7 +332,7 @@ class TopazBook:
rv = genbook.generateBook(self.outdir, raw, fixedimage)
if rv == 0:
print u"Book Successfully generated."
print(u"Book Successfully generated.")
return rv
# try each pid to decode the file
@@ -339,7 +340,7 @@ class TopazBook:
for pid in pidlst:
# use 8 digit pids here
pid = pid[0:8]
print u"Trying: {0}".format(pid)
print(u"Trying: {0}".format(pid))
bookKeys = []
data = keydata
try:
@@ -348,7 +349,7 @@ class TopazBook:
pass
else:
bookKey = bookKeys[0]
print u"Book Key Found! ({0})".format(bookKey.encode('hex'))
print(u"Book Key Found! ({0})".format(bookKey.encode('hex')))
break
if not bookKey:
@@ -357,7 +358,7 @@ class TopazBook:
self.setBookKey(bookKey)
self.createBookDirectory()
self.extractFiles()
print u"Successfully Extracted Topaz contents"
print(u"Successfully Extracted Topaz contents")
if inCalibre:
from calibre_plugins.dedrm import genbook
else:
@@ -365,7 +366,7 @@ class TopazBook:
rv = genbook.generateBook(self.outdir, raw, fixedimage)
if rv == 0:
print u"Book Successfully generated"
print(u"Book Successfully generated")
return rv
def createBookDirectory(self):
@@ -394,7 +395,7 @@ class TopazBook:
ext = u".dat"
if name == 'img': ext = u".jpg"
if name == 'color' : ext = u".jpg"
print u"Processing Section: {0}\n. . .".format(name),
print(u"Processing Section: {0}\n. . .".format(name), end=' ')
for index in range (0,len(self.bookHeaderRecords[name])) :
fname = u"{0}{1:04d}{2}".format(name,index,ext)
destdir = outdir
@@ -407,11 +408,11 @@ class TopazBook:
if name == 'glyphs':
destdir = os.path.join(outdir,u"glyphs")
outputFile = os.path.join(destdir,fname)
print u".",
print(u".", end=' ')
record = self.getBookPayloadRecord(name,index)
if record != '':
file(outputFile, 'wb').write(record)
print u" "
print(u" ")
def getFile(self, zipname):
htmlzip = zipfile.ZipFile(zipname,'w',zipfile.ZIP_DEFLATED, False)
@@ -441,20 +442,20 @@ class TopazBook:
shutil.rmtree(self.outdir, True)
def usage(progname):
print u"Removes DRM protection from Topaz ebooks and extracts the contents"
print u"Usage:"
print u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] <infile> <outdir>".format(progname)
print(u"Removes DRM protection from Topaz ebooks and extracts the contents")
print(u"Usage:")
print(u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] <infile> <outdir>".format(progname))
# Main
def cli_main():
argv=unicode_argv()
progname = os.path.basename(argv[0])
print u"TopazExtract v{0}.".format(__version__)
print(u"TopazExtract v{0}.".format(__version__))
try:
opts, args = getopt.getopt(argv[1:], "k:p:s:x")
except getopt.GetoptError, err:
print u"Error in options or arguments: {0}".format(err.args[0])
print(u"Error in options or arguments: {0}".format(err.args[0]))
usage(progname)
return 1
if len(args)<2:
@@ -464,11 +465,11 @@ def cli_main():
infile = args[0]
outdir = args[1]
if not os.path.isfile(infile):
print u"Input File {0} Does Not Exist.".format(infile)
print(u"Input File {0} Does Not Exist.".format(infile))
return 1
if not os.path.exists(outdir):
print u"Output Directory {0} Does Not Exist.".format(outdir)
print(u"Output Directory {0} Does Not Exist.".format(outdir))
return 1
kDatabaseFiles = []
@@ -493,19 +494,19 @@ def cli_main():
tb = TopazBook(infile)
title = tb.getBookTitle()
print u"Processing Book: {0}".format(title)
print(u"Processing Book: {0}".format(title))
md1, md2 = tb.getPIDMetaInfo()
pids.extend(kgenpids.getPidList(md1, md2, serials, kDatabaseFiles))
try:
print u"Decrypting Book"
print(u"Decrypting Book")
tb.processBook(pids)
print u" Creating HTML ZIP Archive"
print(u" Creating HTML ZIP Archive")
zipname = os.path.join(outdir, bookname + u"_nodrm.htmlz")
tb.getFile(zipname)
print u" Creating SVG ZIP Archive"
print(u" Creating SVG ZIP Archive")
zipname = os.path.join(outdir, bookname + u"_SVG.zip")
tb.getSVGZip(zipname)
@@ -513,7 +514,7 @@ def cli_main():
tb.cleanup()
except DrmException, e:
print u"Decryption failed\n{0}".format(traceback.format_exc())
print(u"Decryption failed\n{0}".format(traceback.format_exc()))
try:
tb.cleanup()
@@ -522,7 +523,7 @@ def cli_main():
return 1
except Exception, e:
print u"Decryption failed\m{0}".format(traceback.format_exc())
print(u"Decryption failed\m{0}".format(traceback.format_exc()))
try:
tb.cleanup()
except:

View File

@@ -3,6 +3,8 @@
from __future__ import with_statement
from ignoblekeygen import generate_key
__license__ = 'GPL v3'
DETAILED_MESSAGE = \

View File

@@ -2,11 +2,12 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from __future__ import print_function
__license__ = 'GPL v3'
# Standard Python modules.
import os, sys, re, hashlib
import os, sys, re, hashlib, traceback
from calibre_plugins.dedrm.__init__ import PLUGIN_NAME, PLUGIN_VERSION
def WineGetKeys(scriptpath, extension, wineprefix=""):
@@ -20,37 +21,39 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
import json
basepath, script = os.path.split(scriptpath)
print u"{0} v{1}: Running {2} under Wine".format(PLUGIN_NAME, PLUGIN_VERSION, script)
print(u"{0} v{1}: Running {2} under Wine".format(PLUGIN_NAME, PLUGIN_VERSION, script))
outdirpath = os.path.join(basepath, u"winekeysdir")
if not os.path.exists(outdirpath):
os.makedirs(outdirpath)
wineprefix = os.path.abspath(os.path.expanduser(os.path.expandvars(wineprefix)))
if wineprefix != "":
wineprefix = os.path.abspath(os.path.expanduser(os.path.expandvars(wineprefix)))
if wineprefix != "" and os.path.exists(wineprefix):
cmdline = u"WINEPREFIX=\"{2}\" wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
else:
cmdline = u"wine python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
print u"{0} v{1}: Command line: '{2}'".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline)
print(u"{0} v{1}: Command line: '{2}'".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline))
try:
cmdline = cmdline.encode(sys.getfilesystemencoding())
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
result = p2.wait("wait")
except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
print(u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]))
if wineprefix != "" and os.path.exists(wineprefix):
cmdline = u"WINEPREFIX=\"{2}\" wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath,wineprefix)
else:
cmdline = u"wine C:\\Python27\\python.exe \"{0}\" \"{1}\"".format(scriptpath,outdirpath)
print u"{0} v{1}: Command line: “{2}".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline)
print(u"{0} v{1}: Command line: “{2}".format(PLUGIN_NAME, PLUGIN_VERSION, cmdline))
try:
cmdline = cmdline.encode(sys.getfilesystemencoding())
p2 = Process(cmdline, shell=True, bufsize=1, stdin=None, stdout=sys.stdout, stderr=STDOUT, close_fds=False)
result = p2.wait("wait")
except Exception, e:
print u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0])
print(u"{0} v{1}: Wine subprocess call error: {2}".format(PLUGIN_NAME, PLUGIN_VERSION, e.args[0]))
# try finding winekeys anyway, even if above code errored
winekeys = []
@@ -66,8 +69,8 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
new_key_value = keyfile.read()
winekeys.append(new_key_value)
except:
print u"{0} v{1}: Error loading file {2}".format(PLUGIN_NAME, PLUGIN_VERSION, filename)
print(u"{0} v{1}: Error loading file {2}".format(PLUGIN_NAME, PLUGIN_VERSION, filename))
traceback.print_exc()
os.remove(fpath)
print u"{0} v{1}: Found and decrypted {2} {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(winekeys), u"key file" if len(winekeys) == 1 else u"key files")
print(u"{0} v{1}: Found and decrypted {2} {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(winekeys), u"key file" if len(winekeys) == 1 else u"key files"))
return winekeys

View File

@@ -14,6 +14,7 @@
"""
Re-write zip (or ePub) fixing problems with file names (and mimetype entry).
"""
from __future__ import print_function
__license__ = 'GPL v3'
__version__ = "1.1"
@@ -156,22 +157,22 @@ class fixZip:
def usage():
print """usage: zipfix.py inputzip outputzip
print("""usage: zipfix.py inputzip outputzip
inputzip is the source zipfile to fix
outputzip is the fixed zip archive
"""
""")
def repairBook(infile, outfile):
if not os.path.exists(infile):
print "Error: Input Zip File does not exist"
print("Error: Input Zip File does not exist")
return 1
try:
fr = fixZip(infile, outfile)
fr.fix()
return 0
except Exception, e:
print "Error Occurred ", e
print("Error Occurred ", e)
return 2

34
DeDRM_plugin_ReadMe.txt Normal file
View File

@@ -0,0 +1,34 @@
DeDRM_plugin.zip
================
This plugin will remove the DRM from:
- Kindle ebooks (files from Kindle for Mac/PC and eInk Kindles).
- Adobe Digital Editions (v2.0.1***) ePubs (including Kobo and Google ePubs downloaded to ADE)
- Adobe Digital Editions (v2.0.1) PDFs
For limitations and work-arounds, see the FAQ at https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md
Installation
------------
Open calibre's Preferences dialog. Click on the "Plugins" button. Next, click on the button, "Load plugin from file". Navigate to the unzipped DeDRM_tools folder, find the file "DeDRM_plugin.zip". Click to select the file and select "Open". Click "Yes" in the "Are you sure?" dialog box. Click the "OK" button in the "Success" dialog box.
Customization
-------------
For Kindle ebooks from an E-Ink based Kindle (e.g. Voyage), or books downloaded from the Amazon web site 'for transfer via USB' to an E-Ink base Kindle, you must enter the Kindle's serial number in the customisation dialog.
When you have finished entering your configuration information, you must click the OK button to save it. If you click the Cancel button, all your changes in all the configuration dialogs will be lost.
Troubleshooting
---------------
If you find that the DeDRM plugin is not working for you (imported ebooks still have DRM - that is, they won't convert or open in the calibre ebook viewer), you should make a log of the import process by deleting the DRMed ebook from calibre and then adding the ebook to calibre when it's running in debug mode. This will generate a lot of helpful debugging info that can be copied into any online help requests. Here's how to do it:
- Remove the DRMed book from calibre.
- Click the Preferences drop-down menu and choose 'Restart in debug mode'.
- Once calibre has re-started, import the problem ebook.
- Now close calibre.
A log will appear that you can copy and paste into a comment at Apprentice Alf's blog, http://apprenticealf.wordpress.com/ or an issue at Apprentice Harper's repository, https://github.com/apprenticeharper/DeDRM_tools/issues . You should also give details of your computer, and how you obtained the ebook file.

100
FAQs.md
View File

@@ -15,50 +15,53 @@ Just download and use these tools, that's all! Uh, almost. There are a few, uh,
* You must own the ebook - the tools won't work on library ebooks or rented ebooks or books from a friend.
* You must not use these tools to give your ebooks to a hundred of your closest friends. Or to a million strangers. Authors need to sell books to be able to write more books. Don't be mean to the authors.
* Do NOT use Adobe Digital Editions 3.0 or later to download your ePubs. ADE 3.0 and later might use a new encryption scheme that the tools can't handle. While major ebook stores aren't using the new scheme yet, using ADE 2.0.1 will ensure that your ebooks are downloaded using the old scheme. Once a book has been downloaded with the new scheme, it's IMPOSSIBLE to re-download using the old scheme (without buying it again).
* Do NOT use Kindle for PC/Mac version 1.25 or later. The tools don't current work with those versions.
But otherwise, if your ebook is from Amazon, Kobo, Barnes & Noble or any of the ebook stores selling ebooks compatible with Adobe Digital Editions 2.0.1, you should be able to remove the DRM that's been applied to your ebooks.
### A Recent Change to Kindle for PC/Kindle for Mac
Starting with version 1.19, Kindle for PC/Mac uses Amazon's new KFX format which these tools can't handle. There are two options to get the older formats that the tools can decrypt. Either stick with version 1.17 or earlier, or modify the executable by changing a file name.
Starting with version 1.19, Kindle for PC/Mac uses Amazon's new KFX format which isn't quite as good a source for conversion to ePub as the older KF8 (& MOBI) formats. There are two options to get the older formats. Either stick with version 1.17 or earlier, or modify the executable by changing a file name (PC) or disabling a component of the application (Mac). Note that with Kindle for **PC** 1.25 and later, there is no current solution even for KFX. You must use 1.24 or earlier. With Kindle for **Mac** 1.25 and later, see instructions in [this post](https://www.mobileread.com/forums/showpost.php?p=3819708&postcount=508). (Note: macOS Catalina can only run 64-bit apps, which means Kindle for Mac 1.25 and later. Earlier versions of Kindle for Mac are 32-bit and will not run on Catalina. If you are planning to upgrade to Catalina, [read this post](https://www.mobileread.com/forums/showpost.php?p=3819708&postcount=508) carefully first.)
Version 1.17 of Kindle is are no longer available directly from Amazon, so you will need to search for the proper file name and find it on a third party site. The name is "KindleForPC-installer-1.17.44170.exe" for PC and "KindleForMac-44182.dmg" for Mac.
Version 1.17 of Kindle is no longer available directly from Amazon, so you will need to search for the proper file name and find it on a third party site. The name is `KindleForPC-installer-1.17.44170.exe` for PC and `KindleForMac-44182.dmg` for Mac.
Verify the one of the following cryptographic hash values, using software of your choice, before installing the downloaded file in order to avoid viruses. If the hash does not match, delete the downloaded file and try again from another site.
Kindle for PC:
MD-5: 53F793B562F4823721AA47D7DE099869
SHA-1: 73C404D719F0DD8D4AE1C2C96612B095D6C86255
SHA-256: 14E0F0053F1276C0C7C446892DC170344F707FBFE99B695176 2C120144163200
Kindle for Mac:
MD-5: E7E36D5369E1F3CF1D28E5D9115DF15F
SHA-1: 7AB9A86B954CB23D622BD79E3257F8E2182D791C
SHA-256: 28DC21246A9C7CDEDD2D6F0F4082E6BF7EF9DB9CE9D485548E 8A9E1D19EAE2AC.
#### Kindle for PC `KindleForPC-installer-1.17.44170.exe`:
* MD-5: 53F793B562F4823721AA47D7DE099869
* SHA-1: 73C404D719F0DD8D4AE1C2C96612B095D6C86255
* SHA-256: 14E0F0053F1276C0C7C446892DC170344F707FBFE99B695176 2C120144163200
#### Kindle for Mac `KindleForMac-44182.dmg`:
* MD-5: E7E36D5369E1F3CF1D28E5D9115DF15F
* SHA-1: 7AB9A86B954CB23D622BD79E3257F8E2182D791C
* SHA-256: 28DC21246A9C7CDEDD2D6F0F4082E6BF7EF9DB9CE9D485548E 8A9E1D19EAE2AC.
You will need to go to the preferences and uncheck the auto update checkbox. Then download and install 1.17 over the top of the 1.19 installation. You'll also need to delete the KFX folders from your My Kindle Content folder.
A second possible solution is to use 1.19 or later, but disable KFX by renaming or disabling a necessary component of the application. This may or may not work on versions after 1.20. In a command window, enter the following commands when Kindle for PC/Mac is not running:
Another possible solution is to use 1.19 or later, but disable KFX by renaming or disabling a necessary component of the application. This may or may not work on versions after 1.20. In a command window, enter the following commands when Kindle for PC/Mac is not running:
#### Windows
ren %localappdata%\Amazon\Kindle\application\renderer-test.exe renderer-test.xxx
`ren %localappdata%\Amazon\Kindle\application\renderer-test.exe renderer-test.xxx`
PC Note: The renderer-test program may be in a different location in some Kindle for PC installations. If the rename command fails look in other folders, such as C:\Program Files\Amazon\Kindle.
PC Note: The renderer-test program may be in a different location in some Kindle for PC installations. If the rename command fails look in other folders, such as `C:\Program Files\Amazon\Kindle`.
#### Macintosh
chmod -x /Applications/Kindle.app/Contents/MacOS/renderer-test
`chmod -x /Applications/Kindle.app/Contents/MacOS/renderer-test`
Mac Note: If the chmod command fails with a permission error try again using sudo before chmod - sudo chmod [...]
Mac Note: If the chmod command fails with a permission error try again using `sudo` before `chmod` - `sudo chmod` [...]
After restarting the Kindle program any books previously downloaded in KFX format will no longer open. You will need to remove them from your device and re-download them. All future downloads will use the older Kindle formats instead of KFX although they will continue to be placed in one individual subdirectory per book.
#### Another Note on KFX
It now possible, but not easy, to convert books from KFX to other formats in calibre by installing the optional KFX Input plugin. The lack of automatic DRM removal makes this process difficult so it is not recommended unless there is no other alternative, such as for Indic language books only available in KFX. There is a windows-only KFX DRM rmeoval program in the repository, but not yet integrated into the tools.
#### Decrypting KFX
Thanks to work by several people, the tools can now decrypt KFX format ebooks from Kindle for PC. In addition to the DeDRM plugin, calibre users will also need to install jhowell's KFX Input plugin which is available through the standard plugin menu in calibre, or directly from [his plugin thread](https://www.mobileread.com/forums/showthread.php?t=291290) on Mobileread. Note that KFX decryption does not work for Kindle for PC/Mac 1.25 and later.
#### Thanks
Thanks to jhowell for his investigations into KFX format and workarounds. Some of these instructions are from [his thread on the subject](https://www.mobileread.com/forums/showthread.php?t=283371) at MobileRead.
Thanks to jhowell for his investigations into KFX format and the KFX Input plugin. Some of these instructions are from [his thread on the subject](https://www.mobileread.com/forums/showthread.php?t=283371) at MobileRead.
## Where can I get the latest version of these free DRM removal tools?
Right here at github. Just go to the [releases page](https://github.com/apprenticeharper/DeDRM_tools/releases) and download the latest zip archive of the tools, named DeDRM\_tools\_X.X.X.zip, where X.X.X is the version number. You do not need to download the source code archive.
Right here at github. Just go to the [releases page](https://github.com/apprenticeharper/DeDRM_tools/releases) and download the latest zip archive of the tools, named `DeDRM\_tools\_X.X.X.zip`, where X.X.X is the version number. You do not need to download the source code archive.
## I've downloaded the tools archive. Now what?
First, unzip the archive. You should now have a DeDRM folder containing several other folders and a ReadMe\_First.txt file. Please read the ReadMe\_First file! That will explain what the folders are, and you'll be able to work out which of the tools you need.
First, unzip the archive. You should now have a DeDRM folder containing several other folders and a `ReadMe_First.txt` file. Please read the `ReadMe_First.txt` file! That will explain what the folders are, and you'll be able to work out which of the tools you need.
## That's a big complicated ReadMe file! Isn't there a quick guide?
Install calibre. Install the DeDRM\_plugin in calibre. Install the Obok\_plugin in calibre. Restart calibre. In the DeDRM_plugin customisation dialog add in any E-Ink Kindle serial numbers and your B&N account email address and password. Remember that the plugin only tries to remove DRM when ebooks are imported.
@@ -66,14 +69,14 @@ Install calibre. Install the DeDRM\_plugin in calibre. Install the Obok\_plugin
# Installing the Tools
## The calibre plugin
### I am trying to install the calibre plugin, but calibre says "ERROR: Unhandled exception: InvalidPlugin: The plugin in u[path]DeDRM\_tools\_6.5.3.zip is invalid. It does not contain a top-level \_\_init\_\_.py file"
You are trying to add the tools archive (e.g. DeDRM\_tools\_6.5.3.zip) instead of the plugin. The tools archive is not the plugin. It is a collection of DRM removal tools which includes the plugin. You must unzip the archive, and install the calibre plugin (DeDRM\_plugin.zip) from a folder called DeDRM\_calibre_plugin in the unzipped archive.
You are trying to add the tools archive (e.g. `DeDRM_tools_6.5.3.zip`) instead of the plugin. The tools archive is not the plugin. It is a collection of DRM removal tools which includes the plugin. You must unzip the archive, and install the calibre plugin `DeDRM_plugin.zip` from a folder called `DeDRM_calibre_plugin` in the unzipped archive.
### Ive unzipped the tools archive, but I cant find the calibre plugin when I try to add them to calibre. I use Windows.
You should select the zip file that is in the DeDRM\_calibre\_plugin folder, not any files inside the plugins zip archive. Make sure you are selecting from the folder that you created when you unzipped the tools archive and not selecting a file inside the still-zipped tools archive.
You should select the zip file that is in the `DeDRM_calibre_plugin` folder, not any files inside the plugins zip archive. Make sure you are selecting from the folder that you created when you unzipped the tools archive and not selecting a file inside the still-zipped tools archive.
(The problem is that Windows will allow apps to browse inside zip archives without needing to unzip them first. If there are zip archives inside the main zip archives, Windows will show them as unzipped as well. So what happens is people will unzip the DeDRM\_tools\_X.X.X.zip to a folder, but when using calibre they will actually navigate to the still zipped file by mistake and cannot tell they have done so because they do not have file extensions showing. So to the unwary Windows user, it appears that the zip archive was unzipped and that everything inside it was unzipped as well so there is no way to install the plugins.
(The problem is that Windows will allow apps to browse inside zip archives without needing to unzip them first. If there are zip archives inside the main zip archives, Windows will show them as unzipped as well. So what happens is people will unzip the `DeDRM_tools_X.X.X.zip` to a folder, but when using calibre they will actually navigate to the still zipped file by mistake and cannot tell they have done so because they do not have file extensions showing. So to the unwary Windows user, it appears that the zip archive was unzipped and that everything inside it was unzipped as well so there is no way to install the plugins.
We strongly recommend renaming the DeDRM\_tools\_X.X.X.zip archive (after extracting its contents) to DeDRM\_tools\_X.X.X_archive.zip. If you do that, you are less likely to navigate to the wrong location from inside calibre.)
We strongly recommend renaming the `DeDRM_tools_X.X.X.zip` archive (after extracting its contents) to `DeDRM_tools_X.X.X_archive.zip`. If you do that, you are less likely to navigate to the wrong location from inside calibre.)
## The Windows Application
### I've installed ActiveState Python and PyCrypto, but the Windows application won't run. What have I done wrong?
@@ -86,15 +89,36 @@ Try right-clicking and select open. That might give you the option to open it an
### I can't open the Macintosh Application at all. I get 'The aplication "DeDRM" can't be opened'
Some unzip applications do not respect the execution bit setting. Try unzipping the main tools archive using the built-in Mac unzip utility.
Alternatively, sometimes the execution bit isn't set correctly in the archive. If you put the extracted DeDRM application in your Applications folder, you can set the executable bit on the 'droplet' file from the terminal using the command `chmod +x /Applications/DeDRM.app/Contents/MacOS/droplet`
### I can't open the Macintosh Application at all. I get 'spawn_via_launchd() failed, errno=111'
There seems to be a bug in Apple's launch services. Try using the free [Maintenance utility](https://www.titanium-software.fr/en/maintenance.html) from Titanium Software to clear the launch cache and database.
### The application opens, but always gives an error in the log 'ImportError: No module named Crypto.Cipher'
Some version of MacOS don't include PyCrpto. You'll need to install it manually. In Terminal window:
`sudo python -m pip install pycrypto`
if error “No module named pip”, type:
`sudo easy_install pip`
try again: `sudo python -m pip install pycrypto`
if installation fails because “C compiler cannot create executables” and pop-up window asks you to install Command Line Tools for XCode, agree by clicking “Continue”
try again: `sudo python -m pip install pycrypto`
If after installing pycrypto decryption still fails with something about pylzma in error log, try:
`sudo python -m pip install pylzma`
# Using the Tools
## I cant get the tools to work on my rented or library ebooks.
The tools are not designed to remove DRM from rented or library ebooks.
## I've unzipped the tools, but what are all the different files, and how do I use them?
Read the ReadMe_First.txt file and then the ReadMe files included in the tools folder(s) you're interested in. That's what they're for.
Read the `ReadMe_First.txt` file and then the ReadMe files included in the tools folder(s) you're interested in. That's what they're for.
## I have installed the calibre plugin, but my books still have DRM. When I try to view or convert my books, calibre says they have DRM.
DRM only gets removed when an ebook is imported into calibre. Also, if the book is already in calibre, by default calibre will discard the newly imported file. You can change this in calibre's Adding books preferences page (Automerge..../Overwrite....), so that newly imported files overwrite existing ebook formats. Then just re-import your books and the DRM-free versions will overwrite the DRMed versions while retaining your books' metadata.
@@ -105,16 +129,16 @@ Your ebooks are stored on your computer or on your ebook reader. You need to fin
### Macintosh
Navigating from your home folder,
Kindle for Mac ebooks are in either Library/Application Support/Kindle/My Kindle Content or Documents/My Kindle Content or Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/My Kindle Content, depending on your version of Kindle for Mac.
Kindle for Mac ebooks are in either `Library/Application Support/Kindle/My Kindle Content` or `Documents/My Kindle Content or Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/My Kindle Content`, depending on your version of Kindle for Mac.
Adobe Digital Editions ebooks are in Documents/Digital Editions
Adobe Digital Editions ebooks are in `Documents/Digital Editions`
### Windows
Navigating from your "Documents" folder ("My Documents" folder, pre-Windows 7)
Navigating from your `Documents` folder (`My Documents` folder, pre-Windows 7)
Kindle for PC ebooks are in My Kindle Content
Kindle for PC ebooks are in `My Kindle Content`
Adobe Digital Editions ebooks are in My Digital Editions
Adobe Digital Editions ebooks are in `My Digital Editions`
## I have installed the calibre plugin, and the book is not already in calibre, but the DRM does not get removed.
@@ -128,15 +152,15 @@ If this book is from an eInk Kindle (e.g. Paperwhite), you must enter the serial
If this book is from Kindle for Mac or Kindle for PC, you must have the Kindle Software installed on the same computer and user account as your copy of calibre.
If this book is from Kindle for Mac or Kindle for PC, you must be using version 1.17 or below, see note at top of this file.
If this book is from Kindle for Mac you must be using version 1.24 or below, even if you have the Input plugin installed.
If the book is from Kindle for PC or Kindle for Mac and you think you are doing everything right, and you are getting this message, it is possible that the files containing the encryption key arent quite in the format the tools expect. To try to fix this:
1. Deregister Kindle for PC(Mac) from your Amazon account.
1. Uninstall Kindle for PC(Mac)
1. Delete the Kindle for PC(Mac) preferences
* PC: Delete the directory [home folder]\AppData\Local\Amazon (it might be hidden) and [home folder]\My Documents\My Kindle Content
* Mac: Delete the directory [home folder]/Library/Application Support/Kindle/and/or [home folder]/Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/ (one or both may be present and should be deleted)
* PC: Delete the directory `[home folder]\AppData\Local\Amazon` (it might be hidden) and `[home folder]\My Documents\My Kindle Content`
* Mac: Delete the directory `[home folder]/Library/Application Support/Kindle/` and/or `[home folder]/Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/` (one or both may be present and should be deleted)
1. Reinstall Kindle for PC(Mac) version 1.17 or earlier (see above for download links).
1. Re-register Kindle for PC(Mac) with your Amazon account
1. Download the ebook again. Do not use the files you have downloaded previously.
@@ -149,7 +173,7 @@ There are several possible reasons why only some books get their DRM removed.
If you are still having problems with particular books, you will need to create a log of the DRM removal attempt for one of the problem books, and post that in a comment at Apprentice Alf's blog or in a new issue at Apprentice Harper's github repository.
## My Kindle book has imported and the DRM has been removed, but all the pictures are gone.
Most likely, this is a book downloaded from Amazon directly to an eInk Kindle (e.g. Paperwhite). Unfortunately, the pictures are probably in a .azw6 file that the tools don't understand. You must download the book manually from Amazon's web site "For transfer via USB" to your Kindle. When you download the eboook in this manner, Amazon will package the pictures in the with text in a single file that the tools will be able to import successfully.
Most likely, this is a book downloaded from Amazon directly to an eInk Kindle (e.g. Paperwhite). Unfortunately, the pictures are probably in a `.azw6` file that the tools don't understand. You must download the book manually from Amazon's web site "For transfer via USB" to your Kindle. When you download the eBook in this manner, Amazon will package the pictures in the with text in a single file that the tools will be able to import successfully.
## My Kindle book has imported, but it's showing up as an AZW4 format. Conversions take a long time and/or are very poor.
You have found a Print Replica Kindle ebook. This is a PDF in a Kindle wrapper. Now the DRM has been removed, you can extract the PDF from the wrapper using the KindleUnpack plugin. Conversion of PDFs rarely gives good results.
@@ -173,8 +197,10 @@ Remove the DRMed book from calibre. Click the Preferences drop-down menu and cho
The Macintosh DeDRM application creates a log file on your desktop every time it is run. After unsuccessfully removing DRM from one ebook, copy the contents of the log file (it is a simple text file) and paste it into your comment at Apprentice Alf's blog or in a new issue at Apprentice Harper's github repository.
## I cannot solve my problem with the Windows DeDRM application, and now I need to post a log. How do I do that?
The Windows DeDRM application creates a log file in your home directory (C:\Users\[username]) every time it is run. After unsuccessfully removing DRM from one ebook, copy the contents of the log file (it is a simple text file) and paste it into your comment at Apprentice Alf's blog or in a new issue at Apprentice Harper's github repository.
The Windows DeDRM application creates a log file in your home directory `C:\Users\[username]` every time it is run. After unsuccessfully removing DRM from one ebook, copy the contents of the log file (it is a simple text file) and paste it into your comment at Apprentice Alf's blog or in a new issue at Apprentice Harper's github repository.
## Is there a way to use the DeDRM plugin for Calibre from the command line?
See the [Calibre command line interface (CLI) instructions](CALIBRE_CLI_INSTRUCTIONS.md).
# General Questions
@@ -207,7 +233,7 @@ Amazon turned off backup for Kindle for Android, so the tools can no longer find
Apple regularly change the details of their DRM and so the tools in the main tools archive will not work with these ebooks. Apples Fairplay DRM scheme can be removed using Requiem if the appropriate version of iTunes can still be installed and used. See the post Apple and ebooks: iBookstore DRM and how to remove it at Apprentice Alf's blog for more details.
## Ive got the tools archive and Ive read all the FAQs but I still cant install the tools and/or the DRM removal doesnt work
* Read the ReadMe_First.txt file in the top level of the tools archive
* Read the `ReadMe_First.txt` file in the top level of the tools archive
* Read the ReadMe file in the folder of the tools you want to use.
* If you still cant remove the DRM, ask in the comments section of Apprentice Alf's blog or create a new issue at Apprentice Harper's github repository, reporting the error as precisely as you can, what platform you use, what tool you have tried, what errors you get, and what versions you are using. If the problem happens when running one of the tools, post a log (see previous questions on how to do this).
@@ -221,7 +247,7 @@ The authors tend to identify themselves only by pseudonyms:
* The Amazon Topaz format conversion was created by some_updates, clarknova, and Bart Simpson
* The DeDRM all-in-one AppleScript application was created by Apprentice Alf
* The DeDRM all-in-one Python application was created by some_updates
* The DeDRM all-in-one calibre plugins was created by Apprentice Alf
* The DeDRM all-in-one calibre plugin was created by Apprentice Alf
* The Scuolabooks tool was created by Hex
* The Microsoft code was created by drs
* The Apple DRM removal tool was created by Brahms

Binary file not shown.

View File

@@ -1,53 +0,0 @@
obok_plugin.zip
================
This plugin will remove the DRM from Kobo ebooks download on Mac or Windows using the Kobo desktop application, or from Kobo ebooks on an attached E-Ink Kobo reader (but not a Kobo Arc or Kobo Vox). If both are available, ebooks will be read from the attached E-Ink Kobo reader. To import from the desktop application, unplug the Kobo reader.
Installation
------------
Open calibre's Preferences dialog. Click on the "Plugins" button. Next, click on the button, "Load plugin from file". Navigate to the unzipped DeDRM_tools folder and, in the folder "obok_calibre_plugin", find the file "obok_plugin.zip". Click to select the file and select "Open". Click "Yes" in the "Are you sure?" dialog box. Click the "OK" button in the "Success" dialog box.
Customization
-------------
No customization is required, except choosing which menus will show the plugin. Altough the ability to enter a device serial number is given, this should not need to be filled in, as the serial number should be picked up automatically from the attached Kobo reader.
Using the plugin
----------------
Select the plugin's menu or icon from whichever part of the calibre interface you have chosen to have it. Follow the instructions in the dialog that appears.
Troubleshooting
---------------
If you find that it's not working for you (imported ebooks still have DRM - that is, they won't convert or open in the calibre ebook viewer), you should make a log of import process by deleting the DRMed ebook from calibre and then adding the ebook to calibre when it's running in debug mode. This will generate a lot of helpful debugging info that can be copied into any online help requests. Here's how to do it:
On Windows, open a terminal/command window. (Start/Run… and then type 'cmd.exe' (without the 's) as the program to run).
On Macintosh, open the Terminal application (in your Utilities folder).
On Linux open a command window. Hopefully all Linux users know how to do this.
You should now have a text-based command-line window open.
Type in "calibre-debug -g" (without the "s but with the space before the -g) and press the return/enter key. Calibre will launch and run as normal, but with debugging information output to the terminal window.
Import the DRMed eBook into calibre in any of the the normal ways. (I usually drag&drop onto the calibre window.)
Debug information will be written to the terminal window.
Copy the output from the terminal window.
On Windows, you must use the window menu (little icon at left of window bar) to select all the text and then to copy it.
On Macintosh and Linux, just use the normal text select and copy commands.
Paste the information into a comment at my blog, http://apprenticealf.wordpress.com/ describing your problem.
Credits
-------
The original obok script was by Physisticated
The plugin conversion was done anonymously.
The Kobo reader support was added by norbusan
Additional improvements to the script and the plugin adaption by numerous anonymous people.

View File

@@ -3,6 +3,7 @@ from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__version__ = '6.7.0'
__docformat__ = 'restructuredtext en'
#####################################################################
@@ -19,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 = (6, 5, 4)
PLUGIN_VERSION_TUPLE = (6, 7, 0)
PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE])
HELPFILE_NAME = PLUGIN_SAFE_NAME + '_Help.htm'
PLUGIN_AUTHORS = 'Anon'

View File

@@ -93,7 +93,7 @@ class InterfacePluginAction(InterfaceAction):
debug_print("Exception getting device path. Probably not an E-Ink Kobo device")
# Get the Kobo Library object (obok v3.01)
self.library = KoboLibrary(tmpserials, device_path)
self.library = KoboLibrary(tmpserials, device_path, cfg['kobo_directory'])
debug_print ("got kobodir %s" % self.library.kobodir)
if (self.library.kobodir == ''):
# linux and no device connected, but could be extended

View File

@@ -8,6 +8,7 @@ __copyright__ = '2012, David Forrester <davidfor@internode.on.net>'
__docformat__ = 'restructuredtext en'
import os, time, re, sys
from datetime import datetime
try:
from PyQt5.Qt import (Qt, QIcon, QPixmap, QLabel, QDialog, QHBoxLayout, QProgressBar,
QTableWidgetItem, QFont, QLineEdit, QComboBox,

View File

@@ -3,9 +3,9 @@ from __future__ import (unicode_literals, division, absolute_import,
print_function)
try:
from PyQt5.Qt import (Qt, QGroupBox, QListWidget, QLineEdit, QDialogButtonBox, QWidget, QLabel, QDialog, QVBoxLayout, QAbstractItemView, QIcon, QHBoxLayout, QComboBox, QListWidgetItem)
from PyQt5.Qt import (Qt, QGroupBox, QListWidget, QLineEdit, QDialogButtonBox, QWidget, QLabel, QDialog, QVBoxLayout, QAbstractItemView, QIcon, QHBoxLayout, QComboBox, QListWidgetItem, QFileDialog)
except ImportError:
from PyQt4.Qt import (Qt, QGroupBox, QListWidget, QLineEdit, QDialogButtonBox, QWidget, QLabel, QDialog, QVBoxLayout, QAbstractItemView, QIcon, QHBoxLayout, QComboBox, QListWidgetItem)
from PyQt4.Qt import (Qt, QGroupBox, QListWidget, QLineEdit, QDialogButtonBox, QWidget, QLabel, QDialog, QVBoxLayout, QAbstractItemView, QIcon, QHBoxLayout, QComboBox, QListWidgetItem, QFileDialog)
try:
from PyQt5 import Qt as QtGui
@@ -18,6 +18,7 @@ from calibre.utils.config import JSONConfig, config_dir
plugin_prefs = JSONConfig('plugins/obok_dedrm_prefs')
plugin_prefs.defaults['finding_homes_for_formats'] = 'Ask'
plugin_prefs.defaults['kobo_serials'] = []
plugin_prefs.defaults['kobo_directory'] = u''
from calibre_plugins.obok_dedrm.__init__ import PLUGIN_NAME, PLUGIN_VERSION
from calibre_plugins.obok_dedrm.utilities import (debug_print)
@@ -37,6 +38,7 @@ class ConfigWidget(QWidget):
# copy of preferences
self.tmpserials = plugin_prefs['kobo_serials']
self.kobodirectory = plugin_prefs['kobo_directory']
combo_label = QLabel(_('When should Obok try to insert EPUBs into existing calibre entries?'), self)
layout.addWidget(combo_label)
@@ -53,15 +55,30 @@ class ConfigWidget(QWidget):
self.serials_button.clicked.connect(self.edit_serials)
layout.addWidget(self.serials_button)
self.kobo_directory_button = QtGui.QPushButton(self)
self.kobo_directory_button.setToolTip(_(u"Click to specify the Kobo directory"))
self.kobo_directory_button.setText(u"Kobo directory")
self.kobo_directory_button.clicked.connect(self.edit_kobo_directory)
layout.addWidget(self.kobo_directory_button)
def edit_serials(self):
d = ManageKeysDialog(self,u"Kobo device serial numbers",self.tmpserials, AddSerialDialog)
d = ManageKeysDialog(self,u"Kobo device serial number",self.tmpserials, AddSerialDialog)
d.exec_()
def edit_kobo_directory(self):
tmpkobodirectory = QFileDialog.getExistingDirectory(self, u"Select Kobo directory", self.kobodirectory or "/home", QFileDialog.ShowDirsOnly)
if tmpkobodirectory != u"" and tmpkobodirectory is not None:
self.kobodirectory = tmpkobodirectory
def save_settings(self):
plugin_prefs['finding_homes_for_formats'] = unicode(self.find_homes.currentText())
plugin_prefs['kobo_serials'] = self.tmpserials
plugin_prefs['kobo_directory'] = self.kobodirectory
@@ -145,28 +162,6 @@ class ManageKeysDialog(QDialog):
self.listy.clear()
self.populate_list()
def rename_key(self):
if not self.listy.currentItem():
errmsg = u"No {0} selected to rename. Highlight a keyfile first.".format(self.key_type_name)
r = error_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION),
_(errmsg), show=True, show_copy_button=False)
return
d = RenameKeyDialog(self)
d.exec_()
if d.result() != d.Accepted:
# rename cancelled or moot.
return
keyname = unicode(self.listy.currentItem().text())
if not question_dialog(self, "{0} {1}: Confirm Rename".format(PLUGIN_NAME, PLUGIN_VERSION), u"Do you really want to rename the {2} named <strong>{0}</strong> to <strong>{1}</strong>?".format(keyname,d.key_name,self.key_type_name), show_copy_button=False, default_yes=False):
return
self.plugin_keys[d.key_name] = self.plugin_keys[keyname]
del self.plugin_keys[keyname]
self.listy.clear()
self.populate_list()
def delete_key(self):
if not self.listy.currentItem():
return

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -150,6 +150,7 @@
# after all.
#
"""Manage all Kobo books, either encrypted or DRM-free."""
from __future__ import print_function
__version__ = '3.2.4'
__about__ = u"Obok v{0}\nCopyright © 2012-2016 Physisticated et al.".format(__version__)
@@ -290,8 +291,8 @@ class KoboLibrary(object):
written by the Kobo Desktop Edition application, including the list
of books, their titles, and the user's encryption key(s)."""
def __init__ (self, serials = [], device_path = None):
print __about__
def __init__ (self, serials = [], device_path = None, desktopkobodir = u""):
print(__about__)
self.kobodir = u""
kobodb = u""
@@ -344,19 +345,23 @@ class KoboLibrary(object):
if (self.kobodir == u""):
# step 4. we haven't found a device with serials, so try desktop apps
if sys.platform.startswith('win'):
import _winreg as winreg
if sys.getwindowsversion().major > 5:
if 'LOCALAPPDATA' in os.environ.keys():
# Python 2.x does not return unicode env. Use Python 3.x
self.kobodir = winreg.ExpandEnvironmentStrings(u"%LOCALAPPDATA%")
if (self.kobodir == u""):
if 'USERPROFILE' in os.environ.keys():
# Python 2.x does not return unicode env. Use Python 3.x
self.kobodir = os.path.join(winreg.ExpandEnvironmentStrings(u"%USERPROFILE%"), u"Local Settings", u"Application Data")
self.kobodir = os.path.join(self.kobodir, u"Kobo", u"Kobo Desktop Edition")
elif sys.platform.startswith('darwin'):
self.kobodir = os.path.join(os.environ['HOME'], u"Library", u"Application Support", u"Kobo", u"Kobo Desktop Edition")
if desktopkobodir != u'':
self.kobodir = desktopkobodir
if (self.kobodir == u""):
if sys.platform.startswith('win'):
import _winreg as winreg
if sys.getwindowsversion().major > 5:
if 'LOCALAPPDATA' in os.environ.keys():
# Python 2.x does not return unicode env. Use Python 3.x
self.kobodir = winreg.ExpandEnvironmentStrings(u"%LOCALAPPDATA%")
if (self.kobodir == u""):
if 'USERPROFILE' in os.environ.keys():
# Python 2.x does not return unicode env. Use Python 3.x
self.kobodir = os.path.join(winreg.ExpandEnvironmentStrings(u"%USERPROFILE%"), u"Local Settings", u"Application Data")
self.kobodir = os.path.join(self.kobodir, u"Kobo", u"Kobo Desktop Edition")
elif sys.platform.startswith('darwin'):
self.kobodir = os.path.join(os.environ['HOME'], u"Library", u"Application Support", u"Kobo", u"Kobo Desktop Edition")
#elif linux_path != None:
# Probably Linux, let's get the wine prefix and path to Kobo.
# self.kobodir = os.path.join(linux_path, u"Local Settings", u"Application Data", u"Kobo", u"Kobo Desktop Edition")
@@ -368,13 +373,12 @@ class KoboLibrary(object):
self.kobodir = u""
kobodb = u""
if (self.kobodir != u""):
self.bookdir = os.path.join(self.kobodir, u"kepub")
# make a copy of the database in a temporary file
# so we can ensure it's not using WAL logging which sqlite3 can't do.
self.newdb = tempfile.NamedTemporaryFile(mode='wb', delete=False)
print self.newdb.name
print(self.newdb.name)
olddb = open(kobodb, 'rb')
self.newdb.write(olddb.read(18))
self.newdb.write('\x01\x01')
@@ -450,7 +454,16 @@ class KoboLibrary(object):
# print u"m:{0}".format(m[0])
macaddrs.append(m[0].upper())
else:
# probably linux, let's try ipconfig under wine
# probably linux
# let's try ip
c = re.compile('\s(' + '[0-9a-f]{2}:' * 5 + '[0-9a-f]{2})(\s|$)', re.IGNORECASE)
for line in os.popen('ip -br link'):
m = c.search(line)
if m:
macaddrs.append(m.group(1).upper())
# let's try ipconfig under wine
c = re.compile('\s(' + '[0-9a-f]{2}-' * 5 + '[0-9a-f]{2})(\s|$)', re.IGNORECASE)
for line in os.popen('ipconfig /all'):
m = c.search(line)
@@ -591,32 +604,32 @@ class KoboFile(object):
# assume utf-8 with no BOM
textoffset = 0
stride = 1
print u"Checking text:{0}:".format(contents[:10])
print(u"Checking text:{0}:".format(contents[:10]))
# check for byte order mark
if contents[:3]=="\xef\xbb\xbf":
# seems to be utf-8 with BOM
print u"Could be utf-8 with BOM"
print(u"Could be utf-8 with BOM")
textoffset = 3
elif contents[:2]=="\xfe\xff":
# seems to be utf-16BE
print u"Could be utf-16BE"
print(u"Could be utf-16BE")
textoffset = 3
stride = 2
elif contents[:2]=="\xff\xfe":
# seems to be utf-16LE
print u"Could be utf-16LE"
print(u"Could be utf-16LE")
textoffset = 2
stride = 2
else:
print u"Perhaps utf-8 without BOM"
print(u"Perhaps utf-8 without BOM")
# now check that the first few characters are in the ASCII range
for i in xrange(textoffset,textoffset+5*stride,stride):
if ord(contents[i])<32 or ord(contents[i])>127:
# Non-ascii, so decryption probably failed
print u"Bad character at {0}, value {1}".format(i,ord(contents[i]))
print(u"Bad character at {0}, value {1}".format(i,ord(contents[i])))
raise ValueError
print u"Seems to be good text"
print(u"Seems to be good text")
return True
if contents[:5]=="<?xml" or contents[:8]=="\xef\xbb\xbf<?xml":
# utf-8
@@ -637,13 +650,13 @@ class KoboFile(object):
# utf-16LE of weird <!DOCTYPE start
return True
else:
print u"Bad XML: {0}".format(contents[:8])
print(u"Bad XML: {0}".format(contents[:8]))
raise ValueError
elif self.mimetype == 'image/jpeg':
if contents[:3] == '\xff\xd8\xff':
return True
else:
print u"Bad JPEG: {0}".format(contents[:3].encode('hex'))
print(u"Bad JPEG: {0}".format(contents[:3].encode('hex')))
raise ValueError()
return False
@@ -666,18 +679,18 @@ class KoboFile(object):
return contents
def decrypt_book(book, lib):
print u"Converting {0}".format(book.title)
print(u"Converting {0}".format(book.title))
zin = zipfile.ZipFile(book.filename, "r")
# make filename out of Unicode alphanumeric and whitespace equivalents from title
outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
if (book.type == 'drm-free'):
print u"DRM-free book, conversion is not needed"
print(u"DRM-free book, conversion is not needed")
shutil.copyfile(book.filename, outname)
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
return 0
result = 1
for userkey in lib.userkeys:
print u"Trying key: {0}".format(userkey.encode('hex_codec'))
print(u"Trying key: {0}".format(userkey.encode('hex_codec')))
try:
zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
for filename in zin.namelist():
@@ -689,12 +702,12 @@ def decrypt_book(book, lib):
file.check(contents)
zout.writestr(filename, contents)
zout.close()
print u"Decryption succeeded."
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
print(u"Decryption succeeded.")
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
result = 0
break
except ValueError:
print u"Decryption failed."
print(u"Decryption failed.")
zout.close()
os.remove(outname)
zin.close()
@@ -719,8 +732,8 @@ def cli_main():
books = lib.books
else:
for i, book in enumerate(lib.books):
print u"{0}: {1}".format(i + 1, book.title)
print u"Or 'all'"
print(u"{0}: {1}".format(i + 1, book.title))
print(u"Or 'all'")
choice = raw_input(u"Convert book number... ")
if choice == u'all':
@@ -730,14 +743,14 @@ def cli_main():
num = int(choice)
books = [lib.books[num - 1]]
except (ValueError, IndexError):
print u"Invalid choice. Exiting..."
print(u"Invalid choice. Exiting...")
exit()
results = [decrypt_book(book, lib) for book in books]
lib.close()
overall_result = all(result != 0 for result in results)
if overall_result != 0:
print u"Could not decrypt book with any of the keys found."
print(u"Could not decrypt book with any of the keys found.")
return overall_result

Binary file not shown.

View File

@@ -0,0 +1,366 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-11-17 12:51+0100\n"
"PO-Revision-Date: 2020-02-02 09:18+0100\n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Last-Translator: \n"
"Language-Team: \n"
"X-Generator: Poedit 2.2.4\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:80
msgid ""
"<p>No books found in Kobo Library\n"
"Are you sure it's installed\\configured\\synchronized?"
msgstr ""
"<p>Inga böcker finns i Kobo-bibliotek\n"
"Är du säker på att den är installerad\\konfigurerad\\synkroniserad?"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:87
msgid "Legacy key found: "
msgstr "Äldre nyckel hittades: "
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:93
msgid "Trouble retrieving keys with newer obok method."
msgstr "Problem med att hämta nycklar med nyare obok-metod."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:97
msgid "Found {0} possible keys to try."
msgstr "Hittade {0} möjliga nycklar att pröva med."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:99
msgid "<p>No userkeys found to decrypt books with. No point in proceeding."
msgstr ""
"<p>Inga användarnycklar hittades för att dekryptera böcker med. Det är ingen "
"idé att fortsätta."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:115
msgid "{} - Decryption canceled by user."
msgstr "{} - Dekryptering avbryts av användaren."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:135
msgid "{} - \"Add books\" canceled by user."
msgstr "{} - \"Lägg till böcker\" avbröts av användaren."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:137
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:156
msgid "{} - wrapping up results."
msgstr "{} - samlar in resultat."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:153
msgid "{} - User opted not to try to insert EPUB formats"
msgstr "{} - Användaren valde att inte försöka infoga EPUB-format"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:188
msgid "{0} - Decrypting {1}"
msgstr "{0} - Dekrypterar {1}"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:197
msgid "{0} - Couldn't decrypt {1}"
msgstr "{0} - Kunde inte dekryptera {1}"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:198
msgid "decryption errors"
msgstr "dekrypteringsfel"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:213
msgid "{0} - Added {1}"
msgstr "{0} - Lade till {1}"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:218
msgid "{0} - {1} already exists. Will try to add format later."
msgstr "{0} - {1} finns redan. Kommer att försöka lägga till format senare."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:219
msgid "duplicate detected"
msgstr "dubblett upptäcktes"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:233
msgid "{0} - Successfully added EPUB format to existing {1}"
msgstr "{0} - Lade till EPUB-format till befintliga {1}"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:236
msgid ""
"{0} - Error adding EPUB format to existing {1}. This really shouldn't happen."
msgstr ""
"{0} - Fel vid tillägg av EPUB-format till befintligt {1}. Det här borde inte "
"hända."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:259
msgid "{} - \"Insert formats\" canceled by user."
msgstr "{} - \"Infoga format\" avbröts av användaren."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:291
msgid ""
"<p><b>{0}</b> EPUB{2} successfully added to library.<br /><br /><b>{1}</b> "
msgstr "<p><b>{0}</b> EPUB{2} lades till bibliotek.<br /><br /><b>{1}</b> "
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:292
msgid ""
"not added because books with the same title/author were detected.<br /><br /"
">Would you like to try and add the EPUB format{0}"
msgstr ""
"inte tillagd eftersom böcker med samma titel/författare upptäcktes.<br/><br /"
">Vill du försöka lägga till EPUB-formatet{0}"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:293
msgid ""
" to those existing entries?<br /><br />NOTE: no pre-existing EPUBs will be "
"overwritten."
msgstr ""
" till dessa befintliga poster?<br /><br />OBS: inga befintliga EPUB:er "
"kommer att skrivas över."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:295
msgid ""
"{0} -- not added because of {1} in your library.\n"
"\n"
msgstr ""
"{0} -- inte tillagd på grund av {1} i ditt bibliotek.\n"
"\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:297
msgid "<p><b>{0}</b> -- not added because of {1} in your library.<br /><br />"
msgstr ""
"<p><b>{0}</b> -- inte tillagd på grund av {1} i ditt bibliotek.<br /><br />"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:298
msgid ""
"Would you like to try and add the EPUB format to an available calibre "
"duplicate?<br /><br />"
msgstr ""
"Vill du försöka lägga till EPUB-formatet till en tillgänglig calibre-"
"dubblett?<br /><br />"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:299
msgid "NOTE: no pre-existing EPUB will be overwritten."
msgstr "OBS: ingen befintlig EPUB kommer att skrivas över."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:346
msgid "Trying key: "
msgstr "Prövar nyckel: "
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:378
msgid "Decryption failed, trying next key."
msgstr "Det gick inte att dekryptera, prövar nästa nyckel."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:382
msgid "Unknown Error decrypting, trying next key.."
msgstr "Okänt fel dekryptering, prövar nästa nyckel.."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:395
msgid ""
"<p>All selected Kobo books added as new calibre books or inserted into "
"existing calibre ebooks.<br /><br />No issues."
msgstr ""
"<p>Alla valda Kobo-böcker läggs till som nya calibre-böcker eller infogas i "
"befintliga calibre-e-böcker.<br /><br />Inga problem."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:399
msgid "<p>{0} successfully added."
msgstr "<p>{0} har lagts till."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:403
msgid ""
"<p>Not all selected Kobo books made it into calibre.<br /><br />View report "
"for details."
msgstr ""
"<p>Inte alla valda Kobo-böcker lades till i calibre.<br /><br />Visa rapport "
"för detaljer."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:404
msgid "<p><b>Total attempted:</b> {}</p>\n"
msgstr "<p><b>Försök totalt:</b> {}</p>\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:405
msgid "<p><b>Decryption errors:</b> {}</p>\n"
msgstr "<p><b>Dekrypteringsfel:</b> {}</p>\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:411
msgid "<p><b>New Books created:</b> {}</p>\n"
msgstr "<p><b>Nya böcker skapade:</b> {}</p>\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:418
msgid "<p><b>Duplicates that weren't added:</b> {}</p>\n"
msgstr "<p><b>Dubbletter som inte tillsattes:</b> {}</p>\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:426
msgid "<p><b>Book imports cancelled by user:</b> {}</p>\n"
msgstr "<p><b>Bokimport avbröts av användaren:</b> {}</p>\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:428
msgid ""
"<p><b>New EPUB formats inserted in existing calibre books:</b> {0}</p>\n"
msgstr ""
"<p><b>Nya EPUB-format infogade i befintliga calibre-böcker:</b> {0}</p>\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:434
msgid ""
"<p><b>EPUB formats NOT inserted into existing calibre books:</b> {}<br />\n"
msgstr ""
"<p><b>EPUB-format som INTE infogats i befintliga calibre-böcker:</b> {}<br /"
">\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:435
msgid ""
"(Either because the user <i>chose</i> not to insert them, or because all "
"duplicates already had an EPUB format)"
msgstr ""
"(Antingen för att användaren <i>valde</i> att inte infoga dem, eller för att "
"alla dubbletter redan hade ett EPUB-format)"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:444
msgid "<p><b>Format imports cancelled by user:</b> {}</p>\n"
msgstr "<p><b>Format-import avbröts av användaren:</b> {}</p>\n"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:458
msgid "Unknown Book Title"
msgstr "Okänd boktitel"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:460
msgid "it couldn't be decrypted."
msgstr "den kunde inte dekrypteras."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:462
msgid ""
"user CHOSE not to insert the new EPUB format, or all existing calibre "
"entries HAD an EPUB format already."
msgstr ""
"användaren VALDE att inte infoga det nya EPUB-formatet, eller alla "
"befintliga calibre-poster hade redan ett EPUB-format."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:464
msgid "of unknown reasons. Gosh I'm embarrassed!"
msgstr "av okända skäl. Jag skäms!"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\action.py:465
msgid "<p>{0} not added because {1}"
msgstr "<p>{0} inte tillagd eftersom {1}"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\common_utils.py:226
msgid "Help"
msgstr "Hjälp"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\common_utils.py:235
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\utilities.py:214
msgid "Restart required"
msgstr "Omstart krävs"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\common_utils.py:236
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\utilities.py:215
msgid ""
"Title image not found - you must restart Calibre before using this plugin!"
msgstr ""
"Titelbild hittades inte - du måste starta calibre innan du använder denna "
"insticksmodul!"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\common_utils.py:322
msgid "Undefined"
msgstr "Obestämd"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\config.py:30
msgid "When should Obok try to insert EPUBs into existing calibre entries?"
msgstr "När ska Obok försöka infoga EPUB:er i befintliga calibre-böcker?"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\config.py:33
msgid ""
"<p>Default behavior when duplicates are detected. None of the choices will "
"cause calibre ebooks to be overwritten"
msgstr ""
"<p>Standardbeteende när dubbletter upptäcks. Inget av alternativen kommer "
"att orsaka calibre-e-böcker att skrivas över"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\config.py:35
msgid "Ask"
msgstr "Fråga"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\config.py:35
msgid "Always"
msgstr "Alltid"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\config.py:35
msgid "Never"
msgstr "Aldrig"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:60
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\utilities.py:150
msgid " v"
msgstr " v"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:65
msgid "Obok DeDRM"
msgstr "Obok DeDRM"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:68
msgid "<a href=\"http://www.foo.com/\">Help</a>"
msgstr "<a href=\"http://www.foo.com/\">Hjälp</a>"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:89
msgid "Select All"
msgstr "Välj alla"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:90
msgid "Select all books to add them to the calibre library."
msgstr "Välj alla böcker för att lägga till dem i calibre-biblioteket."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:92
msgid "All with DRM"
msgstr "Alla med DRM"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:93
msgid "Select all books with DRM."
msgstr "Välj alla böcker med DRM."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:95
msgid "All DRM free"
msgstr "Alla DRM fria"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:96
msgid "Select all books without DRM."
msgstr "Välj alla böcker utan DRM."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:146
msgid "Title"
msgstr "Titel"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:146
msgid "Author"
msgstr "Författare"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:146
msgid "Series"
msgstr "Serier"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:369
msgid "Copy to clipboard"
msgstr "Kopiera till urklipp"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\dialogs.py:397
msgid "View Report"
msgstr "Visa rapport"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\__init__.py:21
msgid "Removes DRM from Kobo kepubs and adds them to the library."
msgstr "Tar bort DRM från Kobo-kepubs och lägger till dem i biblioteket."
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\obok\obok.py:162
msgid "AES improper key used"
msgstr "AES felaktig nyckel används"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\obok\obok.py:167
msgid "Failed to initialize AES key"
msgstr "Det gick inte att initiera AES-nyckel"
#: I:\Herramientas\PoeditPortable\App\Poedit\bin\obok_plugin-3.1.0_trad\obok\obok.py:175
msgid "AES decryption failed"
msgstr "AES dekryptering misslyckades"

49
Other_Tools/Kobo/obok.py Executable file → Normal file
View File

@@ -150,6 +150,7 @@
# after all.
#
"""Manage all Kobo books, either encrypted or DRM-free."""
from __future__ import print_function
__version__ = '3.2.4'
__about__ = u"Obok v{0}\nCopyright © 2012-2016 Physisticated et al.".format(__version__)
@@ -291,7 +292,7 @@ class KoboLibrary(object):
of books, their titles, and the user's encryption key(s)."""
def __init__ (self, serials = [], device_path = None):
print __about__
print(__about__)
self.kobodir = u""
kobodb = u""
@@ -374,7 +375,7 @@ class KoboLibrary(object):
# make a copy of the database in a temporary file
# so we can ensure it's not using WAL logging which sqlite3 can't do.
self.newdb = tempfile.NamedTemporaryFile(mode='wb', delete=False)
print self.newdb.name
print(self.newdb.name)
olddb = open(kobodb, 'rb')
self.newdb.write(olddb.read(18))
self.newdb.write('\x01\x01')
@@ -449,6 +450,10 @@ class KoboLibrary(object):
for m in matches:
# print u"m:{0}".format(m[0])
macaddrs.append(m[0].upper())
elif sys.platform.startswith('linux'):
p_out = subprocess.check_output("ip -br link show | awk '{print $3}'", shell=True)
for line in p_out:
macaddrs.append(line.upper())
else:
# probably linux, let's try ipconfig under wine
c = re.compile('\s(' + '[0-9a-f]{2}-' * 5 + '[0-9a-f]{2})(\s|$)', re.IGNORECASE)
@@ -591,32 +596,32 @@ class KoboFile(object):
# assume utf-8 with no BOM
textoffset = 0
stride = 1
print u"Checking text:{0}:".format(contents[:10])
print(u"Checking text:{0}:".format(contents[:10]))
# check for byte order mark
if contents[:3]=="\xef\xbb\xbf":
# seems to be utf-8 with BOM
print u"Could be utf-8 with BOM"
print(u"Could be utf-8 with BOM")
textoffset = 3
elif contents[:2]=="\xfe\xff":
# seems to be utf-16BE
print u"Could be utf-16BE"
print(u"Could be utf-16BE")
textoffset = 3
stride = 2
elif contents[:2]=="\xff\xfe":
# seems to be utf-16LE
print u"Could be utf-16LE"
print(u"Could be utf-16LE")
textoffset = 2
stride = 2
else:
print u"Perhaps utf-8 without BOM"
print(u"Perhaps utf-8 without BOM")
# now check that the first few characters are in the ASCII range
for i in xrange(textoffset,textoffset+5*stride,stride):
if ord(contents[i])<32 or ord(contents[i])>127:
# Non-ascii, so decryption probably failed
print u"Bad character at {0}, value {1}".format(i,ord(contents[i]))
print(u"Bad character at {0}, value {1}".format(i,ord(contents[i])))
raise ValueError
print u"Seems to be good text"
print(u"Seems to be good text")
return True
if contents[:5]=="<?xml" or contents[:8]=="\xef\xbb\xbf<?xml":
# utf-8
@@ -637,13 +642,13 @@ class KoboFile(object):
# utf-16LE of weird <!DOCTYPE start
return True
else:
print u"Bad XML: {0}".format(contents[:8])
print(u"Bad XML: {0}".format(contents[:8]))
raise ValueError
elif self.mimetype == 'image/jpeg':
if contents[:3] == '\xff\xd8\xff':
return True
else:
print u"Bad JPEG: {0}".format(contents[:3].encode('hex'))
print(u"Bad JPEG: {0}".format(contents[:3].encode('hex')))
raise ValueError()
return False
@@ -666,18 +671,18 @@ class KoboFile(object):
return contents
def decrypt_book(book, lib):
print u"Converting {0}".format(book.title)
print(u"Converting {0}".format(book.title))
zin = zipfile.ZipFile(book.filename, "r")
# make filename out of Unicode alphanumeric and whitespace equivalents from title
outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
if (book.type == 'drm-free'):
print u"DRM-free book, conversion is not needed"
print(u"DRM-free book, conversion is not needed")
shutil.copyfile(book.filename, outname)
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
return 0
result = 1
for userkey in lib.userkeys:
print u"Trying key: {0}".format(userkey.encode('hex_codec'))
print(u"Trying key: {0}".format(userkey.encode('hex_codec')))
try:
zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
for filename in zin.namelist():
@@ -689,12 +694,12 @@ def decrypt_book(book, lib):
file.check(contents)
zout.writestr(filename, contents)
zout.close()
print u"Decryption succeeded."
print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
print(u"Decryption succeeded.")
print(u"Book saved as {0}".format(os.path.join(os.getcwd(), outname)))
result = 0
break
except ValueError:
print u"Decryption failed."
print(u"Decryption failed.")
zout.close()
os.remove(outname)
zin.close()
@@ -719,8 +724,8 @@ def cli_main():
books = lib.books
else:
for i, book in enumerate(lib.books):
print u"{0}: {1}".format(i + 1, book.title)
print u"Or 'all'"
print(u"{0}: {1}".format(i + 1, book.title))
print(u"Or 'all'")
choice = raw_input(u"Convert book number... ")
if choice == u'all':
@@ -730,14 +735,14 @@ def cli_main():
num = int(choice)
books = [lib.books[num - 1]]
except (ValueError, IndexError):
print u"Invalid choice. Exiting..."
print(u"Invalid choice. Exiting...")
exit()
results = [decrypt_book(book, lib) for book in books]
lib.close()
overall_result = all(result != 0 for result in results)
if overall_result != 0:
print u"Could not decrypt book with any of the keys found."
print(u"Could not decrypt book with any of the keys found.")
return overall_result

View File

@@ -8,8 +8,12 @@ Mostly it tracks the tools releases by Apprentice Alf, athough it also includes
Users should download the latest zip archive.
Developers might be interested in forking the repository, as it contains unzipped versions of those tools that are zipped, and text versions of the AppleScripts, to make the changes over time easier to follow.
For the latest Amazon KFX format, users of the calibre plugin should also install the KFX Input plugin from the standard calibre plugin menu. It's also available from the MobileRead thread here: https://www.mobileread.com/forums/showthread.php?t=291290
I welcome contributions from others to improve these tools, from expanding the range of books handled, improving key retrieval, to just general bug fixes, speed improvements and UI enhancements.
I urge people to read the FAQs. But to cover the most common: Use ADE 2.0.1 to be sure not to get the new DRM scheme that these tools can't handle. Use Kindle for Mac/PC 1.24 or earlier, the tools don't currently work with 1.25 or later. Do remember to unzip the downloaded archive to get the plugin. You can't load the whole archive into calibre.
My special thanks to all those developers who have done the hard work of reverse engineering to provide the initial tools.
Apprentice Harper.

View File

@@ -1,161 +0,0 @@
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.6.0 archive from Apprentice Harper's github repository: https://github.com/apprenticeharper/DeDRM_tools/
The is archive includes tools to remove DRM from:
- Kindle ebooks (files from Kindle for Mac/PC* and eInk Kindles**).
- Adobe Digital Editions (v2.0.1***) ePubs (including Kobo and Google ePubs downloaded to ADE)
- Kobo kePubs from the Kobo Desktop application
- Barnes and Noble ePubs
- Adobe Digital Editions (v2.0.1) PDFs
- Scuolabooks (Link to solution by Hex)
- Mobipocket ebooks
- eReader PDB ebooks
- Rocket ebooks (source only)
These tools do NOT work with Apple's iBooks FairPlay DRM (see end of this file.)
* With Kindle for PC/Mac 1.19 and later, Amazon included support for their new KFX format. While the tools now include a first attempt at supporting drm removal for KFX format, we recommend using Kindle for PC/Mac 1.17 or earlier which prevents downloads of the new format, as conversions from the olde KF8 format are likely to be more successful.
** Some later Kindles support Amazon's new KFX format. And some books download in a split azw3/azw6 format. For best results, instead of using files downloaded directly to your Kindle, download from Amazon's web site 'for transfer via USB'. This will give you an single file to import. See also the FAQ entry about this.
*** With Adobe Digital Editions 3.0 and later, Adobe have introduced a new, optional, DRM scheme. To avoid this new scheme, you should use Adobe Digital Editions 2.0.1. Some books are required to use the new DRM scheme and so will not download with ADE 2.0.1. If you still want such a book, you will need to use ADE 3.0 or later to download it, but you should remember that no tools to remove Adobe's new DRM scheme exist as of June 2017.
About the tools
---------------
These tools are updated and maintained by Apprentice Harper and many others. You can find the latest updates at Apprentice Harper's github repository https://github.com/apprenticeharper/DeDRM_tools/ and get support by creating an issue at the repository (github account required) or by posting a comment at Apprentice Alf's blog: http://www.apprenticealf.wordpress.com/
If you re-post these tools, a link to the repository and/or the blog would be appreciated.
DeDRM plugin for calibre (Mac OS X, Windows, and Linux)
-------------------------------------------------------
Calibre is an open source freeware ebook library manager. It is the best tool around for keeping track of your ebooks. The DeDRM plugin for calibre provides the simplest way, especially on Windows, to remove DRM from your Kindle and Adobe DRM ebooks. Just install the DeDRM plugin from the DeDRM_calibre_plugin folder, following the instructions and configuration directions provided in the ReadMe file and the help links in the plugin's configuration dialogs.
Once installed and configured, you can simply add a DRM book to calibre and the DRM-free version will be imported into the calibre database. Note that DRM removal only occurs on IMPORT not on CONVERSION or at any other time. If you have already imported DRM books you'll need to remove them from calibre and re-import them.
For instructions, see the DeDRM_plugin_ReadMe.txt file in the DeDRM_calibre_plugin folder.
Obok plugin for calibre (Mac OS X and Windows)
----------------------------------------------
To import ebooks from the Kobo Desktop app or from a Kobo ebook reader, install the Obok plugin. This works in a different way to the DeDRM plugin, in that it finds your ebooks downloaded using the Kobo Desktop app, or on an attached Kobo ebooks reader, and displays them in a list, so that you can choose the ones you want to import into calibre.
For instructions, see the obok_plugin_ReadMe.txt file in the Obok_calibre_plugin folder.
DeDRM application for Mac OS X users: (Mac OS X 10.4 and above)
---------------------------------------------------------------
This application is a stand-alone DRM removal application for Mac OS X users. It is only needed for people who cannot or will not use the calibre plugin. KFX support has not been tested yet.
For instructions, see the "DeDRM ReadMe.rtf" file in the DeDRM_Macintosh_Application folder.
N.B. Mac OS X 10.4 users need to take extra steps before using the application, see the ReadMe.
DeDRM application for Windows users: (Windows XP through Windows 10)
------------------------------------------------------------------
***This program requires that Python and PyCrypto be properly installed.***
***See below for details on recommended versions and how to install them.***
This application is a stand-alone application for Windows users. It is only needed for people who cannot or will not use the calibre plugin. KFX support has not been tested yet.
For instructions, see the DeDRM_App_ReadMe.txt file in the DeDRM_Windows_Applications folder.
Other_Tools
-----------
This is a folder of other tools that may be useful for DRMed ebooks from certain sources or for Linux users. Most users won't need any of these tools.
B_and_N_Download_Helper
A Javascript to enable a download button at the B&N website for ebooks that normally won't download to your PC. Only for the adventurous.
DRM_Key_Scripts
This folder contains python scripts that create or extract or fetch encryption keyfiles for Barnes and Noble, Adobe Digital Editions, Kindle for Mac/PC and old versons of Kindle for Android.
Kindle_for_Android_Patches
Definitely only for the adventurous, this folder contains information on how to modify the Kindle for Android app to b able to get a PID for use with the other Kindle tools (DeDRM apps and calibre plugin).
Kobo
Contains the standalone obok python script for removing DRM from kePubs downloaded using the kobo desktop application.
Rocket_ebooks
Information about the now-obsolete Rocket ebook format and DRM, along with source for a tool to remove the DRM.
Scuolabook_DRM
A link to the tool for removing DRM from ScuolaBooks PDFs, created by "Hex".
Windows and Python
------------------
We **strongly** recommend using calibre and the plugin.
If you really want to use the WIndows app or the individual scripts, you'll need to install python.
ActiveState's Active Python 2.7 Community Edition for Windowscan be downloaded for free from:
http://www.activestate.com/activepython/downloads
In addition, Windows Users need PyCrypto:
There are many places to get PyCrypto installers for Windows. One such place is:
http://www.voidspace.org.uk/python/modules.shtml
Please get the latest (currently 2.6) PyCrypto meant for Windows Python version 2.7. Note that the PyCrypto binaries have two version numbers. The first is the PyCrypto version, and the second is the python version that they work with. This can be confusing.
Once Windows users have installed Python 2.7, and the matching PyCrypto, they are ready to run the DeDRM application or individual scripts.
For (experimental) KFX support, you also need LZMA support. LZMA is built-in
in Python 3.3+ but not present in Python 2. Choices are backports.lzma and
pylzma, both of which need compiling. Compiling Python extensions on Windows
requires Visual Studio and is a PITA. The recommended way is to install wheels
(binary) directly.
Windows binary wheels for backports.lzma and pylzma could be found here:
https://www.lfd.uci.edu/~gohlke/pythonlibs/
Apple's iBooks FairPlay DRM
---------------------------
The only tool that removes Apple's iBooks Fairplay DRM is Requiem by Brahms version 3.3.6 and works with iTunes 10.5. Requiem 4.0 and later do not remove DRM from ebooks.
Requiem is no longer developed as of 2012, with the last version 4.1.
You can download it from these download links:
Requiem 3.3.6 for Windows: http://www.datafilehost.com/download-f7916922.html
MD5: 10ab191f2d86c692d57f6a07b4622cf8
Requiem 3.3.6 for Mac OS X: http://www.datafilehost.com/download-47fce8b7.html
MD5: 6d4167d47e6982ddbb8528212198b520
Requiem 3.3.6 source code: http://www.datafilehost.com/download-172920e9.html
MD5: 1636862796d573c693d56bcc526b60bd
No support for requiem is provided at Apprentice Alf's blog or Apprentice Harper's github repository.
Credits
-------
The original inept and ignoble scripts were by i♥cabbages
The original mobidedrm and erdr2pml scripts were by The Dark Reverser
The original topaz DRM removal script was by CMBDTC
The original topaz format conversion scripts were by some_updates, clarknova and Bart Simpson
The original KFX format decryption was by lulzkabulz, converted to python by Apprentice Naomi and integrated into the tools by tomthumb1997
The original obok script was by Physisticated
The alfcrypto library is by some_updates
The ePub encryption detection script is by Apprentice Alf, adapted from a script by Paul Durrant
The ignoblekey script is by Apprentice Harper
The DeDRM plugin was based on plugins by DiapDealer and is maintained by Apprentice Alf and Apprentice Harper
The DeDRM AppleScript was by Paul Durrant and is maintained by Apprentice Alf and Apprentice Harper
The DeDRM python GUI was by some_updates and is maintained by Apprentice Alf and Apprentice Harper
The Scuolabooks tool is by Hex
Many fixes, updates and enhancements to the scripts and applicatons have been made by many other people. For more details, see the commments in the individual scripts.

67
ReadMe_Overview.txt Normal file
View File

@@ -0,0 +1,67 @@
Welcome to the tools!
=====================
This file is to give users a quick overview of what is available and how to get started. This document is part of the DeDRM Tools archive from Apprentice Harper's github repository: https://github.com/apprenticeharper/DeDRM_tools/
This archive includes calibre plugins to remove DRM from:
- Kindle ebooks (files from Kindle for Mac/PC and eInk Kindles).
- Adobe Digital Editions (v2.0.1***) ePubs (including Kobo and Google ePubs downloaded to ADE)
- Adobe Digital Editions (v2.0.1) PDFs
- Kobo kePubs from the Kobo Desktop application and attached Kobo readers.
These tools do NOT work with Apple's iBooks FairPlay DRM. Use iBook Copy from TunesKit.
These tools no longer work well with books from Barnes & Noble.
For limitations and work-arounds, see the FAQ at https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md
About the tools
---------------
These tools are updated and maintained by Apprentice Harper and many others. You can find the latest updates at Apprentice Harper's github repository https://github.com/apprenticeharper/DeDRM_tools/ and get support by creating an issue at the repository (github account required) or by posting a comment at Apprentice Alf's blog: http://www.apprenticealf.wordpress.com/
If you re-post these tools, a link to the repository and/or the blog would be appreciated.
The tools are provided in the form of plugins for calibre. Calibre is an open source freeware ebook library manager. It is the best tool around for keeping track of your ebooks.
DeDRM plugin for calibre (Mac OS X, Windows)
-------------------------------------------------------
The DeDRM plugin for calibre removes DRM from your Kindle and Adobe DRM ebooks when they are imported to calibre. Just install the DeDRM plugin (DeDRM_plugin.zip), following the instructions and configuration directions provided in the ReadMe file and the help links in the plugin's configuration dialogs.
Once installed and configured, you can simply add a DRM book to calibre and a DRM-free version will be imported into the calibre database. Note that DRM removal only occurs on IMPORT not on CONVERSION or at any other time. If you have already imported DRMed books you'll need to remove the books from calibre and re-import them.
Obok plugin for calibre (Mac OS X and Windows)
----------------------------------------------
To import ebooks from the Kobo Desktop app or from a Kobo ebook reader, install the Obok plugin. This works in a different way to the DeDRM plugin, in that it finds your ebooks downloaded using the Kobo Desktop app, or on an attached Kobo ebooks reader, and displays them in a list, so that you can choose the ones you want to import into calibre.
For instructions, see the obok_plugin_ReadMe.txt file.
DeDRM application for Mac OS X users: (Mac OS X 10.6 and above)
---------------------------------------------------------------
DeDRM application for Windows users: (Windows XP through Windows 10)
------------------------------------------------------------------
As of Version 6.7 of the tools, these are no longer provided or supported.
Linux support
-------------
It may be possible to use the plugins on a Linux system, but no support is given at this time.
Credits
-------
The original inept and ignoble scripts were by i♥cabbages
The original mobidedrm and erdr2pml scripts were by The Dark Reverser
The original topaz DRM removal script was by CMBDTC
The original topaz format conversion scripts were by some_updates, clarknova and Bart Simpson
The original KFX format decryption was by lulzkabulz, converted to python by Apprentice Naomi and integrated into the tools by tomthumb1997
The alfcrypto library is by some_updates
The DeDRM plugin was based on plugins by DiapDealer and is maintained by Apprentice Alf and Apprentice Harper
The original obok script was by Physisticated
The plugin conversion was done anonymously.
The Kobo reader support was added by norbusan
Fixes, updates and enhancements to the scripts and applicatons have been made by many other anonymous people.

View File

@@ -1,111 +0,0 @@
DeDRM_plugin.zip
================
This calibre plugin replaces many previously separate DRM removal plugins. Before you install this plugin, you should uninstall any older individual DRM removal plugins, e.g. K4MobiDeDRM. The exception is the obok plugin, which should not be removed.
This plugin will remove the DRM from
- Kindle ebooks (files from Kindle for Mac/PC* and eInk Kindles**).
- Barnes and Noble ePubs
- Adobe Digital Editions (v2.0.1***) ePubs (including Kobo and Google ePubs downloaded to ADE)
- Adobe Digital Editions (v2.0.1) PDFs
- Mobipocket ebooks
- eReader PDB books
These tools do NOT work with kepubs downloaded using Kobo's desktop app (see the separate obok plugin) nor Apple's iBooks FairPlay DRM (see details about Requiem at the end of this file.)
* With Kindle for PC/Mac 1.19 and later, Amazon included support for their new KFX format. While the tools now include a first attempt at supporting drm removal for KFX format, we recommend using Kindle for PC/Mac 1.17 or earlier which prevents downloads of the new format, as conversions from the olde KF8 format are likely to be more successful.
** Some later Kindles support Amazon's new KFX format. And some books download in a split azw3/azw6 format. For best results, instead of using files downloaded directly to your Kindle, download from Amazon's web site 'for transfer via USB'. This will give you an single file to import. See also the FAQ entry about this.
*** With Adobe Digital Editions 3.0 and later, Adobe have introduced a new, optional, DRM scheme. To avoid this new scheme, you should use Adobe Digital Editions 2.0.1. Some books are required to use the new DRM scheme and so will not download with ADE 2.0.1. If you still want such a book, you will need to use ADE 3.0 or later to download it, but you should remember that no tools to remove Adobe's new DRM scheme exist as of October 2017.
Installation
------------
Open calibre's Preferences dialog. Click on the "Plugins" button. Next, click on the button, "Load plugin from file". Navigate to the unzipped DeDRM_tools folder and, in the folder "DeDRM_calibre_plugin", find the file "DeDRM_plugin.zip". Click to select the file and select "Open". Click "Yes" in the "Are you sure?" dialog box. Click the "OK" button in the "Success" dialog box.
Customization
-------------
You MUST add some key information for the following kinds of ebooks:
- Kindle ebooks from an E-Ink based Kindle (e.g. Voyage).
- Barnes & Noble ePubs other than those downloaded using NOOK Study
- Mobipocket ebooks
- eReader PDB books
You do not need to add any key information for eBooks
- downloaded using Kindle for Mac/PC
- downloaded using Adobe Digital Editions (v2.0.1)
- downloaded using NOOK Study
as the necessary keys are automatically retrieved from files on your computer.
To add needed key information for other books, highlight the plugin (DeDRM under the "File type plugins" category) and click the "Customize Plugin" button.
The buttons in the configuration dialog will open individual configuration dialogs that will allow you to enter the needed information, depending on the type and source of your DRMed eBooks. Additional help on the information required is available in each of the the dialogs vias the [?] help button.
If you have used previous versions of the various DeDRM plugins on this machine, you may find that some of the configuration dialogs already contain the information you entered through those previous plugins.
When you have finished entering your configuration information, you must click the OK button to save it. If you click the Cancel button, all your changes in all the configuration dialogs will be lost.
Troubleshooting
---------------
If you find that the DeDRM plugin is not working for you (imported ebooks still have DRM - that is, they won't convert or open in the calibre ebook viewer), you should make a log of the import process by deleting the DRMed ebook from calibre and then adding the ebook to calibre when it's running in debug mode. This will generate a lot of helpful debugging info that can be copied into any online help requests. Here's how to do it:
- Remove the DRMed book from calibre.
- Click the Preferences drop-down menu and choose 'Restart in debug mode'.
- Once calibre has re-started, import the problem ebook.
- Now close calibre.
A log will appear that you can copy and paste into a comment at Apprentice Alf's blog, http://apprenticealf.wordpress.com/ or an issue at Apprentice Harper's repository, https://github.com/apprenticeharper/DeDRM_tools/issues . You should also give details of your computer, and how you obtained the ebook file.
Credits
-------
The original inept and ignoble scripts were by i♥cabbages
The original mobidedrm and erdr2pml scripts were by The Dark Reverser
The original topaz DRM removal script was by CMBDTC
The original topaz format conversion scripts were by some_updates, clarknova and Bart Simpson
The original obok script was by Physisticated
The original KFX format decryption was by lulzkabulz, converted to python by Apprentice Naomi and integrated into the tools by tomthumb1997
The alfcrypto library is by some_updates
The ePub encryption detection script is by Apprentice Alf, adapted from a script by Paul Durrant
The ignoblekey script is by Apprentice Harper
The DeDRM plugin was based on plugins by DiapDealer and is maintained by Apprentice Alf and Apprentice Harper
Many fixes, updates and enhancements to the scripts and applicatons have been made by many other people. For more details, see the commments in the individual scripts.
Linux Systems Only
==================
Instructions for installing Wine, Kindle for PC, Adobe Digital Editions, Python and PyCrypto
--------------------------------------------------------------------------------------------
These instructions have been tested with Wine 1.4 on Ubuntu but are now very out of date.
1. First download the software you're going to to have to install.
a. Adobe Digital Editions 1.7.x from http://helpx.adobe.com/digital-editions/kb/cant-install-digital-editions.html
(Adobe Digital Editions 2.x doesn't work with Wine.)
b. Python 2.7.X for Windows (x86) from https://www.python.org/ftp/python/2.7.13/python-2.7.13.msi
c. PyCrypto 2.1 for 32bit Windows and Python 2.7 from http://www.voidspace.org.uk/python/modules.shtml#pycrypto
(PyCrypto downloads as a zip file. You will need to unzip it.)
2. Install Wine for 32-bit x86. (e.g. on Ubuntu, Open the Ubuntu Software Center, search for Wine, and install "Wine Windows Program Loader".)
2a. [update] Kindle for PC now requires Windows 7, so in the following setups, choose any option for Windows 7, not Windows XP.
3. Run "Configure Wine", which will set up the default 'wineprefix'
4. Navigate to "Install an application" and install Kindle. Alternatively, run `winetricks kindle`
5. Install Adobe Digital Editions. Accept all defaults and register with your Adobe ID.
6. Install Python 2.7.x using `msiexec /i python-2.7.8.msi`. Accept all defaults.
7. Install PyCrypto 2.1. Accept all defaults.
8. Unzip DeDRM_plugin.zip and move kindlekey.py to somewhere in drive_c, such as ~/.wine/drive_c/DeDRM/libraryfiles/kindlekey.py.
9. Run `wine 'C:\Python27/python.exe' 'C:\DeDRM/libraryfiles/kindlekey.py'`, or wherever you copied kindlekey.py to.
10. Import the resulting key file to the Calibre plugin through the Kindle for Mac/PC ebooks option.
Instructions for getting Kindle for PC and Adobe Digital Editions default decryption keys
-----------------------------------------------------------------------------------------
If everything has been installed in wine as above, the keys will be retrieved automatically.
If you have a more complex wine installation, you may enter the appropriate WINEPREFIX in the configuration dialogs for Kindle for PC and Adobe Digital Editions. You can also test that you have entered the WINEPREFIX correctly by trying to add the default keys to the preferences by clicking on the green plus button in the configuration dialogs.

View File

@@ -1,99 +0,0 @@
{\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf470
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset134 STHeitiSC-Light;}
{\colortbl;\red255\green255\blue255;}
\paperw11900\paperh16840\vieww12000\viewh15840\viewkind0
\deftab720
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\qc\partightenfactor0
\f0\b\fs24 \cf0 DeDRM ReadMe
\b0 \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\cf0 \
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\b \cf0 First Use for Mac OS X 10.9 and later\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\b0 \cf0 The application is not signed, so the first time you run it you will need to change your security options, or hold down the option key when double-clicking on the icon, or control-click or right-button to get the contextual menu to open it.\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\b \cf0 \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\qj\partightenfactor0
\b0 \cf0 \
\
DeDRM is an application that packs all of the python dm removal software into one easy to use program that remembers preferences and settings.\
It works without manual configuration with Kindle for Mac ebooks, Adobe Digital Editions Adept ePub and PDF ebooks, and Barnes & Noble NOOK Study ebooks.\
\
To remove the DRM of Kindle ebooks from eInk Kindles, other Barnes & Noble ePubs, eReader pdb ebooks, or Mobipocket ebooks, you must first run DeDRM application (by double-clicking it) and set some additional Preferences, depending on the origin of your ebook files:\
\
\b eInk Kindle (not Kindle Fire)
\b0 :
\b \
\b0 16 digit Serial Number, found in your Amazon account web pages.\
\b Barnes & Noble (not from NOOK Study)
\b0 : \
Your account email and password, so the key can be retrieved from the Barnes & Noble servers.\
An active internet connection is required for this.\
\b eReader
\b0 :\
Name and last 8 digits of CC number\
\b Mobipocket
\b0 :\
10 digit PID\
\
A final preference is the destination folder for the DRM-free copies of your ebooks that the application produces. This can be either the same folder as the original ebook, or a folder of your choice.\
\
Once these preferences have been set, you can drag and drop ebooks (or folders of ebooks) onto the DeDRM droplet to remove the DRM.\
\
This program uses notifications, so really needs Mac OS X 10.8 or above. It will not work on Mac OS X 10.4 or earlier. It might work on Mac OS X 10.5-10.7, but the latest Kindle for Mac does not support those System versions.\
\
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\b \cf0 Installation
\b0 \
Drag the DeDRM application from from the DeDRM_Application_Macintosh folder (the location of this ReadMe) to your Applications folder, or anywhere else you find convenient.\
\
\
\b \
Use
\b0 \
1. To set the preferences, double-click the application and follow the instructions in the dialogs.\
2. Drag & Drop DRMed ebooks or folders of DRMed ebooks onto the application icon when it is not running.\
\
\
\b Troubleshooting\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\b0 \cf0 A log is created on your desktop (DeDRM.log) containing detailed information from all the scripts. If you have any problems decrypting your ebooks, copy the contents of this log in a comment at Apprentice Alf's blog.\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
{\field{\*\fldinst{HYPERLINK "http://apprenticealf.wordpress.com/"}}{\fldrslt \cf0 http://apprenticealf.wordpress.com/}}\
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\b \cf0 Credits\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720\partightenfactor0
\b0 \cf0 The original inept and ignoble scripts were by i
\f1 \uc0\u9829
\f0 cabbages\
The original mobidedrm and erdr2pml scripts were by The Dark Reverser\
The original topaz DRM removal script was by CMBDTC\
The original topaz format conversion scripts were by some_updates, clarknova and Bart Simpson\
\
The alfcrypto library is by some_updates\
The ePub encryption detection script is by Apprentice Alf, adapted from a script by Paul Durrant\
The ignoblekey script is by Apprentice Harper\
The DeDRM AppleScript is by Apprentice Alf and Apprentice Harper, adapted from a script by Paul Durrant\
\
Many fixes, updates and enhancements to the scripts and applications have been made by many other people. For more details, see the comments in the individual scripts.\
}

Binary file not shown.

View File

@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>*</string>
</array>
<key>CFBundleTypeOSTypes</key>
<array>
<string>****</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>droplet</string>
<key>CFBundleGetInfoString</key>
<string>DeDRM AppleScript 6.6.1 Written 20102018 by Apprentice Alf et al.</string>
<key>CFBundleIconFile</key>
<string>DeDRM</string>
<key>CFBundleIdentifier</key>
<string>com.apple.ScriptEditor.id.707CCCD5-0C6C-4BEB-B67C-B6E866ADE85A</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>DeDRM</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>6.6.1</string>
<key>CFBundleSignature</key>
<string>dplt</string>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 20102018 Apprentice Alf</string>
<key>WindowState</key>
<dict>
<key>bundleDividerCollapsed</key>
<false/>
<key>bundlePositionOfDivider</key>
<real>1162</real>
<key>dividerCollapsed</key>
<false/>
<key>eventLogLevel</key>
<integer>0</integer>
<key>name</key>
<string>ScriptWindowState</string>
<key>positionOfDivider</key>
<real>651</real>
<key>savedFrame</key>
<string>0 37 1680 990 0 0 1680 1027 </string>
<key>selectedTab</key>
<string>log</string>
</dict>
</dict>
</plist>

Some files were not shown because too many files have changed in this diff Show More