aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Gocobachi <miguel@gocobachi.dev>2021-10-15 05:48:23 +0000
committerMateusz Piotrowski <0mp@FreeBSD.org>2021-10-15 06:00:22 +0000
commit1fe029273d1ecf6dbf40da326cf8388ffda7a949 (patch)
tree35bd73722d51e95f9b96502139c972087203f204
parentc9feb70a1fe715179d95fefb168fff61cb2bf410 (diff)
downloadports-1fe029273d1ecf6dbf40da326cf8388ffda7a949.tar.gz
ports-1fe029273d1ecf6dbf40da326cf8388ffda7a949.zip
deskutils/bookworm: Add new port
Bookworm is a simple, focused eBook reader. Read the books you love without having to worry about the different format complexities like epub, pdf, mobi, cbr, etc. This version supports EPUB, PDF and Comics (CBR and CBZ) formats with support for more formats to follow soon. WWW: https://babluboy.github.io/bookworm/ Reported by: 0mp Differential Revision: https://reviews.freebsd.org/D25569
-rw-r--r--deskutils/Makefile1
-rw-r--r--deskutils/bookworm/Makefile62
-rw-r--r--deskutils/bookworm/distinfo3
-rw-r--r--deskutils/bookworm/files/patch-data_com.github.babluboy.bookworm.appdata.xml.in41
-rw-r--r--deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__dict.py135
-rw-r--r--deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__html.py95
-rw-r--r--deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__index.py91
-rw-r--r--deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__k8proc.py142
-rw-r--r--deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__ncx.py98
-rw-r--r--deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__opf.py38
-rw-r--r--deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__unpack.py354
-rw-r--r--deskutils/bookworm/files/patch-src_bookworm.vala15
-rw-r--r--deskutils/bookworm/files/patch-src_pdfReader.vala62
-rw-r--r--deskutils/bookworm/files/patch-src_utils.vala38
-rw-r--r--deskutils/bookworm/pkg-descr7
-rw-r--r--deskutils/bookworm/pkg-plist223
16 files changed, 1405 insertions, 0 deletions
diff --git a/deskutils/Makefile b/deskutils/Makefile
index f5c6e9860b6e..3aab98e229e1 100644
--- a/deskutils/Makefile
+++ b/deskutils/Makefile
@@ -18,6 +18,7 @@
SUBDIR += bijiben
SUBDIR += birdtray
SUBDIR += bitcollider
+ SUBDIR += bookworm
SUBDIR += cairo-dock
SUBDIR += cairo-dock-plugins
SUBDIR += caja-extensions
diff --git a/deskutils/bookworm/Makefile b/deskutils/bookworm/Makefile
new file mode 100644
index 000000000000..f832ab827aee
--- /dev/null
+++ b/deskutils/bookworm/Makefile
@@ -0,0 +1,62 @@
+PORTNAME= bookworm
+DISTVERSION= 1.1.2
+CATEGORIES= deskutils
+
+MAINTAINER= miguel@gocobachi.dev
+COMMENT= Simple, focused ebook reader
+
+LICENSE= GPLv3
+LICENSE_FILE= ${WRKSRC}/COPYING
+
+BUILD_DEPENDS= curl>0:ftp/curl \
+ html2text>0:textproc/html2text \
+ valac:lang/vala
+LIB_DEPENDS= libappstream-glib.so:devel/appstream-glib \
+ libgee-0.8.so:devel/libgee \
+ libgranite.so:x11-toolkits/granite \
+ libpoppler-glib.so:graphics/poppler-glib \
+ libsoup-2.4.so:devel/libsoup \
+ libwebkit2gtk-4.0.so:www/webkit2-gtk3 \
+ libxml2.so:textproc/libxml2
+RUN_DEPENDS= bash:shells/bash \
+ pdftohtml:graphics/poppler-utils \
+ unar:archivers/unarchiver \
+ unzip:archivers/unzip
+
+USES= desktop-file-utils gettext gnome meson pkgconfig \
+ python:build,run shebangfix sqlite
+USE_GITHUB= yes
+GH_ACCOUNT= babluboy
+USE_GNOME= gdkpixbuf2 glib20 gtk30 libxml2 pango
+
+GLIB_SCHEMAS= com.github.babluboy.bookworm.gschema.xml
+INSTALLS_ICONS= yes
+SHEBANG_FILES= data/scripts/com.github.babluboy.bookworm.search.sh \
+ data/scripts/mobi_lib/mobi_dict.py \
+ data/scripts/mobi_lib/mobi_html.py \
+ data/scripts/mobi_lib/mobi_index.py \
+ data/scripts/mobi_lib/mobi_k8proc.py \
+ data/scripts/mobi_lib/mobi_ncx.py \
+ data/scripts/mobi_lib/mobi_opf.py \
+ data/scripts/mobi_lib/mobi_split.py \
+ data/scripts/mobi_lib/mobi_uncompress.py \
+ data/scripts/mobi_lib/mobi_unpack.py \
+ data/scripts/mobi_lib/mobi_utils.py
+
+MESON_BUILD_DIR= build
+
+PORTDOCS= README.md
+
+OPTIONS_DEFINE= DOCS
+
+post-configure:
+ @${MKDIR} ${WRKSRC}/${MESON_BUILD_DIR}
+
+post-install-DOCS-on:
+ @${MKDIR} ${STAGEDIR}${DOCSDIR}
+ ${INSTALL_DATA} ${WRKSRC}/README.md ${STAGEDIR}${DOCSDIR}
+
+do-test:
+ cd ${WRKSRC}/${MESON_BUILD_DIR} && ninja test
+
+.include <bsd.port.mk>
diff --git a/deskutils/bookworm/distinfo b/deskutils/bookworm/distinfo
new file mode 100644
index 000000000000..62681da78331
--- /dev/null
+++ b/deskutils/bookworm/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1593395828
+SHA256 (babluboy-bookworm-1.1.2_GH0.tar.gz) = 6d27e55697debfa08f7cc15805413b74c94c55111cdf2d333b306228eccad824
+SIZE (babluboy-bookworm-1.1.2_GH0.tar.gz) = 2102426
diff --git a/deskutils/bookworm/files/patch-data_com.github.babluboy.bookworm.appdata.xml.in b/deskutils/bookworm/files/patch-data_com.github.babluboy.bookworm.appdata.xml.in
new file mode 100644
index 000000000000..d474e0772145
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_com.github.babluboy.bookworm.appdata.xml.in
@@ -0,0 +1,41 @@
+--- data/com.github.babluboy.bookworm.appdata.xml.in.orig 2019-08-10 18:20:51 UTC
++++ data/com.github.babluboy.bookworm.appdata.xml.in
+@@ -14,10 +14,6 @@
+ </description>
+ <screenshots>
+ <screenshot type="default">
+- <caption>Bookworm Library View</caption>
+- <image>https://raw.githubusercontent.com/babluboy/bookworm/gh-pages/images/BookwormLibraryView.png</image>
+- </screenshot>
+- <screenshot type="default">
+ <caption>Bookworm Reading View</caption>
+ <image>https://raw.githubusercontent.com/babluboy/bookworm/gh-pages/images/BookwormReadingView.png</image>
+ </screenshot>
+@@ -46,16 +42,6 @@
+ </ul>
+ </description>
+ </release>
+- <release version="1.0.0" date="2018-02-11">
+- <description>
+- <p>Right to Left Reading</p>
+- <ul>
+- <li>Support for right-to-left script</li>
+- <li>A shiny new icon and new cover images</li>
+- <li>Better support for EPUB table of contents</li>
+- </ul>
+- </description>
+- </release>
+ <release version="1.1.0" date="2018-09-30">
+ <description>
+ <p>This release has some new features, fixes and new translations:</p>
+@@ -72,8 +58,8 @@
+ <li>Some minor CSS compatibility with Juno</li>
+ </ul>
+ </description>
+- </release>
+- <release version="1.0.0" date="2018-02-11">
++ </release>
++ <release version="1.0.0" date="2018-02-11">
+ <description>
+ <p>Right to Left Reading</p>
+ <ul>
diff --git a/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__dict.py b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__dict.py
new file mode 100644
index 000000000000..f5695b3b487d
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__dict.py
@@ -0,0 +1,135 @@
+--- data/scripts/mobi_lib/mobi_dict.py.orig 2021-08-16 04:04:05 UTC
++++ data/scripts/mobi_lib/mobi_dict.py
+@@ -27,37 +27,37 @@ class dictSupport:
+
+ decodeInflection = True
+ if metaOrthIndex != 0xFFFFFFFF:
+- print "Info: Document contains orthographic index, handle as dictionary"
++ print("Info: Document contains orthographic index, handle as dictionary")
+ if metaInflIndex == 0xFFFFFFFF:
+ decodeInflection = False
+ else:
+ metaInflIndexData = sect.loadSection(metaInflIndex)
+ metaIndexCount, = struct.unpack_from('>L', metaInflIndexData, 0x18)
+ if metaIndexCount != 1:
+- print "Error: Dictionary contains multiple inflection index sections, which is not yet supported"
++ print("Error: Dictionary contains multiple inflection index sections, which is not yet supported")
+ decodeInflection = False
+ inflIndexData = sect.loadSection(metaInflIndex + 1)
+ inflNameData = sect.loadSection(metaInflIndex + 1 + metaIndexCount)
+ tagSectionStart, = struct.unpack_from('>L', metaInflIndexData, 0x04)
+ inflectionControlByteCount, inflectionTagTable = readTagSection(tagSectionStart, metaInflIndexData)
+ if DEBUG_DICT:
+- print "inflectionTagTable: %s" % inflectionTagTable
++ print("inflectionTagTable: %s" % inflectionTagTable)
+ if self.hasTag(inflectionTagTable, 0x07):
+- print "Error: Dictionary uses obsolete inflection rule scheme which is not yet supported"
++ print("Error: Dictionary uses obsolete inflection rule scheme which is not yet supported")
+ decodeInflection = False
+
+ data = sect.loadSection(metaOrthIndex)
+ tagSectionStart, = struct.unpack_from('>L', data, 0x04)
+ controlByteCount, tagTable = readTagSection(tagSectionStart, data)
+ orthIndexCount, = struct.unpack_from('>L', data, 0x18)
+- print "orthIndexCount is", orthIndexCount
++ print("orthIndexCount is", orthIndexCount)
+ if DEBUG_DICT:
+- print "orthTagTable: %s" % tagTable
++ print("orthTagTable: %s" % tagTable)
+ hasEntryLength = self.hasTag(tagTable, 0x02)
+ if not hasEntryLength:
+- print "Info: Index doesn't contain entry length tags"
++ print("Info: Index doesn't contain entry length tags")
+
+- print "Read dictionary index data"
++ print("Read dictionary index data")
+ for i in range(metaOrthIndex + 1, metaOrthIndex + 1 + orthIndexCount):
+ data = sect.loadSection(i)
+ idxtPos, = struct.unpack_from('>L', data, 0x14)
+@@ -145,10 +145,10 @@ class dictSupport:
+
+ # Make sure that the required tags are available.
+ if 0x05 not in tagMap:
+- print "Error: Required tag 0x05 not found in tagMap"
++ print("Error: Required tag 0x05 not found in tagMap")
+ return ""
+ if 0x1a not in tagMap:
+- print "Error: Required tag 0x1a not found in tagMap"
++ print("Error: Required tag 0x1a not found in tagMap")
+ return ""
+
+ result += "<idx:infl>"
+@@ -230,7 +230,7 @@ class dictSupport:
+ totalConsumed += consumed
+ values.append(data)
+ if totalConsumed != valueBytes:
+- print "Error: Should consume %s bytes, but consumed %s" % (valueBytes, totalConsumed)
++ print("Error: Should consume %s bytes, but consumed %s" % (valueBytes, totalConsumed))
+ tagHashMap[tag] = values
+
+ # Test that all bytes have been processed if endPos is given.
+@@ -238,12 +238,12 @@ class dictSupport:
+ # The last entry might have some zero padding bytes, so complain only if non zero bytes are left.
+ for char in entryData[dataStart:endPos]:
+ if char != chr(0x00):
+- print "Warning: There are unprocessed index bytes left: %s" % toHex(entryData[dataStart:endPos])
++ print("Warning: There are unprocessed index bytes left: %s" % toHex(entryData[dataStart:endPos]))
+ if DEBUG_DICT:
+- print "controlByteCount: %s" % controlByteCount
+- print "tagTable: %s" % tagTable
+- print "data: %s" % toHex(entryData[startPos:endPos])
+- print "tagHashMap: %s" % tagHashMap
++ print("controlByteCount: %s" % controlByteCount)
++ print("tagTable: %s" % tagTable)
++ print("data: %s" % toHex(entryData[startPos:endPos]))
++ print("tagHashMap: %s" % tagHashMap)
+ break
+
+ return tagHashMap
+@@ -273,10 +273,10 @@ class dictSupport:
+ position -= offset
+ elif byte > 0x13:
+ if mode == -1:
+- print "Error: Unexpected first byte %i of inflection rule" % byte
++ print("Error: Unexpected first byte %i of inflection rule" % byte)
+ return None
+ elif position == -1:
+- print "Error: Unexpected first byte %i of inflection rule" % byte
++ print("Error: Unexpected first byte %i of inflection rule" % byte)
+ return None
+ else:
+ if mode == 0x01:
+@@ -292,19 +292,19 @@ class dictSupport:
+ deleted = byteArray.pop(position)
+ if deleted != char:
+ if DEBUG_DICT:
+- print "0x03: %s %s %s %s" % (mainEntry, toHex(inflectionRuleData[start:end]), char, deleted)
+- print "Error: Delete operation of inflection rule failed"
++ print("0x03: %s %s %s %s" % (mainEntry, toHex(inflectionRuleData[start:end]), char, deleted))
++ print("Error: Delete operation of inflection rule failed")
+ return None
+ elif mode == 0x04:
+ # Delete at word start
+ deleted = byteArray.pop(position)
+ if deleted != char:
+ if DEBUG_DICT:
+- print "0x03: %s %s %s %s" % (mainEntry, toHex(inflectionRuleData[start:end]), char, deleted)
+- print "Error: Delete operation of inflection rule failed"
++ print("0x03: %s %s %s %s" % (mainEntry, toHex(inflectionRuleData[start:end]), char, deleted))
++ print("Error: Delete operation of inflection rule failed")
+ return None
+ else:
+- print "Error: Inflection rule mode %x is not implemented" % mode
++ print("Error: Inflection rule mode %x is not implemented" % mode)
+ return None
+ elif byte == 0x01:
+ # Insert at word start
+@@ -327,7 +327,7 @@ class dictSupport:
+ position = 0
+ mode = byte
+ else:
+- print "Error: Inflection rule mode %x is not implemented" % byte
++ print("Error: Inflection rule mode %x is not implemented" % byte)
+ return None
+ return byteArray.tostring()
+
diff --git a/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__html.py b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__html.py
new file mode 100644
index 000000000000..e02d8e2fcfce
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__html.py
@@ -0,0 +1,95 @@
+--- data/scripts/mobi_lib/mobi_html.py.orig 2021-08-16 04:19:38 UTC
++++ data/scripts/mobi_lib/mobi_html.py
+@@ -23,7 +23,7 @@ class HTMLProcessor:
+ def findAnchors(self, rawtext, indx_data, positionMap):
+ # process the raw text
+ # find anchors...
+- print "Find link anchors"
++ print("Find link anchors")
+ link_pattern = re.compile(r'''<[^<>]+filepos=['"]{0,1}(\d+)[^<>]*>''', re.IGNORECASE)
+ # TEST NCX: merge in filepos from indx
+ pos_links = [int(m.group(1)) for m in link_pattern.finditer(rawtext)]
+@@ -38,7 +38,7 @@ class HTMLProcessor:
+ positionMap[position] = '<a id="filepos%d" />' % position
+
+ # apply dictionary metadata and anchors
+- print "Insert data into html"
++ print("Insert data into html")
+ pos = 0
+ lastPos = len(rawtext)
+ dataList = []
+@@ -63,7 +63,7 @@ class HTMLProcessor:
+ metadata = self.metadata
+
+ # put in the hrefs
+- print "Insert hrefs into html"
++ print("Insert hrefs into html")
+ # Two different regex search and replace routines.
+ # Best results are with the second so far IMO (DiapDealer).
+
+@@ -73,11 +73,11 @@ class HTMLProcessor:
+ srctext = link_pattern.sub(r'''<a href="#filepos\1"\2>''', srctext)
+
+ # remove empty anchors
+- print "Remove empty anchors from html"
++ print("Remove empty anchors from html")
+ srctext = re.sub(r"<a/>",r"", srctext)
+
+ # convert image references
+- print "Insert image references into html"
++ print("Insert image references into html")
+ # split string into image tag pieces and other pieces
+ image_pattern = re.compile(r'''(<img.*?>)''', re.IGNORECASE)
+ image_index_pattern = re.compile(r'''recindex=['"]{0,1}([0-9]+)['"]{0,1}''', re.IGNORECASE)
+@@ -91,7 +91,7 @@ class HTMLProcessor:
+ imageNumber = int(m.group(1))
+ imageName = imgnames[imageNumber-1]
+ if imageName is None:
+- print "Error: Referenced image %s was not recognized as a valid image" % imageNumber
++ print("Error: Referenced image %s was not recognized as a valid image" % imageNumber)
+ else:
+ replacement = 'src="images/' + imageName + '"'
+ tag = re.sub(image_index_pattern, replacement, tag, 1)
+@@ -128,7 +128,7 @@ class XHTMLK8Processor:
+ posfid_index_pattern = re.compile(r'''['"]kindle:pos:fid:([0-9|A-V]+):off:([0-9|A-V]+).*?["']''')
+
+ parts = []
+- print "Building proper xhtml for each file"
++ print("Building proper xhtml for each file")
+ for i in xrange(self.k8proc.getNumberOfParts()):
+ part = self.k8proc.getPart(i)
+ [partnum, dir, filename, beg, end, aidtext] = self.k8proc.getPartInfo(i)
+@@ -227,7 +227,7 @@ class XHTMLK8Processor:
+ self.used[imageName] = 'used'
+ tag = re.sub(img_index_pattern, replacement, tag, 1)
+ else:
+- print "Error: Referenced image %s was not recognized as a valid image in %s" % (imageNumber, tag)
++ print("Error: Referenced image %s was not recognized as a valid image in %s" % (imageNumber, tag))
+ srcpieces[j] = tag
+ flowpart = "".join(srcpieces)
+
+@@ -246,13 +246,13 @@ class XHTMLK8Processor:
+ self.used[imageName] = 'used'
+ tag = re.sub(url_img_index_pattern, replacement, tag, 1)
+ else:
+- print "Error: Referenced image %s was not recognized as a valid image in %s" % (imageNumber, tag)
++ print("Error: Referenced image %s was not recognized as a valid image in %s" % (imageNumber, tag))
+ # process links to fonts
+ for m in re.finditer(font_index_pattern, tag):
+ fontNumber = fromBase32(m.group(1))
+ fontName = self.imgnames[fontNumber-1]
+ if fontName is None:
+- print "Error: Referenced font %s was not recognized as a valid font in %s" % (fontNumber, tag)
++ print("Error: Referenced font %s was not recognized as a valid font in %s" % (fontNumber, tag))
+ else:
+ replacement = '"../Fonts/' + fontName + '"'
+ tag = re.sub(font_index_pattern, replacement, tag, 1)
+@@ -345,7 +345,7 @@ class XHTMLK8Processor:
+ self.used[imageName] = 'used'
+ tag = re.sub(img_index_pattern, replacement, tag, 1)
+ else:
+- print "Error: Referenced image %s was not recognized as a valid image in %s" % (imageNumber, tag)
++ print("Error: Referenced image %s was not recognized as a valid image in %s" % (imageNumber, tag))
+ srcpieces[j] = tag
+ part = "".join(srcpieces)
+ # store away modified version
diff --git a/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__index.py b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__index.py
new file mode 100644
index 000000000000..a5d8eb193918
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__index.py
@@ -0,0 +1,91 @@
+--- data/scripts/mobi_lib/mobi_index.py.orig 2021-08-16 04:22:14 UTC
++++ data/scripts/mobi_lib/mobi_index.py
+@@ -32,15 +32,15 @@ class MobiIndex:
+ tagSectionStart = idxhdr['len']
+ controlByteCount, tagTable = readTagSection(tagSectionStart, data)
+ if DEBUG:
+- print "IndexCount is", IndexCount
+- print "TagTable: %s" % tagTable
++ print("IndexCount is", IndexCount)
++ print("TagTable: %s" % tagTable)
+ for i in range(idx + 1, idx + 1 + IndexCount):
+ data = sect.loadSection(i)
+ hdrinfo = self.parseINDXHeader(data)
+ idxtPos = hdrinfo['start']
+ entryCount = hdrinfo['count']
+ if DEBUG:
+- print idxtPos, entryCount
++ print(idxtPos, entryCount)
+ # loop through to build up the IDXT position starts
+ idxPositions = []
+ for j in range(entryCount):
+@@ -57,8 +57,8 @@ class MobiIndex:
+ tagMap = self.getTagMap(controlByteCount, tagTable, data, startPos+1+textLength, endPos)
+ outtbl.append([text, tagMap])
+ if DEBUG:
+- print tagMap
+- print text
++ print(tagMap)
++ print(text)
+ return outtbl, ctoc_text
+
+ def getTagMap(self, controlByteCount, tagTable, entryData, startPos, endPos):
+@@ -118,19 +118,19 @@ class MobiIndex:
+ totalConsumed += consumed
+ values.append(data)
+ if totalConsumed != valueBytes:
+- print "Error: Should consume %s bytes, but consumed %s" % (valueBytes, totalConsumed)
++ print("Error: Should consume %s bytes, but consumed %s" % (valueBytes, totalConsumed))
+ tagHashMap[tag] = values
+ # Test that all bytes have been processed if endPos is given.
+ if endPos is not None and dataStart != endPos:
+ # The last entry might have some zero padding bytes, so complain only if non zero bytes are left.
+ for char in entryData[dataStart:endPos]:
+ if char != chr(0x00):
+- print "Warning: There are unprocessed index bytes left: %s" % toHex(entryData[dataStart:endPos])
++ print("Warning: There are unprocessed index bytes left: %s" % toHex(entryData[dataStart:endPos]))
+ if DEBUG:
+- print "controlByteCount: %s" % controlByteCount
+- print "tagTable: %s" % tagTable
+- print "data: %s" % toHex(entryData[startPos:endPos])
+- print "tagHashMap: %s" % tagHashMap
++ print("controlByteCount: %s" % controlByteCount)
++ print("tagTable: %s" % tagTable)
++ print("data: %s" % toHex(entryData[startPos:endPos]))
++ print("tagHashMap: %s" % tagHashMap)
+ break
+
+ return tagHashMap
+@@ -154,7 +154,7 @@ class MobiIndex:
+ def parseINDXHeader(self, data):
+ "read INDX header"
+ if not data[:4] == 'INDX':
+- print "Warning: index section is not INDX"
++ print("Warning: index section is not INDX")
+ return False
+ words = (
+ 'len', 'nul1', 'type', 'gen', 'start', 'count', 'code',
+@@ -166,10 +166,10 @@ class MobiIndex:
+ for n in range(num):
+ header[words[n]] = values[n]
+ if DEBUG:
+- print "parsed INDX header:"
++ print("parsed INDX header:")
+ for n in words:
+- print n, "%X" % header[n],
+- print
++ print(n, "%X" % header[n])
++ print("")
+ return header
+
+ def readCTOC(self, txtdata):
+@@ -187,7 +187,7 @@ class MobiIndex:
+ name = txtdata[offset:offset+ilen]
+ offset += ilen
+ if DEBUG:
+- print "name length is ", ilen
+- print idx_offs, name
++ print("name length is ", ilen)
++ print(idx_offs, name)
+ ctoc_data[idx_offs] = name
+ return ctoc_data
diff --git a/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__k8proc.py b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__k8proc.py
new file mode 100644
index 000000000000..3c198a5d1216
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__k8proc.py
@@ -0,0 +1,142 @@
+--- data/scripts/mobi_lib/mobi_k8proc.py.orig 2021-08-16 04:24:52 UTC
++++ data/scripts/mobi_lib/mobi_k8proc.py
+@@ -33,11 +33,11 @@ class K8Processor:
+ sections = header[0x0c:]
+ self.fdsttbl = struct.unpack_from('>%dL' % (num_sections*2), sections, 0)[::2] + (0xfffffff, )
+ else:
+- print "Error: K8 Mobi with Missing FDST info"
++ print("Error: K8 Mobi with Missing FDST info")
+ if self.DEBUG:
+- print "\nFDST Section Map: %d entries" % len(self.fdsttbl)
++ print("\nFDST Section Map: %d entries" % len(self.fdsttbl))
+ for j in xrange(len(self.fdsttbl)):
+- print " %d - %0x" % (j, self.fdsttbl[j])
++ print(" %d - %0x" % (j, self.fdsttbl[j]))
+
+ # read/process skeleton index info to create the skeleton table
+ skeltbl = []
+@@ -50,10 +50,10 @@ class K8Processor:
+ fileptr += 1
+ self.skeltbl = skeltbl
+ if self.DEBUG:
+- print "\nSkel Table: %d entries" % len(self.skeltbl)
+- print "table: filenum, skeleton name, div tbl record count, start position, length"
++ print("\nSkel Table: %d entries" % len(self.skeltbl))
++ print("table: filenum, skeleton name, div tbl record count, start position, length")
+ for j in xrange(len(self.skeltbl)):
+- print self.skeltbl[j]
++ print(self.skeltbl[j])
+
+ # read/process the div index to create to <div> (and <p>) table
+ divtbl = []
+@@ -66,10 +66,10 @@ class K8Processor:
+ divtbl.append([int(text), ctocdata, tagMap[3][0], tagMap[4][0], tagMap[6][0], tagMap[6][1]])
+ self.divtbl = divtbl
+ if self.DEBUG:
+- print "\nDiv (Fragment) Table: %d entries" % len(self.divtbl)
+- print "table: file position, link id text, file num, sequence number, start position, length"
++ print("\nDiv (Fragment) Table: %d entries" % len(self.divtbl))
++ print("table: file position, link id text, file num, sequence number, start position, length")
+ for j in xrange(len(self.divtbl)):
+- print self.divtbl[j]
++ print(self.divtbl[j])
+
+ # read / process other index <guide> element of opf
+ othtbl = []
+@@ -88,10 +88,10 @@ class K8Processor:
+ othtbl.append([ref_type, ref_title, fileno])
+ self.othtbl = othtbl
+ if self.DEBUG:
+- print "\nOther (Guide) Table: %d entries" % len(self.othtbl)
+- print "table: ref_type, ref_title, divtbl entry number"
++ print("\nOther (Guide) Table: %d entries" % len(self.othtbl))
++ print("table: ref_type, ref_title, divtbl entry number")
+ for j in xrange(len(self.othtbl)):
+- print self.othtbl[j]
++ print(self.othtbl[j])
+
+
+ def buildParts(self, rawML):
+@@ -103,7 +103,7 @@ class K8Processor:
+ if end == 0xffffffff:
+ end = len(rawML)
+ if self.DEBUG:
+- print "splitting rawml starting at %d and ending at %d into flow piece %d" % (start, end, j)
++ print("splitting rawml starting at %d and ending at %d into flow piece %d" % (start, end, j))
+ self.flows.append(rawML[start:end])
+
+ # the first piece represents the xhtml text
+@@ -114,7 +114,7 @@ class K8Processor:
+ # *without* destroying any file position information needed for later href processing
+ # and create final list of file separation start: stop points and etc in partinfo
+ if self.DEBUG:
+- print "\nRebuilding flow piece 0: the main body of the ebook"
++ print("\nRebuilding flow piece 0: the main body of the ebook")
+ self.parts = []
+ self.partinfo = []
+ divptr = 0
+@@ -125,8 +125,8 @@ class K8Processor:
+ for i in range(divcnt):
+ [insertpos, idtext, filenum, seqnum, startpos, length] = self.divtbl[divptr]
+ if self.DEBUG:
+- print " moving div/frag %d starting at %d of length %d" % (divptr, startpos, length)
+- print " inside of skeleton number %d at postion %d" % (skelnum, insertpos)
++ print(" moving div/frag %d starting at %d of length %d" % (divptr, startpos, length))
++ print(" inside of skeleton number %d at postion %d" % (skelnum, insertpos))
+ if i == 0:
+ aidtext = idtext[12:-2]
+ filename = 'part%04d.xhtml' % filenum
+@@ -198,14 +198,14 @@ class K8Processor:
+ self.flowinfo.append([type, format, dir, fname])
+
+ if self.DEBUG:
+- print "\nFlow Map: %d entries" % len(self.flowinfo)
++ print("\nFlow Map: %d entries" % len(self.flowinfo))
+ for fi in self.flowinfo:
+- print fi
+- print "\n"
++ print(fi)
++ print("\n")
+
+- print "\nXHTML File Part Position Information: %d entries" % len(self.partinfo)
++ print("\nXHTML File Part Position Information: %d entries" % len(self.partinfo))
+ for pi in self.partinfo:
+- print pi
++ print(pi)
+
+ if False: # self.DEBUG:
+ # dump all of the locations of the aid tags used in TEXT
+@@ -214,12 +214,12 @@ class K8Processor:
+ # [^>]* means match any amount of chars except for '>' char
+ # [^'"] match any amount of chars except for the quote character
+ # \s* means match any amount of whitespace
+- print "\npositions of all aid= pieces"
++ print("\npositions of all aid= pieces")
+ id_pattern = re.compile(r'''<[^>]*\said\s*=\s*['"]([^'"]*)['"][^>]*>''',re.IGNORECASE)
+ for m in re.finditer(id_pattern, rawML):
+- print "%0x %s %0x" % (m.start(), m.group(1), fromBase32(m.group(1)))
++ print("%0x %s %0x" % (m.start(), m.group(1), fromBase32(m.group(1))))
+ [filename, partnum, start, end] = self.getFileInfo(m.start())
+- print " in %d %0x %0x" % (partnum, start, end)
++ print(" in %d %0x %0x" % (partnum, start, end))
+
+ return
+
+@@ -300,7 +300,7 @@ class K8Processor:
+ n = len(idtbl)
+ if n == 0:
+ if self.DEBUG:
+- print "Found no id in the textblock, link must be to top of file"
++ print("Found no id in the textblock, link must be to top of file")
+ return ''
+ # if npos is before first id= inside a tag, return the first
+ if npos < idtbl[0][0] :
+@@ -315,7 +315,7 @@ class K8Processor:
+ tgt = r-1
+ break
+ if self.DEBUG:
+- print pos, npos, idtbl[tgt]
++ print(pos, npos, idtbl[tgt])
+ return idtbl[tgt][1]
+
+
diff --git a/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__ncx.py b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__ncx.py
new file mode 100644
index 000000000000..efc028ed0cd2
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__ncx.py
@@ -0,0 +1,98 @@
+--- data/scripts/mobi_lib/mobi_ncx.py.orig 2021-08-16 04:25:11 UTC
++++ data/scripts/mobi_lib/mobi_ncx.py
+@@ -34,8 +34,8 @@ class ncxExtract:
+ if self.ncxidx != 0xffffffff:
+ outtbl, ctoc_text = self.mi.getIndexData(self.ncxidx)
+ if DEBUG_NCX:
+- print ctoc_text
+- print outtbl
++ print(ctoc_text)
++ print(outtbl)
+ num = 0
+ for [text, tagMap] in outtbl:
+ tmp = {
+@@ -68,16 +68,16 @@ class ncxExtract:
+ tmp['kind'] = ctoc_text.get(fieldvalue, 'Unknown Kind')
+ indx_data.append(tmp)
+ if DEBUG_NCX:
+- print "record number: ", num
+- print "name: ", tmp['name'],
+- print "position", tmp['pos']," length: ", tmp['len']
+- print "text: ", tmp['text']
+- print "kind: ", tmp['kind']
+- print "heading level: ", tmp['hlvl']
+- print "parent:", tmp['parent']
+- print "first child: ",tmp['child1']," last child: ", tmp['childn']
+- print "pos_fid is ", tmp['pos_fid']
+- print "\n\n"
++ print("record number: ", num)
++ print("name: ", tmp['name'])
++ print("position", tmp['pos']," length: ", tmp['len'])
++ print("text: ", tmp['text'])
++ print("kind: ", tmp['kind'])
++ print("heading level: ", tmp['hlvl'])
++ print("parent:", tmp['parent'])
++ print("first child: ",tmp['child1']," last child: ", tmp['childn'])
++ print("pos_fid is ", tmp['pos_fid'])
++ print("\n\n")
+ num += 1
+ num += 1
+ self.indx_data = indx_data
+@@ -118,10 +118,10 @@ class ncxExtract:
+ #recursive part
+ def recursINDX(max_lvl=0, num=0, lvl=0, start=-1, end=-1):
+ if start>len(indx_data) or end>len(indx_data):
+- print "Warning: missing INDX child entries", start, end, len(indx_data)
++ print("Warning: missing INDX child entries", start, end, len(indx_data))
+ return ''
+ if DEBUG_NCX:
+- print "recursINDX lvl %d from %d to %d" % (lvl, start, end)
++ print("recursINDX lvl %d from %d to %d" % (lvl, start, end))
+ xml = ''
+ if start <= 0:
+ start = 0
+@@ -155,13 +155,13 @@ class ncxExtract:
+ header = ncx_header % (ident, max_lvl + 1, title)
+ ncx = header + body + ncx_footer
+ if not len(indx_data) == num:
+- print "Warning: different number of entries in NCX", len(indx_data), num
++ print("Warning: different number of entries in NCX", len(indx_data), num)
+ return ncx
+
+ def writeNCX(self, metadata):
+ # build the xml
+ self.isNCX = True
+- print "Write ncx"
++ print("Write ncx")
+ htmlname = os.path.basename(self.files.outbase)
+ htmlname += '.html'
+ xml = self.buildNCX(htmlname, metadata['Title'][0], metadata['UniqueID'][0])
+@@ -202,10 +202,10 @@ class ncxExtract:
+ #recursive part
+ def recursINDX(max_lvl=0, num=0, lvl=0, start=-1, end=-1):
+ if start>len(indx_data) or end>len(indx_data):
+- print "Warning: missing INDX child entries", start, end, len(indx_data)
++ print("Warning: missing INDX child entries", start, end, len(indx_data))
+ return ''
+ if DEBUG_NCX:
+- print "recursINDX lvl %d from %d to %d" % (lvl, start, end)
++ print("recursINDX lvl %d from %d to %d" % (lvl, start, end))
+ xml = ''
+ if start <= 0:
+ start = 0
+@@ -244,13 +244,13 @@ class ncxExtract:
+ header = ncx_header % (ident, max_lvl + 1, title)
+ ncx = header + body + ncx_footer
+ if not len(indx_data) == num:
+- print "Warning: different number of entries in NCX", len(indx_data), num
++ print("Warning: different number of entries in NCX", len(indx_data), num)
+ return ncx
+
+ def writeK8NCX(self, ncx_data, metadata):
+ # build the xml
+ self.isNCX = True
+- print "Write K8 ncx"
++ print("Write K8 ncx")
+ xml = self.buildK8NCX(ncx_data, metadata['Title'][0], metadata['UniqueID'][0])
+ bname = 'toc.ncx'
+ ncxname = os.path.join(self.files.k8oebps,bname)
diff --git a/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__opf.py b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__opf.py
new file mode 100644
index 000000000000..cd27f3646c95
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__opf.py
@@ -0,0 +1,38 @@
+--- data/scripts/mobi_lib/mobi_opf.py.orig 2021-08-16 04:25:19 UTC
++++ data/scripts/mobi_lib/mobi_opf.py
+@@ -21,7 +21,7 @@ class OPFProcessor:
+
+ def writeOPF(self, has_obfuscated_fonts=False):
+ # write out the metadata as an OEB 1.0 OPF file
+- print "Write opf"
++ print("Write opf")
+ metadata = self.metadata
+
+ META_TAGS = ['Drm Server Id', 'Drm Commerce Id', 'Drm Ebookbase Book Id', 'ASIN', 'ThumbOffset', 'Fake Cover',
+@@ -100,7 +100,7 @@ class OPFProcessor:
+ imageNumber = int(metadata['CoverOffset'][0])
+ self.covername = self.imgnames[imageNumber]
+ if self.covername is None:
+- print "Error: Cover image %s was not recognized as a valid image" % imageNumber
++ print("Error: Cover image %s was not recognized as a valid image" % imageNumber)
+ else:
+ if self.isK8:
+ data.append('<meta name="cover" content="cover_img" />\n')
+@@ -126,7 +126,7 @@ class OPFProcessor:
+ priceList = metadata['Price']
+ currencyList = metadata['Currency']
+ if len(priceList) != len(currencyList):
+- print "Error: found %s price entries, but %s currency entries."
++ print("Error: found %s price entries, but %s currency entries.")
+ else:
+ for i in range(len(priceList)):
+ data.append('<SRP Currency="'+currencyList[i]+'">'+priceList[i]+'</SRP>\n')
+@@ -137,7 +137,7 @@ class OPFProcessor:
+ imageNumber = int(metadata['ThumbOffset'][0])
+ imageName = self.imgnames[imageNumber]
+ if imageName is None:
+- print "Error: Cover Thumbnail image %s was not recognized as a valid image" % imageNumber
++ print("Error: Cover Thumbnail image %s was not recognized as a valid image" % imageNumber)
+ else:
+ if self.isK8:
+ data.append('<meta name="Cover ThumbNail Image" content="'+ 'Images/'+imageName+'" />\n')
diff --git a/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__unpack.py b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__unpack.py
new file mode 100644
index 000000000000..dd3ca576da73
--- /dev/null
+++ b/deskutils/bookworm/files/patch-data_scripts_mobi__lib_mobi__unpack.py
@@ -0,0 +1,354 @@
+--- data/scripts/mobi_lib/mobi_unpack.py.orig 2021-08-16 04:42:50 UTC
++++ data/scripts/mobi_lib/mobi_unpack.py
+@@ -256,7 +256,7 @@ class MobiHeader:
+ self.header = self.sect.loadSection(self.start)
+ self.records, = struct.unpack_from('>H', self.header, 0x8)
+ self.length, self.type, self.codepage, self.unique_id, self.version = struct.unpack('>LLLLL', self.header[20:40])
+- print "Mobi Version: ", self.version
++ print("Mobi Version: ", self.version)
+
+ # codec
+ self.codec = 'windows-1252'
+@@ -266,18 +266,18 @@ class MobiHeader:
+ }
+ if self.codepage in codec_map.keys():
+ self.codec = codec_map[self.codepage]
+- print "Codec: ", self.codec
++ print("Codec: ", self.codec)
+
+ # title
+ toff, tlen = struct.unpack('>II', self.header[0x54:0x5c])
+ tend = toff + tlen
+ self.title=self.header[toff:tend]
+- print "Title: ", self.title
++ print("Title: ", self.title)
+
+ # set up for decompression/unpacking
+ compression, = struct.unpack_from('>H', self.header, 0x0)
+ if compression == 0x4448:
+- print "Huffdic compression"
++ print("Huffdic compression")
+ reader = HuffcdicReader()
+ huffoff, huffnum = struct.unpack_from('>LL', self.header, 0x70)
+ huffoff = huffoff + self.start
+@@ -286,10 +286,10 @@ class MobiHeader:
+ reader.loadCdic(self.sect.loadSection(huffoff+i))
+ self.unpack = reader.unpack
+ elif compression == 2:
+- print "Palmdoc compression"
++ print("Palmdoc compression")
+ self.unpack = PalmdocReader().unpack
+ elif compression == 1:
+- print "No compression"
++ print("No compression")
+ self.unpack = UncompressedReader().unpack
+ else:
+ raise unpackException('invalid compression type: 0x%4x' % compression)
+@@ -376,14 +376,14 @@ class MobiHeader:
+ self.fdst += self.start
+
+ if DEBUG:
+- print "firstaddl %0x" % self.firstaddl
+- print "ncxidx %0x" % self.ncxidx
+- print "exth flags %0x" % exth_flag
++ print("firstaddl %0x" % self.firstaddl)
++ print("ncxidx %0x" % self.ncxidx)
++ print("exth flags %0x" % exth_flag)
+ if self.version == 8 or self.start != 0:
+- print "skelidx %0x" % self.skelidx
+- print "dividx %0x" % self.dividx
+- print "othidx %0x" % self.othidx
+- print "fdst %0x" % self.fdst
++ print("skelidx %0x" % self.skelidx)
++ print("dividx %0x" % self.dividx)
++ print("othidx %0x" % self.othidx)
++ print("fdst %0x" % self.fdst)
+
+ # NOTE: See DumpMobiHeader.py for a complete set of header fields
+
+@@ -464,7 +464,7 @@ class MobiHeader:
+ trailers += 1
+ flags = flags >> 1
+ # get raw mobi markup languge
+- print "Unpack raw markup language"
++ print("Unpack raw markup language")
+ dataList = []
+ # offset = 0
+ for i in xrange(1, self.records+1):
+@@ -542,7 +542,7 @@ class MobiHeader:
+ else:
+ metadata[name].append(value)
+ if DEBUG:
+- print "multiple values: metadata[%s]=%s" % (name, metadata[name])
++ print("multiple values: metadata[%s]=%s" % (name, metadata[name]))
+ _length, num_items = struct.unpack('>LL', extheader[4:12])
+ extheader = extheader[12:]
+ pos = 0
+@@ -564,12 +564,12 @@ class MobiHeader:
+ value, = struct.unpack('>L',content)
+ addValue(name, str(value))
+ else:
+- print "Error: Value for %s has unexpected size of %s" % (name, size)
++ print("Error: Value for %s has unexpected size of %s" % (name, size))
+ elif id in id_map_hexstrings.keys():
+ name = id_map_hexstrings[id]
+ addValue(name, content.encode('hex'))
+ else:
+- print "Warning: Unknown metadata with id %s found" % id
++ print("Warning: Unknown metadata with id %s found" % id)
+ name = str(id) + ' (hex)'
+ addValue(name, content.encode('hex'))
+ pos += size
+@@ -600,11 +600,11 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ for mh in mhlst:
+
+ if mh.isK8():
+- print "\n\nProcessing K8 format Ebook ..."
++ print("\n\nProcessing K8 format Ebook ...")
+ elif mh.isPrintReplica():
+- print "\nProcessing PrintReplica (.azw4) format Ebook ..."
++ print("\nProcessing PrintReplica (.azw4) format Ebook ...")
+ else:
+- print "\nProcessing Mobi format Ebook ..."
++ print("\nProcessing Mobi format Ebook ...")
+
+ if DEBUG:
+ # write out raw mobi header data
+@@ -624,8 +624,8 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ metadata['Codec'] = [mh.codec]
+ metadata['UniqueID'] = [str(mh.unique_id)]
+ if DEBUG:
+- print "MetaData from EXTH"
+- print metadata
++ print("MetaData from EXTH")
++ print(metadata)
+
+ # save the raw markup language
+ rawML = mh.getRawML()
+@@ -643,12 +643,12 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+
+ # process additional sections that represent images, resources, fonts, and etc
+ # build up a list of image names to use to postprocess the rawml
+- print "Unpacking images, resources, fonts, etc"
++ print("Unpacking images, resources, fonts, etc")
+ firstaddl = mh.getfirstAddl()
+ if DEBUG:
+- print "firstaddl is ", firstaddl
+- print "num_sections is ", sect.num_sections
+- print "K8Boundary is ", K8Boundary
++ print("firstaddl is ", firstaddl)
++ print("num_sections is ", sect.num_sections)
++ print("K8Boundary is ", K8Boundary)
+ beg = firstaddl
+ end = sect.num_sections
+ if firstaddl < K8Boundary:
+@@ -656,12 +656,12 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ obfuscate_data = []
+ for i in xrange(beg, end):
+ if DEBUG:
+- print "Section is ", i
++ print("Section is ", i)
+ data = sect.loadSection(i)
+ type = data[0:4]
+ if type in ["FLIS", "FCIS", "FDST", "DATP"]:
+ if DEBUG:
+- print 'First 4 bytes: %s' % toHex(data[0:4])
++ print('First 4 bytes: %s' % toHex(data[0:4]))
+ fname = "%05d" % (1+i-beg)
+ fname = type + fname
+ if mh.isK8():
+@@ -669,13 +669,13 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ fname += '.dat'
+ outname= os.path.join(files.outdir, fname)
+ file(outname, 'wb').write(data)
+- print "Skipping ", type, " section"
++ print("Skipping ", type, " section")
+ imgnames.append(None)
+ continue
+ elif type == "SRCS":
+ # The mobi file was created by kindlegen and contains a zip archive with all source files.
+ # Extract the archive and save it.
+- print " Info: File contains kindlegen source archive, extracting as %s" % KINDLEGENSRC_FILENAME
++ print(" Info: File contains kindlegen source archive, extracting as %s" % KINDLEGENSRC_FILENAME)
+ srcname = os.path.join(files.outdir, KINDLEGENSRC_FILENAME)
+ file(srcname, 'wb').write(data[16:])
+ imgnames.append(None)
+@@ -709,29 +709,29 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ adler32, = struct.unpack_from('>I', font_data, len(font_data) - 4)
+ font_data = zlib.decompress(font_data[2:-4], -wbits, usize)
+ if len(font_data) != usize:
+- print 'Font Decompression Error: Uncompressed font size mismatch'
++ print('Font Decompression Error: Uncompressed font size mismatch')
+ if False:
+ # For some reason these almost never match, probably Amazon has a
+ # buggy Adler32 implementation
+ sig = (zlib.adler32(font_data) & 0xffffffff)
+ if sig != adler32:
+- print 'Font Decompression Error'
+- print 'Adler checksum did not match. Stored: %d Calculated: %d' % (adler32, sig)
++ print('Font Decompression Error')
++ print('Adler checksum did not match. Stored: %d Calculated: %d' % (adler32, sig))
+ else:
+- print "Error Decoding Font", str(err)
++ print("Error Decoding Font", str(err))
+ hdr = font_data[0:4]
+ if hdr == '\0\1\0\0' or hdr == 'true' or hdr == 'ttcf':
+ ext = '.ttf'
+ elif hdr == 'OTTO':
+ ext = '.otf'
+ else:
+- print "Warning: unknown font header %s" % hdr.encode('hex')
++ print("Warning: unknown font header %s" % hdr.encode('hex'))
+ ext = '.dat'
+ fontname = "font%05d" % (1+i-beg)
+ fontname += ext
+ if (ext == '.ttf' or ext == '.otf') and (fflags & 0x0002):
+ obfuscate_data.append(fontname)
+- print " extracting font: ", fontname
++ print(" extracting font: ", fontname)
+ outfnt = os.path.join(files.imgdir, fontname)
+ file(outfnt, 'wb').write(font_data)
+ imgnames.append(fontname)
+@@ -746,7 +746,7 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ if DEBUG:
+ data = data[4:]
+ rescname = "resc%05d.dat" % (1+i-beg)
+- print " extracting resource: ", rescname
++ print(" extracting resource: ", rescname)
+ outrsc = os.path.join(files.imgdir, rescname)
+ file(outrsc, 'wb').write(data)
+ imgnames.append(None)
+@@ -754,7 +754,7 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+
+ if data == EOF_RECORD:
+ if DEBUG:
+- print "Skip section %i as it contains the EOF record." % i
++ print("Skip section %i as it contains the EOF record." % i)
+ imgnames.append(None)
+ continue
+
+@@ -762,16 +762,16 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ # Get the proper file extension
+ imgtype = imghdr.what(None, data)
+ if imgtype is None:
+- print "Warning: Section %s contains no image or an unknown image format" % i
++ print("Warning: Section %s contains no image or an unknown image format" % i)
+ imgnames.append(None)
+ if DEBUG:
+- print 'First 4 bytes: %s' % toHex(data[0:4])
++ print('First 4 bytes: %s' % toHex(data[0:4]))
+ fname = "unknown%05d.dat" % (1+i-beg)
+ outname= os.path.join(files.outdir, fname)
+ file(outname, 'wb').write(data)
+ else:
+ imgname = "image%05d.%s" % (1+i-beg, imgtype)
+- print " extracting image: ", imgname
++ print(" extracting image: ", imgname)
+ outimg = os.path.join(files.imgdir, imgname)
+ file(outimg, 'wb').write(data)
+ imgnames.append(imgname)
+@@ -781,11 +781,11 @@ def process_all_mobi_headers(files, sect, mhlst, K8Bou
+ # Process print replica book.
+ if mh.isPrintReplica() and not k8only:
+ filenames = []
+- print "Print Replica ebook detected"
++ print("Print Replica ebook detected")
+ try:
+ mh.processPrintReplica(files)
+- except Exception, e:
+- print 'Error processing Print Replica: ' + str(e)
++ except Exception as e:
++ print('Error processing Print Replica: ' + str(e))
+ filenames.append(['', files.getInputFileBasename() + '.pdf'])
+ usedmap = {}
+ for name in imgnames:
+@@ -915,7 +915,7 @@ def unpackBook(infile, outdir):
+
+ # process the PalmDoc database header and verify it is a mobi
+ sect = Sectionizer(infile)
+- print "Palm DB type: ", sect.ident
++ print("Palm DB type: ", sect.ident)
+ if sect.ident != 'BOOKMOBI' and sect.ident != 'TEXtREAd':
+ raise unpackException('invalid file format')
+
+@@ -945,7 +945,7 @@ def unpackBook(infile, outdir):
+ if (after - before) == 8:
+ data = sect.loadSection(i)
+ if data == K8_BOUNDARY:
+- print "Mobi Ebook uses the new K8 file format"
++ print("Mobi Ebook uses the new K8 file format")
+ mh = MobiHeader(sect,i+1)
+ hasK8 = hasK8 or mh.isK8()
+ mhlst.append(mh)
+@@ -1010,32 +1010,32 @@ class Mobi8Reader:
+
+
+ def usage(progname):
+- print ""
+- print "Description:"
+- print " Unpacks an unencrypted Kindle/MobiPocket ebook to html and images"
+- print " or an unencrypted Kindle/Print Replica ebook to PDF and images"
+- print " into the specified output folder."
+- print "Usage:"
+- print " %s -r -s -d -h infile [outdir]" % progname
+- print "Options:"
+- print " -r write raw data to the output folder"
+- print " -s split combination mobis into mobi7 and mobi8 ebooks"
+- print " -d enable verbose debugging"
+- print " -h print this help message"
++ print("")
++ print("Description:")
++ print(" Unpacks an unencrypted Kindle/MobiPocket ebook to html and images")
++ print(" or an unencrypted Kindle/Print Replica ebook to PDF and images")
++ print(" into the specified output folder.")
++ print("Usage:")
++ print(" %s -r -s -d -h infile [outdir]" % progname)
++ print("Options:")
++ print(" -r write raw data to the output folder")
++ print(" -s split combination mobis into mobi7 and mobi8 ebooks")
++ print(" -d enable verbose debugging")
++ print(" -h print this help message")
+
+
+ def main(argv=sys.argv):
+ global DEBUG
+ global WRITE_RAW_DATA
+ global SPLIT_COMBO_MOBIS
+- print "MobiUnpack 0.47"
+- print " Copyright (c) 2009 Charles M. Hannum <root@ihack.net>"
+- print " With Additions by P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding."
++ print("MobiUnpack 0.47")
++ print(" Copyright (c) 2009 Charles M. Hannum <root@ihack.net>")
++ print(" With Additions by P. Durrant, K. Hendricks, S. Siebert, fandrieu, DiapDealer, nickredding.")
+ progname = os.path.basename(argv[0])
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "hdrs")
+- except getopt.GetoptError, err:
+- print str(err)
++ except getopt.GetoptError as err:
++ print(str(err))
+ usage(progname)
+ sys.exit(2)
+
+@@ -1062,16 +1062,16 @@ def main(argv=sys.argv):
+
+ infileext = os.path.splitext(infile)[1].upper()
+ if infileext not in ['.MOBI', '.PRC', '.AZW', '.AZW4']:
+- print "Error: first parameter must be a Kindle/Mobipocket ebook or a Kindle/Print Replica ebook."
++ print("Error: first parameter must be a Kindle/Mobipocket ebook or a Kindle/Print Replica ebook.")
+ return 1
+
+ try:
+- print 'Unpacking Book...'
++ print('Unpacking Book...')
+ unpackBook(infile, outdir)
+- print 'Completed'
++ print('Completed')
+
+- except ValueError, e:
+- print "Error: %s" % e
++ except ValueError as e:
++ print("Error: %s" % e)
+ return 1
+
+ return 0
diff --git a/deskutils/bookworm/files/patch-src_bookworm.vala b/deskutils/bookworm/files/patch-src_bookworm.vala
new file mode 100644
index 000000000000..162cbd1b28bb
--- /dev/null
+++ b/deskutils/bookworm/files/patch-src_bookworm.vala
@@ -0,0 +1,15 @@
+--- src/bookworm.vala.orig 2019-08-10 18:20:51 UTC
++++ src/bookworm.vala
+@@ -481,7 +481,11 @@ public class BookwormApp.Bookworm : Granite.Applicatio
+ //Run dicovery of books as a background task if not already running
+ string checkBackgroundTask = BookwormApp.Utils.execute_sync_command("ps -ef");
+ if(checkBackgroundTask.index_of("bookworm --discover") == -1){
+- BookwormApp.Utils.execute_async_multiarg_command_pipes({"com.github.babluboy.bookworm", "--discover", "&"});
++ BookwormApp.Utils.execute_async_command({
++ "com.github.babluboy.bookworm",
++ "--discover",
++ "&"
++ });
+ }else{
+ debug("Bookworm discover process already running....");
+ }
diff --git a/deskutils/bookworm/files/patch-src_pdfReader.vala b/deskutils/bookworm/files/patch-src_pdfReader.vala
new file mode 100644
index 000000000000..179345937e4d
--- /dev/null
+++ b/deskutils/bookworm/files/patch-src_pdfReader.vala
@@ -0,0 +1,62 @@
+--- src/pdfReader.vala.orig 2019-08-10 18:20:51 UTC
++++ src/pdfReader.vala
+@@ -26,6 +26,7 @@ public class BookwormApp.pdfReader {
+ debug("Initiated process for parsing of PDF Book located at:"+aBook.getBookLocation());
+ //Extract the content of the PDF
+ string extractionLocation = extractEBook(aBook.getBookLocation());
++
+ if("false" == extractionLocation){ //handle error condition
+ aBook.setIsBookParsed(false);
+ aBook.setParsingIssue(BookwormApp.Constants.TEXT_FOR_EXTRACTION_ISSUE);
+@@ -60,30 +61,38 @@ public class BookwormApp.pdfReader {
+ public static string extractEBook(string eBookLocation){
+ info("[START] [FUNCTION:extractEBook] eBookLocation="+eBookLocation);
+ string extractionLocation = "false";
+- debug("Initiated process for content extraction of PDF Book located at:"+eBookLocation);
++
++ debug("Initiated process for content extraction of PDF Book located at:"+eBookLocation);
++
+ if(BookwormApp.Bookworm.settings == null){
+ BookwormApp.Bookworm.settings = BookwormApp.Settings.get_instance();
+ }
++
+ //create a location for extraction of eBook based on local storage prefference
+ if(BookwormApp.Bookworm.settings.is_local_storage_enabled){
+ extractionLocation = BookwormApp.Bookworm.bookworm_config_path + "/books/" + File.new_for_path(eBookLocation).get_basename();
+ }else{
+ extractionLocation = BookwormApp.Constants.EBOOK_EXTRACTION_LOCATION + File.new_for_path(eBookLocation).get_basename();
+ }
++
+ //check and create directory for extracting contents of ebook
+ BookwormApp.Utils.fileOperations("CREATEDIR", extractionLocation, "", "");
+- //extract eBook contents into temp location
+- BookwormApp.Utils.execute_async_multiarg_command_pipes({"pdftohtml",
+- "-noframes",
+- "-zoom", "2.0",
+- "-wbt", "20.0",
+- "-nomerge",
+- eBookLocation,
+- extractionLocation + "/" + File.new_for_path(eBookLocation).get_basename()+".html"
+- });
+-
+- debug("Output of pdftohtml command:"+BookwormApp.Utils.spawn_async_with_pipes_output.str);
+- info("[END] [FUNCTION:extractEBook] extractionLocation="+extractionLocation);
++
++ BookwormApp.Utils.execute_async_command({
++ "pdftohtml",
++ "-noframes",
++ "-zoom", "2.0",
++ "-wbt", "20.0",
++ "-nomerge",
++ eBookLocation,
++ extractionLocation
++ + "/"
++ + File.new_for_path(eBookLocation).get_basename()
++ + ".html"
++ });
++
++ info("[END] [FUNCTION:extractEBook] extractionLocation=" + extractionLocation);
++
+ return extractionLocation;
+ }
+
diff --git a/deskutils/bookworm/files/patch-src_utils.vala b/deskutils/bookworm/files/patch-src_utils.vala
new file mode 100644
index 000000000000..a214dd77af44
--- /dev/null
+++ b/deskutils/bookworm/files/patch-src_utils.vala
@@ -0,0 +1,38 @@
+--- src/utils.vala.orig 2019-08-10 18:20:51 UTC
++++ src/utils.vala
+@@ -94,6 +94,35 @@ namespace BookwormApp.Utils {
+ debug("Completed executing async command["+string.joinv(" ", spawn_args)+"]...");
+ return 0;
+ }
++
++ public int execute_async_command(string[] args) {
++ MainLoop loop = new MainLoop();
++
++ try {
++ Pid child;
++
++ Process.spawn_async(
++ "/",
++ args,
++ null,
++ SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
++ null,
++ out child
++ );
++
++ ChildWatch.add(child, (pid, status) => {
++ Process.close_pid(pid);
++
++ loop.quit();
++ });
++
++ loop.run();
++ } catch (SpawnError error) {
++ warning("ERROR execute_async_command (" + string.joinv(" ", args) + ")");
++ }
++
++ return 0;
++ }
+
+ public string execute_sync_command (string cmd){
+ debug("Starting to execute sync command ["+cmd+"]...");
diff --git a/deskutils/bookworm/pkg-descr b/deskutils/bookworm/pkg-descr
new file mode 100644
index 000000000000..4dc867314c69
--- /dev/null
+++ b/deskutils/bookworm/pkg-descr
@@ -0,0 +1,7 @@
+Bookworm is a simple, focused eBook reader.
+
+Read the books you love without having to worry about the different format
+complexities like epub, pdf, mobi, cbr, etc. This version supports EPUB, PDF
+and Comics (CBR and CBZ) formats with support for more formats to follow soon.
+
+WWW: https://babluboy.github.io/bookworm/
diff --git a/deskutils/bookworm/pkg-plist b/deskutils/bookworm/pkg-plist
new file mode 100644
index 000000000000..dd3fbda7ba73
--- /dev/null
+++ b/deskutils/bookworm/pkg-plist
@@ -0,0 +1,223 @@
+bin/com.github.babluboy.bookworm
+share/applications/com.github.babluboy.bookworm.desktop
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_dict.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_html.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_index.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_k8proc.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_ncx.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_opf.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_split.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_uncompress.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_unpack.py
+share/com.github.babluboy.bookworm/scripts/mobi_lib/mobi_utils.py
+share/com.github.babluboy.bookworm/scripts/tasks/com.github.babluboy.bookworm.dictionary.sh
+share/com.github.babluboy.bookworm/scripts/tasks/com.github.babluboy.bookworm.search.sh
+share/icons/hicolor/128x128/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/128x128@2/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/16x16/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/16x16@2/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/24x24/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/24x24@2/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/32x32/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/32x32@2/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/48x48/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/48x48@2/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/64x64/apps/com.github.babluboy.bookworm.svg
+share/icons/hicolor/64x64@2/apps/com.github.babluboy.bookworm.svg
+share/locale/aa/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ab/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ae/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/af/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ak/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/am/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/an/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ar/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/as/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ast/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/av/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ay/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/az/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ba/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/be/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/bg/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/bh/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/bi/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/bm/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/bn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/bo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/br/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/bs/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ca/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ce/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ch/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ckb/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/co/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/cr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/cs/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/cu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/cv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/cy/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/da/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/de/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/dv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/dz/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ee/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/el/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/en_AU/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/en_CA/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/en_GB/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/eo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/es/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/es_MX/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/et/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/eu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/fa/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ff/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/fi/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/fj/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/fo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/fr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/fr_CA/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/fy/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ga/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/gd/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/gl/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/gn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/gu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/gv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ha/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/he/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/hi/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ho/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/hr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ht/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/hu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/hy/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/hz/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ia/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/id/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ie/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ig/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ii/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ik/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/io/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/is/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/it/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/iu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ja/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/jv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ka/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kg/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ki/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kj/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kk/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kl/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/km/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ko/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ks/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ku/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/kw/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ky/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/la/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/lb/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/lg/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/li/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ln/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/lo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/lt/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/lu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/lv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mg/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mh/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mi/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mk/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ml/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ms/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/mt/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/my/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/na/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/nb_NO/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/nd/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ne/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ng/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/nl/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/nn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/nr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/nv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ny/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/oc/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/oj/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/om/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/or/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/os/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/pa/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/pi/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/pl/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ps/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/pt/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/pt_BR/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/qu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/rm/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/rn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ro/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ru/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/rue/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/rw/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sa/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sc/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sd/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/se/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sg/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/si/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sk/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sl/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sm/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sma/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/so/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sq/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ss/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/st/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/su/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sv/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/sw/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ta/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/te/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/tg/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/th/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ti/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/tk/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/tl/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/tn/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/to/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/tr/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ts/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/tt/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/tw/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ty/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ug/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/uk/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ur/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/uz/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/ve/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/vi/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/vo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/wa/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/wo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/xh/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/yi/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/yo/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/za/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/zh/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/zh_CN/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/zh_HK/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/zh_TW/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/locale/zu/LC_MESSAGES/com.github.babluboy.bookworm.mo
+share/metainfo/com.github.babluboy.bookworm.appdata.xml