]> xmof Git - DeDRM.git/commitdiff
Change to unicode strings to fix stand-alone character encoding problems
authorapprenticeharper <apprenticeharper@gmail.com>
Wed, 30 Sep 2015 06:39:29 +0000 (07:39 +0100)
committerapprenticeharper <apprenticeharper@gmail.com>
Wed, 30 Sep 2015 06:39:29 +0000 (07:39 +0100)
Obok_calibre_plugin/obok_plugin.zip
Obok_calibre_plugin/obok_plugin/__init__.py
Obok_calibre_plugin/obok_plugin/obok/obok.py
Other_Tools/Kobo/obok.py

index 3e1b918528975c691398c6c3339748fe7af4e948..2e091bcefada22d57a687072de2297bd44a89ccf 100644 (file)
Binary files a/Obok_calibre_plugin/obok_plugin.zip and b/Obok_calibre_plugin/obok_plugin.zip differ
index dd643c7ea0fbf475a7efab205c82ba6d1ecdf350..5a5eea049d4c3f516ec6123ffc9dd5ef7b1d0773 100644 (file)
@@ -19,7 +19,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 = (3, 1, 5)
+PLUGIN_VERSION_TUPLE = (3, 1, 6)
 PLUGIN_VERSION = '.'.join([str(x) for x in PLUGIN_VERSION_TUPLE])
 HELPFILE_NAME = PLUGIN_SAFE_NAME + '_Help.htm'
 PLUGIN_AUTHORS = 'Anon'
index ca74284a1d071a6f8cfefa98d0599456ee7569ab..04b907592298da6a96404d25b0cd250e65b580bb 100644 (file)
@@ -1,6 +1,10 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+# Version 3.1.6 September 2015
+# Enable support for Kobo devices
+# More character encoding fixes (unicode strings)
+#
 # Version 3.1.5 September 2015
 # Removed requirement that a purchase has been made.
 # Also add in character encoding fixes
 #
 """Manage all Kobo books, either encrypted or DRM-free."""
 
-__version__ = '3.1.5'
+__version__ = '3.1.6'
 
 import sys
 import os
@@ -246,36 +250,41 @@ class KoboLibrary(object):
 
     def __init__ (self, serials = [], device_path = None):
         print u"Obok v{0}\nCopyright © 2012-2015 Physisticated et al.".format(__version__)
-        self.kobodir = ''
-        kobodb = ''
+        self.kobodir = u""
+        kobodb = u""
 
         # - first check whether serials have been found or are provided 
         #   and a device is connected. In this case, use the device
         # - otherwise fall back to Kobo Desktop Application for Windows and Mac
         if (device_path and (len(serials) > 0)):
-            self.kobodir = os.path.join(device_path, '.kobo')
+            self.kobodir = os.path.join(device_path, u".kobo")
             # devices use KoboReader.sqlite
-            kobodb  = os.path.join(self.kobodir, 'KoboReader.sqlite')
+            kobodb  = os.path.join(self.kobodir, u"KoboReader.sqlite")
             if (not(os.path.exists(kobodb))):
                 # give up here, we haven't found anything useful
-                self.kobodir = ''
-                kobodb  = ''
+                self.kobodir = u""
+                kobodb  = u""
 
-        if (self.kobodir == ''):
+        if (self.kobodir == u""):
             # 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:
-                    self.kobodir = os.environ['LOCALAPPDATA']
-                else:
-                    self.kobodir = os.path.join(os.environ['USERPROFILE'], 'Local Settings', 'Application Data')
-                self.kobodir = os.path.join(self.kobodir, 'Kobo', 'Kobo Desktop Edition')
+                    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'], 'Library', 'Application Support', 'Kobo', 'Kobo Desktop Edition')
+                self.kobodir = os.path.join(os.environ['HOME'], u"Library", u"Application Support", u"Kobo", u"Kobo Desktop Edition")
             # desktop versions use Kobo.sqlite
-            kobodb = os.path.join(self.kobodir, 'Kobo.sqlite')
+            kobodb = os.path.join(self.kobodir, u"Kobo.sqlite")
         
-        if (self.kobodir != ''):
-            self.bookdir = os.path.join(self.kobodir, 'kepub')
+        if (self.kobodir != u""):
+            self.bookdir = os.path.join(self.kobodir, u"kepub")
             self.__sqlite = sqlite3.connect(kobodb)
             self.__cursor = self.__sqlite.cursor()
             self._userkeys = []
@@ -322,7 +331,7 @@ class KoboLibrary(object):
 
     def __bookfile (self, volumeid):
         """The filename needed to open a given book."""
