From 2abcf9bc68d62e605e086f4a14e583417ed02728 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Sat, 7 Mar 2026 19:33:02 +0100 Subject: [PATCH] Review fixes --- lib/Epub/Epub/parsers/ContentOpfParser.cpp | 20 ++++++++++++++++---- src/RecentBooksStore.cpp | 4 ++-- src/activities/home/FileBrowserActivity.cpp | 6 ++++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/Epub/Epub/parsers/ContentOpfParser.cpp b/lib/Epub/Epub/parsers/ContentOpfParser.cpp index 0b7455d2..58ea3225 100644 --- a/lib/Epub/Epub/parsers/ContentOpfParser.cpp +++ b/lib/Epub/Epub/parsers/ContentOpfParser.cpp @@ -10,6 +10,7 @@ namespace { constexpr char MEDIA_TYPE_NCX[] = "application/x-dtbncx+xml"; constexpr char MEDIA_TYPE_CSS[] = "text/css"; constexpr char itemCacheFile[] = "/.items.bin"; +constexpr size_t MAX_DESCRIPTION_LENGTH = 1024; // Strip HTML tags and collapse whitespace from a description string. // Expat already decodes XML entities (< → <), so we see raw angle brackets. @@ -20,9 +21,17 @@ std::string stripHtml(const std::string& html) { for (size_t i = 0; i < html.size(); ++i) { const char c = html[i]; if (c == '<') { - inTag = true; - // Ensure words don't merge when a tag is removed - if (!result.empty() && result.back() != ' ') result += ' '; + // Only treat as a tag if followed by a tag-like character; otherwise keep literal '<' + size_t j = i + 1; + while (j < html.size() && html[j] == ' ') ++j; + if (j < html.size() && + (isalpha(static_cast(html[j])) || html[j] == '/' || html[j] == '!' || html[j] == '?')) { + inTag = true; + // Ensure words don't merge when a tag is removed + if (!result.empty() && result.back() != ' ') result += ' '; + } else { + result += c; + } } else if (c == '>') { inTag = false; } else if (!inTag) { @@ -440,7 +449,10 @@ void XMLCALL ContentOpfParser::characterData(void* userData, const XML_Char* s, } if (self->state == IN_BOOK_DESCRIPTION) { - self->description.append(s, len); + if (self->description.size() < MAX_DESCRIPTION_LENGTH) { + const size_t remaining = MAX_DESCRIPTION_LENGTH - self->description.size(); + self->description.append(s, std::min(static_cast(len), remaining)); + } return; } diff --git a/src/RecentBooksStore.cpp b/src/RecentBooksStore.cpp index 075947e8..18a98c43 100644 --- a/src/RecentBooksStore.cpp +++ b/src/RecentBooksStore.cpp @@ -134,7 +134,7 @@ bool RecentBooksStore::loadFromBinaryFile() { std::string title, author; serialization::readString(inputFile, title); serialization::readString(inputFile, author); - recentBooks.push_back({path, title, author, ""}); + recentBooks.push_back({path, title, author, "", ""}); } else { recentBooks.push_back(book); } @@ -160,7 +160,7 @@ bool RecentBooksStore::loadFromBinaryFile() { continue; } - recentBooks.push_back({path, title, author, coverBmpPath}); + recentBooks.push_back({path, title, author, "", coverBmpPath}); } if (omitted > 0) { diff --git a/src/activities/home/FileBrowserActivity.cpp b/src/activities/home/FileBrowserActivity.cpp index b6fc0da4..be45471a 100644 --- a/src/activities/home/FileBrowserActivity.cpp +++ b/src/activities/home/FileBrowserActivity.cpp @@ -160,14 +160,16 @@ void FileBrowserActivity::loop() { const std::string& entry = files[selectorIndex]; const bool isDirectory = (entry.back() == '/'); - if (basepath.back() != '/') basepath += "/"; if (isDirectory) { + if (basepath.back() != '/') basepath += "/"; basepath += entry.substr(0, entry.length() - 1); loadFiles(); selectorIndex = 0; requestUpdate(); } else { - onSelectBook(basepath + entry); + std::string fullPath = basepath; + if (fullPath.back() != '/') fullPath += "/"; + onSelectBook(fullPath + entry); } return; }