From 8b85cbf157293d8241fe0a33712dd6b424a13ff6 Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 6 Oct 2015 21:18:07 +0800 Subject: [PATCH 1/9] add support for password protected zip/cbz documents --- base | 2 +- frontend/apps/reader/readerui.lua | 68 +++++++++++++++++++++++++++++- frontend/document/pdfdocument.lua | 8 ++-- frontend/ui/widget/inputdialog.lua | 1 + 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/base b/base index d0bed73cd..d8403c089 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit d0bed73cd630aa7f304cd7447eea8abfd3500aec +Subproject commit d8403c08984ccd9e3ede9f9ef32713f832b51de1 diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index 4418e854a..659917b3b 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -1,6 +1,7 @@ local InputContainer = require("ui/widget/container/inputcontainer") local DocumentRegistry = require("document/documentregistry") local InfoMessage = require("ui/widget/infomessage") +local InputDialog = require("ui/widget/inputdialog") local ConfirmBox = require("ui/widget/confirmbox") local lfs = require("libs/libkoreader-lfs") local DocSettings = require("docsettings") @@ -321,7 +322,13 @@ function ReaderUI:showReader(file) text = T( _("Opening file '%1'."), file), timeout = 0.1, }) - UIManager:scheduleIn(0.1, function() self:doShowReader(file) end) + UIManager:scheduleIn(0.1, function() + DEBUG("creating coroutine for showing reader") + local co = coroutine.create(function() + self:doShowReader(file) + end) + coroutine.resume(co) + end) end local running_instance = nil @@ -338,6 +345,17 @@ function ReaderUI:doShowReader(file) }) return end + if document.is_locked then + DEBUG("document is locked") + self._coroutine = coroutine.running() or self._coroutine + self:unlockDocumentWithPassword(document) + if coroutine.running() then + local unlock_success = coroutine.yield() + if not unlock_success then + return + end + end + end G_reader_settings:saveSetting("lastfile", file) local reader = ReaderUI:new{ @@ -348,6 +366,54 @@ function ReaderUI:doShowReader(file) running_instance = reader end +function ReaderUI:unlockDocumentWithPassword(document, try_again) + DEBUG("show input password dialog") + self.password_dialog = InputDialog:new{ + title = try_again and _("Password is incorrect, try again?") + or _("Input document password"), + buttons = { + { + { + text = _("Cancel"), + enabled = true, + callback = function() + self:closeDialog() + coroutine.resume(self._coroutine) + end, + }, + { + text = _("OK"), + enabled = true, + callback = function() + local success = self:onVerifyPassword(document) + self:closeDialog() + if success then + coroutine.resume(self._coroutine, success) + else + self:unlockDocumentWithPassword(document, true) + end + end, + }, + }, + }, + text_type = "password", + width = Screen:getWidth() * 0.8, + height = Screen:getHeight() * 0.2, + } + self.password_dialog:onShowKeyboard() + UIManager:show(self.password_dialog) +end + +function ReaderUI:onVerifyPassword(document) + local password = self.password_dialog:getInputText() + return document:unlock(password) +end + +function ReaderUI:closeDialog() + self.password_dialog:onClose() + UIManager:close(self.password_dialog) +end + function ReaderUI:onSetDimensions(dimen) self.dimen = dimen end diff --git a/frontend/document/pdfdocument.lua b/frontend/document/pdfdocument.lua index d0cc3a6a0..6fd2f51ea 100644 --- a/frontend/document/pdfdocument.lua +++ b/frontend/document/pdfdocument.lua @@ -32,17 +32,17 @@ function PdfDocument:init() self:_readMetadata() end if not (self.info.number_of_pages > 0) then - error("No page found in PDF file") + --error("No page found in PDF file") end end function PdfDocument:unlock(password) if not self._document:authenticatePassword(password) then - self._document:close() - return false, "wrong password" + return false end self.is_locked = false - return self:_readMetadata() + self:_readMetadata() + return true end function PdfDocument:getPageTextBoxes(pageno) diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index af2a03763..7a9627d1a 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -60,6 +60,7 @@ function InputDialog:init() face = self.input_face, width = self.width * 0.9, input_type = self.input_type, + text_type = self.text_type, enter_callback = self.enter_callback, scroll = false, parent = self, From 10895d30c906a7d4a65dd5b25dd526a10fb1ea6b Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 6 Oct 2015 22:14:26 +0800 Subject: [PATCH 2/9] update README file for build instructions --- README.md | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index bfb479902..683bb1218 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ KOReader ======== -[![Join the chat at https://gitter.im/koreader/koreader](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/koreader/koreader?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Join the chat][gitter-badge]][gitter-link] KOReader is a document viewer application, originally created for Kindle -e-ink readers. It currently runs on Kindle 5 (Touch), Kindle Paperwhite, -Kobo, PocketBook and Android (2.3+) devices. Developers can also run Koreader emulator -for development purpose on desktop PC with Linux or Windows operating system. +e-ink readers. It currently runs on Kindle, Kobo, PocketBook, Ubuntu Touch +and Android (2.3+) devices. Developers can also run Koreader emulator +for development purpose on desktop PC with Linux and Windows operating system. Main features for users ----------------------- @@ -67,7 +67,7 @@ These instructions for how to get and compile the source are intended for a Linu OS. Windows users are suggested to develop in a [Linux VM][linux-vm] or use Wubi. To get and compile the source you must have `patch`, `wget`, `unzip`, `git`, -`subversion`, `cmake` and `luarocks` installed, as well as a version of `autoconf` +`cmake` and `luarocks` installed, as well as a version of `autoconf` greater than 2.64. You also need `nasm` and of course a compiler like `gcc` or `clang`. If you want to cross-compile for other architectures, you need a proper cross-compile toolchain. Your GCC should be at least of version 4.7 for both native @@ -75,9 +75,11 @@ and cross compiling. Users of Debian and Ubuntu can install the required packages using: ``` -sudo apt-get install build-essential libtool gcc-multilib libffi-dev linux-libc-dev:i386 \ -patch wget unzip git autoconf subversion cmake nasm libsdl1.2-dev luarocks +sudo apt-get install build-essential git patch wget unzip \ +autoconf cmake libtool nasm luarocks \ +libssl-dev libffi-dev libsdl2-dev linux-libc-dev:i386 ``` +Note that the `linux-libc-dev:i386` package is only necessary for x86_64 machines. Cross compile toolchains are available for Ubuntu users through these commands: ``` @@ -95,9 +97,15 @@ Koreader for Android devices. sudo apt-get install ant ``` +In order to build Koreader package for Ubuntu Touch, the `click` package management +tool is needed, Ubuntu users can install it with: +``` +sudo apt-get install click +``` + You might also need SDL library packages if you want to compile and run -koreader on Linux PC. Fedora users can install `SDL` and `SDL-devel` package. -Ubuntu users probably need to install `libsdl1.2-dev` package: +Koreader on Linux PC. Fedora users can install `SDL` and `SDL-devel` package. +Ubuntu users probably need to install `libsdl2-dev` package: Getting the source ======== @@ -134,7 +142,7 @@ then similarly with Kindle and Kobo building run this command: make TARGET=pocketbook clean update ``` -To build installable package for Ubuntu touch +To build installable package for Ubuntu Touch ``` make TARGET=ubuntu-touch clean update ``` @@ -176,7 +184,7 @@ If you want to compile the emulator for Windows you need to run: make TARGET=win32 clean && make TARGET=win32 ``` -To run koreader on your developing machine +To run Koreader on your developing machine (you may need to change $(MACHINE) to the arch of your machine such as 'x86_64'): ``` cd koreader-emulator-$(MACHINE)/koreader && ./reader.lua -d ../../test @@ -276,3 +284,5 @@ http://ccache.samba.org [coverage-badge]:https://coveralls.io/repos/koreader/koreader/badge.svg [coverage-link]:https://coveralls.io/r/koreader/koreader [licence-badge]:http://img.shields.io/badge/licence-AGPL-brightgreen.svg +[gitter-badge]:https://badges.gitter.im/Join%20Chat.svg +[gitter-link]:https://gitter.im/koreader/koreader?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge From 5bab00ff9bbb6ea661697232240c4be4f6abe65d Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 6 Oct 2015 22:15:38 +0800 Subject: [PATCH 3/9] add apparmor.openstore file for openstore submission --- Makefile | 1 + platform/ubuntu-touch/koreader.apparmor.openstore | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 platform/ubuntu-touch/koreader.apparmor.openstore diff --git a/Makefile b/Makefile index e998c34d9..58db7b5c1 100644 --- a/Makefile +++ b/Makefile @@ -241,6 +241,7 @@ utupdate: all ln -sf ../../$(UBUNTUTOUCH_DIR)/koreader.sh $(INSTALL_DIR)/koreader ln -sf ../../$(UBUNTUTOUCH_DIR)/manifest.json $(INSTALL_DIR)/koreader ln -sf ../../$(UBUNTUTOUCH_DIR)/koreader.apparmor $(INSTALL_DIR)/koreader + ln -sf ../../$(UBUNTUTOUCH_DIR)/koreader.apparmor.openstore $(INSTALL_DIR)/koreader ln -sf ../../$(UBUNTUTOUCH_DIR)/koreader.desktop $(INSTALL_DIR)/koreader ln -sf ../../$(UBUNTUTOUCH_DIR)/koreader.png $(INSTALL_DIR)/koreader ln -sf ../../../$(UBUNTUTOUCH_SDL_DIR)/lib/arm-linux-gnueabihf/libSDL2.so $(INSTALL_DIR)/koreader/libs diff --git a/platform/ubuntu-touch/koreader.apparmor.openstore b/platform/ubuntu-touch/koreader.apparmor.openstore new file mode 100644 index 000000000..a45b2c473 --- /dev/null +++ b/platform/ubuntu-touch/koreader.apparmor.openstore @@ -0,0 +1,15 @@ +{ + "policy_groups": [ + "networking" + ], + "read_path": [ + "@{HOME}/", + "/media/*/*/[Dd][Oo][Cc][Uu][Mm][Ee][Nn][Tt][Ss]/", + "@{PROC}/*/mounts", + "/dev/disk/by-label/" + ], + "write_path": [ + "@{HOME}/" + ], + "policy_version": 1.2 +} From eeafa55abdc83b507d4a9adee3411aeefc6e6c35 Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 6 Oct 2015 23:02:41 +0800 Subject: [PATCH 4/9] update koreader-base --- base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base b/base index d8403c089..891db8c2d 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit d8403c08984ccd9e3ede9f9ef32713f832b51de1 +Subproject commit 891db8c2d296b05f7d91047767ca98d74a8f8638 From 1e4ac8c3b5a611c34b9b9b375169fc90b8ab1aeb Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 7 Oct 2015 13:57:06 +0800 Subject: [PATCH 5/9] fix pthread invoke on Android --- base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base b/base index 891db8c2d..05b04b0a2 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit 891db8c2d296b05f7d91047767ca98d74a8f8638 +Subproject commit 05b04b0a20c3cc9c9969537f805e378a530c079a From 429eeed3728ff9db997d11dcf337512739640e21 Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 7 Oct 2015 15:14:27 +0800 Subject: [PATCH 6/9] verbose unit test log so that we have a clue when there is segfault --- .travis.yml | 1 + Makefile | 2 +- spec/unit/verbose_print.lua | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 spec/unit/verbose_print.lua diff --git a/.travis.yml b/.travis.yml index 2ee0b22ba..c9a2947a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,6 +46,7 @@ install: - cp /etc/luarocks/config.lua $HOME/.luarocks/config.lua - echo "wrap_bin_scripts = false" >> $HOME/.luarocks/config.lua - travis_retry luarocks --local install lua_cliargs + - travis_retry luarocks --local install ansicolors - travis_retry luarocks --local install busted #- travis_retry luarocks --local install busted 1.11.1-1 #- mv -f $HOME/.luarocks/bin/busted_bootstrap $HOME/.luarocks/bin/busted diff --git a/Makefile b/Makefile index 58db7b5c1..35a40972a 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ $(INSTALL_DIR)/koreader/.luacov: ln -sf ../../.luacov $(INSTALL_DIR)/koreader testfront: $(INSTALL_DIR)/koreader/.busted - cd $(INSTALL_DIR)/koreader && ./luajit $(shell which busted) --exclude-tags=notest + cd $(INSTALL_DIR)/koreader && ./luajit $(shell which busted) -o verbose_print --exclude-tags=notest test: $(MAKE) -C $(KOR_BASE) test diff --git a/spec/unit/verbose_print.lua b/spec/unit/verbose_print.lua new file mode 100644 index 000000000..f194a8dbe --- /dev/null +++ b/spec/unit/verbose_print.lua @@ -0,0 +1,22 @@ +-- from Mashape/kong/spec/busted-print.lua +local ansicolors = require 'ansicolors' + +return function(options) + local handler = require 'busted.outputHandlers.utfTerminal'(options) + + handler.fileStart = function(file) + io.write('\n' .. ansicolors('%{cyan}' .. file.name) .. ':') + end + + handler.testStart = function(element, parent, status, debug) + io.write('\n ' .. handler.getFullName(element) .. ' ... ') + io.flush() + end + + local busted = require 'busted' + + busted.subscribe({ 'file', 'start' }, handler.fileStart) + busted.subscribe({ 'test', 'start' }, handler.testStart) + + return handler +end From 970f9a78018751cc2dfadfb63bc8fa4f4560296d Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 7 Oct 2015 22:41:14 +0800 Subject: [PATCH 7/9] verbose coverage test --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 35a40972a..b31b7f261 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,7 @@ test: $(MAKE) testfront coverage: $(INSTALL_DIR)/koreader/.luacov - cd $(INSTALL_DIR)/koreader && ./luajit $(shell which busted) --coverage --exclude-tags=nocov + cd $(INSTALL_DIR)/koreader && ./luajit $(shell which busted) -o verbose_print --coverage --exclude-tags=nocov # coverage report summary cd $(INSTALL_DIR)/koreader && tail -n \ +$$(($$(grep -nm1 Summary luacov.report.out|cut -d: -f1)-1)) \ From 54f5166254b081be6e63213b6aeabb63417f01bd Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 7 Oct 2015 22:42:12 +0800 Subject: [PATCH 8/9] add koptinterface spec --- frontend/document/koptinterface.lua | 1 + spec/unit/commonrequire.lua | 27 ++++++++++ spec/unit/document_spec.lua | 6 +++ spec/unit/koptinterface_spec.lua | 83 +++++++++++++++++++++++++++++ spec/unit/kosync_spec.lua | 2 +- 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 spec/unit/koptinterface_spec.lua diff --git a/frontend/document/koptinterface.lua b/frontend/document/koptinterface.lua index 94bc73cdb..dd5046071 100644 --- a/frontend/document/koptinterface.lua +++ b/frontend/document/koptinterface.lua @@ -206,6 +206,7 @@ function KoptInterface:getCachedContext(doc, pageno) -- If kctx is not cached, create one and get reflowed bmp in foreground. local kc = self:createContext(doc, pageno, bbox) local page = doc._document:openPage(pageno) + DEBUG("reflowing page", pageno, "in foreground") -- reflow page --local secs, usecs = util.gettime() page:reflow(kc, 0) diff --git a/spec/unit/commonrequire.lua b/spec/unit/commonrequire.lua index 2e0f49531..6f6b2c188 100644 --- a/spec/unit/commonrequire.lua +++ b/spec/unit/commonrequire.lua @@ -21,3 +21,30 @@ Input.dummy = true -- turn on debug local DEBUG = require("dbg") --DEBUG:turnOn() + +function assertAlmostEquals(expected, actual, margin) + if type(actual) ~= 'number' or type(expected) ~= 'number' + or type(margin) ~= 'number' then + error('assertAlmostEquals: must supply only number arguments.', 2) + end + + assert(math.abs(expected - actual) <= margin, + 'Values are not almost equal\n' + .. 'Expected: ' .. expected .. ' with margin of ' .. margin + .. ', received: ' .. actual + ) +end + +function assertNotAlmostEquals(expected, actual, margin) + if type(actual) ~= 'number' or type(expected) ~= 'number' + or type(margin) ~= 'number' then + error('assertAlmostEquals: must supply only number arguments.', 2) + end + + assert(math.abs(expected - actual) > margin, + 'Values are almost equal\n' + .. 'Expected: ' .. expected .. ' with margin of ' .. margin + .. ', received: ' .. actual + ) +end + diff --git a/spec/unit/document_spec.lua b/spec/unit/document_spec.lua index 68e99a8e5..836fb94de 100644 --- a/spec/unit/document_spec.lua +++ b/spec/unit/document_spec.lua @@ -13,6 +13,12 @@ describe("PDF document module", function() assert.are.same(dimen.w, 567) assert.are.same(dimen.h, 1418) end) + it("should get cover image", function() + local image = doc:getCoverPageImage() + assert.truthy(image) + assert.are.same(320, image:getWidth()) + assert.are.same(800, image:getHeight()) + end) local pos0 = {page = 1, x = 0, y = 20} local pos1 = {page = 1, x = 300, y = 120} local pboxes = { diff --git a/spec/unit/koptinterface_spec.lua b/spec/unit/koptinterface_spec.lua new file mode 100644 index 000000000..02cb51a1d --- /dev/null +++ b/spec/unit/koptinterface_spec.lua @@ -0,0 +1,83 @@ +require("commonrequire") +local DocumentRegistry = require("document/documentregistry") +local Koptinterface = require("document/koptinterface") +local Cache = require("cache") +local DEBUG = require("dbg") +DEBUG:turnOn() + +describe("Koptinterface module", function() + local sample_pdf = "spec/front/unit/data/tall.pdf" + local doc + + before_each(function() + doc = DocumentRegistry:openDocument(sample_pdf) + Cache:clear() + end) + + after_each(function() + doc:close() + end) + + it("should get auto bbox", function() + local auto_bbox = Koptinterface:getAutoBBox(doc, 1) + assertAlmostEquals(22, auto_bbox.x0, 0.5) + assertAlmostEquals(38, auto_bbox.y0, 0.5) + assertAlmostEquals(548, auto_bbox.x1, 0.5) + assertAlmostEquals(1387, auto_bbox.y1, 0.5) + end) + + it("should get semi auto bbox", function() + local semiauto_bbox = Koptinterface:getSemiAutoBBox(doc, 1) + local page_bbox = doc:getPageBBox(1) + doc.bbox[1] = { + x0 = page_bbox.x0 + 10, + y0 = page_bbox.y0 + 10, + x1 = page_bbox.x1 - 10, + y1 = page_bbox.y1 - 10, + } + + local bbox = Koptinterface:getSemiAutoBBox(doc, 1) + assertNotAlmostEquals(semiauto_bbox.x0, bbox.x0, 0.5) + assertNotAlmostEquals(semiauto_bbox.y0, bbox.y0, 0.5) + assertNotAlmostEquals(semiauto_bbox.x1, bbox.x1, 0.5) + assertNotAlmostEquals(semiauto_bbox.y1, bbox.y1, 0.5) + end) + + it("should render optimized page to de-watermark", function() + local page_dimen = doc:getPageDimensions(1, 1.0, 0) + local tile = Koptinterface:renderOptimizedPage(doc, 1, nil, + 1.0, 0, 0) + assert.truthy(tile) + assert.are.same(page_dimen, tile.excerpt) + end) + + it("should reflow page in foreground", function() + doc.configurable.text_wrap = 1 + local kc = Koptinterface:getCachedContext(doc, 1) + assert.truthy(kc) + end) + + it("should hint reflowed page in background", function() + doc.configurable.text_wrap = 1 + Koptinterface:hintReflowedPage(doc, 1, 1.0, 0, 1.0, 0) + -- and wait for reflowing to complete + local kc = Koptinterface:getCachedContext(doc, 1) + assert.truthy(kc) + end) + + it("should get native text boxes", function() + local kc = Koptinterface:getCachedContext(doc, 1) + local boxes = Koptinterface:getNativeTextBoxes(doc, 1) + local lines_in_native_page = #boxes + assert.truthy(lines_in_native_page == 60) + end) + + it("should get reflow text boxes", function() + doc.configurable.text_wrap = 1 + local kc = Koptinterface:getCachedContext(doc, 1) + local boxes = Koptinterface:getReflowedTextBoxes(doc, 1) + local lines_in_reflowed_page = #boxes + assert.truthy(lines_in_reflowed_page > 60) + end) + +end) diff --git a/spec/unit/kosync_spec.lua b/spec/unit/kosync_spec.lua index 279b3339d..99e9adb7d 100644 --- a/spec/unit/kosync_spec.lua +++ b/spec/unit/kosync_spec.lua @@ -1,6 +1,5 @@ require("commonrequire") local UIManager = require("ui/uimanager") -local HTTPClient = require("httpclient") local DEBUG = require("dbg") local md5 = require("MD5") --DEBUG:turnOn() @@ -58,6 +57,7 @@ local service = [[ ]] describe("KOSync modules #notest #nocov", function() + local HTTPClient = require("httpclient") local Spore = require("Spore") local client = Spore.new_from_string(service) package.loaded['Spore.Middleware.GinClient'] = {} From 19979fb8f8f19b1e1d5ec6a67f006344b637eb5e Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 7 Oct 2015 23:00:49 +0800 Subject: [PATCH 9/9] postpone loading of httpclient module in unit test --- spec/unit/httpclient_spec.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/unit/httpclient_spec.lua b/spec/unit/httpclient_spec.lua index 16e887071..46f6cc4f7 100644 --- a/spec/unit/httpclient_spec.lua +++ b/spec/unit/httpclient_spec.lua @@ -1,6 +1,5 @@ require("commonrequire") local UIManager = require("ui/uimanager") -local HTTPClient = require("httpclient") local DEBUG = require("dbg") --DEBUG:turnOn() @@ -15,8 +14,9 @@ describe("HTTP client module #notest #nocov", function() assert(not res.error, "error occurs") assert(res.body) end - local async_client = HTTPClient:new() it("should get response from async GET request", function() + local HTTPClient = require("httpclient") + local async_client = HTTPClient:new() UIManager:quit() local urls = { "http://www.example.com",