diff --git a/lib/Epub/Epub.cpp b/lib/Epub/Epub.cpp index 876bea75c..cb0b18017 100644 --- a/lib/Epub/Epub.cpp +++ b/lib/Epub/Epub.cpp @@ -103,14 +103,11 @@ bool Epub::parseContentOpf(BookMetadataCache::BookMetadata& bookMetadata) { pos += strlen(pattern); const auto endPos = coverPageHtml.find('"', pos); if (endPos != std::string::npos) { - const auto ref = coverPageHtml.substr(pos, endPos - pos); + const auto ref = std::string_view{coverPageHtml}.substr(pos, endPos - pos); // Check if it's an image file - if (ref.length() >= 4) { - const auto ext = ref.substr(ref.length() - 4); - if (ext == ".png" || ext == ".jpg" || ext == "jpeg" || ext == ".gif") { - imageRef = ref; - break; - } + if (FsHelpers::hasPngExtension(ref) || FsHelpers::hasJpgExtension(ref) || FsHelpers::hasGifExtension(ref)) { + imageRef = ref; + break; } } pos = coverPageHtml.find(pattern, pos); @@ -541,8 +538,7 @@ bool Epub::generateCoverBmp(bool cropped) const { return false; } - if (coverImageHref.substr(coverImageHref.length() - 4) == ".jpg" || - coverImageHref.substr(coverImageHref.length() - 5) == ".jpeg") { + if (FsHelpers::hasJpgExtension(coverImageHref)) { LOG_DBG("EBP", "Generating BMP from JPG cover image (%s mode)", cropped ? "cropped" : "fit"); const auto coverJpgTempPath = getCachePath() + "/.cover.jpg"; @@ -575,7 +571,7 @@ bool Epub::generateCoverBmp(bool cropped) const { return success; } - if (coverImageHref.substr(coverImageHref.length() - 4) == ".png") { + if (FsHelpers::hasPngExtension(coverImageHref)) { LOG_DBG("EBP", "Generating BMP from PNG cover image (%s mode)", cropped ? "cropped" : "fit"); const auto coverPngTempPath = getCachePath() + "/.cover.png"; @@ -629,8 +625,7 @@ bool Epub::generateThumbBmp(int height) const { const auto coverImageHref = bookMetadataCache->coreMetadata.coverItemHref; if (coverImageHref.empty()) { LOG_DBG("EBP", "No known cover image for thumbnail"); - } else if (coverImageHref.substr(coverImageHref.length() - 4) == ".jpg" || - coverImageHref.substr(coverImageHref.length() - 5) == ".jpeg") { + } else if (FsHelpers::hasJpgExtension(coverImageHref)) { LOG_DBG("EBP", "Generating thumb BMP from JPG cover image"); const auto coverJpgTempPath = getCachePath() + "/.cover.jpg"; @@ -666,7 +661,7 @@ bool Epub::generateThumbBmp(int height) const { } LOG_DBG("EBP", "Generated thumb BMP from JPG cover image, success: %s", success ? "yes" : "no"); return success; - } else if (coverImageHref.substr(coverImageHref.length() - 4) == ".png") { + } else if (FsHelpers::hasPngExtension(coverImageHref)) { LOG_DBG("EBP", "Generating thumb BMP from PNG cover image"); const auto coverPngTempPath = getCachePath() + "/.cover.png"; diff --git a/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp b/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp index eb1f93b5f..52aa6aec7 100644 --- a/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp +++ b/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp @@ -1,5 +1,6 @@ #include "JpegToFramebufferConverter.h" +#include #include #include #include @@ -486,9 +487,5 @@ bool JpegToFramebufferConverter::decodeToFramebuffer(const std::string& imagePat } bool JpegToFramebufferConverter::supportsFormat(const std::string& extension) { - std::string ext = extension; - for (auto& c : ext) { - c = tolower(c); - } - return (ext == ".jpg" || ext == ".jpeg"); + return FsHelpers::hasJpgExtension(extension); } diff --git a/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp b/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp index 3b15ebf0b..6ba1bcdff 100644 --- a/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp +++ b/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp @@ -1,5 +1,6 @@ #include "PngToFramebufferConverter.h" +#include #include #include #include @@ -391,9 +392,5 @@ bool PngToFramebufferConverter::decodeToFramebuffer(const std::string& imagePath } bool PngToFramebufferConverter::supportsFormat(const std::string& extension) { - std::string ext = extension; - for (auto& c : ext) { - c = tolower(c); - } - return (ext == ".png"); + return FsHelpers::hasPngExtension(extension); } diff --git a/lib/FsHelpers/FsHelpers.cpp b/lib/FsHelpers/FsHelpers.cpp index 4bd8fbfe8..08ca44606 100644 --- a/lib/FsHelpers/FsHelpers.cpp +++ b/lib/FsHelpers/FsHelpers.cpp @@ -1,8 +1,12 @@ #include "FsHelpers.h" +#include +#include #include -std::string FsHelpers::normalisePath(const std::string& path) { +namespace FsHelpers { + +std::string normalisePath(const std::string& path) { std::vector components; std::string component; @@ -37,3 +41,41 @@ std::string FsHelpers::normalisePath(const std::string& path) { return result; } + +bool checkFileExtension(std::string_view fileName, const char* extension) { + const size_t extLen = strlen(extension); + if (fileName.length() < extLen) { + return false; + } + + const size_t offset = fileName.length() - extLen; + for (size_t i = 0; i < extLen; i++) { + if (tolower(static_cast(fileName[offset + i])) != + tolower(static_cast(extension[i]))) { + return false; + } + } + return true; +} + +bool hasJpgExtension(std::string_view fileName) { + return checkFileExtension(fileName, ".jpg") || checkFileExtension(fileName, ".jpeg"); +} + +bool hasPngExtension(std::string_view fileName) { return checkFileExtension(fileName, ".png"); } + +bool hasBmpExtension(std::string_view fileName) { return checkFileExtension(fileName, ".bmp"); } + +bool hasGifExtension(std::string_view fileName) { return checkFileExtension(fileName, ".gif"); } + +bool hasEpubExtension(std::string_view fileName) { return checkFileExtension(fileName, ".epub"); } + +bool hasXtcExtension(std::string_view fileName) { + return checkFileExtension(fileName, ".xtc") || checkFileExtension(fileName, ".xtch"); +} + +bool hasTxtExtension(std::string_view fileName) { return checkFileExtension(fileName, ".txt"); } + +bool hasMarkdownExtension(std::string_view fileName) { return checkFileExtension(fileName, ".md"); } + +} // namespace FsHelpers diff --git a/lib/FsHelpers/FsHelpers.h b/lib/FsHelpers/FsHelpers.h index 5bb4218e0..a21135127 100644 --- a/lib/FsHelpers/FsHelpers.h +++ b/lib/FsHelpers/FsHelpers.h @@ -1,7 +1,58 @@ #pragma once -#include +#include -class FsHelpers { - public: - static std::string normalisePath(const std::string& path); -}; +#include +#include + +namespace FsHelpers { + +std::string normalisePath(const std::string& path); + +/** + * Check if the given filename ends with the specified extension (case-insensitive). + */ +bool checkFileExtension(std::string_view fileName, const char* extension); +inline bool checkFileExtension(const String& fileName, const char* extension) { + return checkFileExtension(std::string_view{fileName.c_str(), fileName.length()}, extension); +} + +// Check for either .jpg or .jpeg extension (case-insensitive) +bool hasJpgExtension(std::string_view fileName); +inline bool hasJpgExtension(const String& fileName) { + return hasJpgExtension(std::string_view{fileName.c_str(), fileName.length()}); +} + +// Check for .png extension (case-insensitive) +bool hasPngExtension(std::string_view fileName); +inline bool hasPngExtension(const String& fileName) { + return hasPngExtension(std::string_view{fileName.c_str(), fileName.length()}); +} + +// Check for .bmp extension (case-insensitive) +bool hasBmpExtension(std::string_view fileName); + +// Check for .gif extension (case-insensitive) +bool hasGifExtension(std::string_view fileName); +inline bool hasGifExtension(const String& fileName) { + return hasGifExtension(std::string_view{fileName.c_str(), fileName.length()}); +} + +// Check for .epub extension (case-insensitive) +bool hasEpubExtension(std::string_view fileName); +inline bool hasEpubExtension(const String& fileName) { + return hasEpubExtension(std::string_view{fileName.c_str(), fileName.length()}); +} + +// Check for either .xtc or .xtch extension (case-insensitive) +bool hasXtcExtension(std::string_view fileName); + +// Check for .txt extension (case-insensitive) +bool hasTxtExtension(std::string_view fileName); +inline bool hasTxtExtension(const String& fileName) { + return hasTxtExtension(std::string_view{fileName.c_str(), fileName.length()}); +} + +// Check for .md extension (case-insensitive) +bool hasMarkdownExtension(std::string_view fileName); + +} // namespace FsHelpers diff --git a/lib/Txt/Txt.cpp b/lib/Txt/Txt.cpp index bb20a2bcd..83ef123cc 100644 --- a/lib/Txt/Txt.cpp +++ b/lib/Txt/Txt.cpp @@ -41,7 +41,7 @@ std::string Txt::getTitle() const { std::string filename = (lastSlash != std::string::npos) ? filepath.substr(lastSlash + 1) : filepath; // Remove .txt extension - if (filename.length() >= 4 && filename.substr(filename.length() - 4) == ".txt") { + if (FsHelpers::hasTxtExtension(filename)) { filename = filename.substr(0, filename.length() - 4); } @@ -112,14 +112,7 @@ bool Txt::generateCoverBmp() const { // Setup cache directory setupCacheDir(); - // Get file extension - const size_t len = coverImagePath.length(); - const bool isJpg = - (len >= 4 && (coverImagePath.substr(len - 4) == ".jpg" || coverImagePath.substr(len - 4) == ".JPG")) || - (len >= 5 && (coverImagePath.substr(len - 5) == ".jpeg" || coverImagePath.substr(len - 5) == ".JPEG")); - const bool isBmp = len >= 4 && (coverImagePath.substr(len - 4) == ".bmp" || coverImagePath.substr(len - 4) == ".BMP"); - - if (isBmp) { + if (FsHelpers::hasBmpExtension(coverImagePath)) { // Copy BMP file to cache LOG_DBG("TXT", "Copying BMP cover image to cache"); FsFile src, dst; @@ -139,9 +132,7 @@ bool Txt::generateCoverBmp() const { dst.close(); LOG_DBG("TXT", "Copied BMP cover to cache"); return true; - } - - if (isJpg) { + } else if (FsHelpers::hasJpgExtension(coverImagePath)) { // Convert JPG/JPEG to BMP (same approach as Epub) LOG_DBG("TXT", "Generating BMP from JPG cover image"); FsFile coverJpg, coverBmp; diff --git a/lib/Xtc/Xtc/XtcTypes.h b/lib/Xtc/Xtc/XtcTypes.h index 773c7ad53..5cee691da 100644 --- a/lib/Xtc/Xtc/XtcTypes.h +++ b/lib/Xtc/Xtc/XtcTypes.h @@ -144,14 +144,4 @@ inline const char* errorToString(XtcError err) { } } -/** - * Check if filename has XTC/XTCH extension - */ -inline bool isXtcExtension(const char* filename) { - if (!filename) return false; - const char* ext = strrchr(filename, '.'); - if (!ext) return false; - return (strcasecmp(ext, ".xtc") == 0 || strcasecmp(ext, ".xtch") == 0); -} - } // namespace xtc diff --git a/src/RecentBooksStore.cpp b/src/RecentBooksStore.cpp index e903aa8fd..f5a2c0483 100644 --- a/src/RecentBooksStore.cpp +++ b/src/RecentBooksStore.cpp @@ -1,6 +1,7 @@ #include "RecentBooksStore.h" #include +#include #include #include #include @@ -9,8 +10,6 @@ #include -#include "util/StringUtils.h" - namespace { constexpr uint8_t RECENT_BOOKS_FILE_VERSION = 3; constexpr char RECENT_BOOKS_FILE_BIN[] = "/.crosspoint/recent.bin"; @@ -71,19 +70,17 @@ RecentBook RecentBooksStore::getDataFromBook(std::string path) const { // If epub, try to load the metadata for title/author and cover. // Use buildIfMissing=false to avoid heavy epub loading on boot; getTitle()/getAuthor() may be // blank until the book is opened, and entries with missing title are omitted from recent list. - if (StringUtils::checkFileExtension(lastBookFileName, ".epub")) { + if (FsHelpers::hasEpubExtension(lastBookFileName)) { Epub epub(path, "/.crosspoint"); epub.load(false, true); return RecentBook{path, epub.getTitle(), epub.getAuthor(), epub.getThumbBmpPath()}; - } else if (StringUtils::checkFileExtension(lastBookFileName, ".xtch") || - StringUtils::checkFileExtension(lastBookFileName, ".xtc")) { + } else if (FsHelpers::hasXtcExtension(lastBookFileName)) { // Handle XTC file Xtc xtc(path, "/.crosspoint"); if (xtc.load()) { return RecentBook{path, xtc.getTitle(), xtc.getAuthor(), xtc.getThumbBmpPath()}; } - } else if (StringUtils::checkFileExtension(lastBookFileName, ".txt") || - StringUtils::checkFileExtension(lastBookFileName, ".md")) { + } else if (FsHelpers::hasTxtExtension(lastBookFileName) || FsHelpers::hasMarkdownExtension(lastBookFileName)) { return RecentBook{path, lastBookFileName, "", ""}; } return RecentBook{path, "", "", ""}; diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 35a0ee505..0b2c18259 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -1,6 +1,7 @@ #include "SleepActivity.h" #include +#include #include #include #include @@ -12,7 +13,6 @@ #include "components/UITheme.h" #include "fontIds.h" #include "images/Logo120.h" -#include "util/StringUtils.h" void SleepActivity::onEnter() { Activity::onEnter(); @@ -61,7 +61,7 @@ void SleepActivity::renderCustomSleepScreen() const { continue; } - if (filename.substr(filename.length() - 4) != ".bmp") { + if (!FsHelpers::hasBmpExtension(filename)) { LOG_DBG("SLP", "Skipping non-.bmp file name: %s", name); file.close(); continue; @@ -228,8 +228,7 @@ void SleepActivity::renderCoverSleepScreen() const { bool cropped = SETTINGS.sleepScreenCoverMode == CrossPointSettings::SLEEP_SCREEN_COVER_MODE::CROP; // Check if the current book is XTC, TXT, or EPUB - if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtc") || - StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtch")) { + if (FsHelpers::hasXtcExtension(APP_STATE.openEpubPath)) { // Handle XTC file Xtc lastXtc(APP_STATE.openEpubPath, "/.crosspoint"); if (!lastXtc.load()) { @@ -243,7 +242,7 @@ void SleepActivity::renderCoverSleepScreen() const { } coverBmpPath = lastXtc.getCoverBmpPath(); - } else if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".txt")) { + } else if (FsHelpers::hasTxtExtension(APP_STATE.openEpubPath)) { // Handle TXT file - looks for cover image in the same folder Txt lastTxt(APP_STATE.openEpubPath, "/.crosspoint"); if (!lastTxt.load()) { @@ -257,7 +256,7 @@ void SleepActivity::renderCoverSleepScreen() const { } coverBmpPath = lastTxt.getCoverBmpPath(); - } else if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".epub")) { + } else if (FsHelpers::hasEpubExtension(APP_STATE.openEpubPath)) { // Handle EPUB file Epub lastEpub(APP_STATE.openEpubPath, "/.crosspoint"); // Skip loading css since we only need metadata here diff --git a/src/activities/home/FileBrowserActivity.cpp b/src/activities/home/FileBrowserActivity.cpp index 1e394d147..b8b910ba4 100644 --- a/src/activities/home/FileBrowserActivity.cpp +++ b/src/activities/home/FileBrowserActivity.cpp @@ -1,6 +1,7 @@ #include "FileBrowserActivity.h" #include +#include #include #include #include @@ -11,7 +12,6 @@ #include "MappedInputManager.h" #include "components/UITheme.h" #include "fontIds.h" -#include "util/StringUtils.h" namespace { constexpr unsigned long GO_HOME_MS = 1000; @@ -91,10 +91,10 @@ void FileBrowserActivity::loadFiles() { if (file.isDirectory()) { files.emplace_back(std::string(name) + "/"); } else { - auto filename = std::string(name); - if (StringUtils::checkFileExtension(filename, ".epub") || StringUtils::checkFileExtension(filename, ".xtch") || - StringUtils::checkFileExtension(filename, ".xtc") || StringUtils::checkFileExtension(filename, ".txt") || - StringUtils::checkFileExtension(filename, ".md") || StringUtils::checkFileExtension(filename, ".bmp")) { + std::string_view filename{name}; + if (FsHelpers::hasEpubExtension(filename) || FsHelpers::hasXtcExtension(filename) || + FsHelpers::hasTxtExtension(filename) || FsHelpers::hasMarkdownExtension(filename) || + FsHelpers::hasBmpExtension(filename)) { files.emplace_back(filename); } } @@ -120,7 +120,7 @@ void FileBrowserActivity::onExit() { void FileBrowserActivity::clearFileMetadata(const std::string& fullPath) { // Only clear cache for .epub files - if (StringUtils::checkFileExtension(fullPath, ".epub")) { + if (FsHelpers::hasEpubExtension(fullPath)) { Epub(fullPath, "/.crosspoint").clearCache(); LOG_DBG("FileBrowser", "Cleared metadata cache for: %s", fullPath.c_str()); } diff --git a/src/activities/home/HomeActivity.cpp b/src/activities/home/HomeActivity.cpp index bfab4874a..810cb50bb 100644 --- a/src/activities/home/HomeActivity.cpp +++ b/src/activities/home/HomeActivity.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -17,7 +18,6 @@ #include "RecentBooksStore.h" #include "components/UITheme.h" #include "fontIds.h" -#include "util/StringUtils.h" int HomeActivity::getMenuItemCount() const { int count = 4; // File Browser, Recents, File transfer, Settings @@ -61,7 +61,7 @@ void HomeActivity::loadRecentCovers(int coverHeight) { std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight); if (!Storage.exists(coverPath.c_str())) { // If epub, try to load the metadata for title/author and cover - if (StringUtils::checkFileExtension(book.path, ".epub")) { + if (FsHelpers::hasEpubExtension(book.path)) { Epub epub(book.path, "/.crosspoint"); // Skip loading css since we only need metadata here epub.load(false, true); @@ -79,8 +79,7 @@ void HomeActivity::loadRecentCovers(int coverHeight) { } coverRendered = false; requestUpdate(); - } else if (StringUtils::checkFileExtension(book.path, ".xtch") || - StringUtils::checkFileExtension(book.path, ".xtc")) { + } else if (FsHelpers::hasXtcExtension(book.path)) { // Handle XTC file Xtc xtc(book.path, "/.crosspoint"); if (xtc.load()) { diff --git a/src/activities/home/RecentBooksActivity.cpp b/src/activities/home/RecentBooksActivity.cpp index e3e611fbe..6ba8f8cf1 100644 --- a/src/activities/home/RecentBooksActivity.cpp +++ b/src/activities/home/RecentBooksActivity.cpp @@ -10,7 +10,6 @@ #include "RecentBooksStore.h" #include "components/UITheme.h" #include "fontIds.h" -#include "util/StringUtils.h" namespace { constexpr unsigned long GO_HOME_MS = 1000; diff --git a/src/activities/reader/ReaderActivity.cpp b/src/activities/reader/ReaderActivity.cpp index a7842a9ed..2164a7f66 100644 --- a/src/activities/reader/ReaderActivity.cpp +++ b/src/activities/reader/ReaderActivity.cpp @@ -1,5 +1,6 @@ #include "ReaderActivity.h" +#include #include #include "CrossPointSettings.h" @@ -11,7 +12,6 @@ #include "XtcReaderActivity.h" #include "activities/util/BmpViewerActivity.h" #include "activities/util/FullScreenMessageActivity.h" -#include "util/StringUtils.h" std::string ReaderActivity::extractFolderPath(const std::string& filePath) { const auto lastSlash = filePath.find_last_of('/'); @@ -21,16 +21,14 @@ std::string ReaderActivity::extractFolderPath(const std::string& filePath) { return filePath.substr(0, lastSlash); } -bool ReaderActivity::isXtcFile(const std::string& path) { - return StringUtils::checkFileExtension(path, ".xtc") || StringUtils::checkFileExtension(path, ".xtch"); -} +bool ReaderActivity::isXtcFile(const std::string& path) { return FsHelpers::hasXtcExtension(path); } bool ReaderActivity::isTxtFile(const std::string& path) { - return StringUtils::checkFileExtension(path, ".txt") || - StringUtils::checkFileExtension(path, ".md"); // Treat .md as txt files (until we have a markdown reader) + return FsHelpers::hasTxtExtension(path) || + FsHelpers::hasMarkdownExtension(path); // Treat .md as txt files (until we have a markdown reader) } -bool ReaderActivity::isBmpFile(const std::string& path) { return StringUtils::checkFileExtension(path, ".bmp"); } +bool ReaderActivity::isBmpFile(const std::string& path) { return FsHelpers::hasBmpExtension(path); } std::unique_ptr ReaderActivity::loadEpub(const std::string& path) { if (!Storage.exists(path.c_str())) { diff --git a/src/components/UITheme.cpp b/src/components/UITheme.cpp index e29db8726..57e494840 100644 --- a/src/components/UITheme.cpp +++ b/src/components/UITheme.cpp @@ -1,5 +1,6 @@ #include "UITheme.h" +#include #include #include @@ -10,7 +11,6 @@ #include "components/themes/BaseTheme.h" #include "components/themes/lyra/Lyra3CoversTheme.h" #include "components/themes/lyra/LyraTheme.h" -#include "util/StringUtils.h" namespace { constexpr int SKIP_PAGE_MS = 700; @@ -74,18 +74,17 @@ std::string UITheme::getCoverThumbPath(std::string coverBmpPath, int coverHeight return coverBmpPath; } -UIIcon UITheme::getFileIcon(std::string filename) { +UIIcon UITheme::getFileIcon(const std::string& filename) { if (filename.back() == '/') { return Folder; } - if (StringUtils::checkFileExtension(filename, ".epub") || StringUtils::checkFileExtension(filename, ".xtch") || - StringUtils::checkFileExtension(filename, ".xtc")) { + if (FsHelpers::hasEpubExtension(filename) || FsHelpers::hasXtcExtension(filename)) { return Book; } - if (StringUtils::checkFileExtension(filename, ".txt") || StringUtils::checkFileExtension(filename, ".md")) { + if (FsHelpers::hasTxtExtension(filename) || FsHelpers::hasMarkdownExtension(filename)) { return Text; } - if (StringUtils::checkFileExtension(filename, ".bmp")) { + if (FsHelpers::hasBmpExtension(filename)) { return Image; } return File; diff --git a/src/components/UITheme.h b/src/components/UITheme.h index 5befe279f..daa1ec452 100644 --- a/src/components/UITheme.h +++ b/src/components/UITheme.h @@ -21,7 +21,7 @@ class UITheme { static int getNumberOfItemsPerPage(const GfxRenderer& renderer, bool hasHeader, bool hasTabBar, bool hasButtonHints, bool hasSubtitle); static std::string getCoverThumbPath(std::string coverBmpPath, int coverHeight); - static UIIcon getFileIcon(std::string filename); + static UIIcon getFileIcon(const std::string& filename); static int getStatusBarHeight(); static int getProgressBarHeight(); diff --git a/src/network/CrossPointWebServer.cpp b/src/network/CrossPointWebServer.cpp index 5578c59e1..ede4aa399 100644 --- a/src/network/CrossPointWebServer.cpp +++ b/src/network/CrossPointWebServer.cpp @@ -16,7 +16,6 @@ #include "html/FilesPageHtml.generated.h" #include "html/HomePageHtml.generated.h" #include "html/SettingsPageHtml.generated.h" -#include "util/StringUtils.h" namespace { // Folders/files to hide from the web interface file browser @@ -44,7 +43,7 @@ unsigned long wsLastCompleteAt = 0; // Helper function to clear epub cache after upload void clearEpubCacheIfNeeded(const String& filePath) { // Only clear cache for .epub files - if (StringUtils::checkFileExtension(filePath, ".epub")) { + if (FsHelpers::hasEpubExtension(filePath)) { Epub(filePath.c_str(), "/.crosspoint").clearCache(); LOG_DBG("WEB", "Cleared epub cache for: %s", filePath.c_str()); } @@ -391,11 +390,7 @@ void CrossPointWebServer::scanFiles(const char* path, const std::function #include -#include "util/StringUtils.h" - namespace { const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"}; constexpr size_t HIDDEN_ITEMS_COUNT = sizeof(HIDDEN_ITEMS) / sizeof(HIDDEN_ITEMS[0]); @@ -801,28 +799,26 @@ bool WebDAVHandler::getOverwrite(WebServer& s) const { } void WebDAVHandler::clearEpubCacheIfNeeded(const String& path) const { - if (StringUtils::checkFileExtension(path, ".epub")) { + if (FsHelpers::hasEpubExtension(path)) { Epub(path.c_str(), "/.crosspoint").clearCache(); LOG_DBG("DAV", "Cleared epub cache for: %s", path.c_str()); } } String WebDAVHandler::getMimeType(const String& path) const { - if (StringUtils::checkFileExtension(path, ".epub")) return "application/epub+zip"; - if (StringUtils::checkFileExtension(path, ".pdf")) return "application/pdf"; - if (StringUtils::checkFileExtension(path, ".txt")) return "text/plain"; - if (StringUtils::checkFileExtension(path, ".html") || StringUtils::checkFileExtension(path, ".htm")) - return "text/html"; - if (StringUtils::checkFileExtension(path, ".css")) return "text/css"; - if (StringUtils::checkFileExtension(path, ".js")) return "application/javascript"; - if (StringUtils::checkFileExtension(path, ".json")) return "application/json"; - if (StringUtils::checkFileExtension(path, ".xml")) return "application/xml"; - if (StringUtils::checkFileExtension(path, ".jpg") || StringUtils::checkFileExtension(path, ".jpeg")) - return "image/jpeg"; - if (StringUtils::checkFileExtension(path, ".png")) return "image/png"; - if (StringUtils::checkFileExtension(path, ".gif")) return "image/gif"; - if (StringUtils::checkFileExtension(path, ".svg")) return "image/svg+xml"; - if (StringUtils::checkFileExtension(path, ".zip")) return "application/zip"; - if (StringUtils::checkFileExtension(path, ".gz")) return "application/gzip"; + if (FsHelpers::hasEpubExtension(path)) return "application/epub+zip"; + if (FsHelpers::checkFileExtension(path, ".pdf")) return "application/pdf"; + if (FsHelpers::hasTxtExtension(path)) return "text/plain"; + if (FsHelpers::checkFileExtension(path, ".html") || FsHelpers::checkFileExtension(path, ".htm")) return "text/html"; + if (FsHelpers::checkFileExtension(path, ".css")) return "text/css"; + if (FsHelpers::checkFileExtension(path, ".js")) return "application/javascript"; + if (FsHelpers::checkFileExtension(path, ".json")) return "application/json"; + if (FsHelpers::checkFileExtension(path, ".xml")) return "application/xml"; + if (FsHelpers::hasJpgExtension(path)) return "image/jpeg"; + if (FsHelpers::hasPngExtension(path)) return "image/png"; + if (FsHelpers::hasGifExtension(path)) return "image/gif"; + if (FsHelpers::checkFileExtension(path, ".svg")) return "image/svg+xml"; + if (FsHelpers::checkFileExtension(path, ".zip")) return "application/zip"; + if (FsHelpers::checkFileExtension(path, ".gz")) return "application/gzip"; return "application/octet-stream"; } diff --git a/src/util/StringUtils.cpp b/src/util/StringUtils.cpp index ed989d556..81be07ee4 100644 --- a/src/util/StringUtils.cpp +++ b/src/util/StringUtils.cpp @@ -2,8 +2,6 @@ #include -#include - namespace StringUtils { std::string sanitizeFilename(const std::string& name, size_t maxBytes) { @@ -45,30 +43,4 @@ std::string sanitizeFilename(const std::string& name, size_t maxBytes) { return result.empty() ? "book" : result; } -bool checkFileExtension(const std::string& fileName, const char* extension) { - if (fileName.length() < strlen(extension)) { - return false; - } - - const std::string fileExt = fileName.substr(fileName.length() - strlen(extension)); - for (size_t i = 0; i < fileExt.length(); i++) { - if (tolower(fileExt[i]) != tolower(extension[i])) { - return false; - } - } - return true; -} - -bool checkFileExtension(const String& fileName, const char* extension) { - if (fileName.length() < strlen(extension)) { - return false; - } - - String localFile(fileName); - String localExtension(extension); - localFile.toLowerCase(); - localExtension.toLowerCase(); - return localFile.endsWith(localExtension); -} - } // namespace StringUtils diff --git a/src/util/StringUtils.h b/src/util/StringUtils.h index 7909fe444..1fa6cc01e 100644 --- a/src/util/StringUtils.h +++ b/src/util/StringUtils.h @@ -1,7 +1,5 @@ #pragma once -#include - #include namespace StringUtils { @@ -13,10 +11,4 @@ namespace StringUtils { */ std::string sanitizeFilename(const std::string& name, size_t maxBytes = 100); -/** - * Check if the given filename ends with the specified extension (case-insensitive). - */ -bool checkFileExtension(const std::string& fileName, const char* extension); -bool checkFileExtension(const String& fileName, const char* extension); - } // namespace StringUtils