Fixes
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Returns the length of href after trimming trailing slashes.
|
// Returns the length of href after trimming trailing slashes.
|
||||||
@@ -198,7 +199,7 @@ void XMLCALL OpdsParser::startElement(void* userData, const XML_Char* name, cons
|
|||||||
self->currentEntry.acquisitionLinks.push_back(acquisition);
|
self->currentEntry.acquisitionLinks.push_back(acquisition);
|
||||||
}
|
}
|
||||||
} else if (rel && type && strstr(rel, "opds-spec.org/image") != nullptr &&
|
} else if (rel && type && strstr(rel, "opds-spec.org/image") != nullptr &&
|
||||||
strstr(rel, "thumbnail") == nullptr && strstr(type, "image/jpeg") != nullptr &&
|
strstr(rel, "thumbnail") == nullptr && strncmp(type, "image/", 6) == 0 &&
|
||||||
self->currentEntry.imageHref.empty()) {
|
self->currentEntry.imageHref.empty()) {
|
||||||
self->currentEntry.imageHref = href;
|
self->currentEntry.imageHref = href;
|
||||||
} else if (type && strstr(type, "application/atom+xml") != nullptr) {
|
} else if (type && strstr(type, "application/atom+xml") != nullptr) {
|
||||||
@@ -238,7 +239,10 @@ void XMLCALL OpdsParser::endElement(void* userData, const XML_Char* name) {
|
|||||||
|
|
||||||
if (strcmp(name, "entry") == 0 || strstr(name, ":entry") != nullptr) {
|
if (strcmp(name, "entry") == 0 || strstr(name, ":entry") != nullptr) {
|
||||||
if (!self->currentEntry.title.empty() && !self->currentEntry.href.empty()) {
|
if (!self->currentEntry.title.empty() && !self->currentEntry.href.empty()) {
|
||||||
if (self->onEntryParsed) self->onEntryParsed(self->currentEntry);
|
if (self->onEntryParsed) {
|
||||||
|
self->onEntryParsed(std::move(self->currentEntry));
|
||||||
|
self->currentEntry = OpdsEntry{};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self->inEntry = false;
|
self->inEntry = false;
|
||||||
} else if (self->inEntry) {
|
} else if (self->inEntry) {
|
||||||
|
|||||||
@@ -43,14 +43,17 @@ using OpdsBook = OpdsEntry;
|
|||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* OpdsParser parser;
|
* OpdsParser parser;
|
||||||
* if (parser.parse(xmlData, xmlLength)) {
|
* parser.onEntryParsed = [](OpdsEntry entry) {
|
||||||
* for (const auto& entry : parser.getEntries()) {
|
* if (entry.type == OpdsEntryType::BOOK) {
|
||||||
* if (entry.type == OpdsEntryType::BOOK) {
|
* // Process downloadable book
|
||||||
* // Downloadable book
|
* } else {
|
||||||
* } else {
|
* // Process navigation link
|
||||||
* // Navigation link to another catalog
|
|
||||||
* }
|
|
||||||
* }
|
* }
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* // Entries are emitted immediately as they are parsed from the stream.
|
||||||
|
* if (parser.parse(xmlData, xmlLength)) {
|
||||||
|
* // Parsing completed successfully
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
class OpdsParser final : public Print {
|
class OpdsParser final : public Print {
|
||||||
|
|||||||
@@ -403,6 +403,8 @@ void OpdsBookBrowserActivity::fetchFeed(const std::string& path) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entryOffsets.clear();
|
||||||
|
|
||||||
std::string url = (path.find("http") == 0) ? path : UrlUtils::buildUrl(server.url, path);
|
std::string url = (path.find("http") == 0) ? path : UrlUtils::buildUrl(server.url, path);
|
||||||
LOG_DBG("OPDS", "Fetching: %s", url.c_str());
|
LOG_DBG("OPDS", "Fetching: %s", url.c_str());
|
||||||
|
|
||||||
@@ -448,12 +450,14 @@ void OpdsBookBrowserActivity::fetchFeed(const std::string& path) {
|
|||||||
const auto& prevUrl = parser.getPrevPageUrl();
|
const auto& prevUrl = parser.getPrevPageUrl();
|
||||||
|
|
||||||
if (!prevUrl.empty()) {
|
if (!prevUrl.empty()) {
|
||||||
OpdsEntry prevEntry{OpdsEntryType::NAVIGATION, tr(STR_PREV_PAGE), "", prevUrl, ""};
|
std::string resolvedPrevUrl = UrlUtils::buildUrl(url, prevUrl);
|
||||||
|
OpdsEntry prevEntry{OpdsEntryType::NAVIGATION, tr(STR_PREV_PAGE), "", resolvedPrevUrl, ""};
|
||||||
entryOffsets.insert(entryOffsets.begin(), cacheFile.position());
|
entryOffsets.insert(entryOffsets.begin(), cacheFile.position());
|
||||||
writeEntryToCache(cacheFile, prevEntry);
|
writeEntryToCache(cacheFile, prevEntry);
|
||||||
}
|
}
|
||||||
if (!nextUrl.empty()) {
|
if (!nextUrl.empty()) {
|
||||||
OpdsEntry nextEntry{OpdsEntryType::NAVIGATION, tr(STR_NEXT_PAGE), "", nextUrl, ""};
|
std::string resolvedNextUrl = UrlUtils::buildUrl(url, nextUrl);
|
||||||
|
OpdsEntry nextEntry{OpdsEntryType::NAVIGATION, tr(STR_NEXT_PAGE), "", resolvedNextUrl, ""};
|
||||||
entryOffsets.push_back(cacheFile.position());
|
entryOffsets.push_back(cacheFile.position());
|
||||||
writeEntryToCache(cacheFile, nextEntry);
|
writeEntryToCache(cacheFile, nextEntry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -509,9 +509,6 @@ void loop() {
|
|||||||
while (buttonEventManager.consumeEvent(ev)) {
|
while (buttonEventManager.consumeEvent(ev)) {
|
||||||
const uint8_t action = actionFor(ev);
|
const uint8_t action = actionFor(ev);
|
||||||
if (action == BA::BTN_DEFAULT) {
|
if (action == BA::BTN_DEFAULT) {
|
||||||
if (ev.type == ButtonEventManager::PressType::Double) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
defaultEvents.push_back(ev);
|
defaultEvents.push_back(ev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ bool parseSingleBookEntry(OpdsEntry& entryOut, const char* href, const char* typ
|
|||||||
</entry>
|
</entry>
|
||||||
</feed>)";
|
</feed>)";
|
||||||
|
|
||||||
|
std::vector<OpdsEntry> entries;
|
||||||
OpdsParser parser;
|
OpdsParser parser;
|
||||||
|
parser.onEntryParsed = [&](OpdsEntry e) { entries.push_back(std::move(e)); };
|
||||||
parser.write(reinterpret_cast<const uint8_t*>(xml.data()), xml.size());
|
parser.write(reinterpret_cast<const uint8_t*>(xml.data()), xml.size());
|
||||||
parser.flush();
|
parser.flush();
|
||||||
|
|
||||||
@@ -60,7 +62,6 @@ bool parseSingleBookEntry(OpdsEntry& entryOut, const char* href, const char* typ
|
|||||||
testsFailed++;
|
testsFailed++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto& entries = parser.getEntries();
|
|
||||||
if (entries.size() != 1) {
|
if (entries.size() != 1) {
|
||||||
fprintf(stderr, " FAIL: %s:%d: entries.size() == %zu, expected 1\n", __FILE__, __LINE__, entries.size());
|
fprintf(stderr, " FAIL: %s:%d: entries.size() == %zu, expected 1\n", __FILE__, __LINE__, entries.size());
|
||||||
testsFailed++;
|
testsFailed++;
|
||||||
@@ -153,12 +154,13 @@ void testDistinctAcquisitionFormatsRemainSeparate() {
|
|||||||
</entry>
|
</entry>
|
||||||
</feed>)";
|
</feed>)";
|
||||||
|
|
||||||
|
std::vector<OpdsEntry> entries;
|
||||||
OpdsParser parser;
|
OpdsParser parser;
|
||||||
|
parser.onEntryParsed = [&](OpdsEntry e) { entries.push_back(std::move(e)); };
|
||||||
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
||||||
parser.flush();
|
parser.flush();
|
||||||
|
|
||||||
ASSERT_TRUE(!parser.error());
|
ASSERT_TRUE(!parser.error());
|
||||||
const auto& entries = parser.getEntries();
|
|
||||||
ASSERT_SIZE(entries.size(), 1);
|
ASSERT_SIZE(entries.size(), 1);
|
||||||
const auto& links = entries.front().acquisitionLinks;
|
const auto& links = entries.front().acquisitionLinks;
|
||||||
ASSERT_SIZE(links.size(), 4);
|
ASSERT_SIZE(links.size(), 4);
|
||||||
@@ -181,12 +183,14 @@ void testUnsupportedMimeType() {
|
|||||||
</entry>
|
</entry>
|
||||||
</feed>)";
|
</feed>)";
|
||||||
|
|
||||||
|
std::vector<OpdsEntry> entries;
|
||||||
OpdsParser parser;
|
OpdsParser parser;
|
||||||
|
parser.onEntryParsed = [&](OpdsEntry e) { entries.push_back(std::move(e)); };
|
||||||
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
||||||
parser.flush();
|
parser.flush();
|
||||||
|
|
||||||
ASSERT_TRUE(!parser.error());
|
ASSERT_TRUE(!parser.error());
|
||||||
ASSERT_SIZE(parser.getEntries().size(), 0);
|
ASSERT_SIZE(entries.size(), 0);
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,12 +224,13 @@ void testEmptyHrefOrType() {
|
|||||||
</entry>
|
</entry>
|
||||||
</feed>)";
|
</feed>)";
|
||||||
|
|
||||||
|
std::vector<OpdsEntry> entries;
|
||||||
OpdsParser parser;
|
OpdsParser parser;
|
||||||
|
parser.onEntryParsed = [&](OpdsEntry e) { entries.push_back(std::move(e)); };
|
||||||
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
||||||
parser.flush();
|
parser.flush();
|
||||||
|
|
||||||
ASSERT_TRUE(!parser.error());
|
ASSERT_TRUE(!parser.error());
|
||||||
const auto& entries = parser.getEntries();
|
|
||||||
ASSERT_SIZE(entries.size(), 0);
|
ASSERT_SIZE(entries.size(), 0);
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
@@ -243,12 +248,13 @@ void testDuplicateAcquisitionLinks() {
|
|||||||
</entry>
|
</entry>
|
||||||
</feed>)";
|
</feed>)";
|
||||||
|
|
||||||
|
std::vector<OpdsEntry> entries;
|
||||||
OpdsParser parser;
|
OpdsParser parser;
|
||||||
|
parser.onEntryParsed = [&](OpdsEntry e) { entries.push_back(std::move(e)); };
|
||||||
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
||||||
parser.flush();
|
parser.flush();
|
||||||
|
|
||||||
ASSERT_TRUE(!parser.error());
|
ASSERT_TRUE(!parser.error());
|
||||||
const auto& entries = parser.getEntries();
|
|
||||||
ASSERT_SIZE(entries.size(), 1);
|
ASSERT_SIZE(entries.size(), 1);
|
||||||
const auto& links = entries.front().acquisitionLinks;
|
const auto& links = entries.front().acquisitionLinks;
|
||||||
ASSERT_SIZE(links.size(), 2);
|
ASSERT_SIZE(links.size(), 2);
|
||||||
@@ -272,12 +278,13 @@ void testIdenticalHrefAcquisitionLinksAreDeduplicated() {
|
|||||||
</entry>
|
</entry>
|
||||||
</feed>)";
|
</feed>)";
|
||||||
|
|
||||||
|
std::vector<OpdsEntry> entries;
|
||||||
OpdsParser parser;
|
OpdsParser parser;
|
||||||
|
parser.onEntryParsed = [&](OpdsEntry e) { entries.push_back(std::move(e)); };
|
||||||
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
||||||
parser.flush();
|
parser.flush();
|
||||||
|
|
||||||
ASSERT_TRUE(!parser.error());
|
ASSERT_TRUE(!parser.error());
|
||||||
const auto& entries = parser.getEntries();
|
|
||||||
ASSERT_SIZE(entries.size(), 1);
|
ASSERT_SIZE(entries.size(), 1);
|
||||||
const auto& links = entries.front().acquisitionLinks;
|
const auto& links = entries.front().acquisitionLinks;
|
||||||
ASSERT_SIZE(links.size(), 1);
|
ASSERT_SIZE(links.size(), 1);
|
||||||
@@ -299,12 +306,13 @@ void testSlashVariantHrefAcquisitionLinksAreDeduplicated() {
|
|||||||
</entry>
|
</entry>
|
||||||
</feed>)";
|
</feed>)";
|
||||||
|
|
||||||
|
std::vector<OpdsEntry> entries;
|
||||||
OpdsParser parser;
|
OpdsParser parser;
|
||||||
|
parser.onEntryParsed = [&](OpdsEntry e) { entries.push_back(std::move(e)); };
|
||||||
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
parser.write(reinterpret_cast<const uint8_t*>(xml), strlen(xml));
|
||||||
parser.flush();
|
parser.flush();
|
||||||
|
|
||||||
ASSERT_TRUE(!parser.error());
|
ASSERT_TRUE(!parser.error());
|
||||||
const auto& entries = parser.getEntries();
|
|
||||||
ASSERT_SIZE(entries.size(), 1);
|
ASSERT_SIZE(entries.size(), 1);
|
||||||
const auto& links = entries.front().acquisitionLinks;
|
const auto& links = entries.front().acquisitionLinks;
|
||||||
ASSERT_SIZE(links.size(), 1);
|
ASSERT_SIZE(links.size(), 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user