Merge remote branch 'hwhw/master'

* hwhw/master:
  Password input, handling for broken documents
  factored pages count out, better error and password handling
  factored pages counter out of document struct
pull/2/merge
traycold 12 years ago
commit fd6c6dbe60

@ -31,7 +31,6 @@
typedef struct DjvuDocument {
ddjvu_context_t *context;
ddjvu_document_t *doc_ref;
int pages;
} DjvuDocument;
typedef struct DjvuPage {
@ -90,7 +89,6 @@ static int openDocument(lua_State *L) {
return luaL_error(L, "cannot open DJVU file <%s>", filename);
}
doc->pages = ddjvu_document_get_pagenum(doc->doc_ref);
return 1;
}
@ -109,7 +107,7 @@ static int closeDocument(lua_State *L) {
static int getNumberOfPages(lua_State *L) {
DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument");
lua_pushinteger(L, doc->pages);
lua_pushinteger(L, ddjvu_document_get_pagenum(doc->doc_ref));
return 1;
}
@ -175,8 +173,8 @@ static int openPage(lua_State *L) {
DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument");
int pageno = luaL_checkint(L, 2);
if(pageno < 1 || pageno > doc->pages) {
return luaL_error(L, "cannot open page #%d, out of range (1-%d)", pageno, doc->pages);
if(pageno < 1 || pageno > ddjvu_document_get_pagenum(doc->doc_ref)) {
return luaL_error(L, "cannot open page #%d, out of range (1-%d)", pageno, ddjvu_document_get_pagenum(doc->doc_ref));
}
DjvuPage *page = (DjvuPage*) lua_newuserdata(L, sizeof(DjvuPage));

@ -5,6 +5,10 @@ DJVUReader = UniReader:new{}
-- open a DJVU file and its settings store
-- DJVU does not support password yet
function DJVUReader:open(filename)
self.doc = djvu.openDocument(filename)
return self:loadSettings(filename)
local ok
ok, self.doc = pcall(djvu.openDocument, filename)
if not ok then
return ok, self.doc -- this will be the error message instead
end
return ok
end

62
pdf.c

@ -24,7 +24,6 @@
typedef struct PdfDocument {
fz_document *xref;
fz_context *context;
int pages;
} PdfDocument;
typedef struct PdfPage {
@ -38,8 +37,7 @@ typedef struct PdfPage {
static int openDocument(lua_State *L) {
char *filename = strdup(luaL_checkstring(L, 1));
char *password = strdup(luaL_checkstring(L, 2));
int cachesize = luaL_optint(L, 3, 64 << 20); // 64 MB limit default
int cachesize = luaL_optint(L, 2, 64 << 20); // 64 MB limit default
PdfDocument *doc = (PdfDocument*) lua_newuserdata(L, sizeof(PdfDocument));
@ -53,19 +51,28 @@ static int openDocument(lua_State *L) {
}
fz_catch(doc->context) {
free(filename);
free(password);
return luaL_error(L, "cannot open PDF file <%s>", filename);
return luaL_error(L, "cannot open PDF file");
}
if(fz_needs_password(doc->xref)) {
if (!fz_authenticate_password(doc->xref, password)) {
free(filename);
free(password);
return luaL_error(L, "cannot authenticate");
}
}
doc->pages = fz_count_pages(doc->xref);
free(filename);
return 1;
}
static int needsPassword(lua_State *L) {
PdfDocument *doc = (PdfDocument*) luaL_checkudata(L, 1, "pdfdocument");
lua_pushboolean(L, fz_needs_password(doc->xref));
return 1;
}
static int authenticatePassword(lua_State *L) {
PdfDocument *doc = (PdfDocument*) luaL_checkudata(L, 1, "pdfdocument");
char *password = strdup(luaL_checkstring(L, 2));
if (!fz_authenticate_password(doc->xref, password)) {
lua_pushboolean(L, 0);
} else {
lua_pushboolean(L, 1);
}
free(password);
return 1;
}
@ -85,7 +92,12 @@ static int closeDocument(lua_State *L) {
static int getNumberOfPages(lua_State *L) {
PdfDocument *doc = (PdfDocument*) luaL_checkudata(L, 1, "pdfdocument");
lua_pushinteger(L, doc->pages);
fz_try(doc->context) {
lua_pushinteger(L, fz_count_pages(doc->xref));
}
fz_catch(doc->context) {
return luaL_error(L, "cannot access page tree");
}
return 1;
}
@ -148,24 +160,24 @@ static int openPage(lua_State *L) {
int pageno = luaL_checkint(L, 2);
if(pageno < 1 || pageno > doc->pages) {
return luaL_error(L, "cannot open page #%d, out of range (1-%d)", pageno, doc->pages);
}
fz_try(doc->context) {
if(pageno < 1 || pageno > fz_count_pages(doc->xref)) {
return luaL_error(L, "cannot open page #%d, out of range (1-%d)",
pageno, fz_count_pages(doc->xref));
}
PdfPage *page = (PdfPage*) lua_newuserdata(L, sizeof(PdfPage));
PdfPage *page = (PdfPage*) lua_newuserdata(L, sizeof(PdfPage));
luaL_getmetatable(L, "pdfpage");
lua_setmetatable(L, -2);
luaL_getmetatable(L, "pdfpage");
lua_setmetatable(L, -2);
fz_try(doc->context) {
page->page = fz_load_page(doc->xref, pageno - 1);
page->doc = doc;
}
fz_catch(doc->context) {
return luaL_error(L, "cannot open page #%d", pageno);
}
page->doc = doc;
return 1;
}
@ -288,6 +300,8 @@ static const struct luaL_Reg pdf_func[] = {
};
static const struct luaL_Reg pdfdocument_meth[] = {
{"needsPassword", needsPassword},
{"authenticatePassword", authenticatePassword},
{"openPage", openPage},
{"getPages", getNumberOfPages},
{"getTOC", getTableOfContent},

@ -1,9 +1,32 @@
require "unireader"
require "inputbox"
PDFReader = UniReader:new{}
-- open a PDF file and its settings store
function PDFReader:open(filename, password)
self.doc = pdf.openDocument(filename, password or "")
return self:loadSettings(filename)
function PDFReader:open(filename)
-- muPDF manages its own cache, set second parameter
-- to the maximum size you want it to grow
local ok
ok, self.doc = pcall(pdf.openDocument, filename, 64*1024*1024)
if not ok then
return false, self.doc -- will contain error message
end
if self.doc:needsPassword() then
local password = InputBox:input(height-100, 100, "Pass:")
if not password or not self.doc:authenticatePassword(password) then
self.doc:close()
self.doc = nil
return false, "wrong or missing password"
end
-- password wrong or not entered
end
local ok, err = pcall(self.doc.getPages, self.doc)
if not ok then
-- for PDFs, they might trigger errors later when accessing page tree
self.doc:close()
self.doc = nil
return false, "damaged page tree"
end
return true
end

@ -37,21 +37,25 @@ longopts = {
function openFile(filename)
local file_type = string.lower(string.match(filename, ".+%.([^.]+)"))
local reader = nil
if file_type == "djvu" then
if DJVUReader:open(filename) then
page_num = DJVUReader.settings:readsetting("last_page") or 1
DJVUReader:goto(tonumber(page_num))
reader_settings:savesetting("lastfile", filename)
return DJVUReader:inputloop()
end
reader = DJVUReader
elseif file_type == "pdf" or file_type == "xps" or file_type == "cbz" then
if PDFReader:open(filename,"") then -- TODO: query for password
page_num = PDFReader.settings:readsetting("last_page") or 1
PDFReader:goto(tonumber(page_num))
reader = PDFReader
end
if reader then
local ok, err = reader:open(filename)
if ok then
reader:loadSettings(filename)
page_num = reader.settings:readsetting("last_page") or 1
reader:goto(tonumber(page_num))
reader_settings:savesetting("lastfile", filename)
return PDFReader:inputloop()
return reader:inputloop()
else
-- TODO: error handling
end
end
return true -- on failed attempts, we signal to keep running
end
function showusage()

@ -181,7 +181,11 @@ function UniReader:draworcache(no, preCache)
-- #4 goal: we render next page, too. (TODO)
-- ideally, this should be factored out and only be called when needed (TODO)
local page = self.doc:openPage(no)
local ok, page = pcall(self.doc.openPage, self.doc, no)
if not ok then
-- TODO: error handling
return nil
end
local dc = self:setzoom(page)
-- offset_x_in_page & offset_y_in_page is the offset within zoomed page
@ -439,6 +443,9 @@ end
-- render and blit a page
function UniReader:show(no)
local pagehash, offset_x, offset_y = self:draworcache(no)
if not pagehash then
return
end
self.pagehash = pagehash
local bb = self.cache[pagehash].bb
local dest_x = 0

Loading…
Cancel
Save