diff --git a/frontend/ui/opdsparser.lua b/frontend/ui/opdsparser.lua index 7883cd701..eba8f8a85 100644 --- a/frontend/ui/opdsparser.lua +++ b/frontend/ui/opdsparser.lua @@ -20,62 +20,56 @@ local unescape_map = { local gsub = string.gsub local function unescape(str) return gsub(str, '(&(#?)([%d%a]+);)', function(orig, n, s) - return unescape_map[s] or n=="#" and util.unichar(tonumber(s)) or orig + if unescape_map[s] then + return unescape_map[s] + elseif n == "#" then -- unescape unicode + return util.unichar(tonumber(s)) + else + return orig + end end) end -function OPDSParser:createFlatXTable(xlex, currentelement) - currentelement = currentelement or {} +function OPDSParser:createFlatXTable(xlex, curr_element) + curr_element = curr_element or {} - local currentattributename = nil; - local attribute_count = 0; + local curr_attr_name; + local attr_count = 0; -- start reading the thing local txt for event, offset, size in xlex:Lexemes() do txt = ffi.string(xlex.buf + offset, size) - - if event == luxl.EVENT_START and txt ~= "xml" then - -- does current element already have something - -- with this name? - - -- if it does, if it's a table, add to it - -- if it doesn't, then add a table - local tab = self:createFlatXTable(xlex) - if txt == "entry" or txt == "link" then - if currentelement[txt] == nil then - currentelement[txt] = {} + if event == luxl.EVENT_START then + if txt ~= "xml" then + -- does current element already have something + -- with this name? + + -- if it does, if it's a table, add to it + -- if it doesn't, then add a table + local tab = self:createFlatXTable(xlex) + if txt == "entry" or txt == "link" then + if curr_element[txt] == nil then + curr_element[txt] = {} + end + table.insert(curr_element[txt], tab) + elseif type(curr_element) == "table" then + curr_element[txt] = tab end - table.insert(currentelement[txt], tab) - elseif type(currentelement) == "table" then - currentelement[txt] = tab end - end - - if event == luxl.EVENT_ATTR_NAME then - currentattributename = txt - end - - if event == luxl.EVENT_ATTR_VAL then - currentelement[currentattributename] = txt - attribute_count = attribute_count + 1; - currentattributename = nil - end - - if event == luxl.EVENT_TEXT then - --if attribute_count < 1 then - -- return txt - --end - - currentelement = unescape(txt) - end - - if event == luxl.EVENT_END then - return currentelement + elseif event == luxl.EVENT_ATTR_NAME then + curr_attr_name = unescape(txt) + elseif event == luxl.EVENT_ATTR_VAL then + curr_element[curr_attr_name] = unescape(txt) + attr_count = attr_count + 1; + curr_attr_name = nil + elseif event == luxl.EVENT_TEXT then + curr_element = unescape(txt) + elseif event == luxl.EVENT_END then + return curr_element end end - - return currentelement + return curr_element end function OPDSParser:parse(text) diff --git a/frontend/ui/widget/opdsbrowser.lua b/frontend/ui/widget/opdsbrowser.lua index a110c01a3..0119d07dd 100644 --- a/frontend/ui/widget/opdsbrowser.lua +++ b/frontend/ui/widget/opdsbrowser.lua @@ -367,74 +367,83 @@ end function OPDSBrowser:genItemTableFromCatalog(catalog, item_url) local item_table = {} - if catalog then - local feed = catalog.feed or catalog - local function build_href(href) - --DEBUG("building href", item_url, href) - return url.absolute(item_url, href) - end - local hrefs = {} - if feed.link then - for _, link in ipairs(feed.link) do - if link.type ~= nil then - if link.type:find(self.catalog_type) or - link.type:find(self.search_type) then - if link.rel and link.href then - hrefs[link.rel] = build_href(link.href) - end + if not catalog then + return item_table + end + + local feed = catalog.feed or catalog + + local function build_href(href) + return url.absolute(item_url, href) + end + + local hrefs = {} + if feed.link then + for _, link in ipairs(feed.link) do + if link.type ~= nil then + if link.type:find(self.catalog_type) or + link.type:find(self.search_type) then + if link.rel and link.href then + hrefs[link.rel] = build_href(link.href) end end end end - item_table.hrefs = hrefs - if feed.entry then - for _, entry in ipairs(feed.entry) do - local item = {} - item.acquisitions = {} - if entry.link then - for _, link in ipairs(entry.link) do - if link.type:find(self.catalog_type) and (not link.rel or link.rel == "subsection" or link.rel == "http://opds-spec.org/sort/popular" or link.rel == "http://opds-spec.org/sort/new") then - item.url = build_href(link.href) - end - if link.rel and link.rel:match(self.acquisition_rel) then - table.insert(item.acquisitions, { - type = link.type, - --DEBUG("building acquisition url", link); - href = build_href(link.href), - }) - end - if link.rel == self.thumbnail_rel then - item.thumbnail = build_href(link.href) - end - if link.rel == self.image_rel then - item.image = build_href(link.href) - end - end + end + item_table.hrefs = hrefs + + if not feed.entry then + return item_table + end + + for _, entry in ipairs(feed.entry) do + local item = {} + item.acquisitions = {} + if entry.link then + for _, link in ipairs(entry.link) do + if link.type:find(self.catalog_type) + and (not link.rel + or link.rel == "subsection" + or link.rel == "http://opds-spec.org/sort/popular" + or link.rel == "http://opds-spec.org/sort/new") then + item.url = build_href(link.href) end - local title = "Unknown" - if type(entry.title) == "string" then - title = entry.title - elseif type(entry.title) == "table" then - if type(entry.title.type) == "string" and entry.title.div ~= "" then - title = entry.title.div + if link.rel then + if link.rel:match(self.acquisition_rel) then + table.insert(item.acquisitions, { + type = link.type, + href = build_href(link.href), + }) + elseif link.rel == self.thumbnail_rel then + item.thumbnail = build_href(link.href) + elseif link.rel == self.image_rel then + item.image = build_href(link.href) end end - if title == "Unknown" then - DEBUG("Cannot handle title", entry.title) - end - local author = "Unknown Author" - if type(entry.author) == "table" and entry.author.name then - author = entry.author.name - end - item.text = title - item.title = title - item.author = author - item.id = entry.id - item.content = entry.content - item.updated = entry.updated - table.insert(item_table, item) end end + local title = "Unknown" + if type(entry.title) == "string" then + title = entry.title + elseif type(entry.title) == "table" then + if type(entry.title.type) == "string" and entry.title.div ~= "" then + title = entry.title.div + end + end + if title == "Unknown" then + DEBUG("Cannot handle title", entry.title) + end + local author = "Unknown Author" + if type(entry.author) == "table" and entry.author.name then + author = entry.author.name + end + item.text = title + item.title = title + item.author = author + item.id = entry.id + item.content = entry.content + item.updated = entry.updated + table.insert(item_table, item) end return item_table end diff --git a/spec/unit/opds_spec.lua b/spec/unit/opds_spec.lua index 0328c4b26..ace2fb4d6 100644 --- a/spec/unit/opds_spec.lua +++ b/spec/unit/opds_spec.lua @@ -48,7 +48,7 @@ which contains *all* Project Gutenberg metadata in one RDF/XML file. http://m.gutenberg.org/ebooks/search.opds/?sort_order=random Random Random books. - + @@ -236,7 +236,6 @@ describe("OPDS module #nocov", function() it("should parse OPDS navigation catalog", function() local catalog = OPDSParser:parse(navigation_sample) local feed = catalog.feed - --DEBUG(feed) assert.truthy(feed) assert.are.same(feed.title, "Project Gutenberg") local entries = feed.entry @@ -245,17 +244,18 @@ describe("OPDS module #nocov", function() local entry = entries[3] assert.are.same(entry.title, "Random") assert.are.same(entry.id, "http://m.gutenberg.org/ebooks/search.opds/?sort_order=random") + assert.are.same( + "/ebooks/search.opds/?sort_order=random&limit=5", + entry.link[1].href) end) it("should parse OPDS acquisition catalog", function() local catalog = OPDSParser:parse(acquisition_sample) local feed = catalog.feed - --DEBUG(feed) assert.truthy(feed) local entries = feed.entry assert.truthy(entries) assert.are.same(#entries, 2) local entry = entries[2] - --DEBUG(entry) assert.are.same(entry.title, "1000 Mythological Characters Briefly Described") assert.are.same(entry.link[1].href, "//www.gutenberg.org/ebooks/42474.epub.images") end)