diff options
author | apprenticeharper <[email protected]> | 2015-09-30 07:39:29 +0100 |
---|---|---|
committer | apprenticeharper <[email protected]> | 2015-09-30 07:39:29 +0100 |
commit | 4ea0d81144e7221d1682a0f9db54ce99ff436a8f (patch) | |
tree | 91aefa950736b02021fb169bfa2d315ffd59f78b /Other_Tools | |
parent | b1cccf4b251c9267a9a0d8e182c41a70b073efc8 (diff) |
Change to unicode strings to fix stand-alone character encoding problems
Diffstat (limited to 'Other_Tools')
-rw-r--r-- | Other_Tools/Kobo/obok.py | 102 |
1 files changed, 69 insertions, 33 deletions
diff --git a/Other_Tools/Kobo/obok.py b/Other_Tools/Kobo/obok.py index 18e629b..04b9075 100644 --- a/Other_Tools/Kobo/obok.py +++ b/Other_Tools/Kobo/obok.py @@ -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 @@ -119,7 +123,7 @@ # """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__': |