From 956f3034ada12a07f8df4f08d134a2c70c9a4d05 Mon Sep 17 00:00:00 2001 From: Apprentice Harper Date: Thu, 12 Jan 2017 07:24:42 +0000 Subject: [PATCH] Explicitly warn about KFX files. Bump version number to 6.5.3 --- .../DeDRM.app/Contents/Info.plist | 6 +-- .../DeDRM.app/Contents/Resources/__init__.py | 3 +- .../Contents/Resources/k4mobidedrm.py | 12 +++-- .../DeDRM_App/DeDRM_lib/DeDRM_App.pyw | 3 +- .../DeDRM_App/DeDRM_lib/lib/__init__.py | 3 +- .../DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py | 12 +++-- .../DeDRM_App_ReadMe.txt | 2 +- DeDRM_calibre_plugin/DeDRM_plugin.zip | Bin 353597 -> 353739 bytes DeDRM_calibre_plugin/DeDRM_plugin/__init__.py | 3 +- .../DeDRM_plugin/k4mobidedrm.py | 12 +++-- Other_Tools/Kobo/obok.py | 42 ++++++++++++++++-- 11 files changed, 78 insertions(+), 20 deletions(-) diff --git a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Info.plist b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Info.plist index a079e5a..898ac04 100644 --- a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Info.plist +++ b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Info.plist @@ -24,7 +24,7 @@ CFBundleExecutable droplet CFBundleGetInfoString - DeDRM AppleScript 6.5.2 Written 2010–2016 by Apprentice Alf et al. + DeDRM AppleScript 6.5.3 Written 2010–2017 by Apprentice Alf et al. CFBundleIconFile DeDRM CFBundleIdentifier @@ -36,13 +36,13 @@ CFBundlePackageType APPL CFBundleShortVersionString - 6.5.2 + 6.5.3 CFBundleSignature dplt LSRequiresCarbon NSHumanReadableCopyright - Copyright © 2010–2016 Apprentice Alf and Apprentice Harper + Copyright © 2010–2017 Apprentice Alf WindowState bundleDividerCollapsed diff --git a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/__init__.py b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/__init__.py index b359451..6fffb40 100644 --- a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/__init__.py +++ b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/__init__.py @@ -56,6 +56,7 @@ __docformat__ = 'restructuredtext en' # Fix an error in wineutils.py # 6.5.1 - Updated version number, added PDF check for DRM-free documents # 6.5.2 - Another Topaz fix +# 6.5.3 - Warn about KFX files explicitly """ @@ -63,7 +64,7 @@ Decrypt DRMed ebooks. """ PLUGIN_NAME = u"DeDRM" -PLUGIN_VERSION_TUPLE = (6, 5, 2) +PLUGIN_VERSION_TUPLE = (6, 5, 3) 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' diff --git a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/k4mobidedrm.py b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/k4mobidedrm.py index 67eb4cb..c3e475c 100644 --- a/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/k4mobidedrm.py +++ b/DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/k4mobidedrm.py @@ -56,8 +56,9 @@ from __future__ import with_statement # 5.1 - moved unicode_argv call inside main for Windows DeDRM compatibility # 5.2 - Fixed error in command line processing of unicode arguments # 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. -__version__ = '5.3' +__version__ = '5.4' import sys, os, re @@ -194,7 +195,11 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime raise DrmException(u"Input file does not exist.") mobi = True - magic3 = open(infile,'rb').read(3) + magic8 = open(infile,'rb').read(8) + if magic8 == '\xeaDRMION\xee': + raise DrmException(u"KFX format detected. This format cannot be decrypted yet.") + + magic3 = magic8[:3] if magic3 == 'TPZ': mobi = False @@ -215,8 +220,9 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime md1, md2 = mb.getPIDMetaInfo() totalpids.extend(kgenpids.getPidList(md1, md2, serials, kDatabases)) # remove any duplicates - totalpid = list(set(totalpids)) + totalpids = list(set(totalpids)) print u"Found {1:d} keys to try after {0:.1f} seconds".format(time.time()-starttime, len(totalpids)) + #print totalpids try: mb.processBook(totalpids) diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_App.pyw b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_App.pyw index c3a40d4..f4864f8 100644 --- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_App.pyw +++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/DeDRM_App.pyw @@ -28,8 +28,9 @@ # 6.5.0 - Fix for some new tags in Topaz ebooks # 6.5.1 - Version bump to match plugin & Mac app # 6.5.2 - Fix for a new tag in Topaz ebooks +# 6.5.3 - Explicitly warn about KFX files -__version__ = '6.5.2' +__version__ = '6.5.3' import sys import os, os.path diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/__init__.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/__init__.py index b359451..6fffb40 100644 --- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/__init__.py +++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/__init__.py @@ -56,6 +56,7 @@ __docformat__ = 'restructuredtext en' # Fix an error in wineutils.py # 6.5.1 - Updated version number, added PDF check for DRM-free documents # 6.5.2 - Another Topaz fix +# 6.5.3 - Warn about KFX files explicitly """ @@ -63,7 +64,7 @@ Decrypt DRMed ebooks. """ PLUGIN_NAME = u"DeDRM" -PLUGIN_VERSION_TUPLE = (6, 5, 2) +PLUGIN_VERSION_TUPLE = (6, 5, 3) 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' diff --git a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py index 67eb4cb..c3e475c 100644 --- a/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py +++ b/DeDRM_Windows_Application/DeDRM_App/DeDRM_lib/lib/k4mobidedrm.py @@ -56,8 +56,9 @@ from __future__ import with_statement # 5.1 - moved unicode_argv call inside main for Windows DeDRM compatibility # 5.2 - Fixed error in command line processing of unicode arguments # 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. -__version__ = '5.3' +__version__ = '5.4' import sys, os, re @@ -194,7 +195,11 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime raise DrmException(u"Input file does not exist.") mobi = True - magic3 = open(infile,'rb').read(3) + magic8 = open(infile,'rb').read(8) + if magic8 == '\xeaDRMION\xee': + raise DrmException(u"KFX format detected. This format cannot be decrypted yet.") + + magic3 = magic8[:3] if magic3 == 'TPZ': mobi = False @@ -215,8 +220,9 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime md1, md2 = mb.getPIDMetaInfo() totalpids.extend(kgenpids.getPidList(md1, md2, serials, kDatabases)) # remove any duplicates - totalpid = list(set(totalpids)) + totalpids = list(set(totalpids)) print u"Found {1:d} keys to try after {0:.1f} seconds".format(time.time()-starttime, len(totalpids)) + #print totalpids try: mb.processBook(totalpids) diff --git a/DeDRM_Windows_Application/DeDRM_App_ReadMe.txt b/DeDRM_Windows_Application/DeDRM_App_ReadMe.txt index 056dc3f..772b946 100644 --- a/DeDRM_Windows_Application/DeDRM_App_ReadMe.txt +++ b/DeDRM_Windows_Application/DeDRM_App_ReadMe.txt @@ -20,7 +20,7 @@ Installation ------------ 0. If you don't already have a correct version of Python and PyCrypto installed, follow the "Installing Python on Windows" and "Installing PyCrypto on Windows" sections below before continuing. -1. Drag the DeDRM_App folder from tools_v6.3.4a/DeDRM_Application_Windows to your "My Documents" folder. +1. Drag the DeDRM_App folder from DeDRM_Application_Windows to your "My Documents" folder. 2. Open the DeDRM_App folder you've just dragged, and make a short-cut of the DeDRM_Drop_Target.bat file (right-click/Create Shortcut). Drag the shortcut file onto your Desktop. diff --git a/DeDRM_calibre_plugin/DeDRM_plugin.zip b/DeDRM_calibre_plugin/DeDRM_plugin.zip index 9dcade7fc8bd304923fff2757f8d6bd02108b8d8..16233372f66c20325dacb1ce8c55131fecbdbc49 100644 GIT binary patch delta 13135 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 VJXkH zSjCS6<9+7IzUSUH*qTrwvZ=CJ(bwXo5wrh-HfghN(LmatRDk0AeIu=HW2(+TG$E}$ zfwHvx+Y4S>Q~1(xeMTF~os6Jk`Us^7(TK+_6`VM-OiJlFVO6S-W5MBeeCN<;HF53l zCwp{P^`|@~3tB^_O99etlM5^Rr>c%pI!DPb;OxPNNz-4W9TmAemJ1pClZp21QxgBy(W4$_P$}t2n^L|76n7X)g z$6J_(z|?3YW`U)oXHH7GnGZ@WaOJof*+gldrW3_w*xA1{Pq5q*Og^9KTYC^6irjWo zgNHu=&HbwH9KAa~XRG6oEOJi}^w;sv>cVZ7)pUPo^^GE8c}mXHIWJ~J);pb^nd_tr zDRphpqAicJ65vv8kkd}x86u@^Z^L%&<3-T7UL^9dY56cdH9eWGMc`9{%zTcpFKL$J z-SZ*AIrs~#UZ1RA_7Or*8hqT3kZ*$(2jCs#M!B$1rGhZnqSlzx1w!M1+yo#;Kx?u~ zU-DvV-l$`MKlqR$cni|!5>(hv`a;uiVPyw6?30GaH6Z zi(=!M4Qa34M8&^nBCAD=`>d<$_Jhl$Yd~F`08|q3`xe~NkXxALDPcIjo67^2r(*I- zvXk(_Iidao&sKlcfjAxbgLi$^ZA&?^d$%9w1K50Bqmv|r_GI{_l-QU?5G%ZP_yfJ2 zPO|xcZ?iRoc(1!O)r~8?KQY-NIpZCeju%I$shC75UaY`n<86NBsK$%eAp#S)#YbYF}y>S1B?4VrY_Q+SrkFK}R zbkD(r^@~1Q*IOU1{vUqwyy?y@}1TP8g+YBOzEpCYL+B>e;HkBl!&^K27mvV z*w2?XPqN~%66u+%gmokD$Y&M;>|v#Z;fI>^9( z$Fo=Ufv^3K%OZ(|a$tKI)3jj2WKGs*rA}U#b=?9^-deevx<$jj7%&yse2~#x$7@Cl zM;yFls+jW3J5!=-XV3lU+4zv%_=4N`4AvUet_*O$#Tk2^Y@|8cq55>Fll0L_(?7W&(fJl zE7Gq_aRi*CeNwe?p8{fR!C!Fzzh}Jvt;Mw#>cA?!Dq5#zuwsf(WUGdac~#EZn_wp+ zp%^0wN68Mw8V5LhAt(-ghD#xaqQL+hB~)311dhP*Luu;>T*|9prZ@*z4Fkpdc{tuz z&b|Sc2ZG|{E*$==u(rPsxBe=$jU2;$e+`>@_xe9;>$@koWE?0T!U8eE!f>=+;DBsj zg*yWR5GD^49aKU1i0J?MzS z?F*IF)D&TWIDmh@zGh*5kV6WX+hZbuig4Bd01{M$dmS(Ua_FxYL`@F_RrVnEdQhh$ zkVrici6GPhx%aOh2lPX25qbas^>sOP{A)qH0}bV9W9jDW;^F)su>b%TX2|-hA8*K` z9*6?!l~fQ>*k&NW?!A+u zaIv!auL}Ne683Afe=Bd5f`tm&kT~;y9w8Vr5HXNS7eZzRf@ zmAYkUDs2wk<~P{?oniwd3F-jqr}ovYP%~uQ?4L*K^p&CtK~T*>X zZ1K-&&4(HR{T3iyP=r?S3ktA}8*mWu4LEEFs^vdV1feB#Qhg5&@_QE!2crD%q#<+? zXnz3lwFHrXp|N5W*g`#M?L{pS^j2nb_kmPZLIS%u(Qf!@NjK$xxmsY%J|weN2r z_EsPw8V)%5vw&WCQ8)l#8QS;%yg%J>K>%;)X@m6YgP^ZcAU#k^m=(yX)j!+${K`%s PMAjf;c#s}6J;46~P&k8| delta 12888 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 diff --git a/DeDRM_calibre_plugin/DeDRM_plugin/__init__.py b/DeDRM_calibre_plugin/DeDRM_plugin/__init__.py index b359451..6fffb40 100644 --- a/DeDRM_calibre_plugin/DeDRM_plugin/__init__.py +++ b/DeDRM_calibre_plugin/DeDRM_plugin/__init__.py @@ -56,6 +56,7 @@ __docformat__ = 'restructuredtext en' # Fix an error in wineutils.py # 6.5.1 - Updated version number, added PDF check for DRM-free documents # 6.5.2 - Another Topaz fix +# 6.5.3 - Warn about KFX files explicitly """ @@ -63,7 +64,7 @@ Decrypt DRMed ebooks. """ PLUGIN_NAME = u"DeDRM" -PLUGIN_VERSION_TUPLE = (6, 5, 2) +PLUGIN_VERSION_TUPLE = (6, 5, 3) 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' diff --git a/DeDRM_calibre_plugin/DeDRM_plugin/k4mobidedrm.py b/DeDRM_calibre_plugin/DeDRM_plugin/k4mobidedrm.py index 67eb4cb..c3e475c 100644 --- a/DeDRM_calibre_plugin/DeDRM_plugin/k4mobidedrm.py +++ b/DeDRM_calibre_plugin/DeDRM_plugin/k4mobidedrm.py @@ -56,8 +56,9 @@ from __future__ import with_statement # 5.1 - moved unicode_argv call inside main for Windows DeDRM compatibility # 5.2 - Fixed error in command line processing of unicode arguments # 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. -__version__ = '5.3' +__version__ = '5.4' import sys, os, re @@ -194,7 +195,11 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime raise DrmException(u"Input file does not exist.") mobi = True - magic3 = open(infile,'rb').read(3) + magic8 = open(infile,'rb').read(8) + if magic8 == '\xeaDRMION\xee': + raise DrmException(u"KFX format detected. This format cannot be decrypted yet.") + + magic3 = magic8[:3] if magic3 == 'TPZ': mobi = False @@ -215,8 +220,9 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime md1, md2 = mb.getPIDMetaInfo() totalpids.extend(kgenpids.getPidList(md1, md2, serials, kDatabases)) # remove any duplicates - totalpid = list(set(totalpids)) + totalpids = list(set(totalpids)) print u"Found {1:d} keys to try after {0:.1f} seconds".format(time.time()-starttime, len(totalpids)) + #print totalpids try: mb.processBook(totalpids) diff --git a/Other_Tools/Kobo/obok.py b/Other_Tools/Kobo/obok.py index 149d09c..d2188e3 100644 --- a/Other_Tools/Kobo/obok.py +++ b/Other_Tools/Kobo/obok.py @@ -1,6 +1,12 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# Version 3.2.5 December 2016 +# Improve detection of good text decryption. +# +# Version 3.2.4 December 2016 +# Remove incorrect support for Kobo Desktop under Wine +# # Version 3.2.3 October 2016 # Fix for windows network user and more xml fixes # @@ -145,7 +151,7 @@ # """Manage all Kobo books, either encrypted or DRM-free.""" -__version__ = '3.2.3' +__version__ = '3.2.4' __about__ = u"Obok v{0}\nCopyright © 2012-2016 Physisticated et al.".format(__version__) import sys @@ -351,9 +357,9 @@ class KoboLibrary(object): 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: + #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") + # self.kobodir = os.path.join(linux_path, u"Local Settings", u"Application Data", u"Kobo", u"Kobo Desktop Edition") # desktop versions use Kobo.sqlite kobodb = os.path.join(self.kobodir, u"Kobo.sqlite") # check for existence of file @@ -582,6 +588,36 @@ class KoboFile(object): Returns True if the content was checked, False if it was not checked.""" if self.mimetype == 'application/xhtml+xml': + # assume utf-8 with no BOM + textoffset = 0 + stride = 1 + 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" + textoffset = 3 + elif contents[:2]=="\xfe\xff": + # seems to 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" + textoffset = 2 + stride = 2 + else: + 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])) + raise ValueError + print u"Seems to be good text" + return True if contents[:5]=="