diff options
Diffstat (limited to 'deskutils/bookworm')
15 files changed, 1402 insertions, 0 deletions
diff --git a/deskutils/bookworm/Makefile b/deskutils/bookworm/Makefile new file mode 100644 index 000000000000..0e680d9107c3 --- /dev/null +++ b/deskutils/bookworm/Makefile @@ -0,0 +1,62 @@ +PORTNAME= bookworm +DISTVERSION= 1.1.2 +PORTREVISION= 21 +CATEGORIES= deskutils + +MAINTAINER= miguel@gocobachi.dev +COMMENT= Simple, focused ebook reader +WWW= https://babluboy.github.io/bookworm/ + +LICENSE= GPLv3 +LICENSE_FILE= ${WRKSRC}/COPYING + +BUILD_DEPENDS= curl>0:ftp/curl \ + html2text>0:textproc/html2text +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 shebangfix sqlite vala:build +USE_GITHUB= yes +GH_ACCOUNT= babluboy +USE_GNOME= gdkpixbuf2 glib20 gtk30 libxml2 pango + +GLIB_SCHEMAS= com.github.babluboy.bookworm.gschema.xml +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} && ${LOCALBASE}/bin/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..9a11b99d80b8 --- /dev/null +++ b/deskutils/bookworm/pkg-descr @@ -0,0 +1,5 @@ +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. 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 |