-        return os.path.join(self.kobodir, 'kepub', volumeid)
+        return os.path.join(self.kobodir, u"kepub", volumeid)
 
     def __getmacaddrs (self):
         """The list of all MAC addresses on this machine."""
@@ -338,7 +347,7 @@ class KoboLibrary(object):
             output = subprocess.check_output('/sbin/ifconfig -a', shell=True)
             matches = c.findall(output)
             for m in matches:
-                # print "m:",m[0]
+                # print u"m:{0}".format(m[0])
                 macaddrs.append(m[0].upper())
 
         # extend the list of macaddrs in any case with the serials
@@ -480,13 +489,13 @@ class KoboFile(object):
             if contents[:5]=="<?xml":
                 return True
             else:
-                print "Bad XML: ",contents[:5]
+                print u"Bad XML: {0}".format(contents[:5])
                 raise ValueError
         if self.mimetype == 'image/jpeg':
             if contents[:3] == '\xff\xd8\xff':
                 return True
             else:
-                print "Bad JPEG: ", contents[:3].encode('hex')
+                print u"Bad JPEG: {0}".format(contents[:3].encode('hex'))
                 raise ValueError()
         return False
 
@@ -512,31 +521,30 @@ def cli_main():
     lib = KoboLibrary()
 
     for i, book in enumerate(lib.books):
-        print ('%d: %s' % (i + 1, book.title)).encode('ascii', 'ignore')
+        print u"{0}: {1}".format(i + 1, book.title)
 
-    num_string = raw_input("Convert book number... ")
+    num_string = raw_input(u"Convert book number... ")
     try:
         num = int(num_string)
         book = lib.books[num - 1]
     except (ValueError, IndexError):
         exit()
 
-    print "Converting", 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 = "%s.epub" % (re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
+    outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
 
     if (book.type == 'drm-free'):
-        print "DRM-free book, conversion is not needed"
+        print u"DRM-free book, conversion is not needed"
         shutil.copyfile(book.filename, outname)
-        print "Book saved as", os.path.join(os.getcwd(), outname)
+        print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
         exit(0)
 
     result = 1
     for userkey in lib.userkeys:
-        # print "Trying key: ",userkey.encode('hex_codec')
-        confirmedGood = False
+        print u"Trying key: {0}".format(userkey.encode('hex_codec'))
         try:
             zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
             for filename in zin.namelist():
@@ -545,20 +553,22 @@ def cli_main():
                     file = book.encryptedfiles[filename]
                     contents = file.decrypt(userkey, contents)
                     # Parse failures mean the key is probably wrong.
-                    if not confirmedGood:
-                        confirmedGood = file.check(contents)
+                    file.check(contents)
                 zout.writestr(filename, contents)
             zout.close()
-            print "Book saved as", 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 "Decryption failed, trying next key"
+            print u"Decryption failed."
             zout.close()
             os.remove(outname)
 
     zin.close()
     lib.close()
+    if result != 0:
+        print u"Could not decrypt book with any of the keys found."
     return result
 
 if __name__ == '__main__':
index 18e629bccef21148db2e7ea9c0aa8a339b20d93b..04b907592298da6a96404d25b0cd250e65b580bb 100644 (file)
@@ -1,6 +1,10 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+# Version 3.1.6 September 2015
+# Enable support for Kobo devices
+# More character encoding fixes (unicode strings)
+#
 # Version 3.1.5 September 2015
 # Removed requirement that a purchase has been made.
 # Also add in character encoding fixes
 #
 """Manage all Kobo books, either encrypted or DRM-free."""
 
-__version__ = '3.1.5'
+__version__ = '3.1.6'
 
 import sys
 import os
@@ -244,23 +248,49 @@ 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):
+    def __init__ (self, serials = [], device_path = None):
         print u"Obok v{0}\nCopyright © 2012-2015 Physisticated et al.".format(__version__)
-        if sys.platform.startswith('win'):
-            if sys.getwindowsversion().major > 5:
-                self.kobodir = os.environ['LOCALAPPDATA']
-            else:
-                self.kobodir = os.path.join(os.environ['USERPROFILE'], 'Local Settings', 'Application Data')
-            self.kobodir = os.path.join(self.kobodir, 'Kobo', 'Kobo Desktop Edition')
-        elif sys.platform.startswith('darwin'):
-            self.kobodir = os.path.join(os.environ['HOME'], 'Library', 'Application Support', 'Kobo', 'Kobo Desktop Edition')
-        self.bookdir = os.path.join(self.kobodir, 'kepub')
-        kobodb = os.path.join(self.kobodir, 'Kobo.sqlite')
-        self.__sqlite = sqlite3.connect(kobodb)
-        self.__cursor = self.__sqlite.cursor()
-        self._userkeys = []
-        self._books = []
-        self._volumeID = []
+        self.kobodir = u""
+        kobodb = u""
+
+        # - first check whether serials have been found or are provided 
+        #   and a device is connected. In this case, use the device
+        # - otherwise fall back to Kobo Desktop Application for Windows and Mac
+        if (device_path and (len(serials) > 0)):
+            self.kobodir = os.path.join(device_path, u".kobo")
+            # devices use KoboReader.sqlite
+            kobodb  = os.path.join(self.kobodir, u"KoboReader.sqlite")
+            if (not(os.path.exists(kobodb))):
+                # give up here, we haven't found anything useful
+                self.kobodir = u""
+                kobodb  = u""
+
+        if (self.kobodir == u""):
+            # 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")
+            # desktop versions use Kobo.sqlite
+            kobodb = os.path.join(self.kobodir, u"Kobo.sqlite")
+        
+        if (self.kobodir != u""):
+            self.bookdir = os.path.join(self.kobodir, u"kepub")
+            self.__sqlite = sqlite3.connect(kobodb)
+            self.__cursor = self.__sqlite.cursor()
+            self._userkeys = []
+            self._books = []
+            self._volumeID = []
+            self._serials = serials
 
     def close (self):
         """Closes the database used by the library."""
@@ -301,7 +331,7 @@ class KoboLibrary(object):
 
     def __bookfile (self, volumeid):
         """The filename needed to open a given book."""
-        return os.path.join(self.kobodir, 'kepub', volumeid)
+        return os.path.join(self.kobodir, u"kepub", volumeid)
 
     def __getmacaddrs (self):
         """The list of all MAC addresses on this machine."""
@@ -317,8 +347,13 @@ class KoboLibrary(object):
             output = subprocess.check_output('/sbin/ifconfig -a', shell=True)
             matches = c.findall(output)
             for m in matches:
-                # print "m:",m[0]
+                # print u"m:{0}".format(m[0])
                 macaddrs.append(m[0].upper())
+
+        # extend the list of macaddrs in any case with the serials
+        # cannot hurt ;-)
+        macaddrs.extend(self._serials)
+
         return macaddrs
 
     def __getuserids (self):
@@ -454,13 +489,13 @@ class KoboFile(object):
             if contents[:5]=="<?xml":
                 return True
             else:
-                print "Bad XML: ",contents[:5]
+                print u"Bad XML: {0}".format(contents[:5])
                 raise ValueError
         if self.mimetype == 'image/jpeg':
             if contents[:3] == '\xff\xd8\xff':
                 return True
             else:
-                print "Bad JPEG: ", contents[:3].encode('hex')
+                print u"Bad JPEG: {0}".format(contents[:3].encode('hex'))
                 raise ValueError()
         return False
 
@@ -486,31 +521,30 @@ def cli_main():
     lib = KoboLibrary()
 
     for i, book in enumerate(lib.books):
-        print ('%d: %s' % (i + 1, book.title))
+        print u"{0}: {1}".format(i + 1, book.title)
 
-    num_string = raw_input("Convert book number... ")
+    num_string = raw_input(u"Convert book number... ")
     try:
         num = int(num_string)
         book = lib.books[num - 1]
     except (ValueError, IndexError):
         exit()
 
-    print "Converting", 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 = "%s.epub" % (re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
+    outname = u"{0}.epub".format(re.sub('[^\s\w]', '_', book.title, 0, re.UNICODE))
 
     if (book.type == 'drm-free'):
-        print "DRM-free book, conversion is not needed"
+        print u"DRM-free book, conversion is not needed"
         shutil.copyfile(book.filename, outname)
-        print "Book saved as", os.path.join(os.getcwd(), outname)
+        print u"Book saved as {0}".format(os.path.join(os.getcwd(), outname))
         exit(0)
 
     result = 1
     for userkey in lib.userkeys:
-        # print "Trying key: ",userkey.encode('hex_codec')
-        confirmedGood = False
+        print u"Trying key: {0}".format(userkey.encode('hex_codec'))
         try:
             zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED)
             for filename in zin.namelist():
@@ -519,20 +553,22 @@ def cli_main():
                     file = book.encryptedfiles[filename]
                     contents = file.decrypt(userkey, contents)
                     # Parse failures mean the key is probably wrong.
-                    if not confirmedGood:
-                        confirmedGood = file.check(contents)
+                    file.check(contents)
                 zout.writestr(filename, contents)
             zout.close()
-            print "Book saved as", 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 "Decryption failed, trying next key"
+            print u"Decryption failed."
             zout.close()
             os.remove(outname)
 
     zin.close()
     lib.close()
+    if result != 0:
+        print u"Could not decrypt book with any of the keys found."
     return result
 
 if __name__ == '__main__':