Make extension checks case-insensitive (#273)

## Summary

* Implement new `StringUtils::checkFileExtension` which does case
insensitive checking
* Move all checks over to this
This commit is contained in:
Dave Allie 2026-01-07 20:07:23 +10:00 committed by GitHub
parent 0cc2c64df2
commit 46fa186b82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 38 additions and 34 deletions

View File

@ -9,20 +9,7 @@
#include "CrossPointState.h"
#include "fontIds.h"
#include "images/CrossLarge.h"
namespace {
// Check if path has XTC extension (.xtc or .xtch)
bool isXtcFile(const std::string& path) {
if (path.length() < 4) return false;
std::string ext4 = path.substr(path.length() - 4);
if (ext4 == ".xtc") return true;
if (path.length() >= 5) {
std::string ext5 = path.substr(path.length() - 5);
if (ext5 == ".xtch") return true;
}
return false;
}
} // namespace
#include "util/StringUtils.h"
void SleepActivity::onEnter() {
Activity::onEnter();
@ -213,8 +200,8 @@ void SleepActivity::renderCoverSleepScreen() const {
std::string coverBmpPath;
// Check if the current book is XTC or EPUB
if (isXtcFile(APP_STATE.openEpubPath)) {
if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtc") ||
StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".xtch")) {
// Handle XTC file
Xtc lastXtc(APP_STATE.openEpubPath, "/.crosspoint");
if (!lastXtc.load()) {
@ -228,7 +215,7 @@ void SleepActivity::renderCoverSleepScreen() const {
}
coverBmpPath = lastXtc.getCoverBmpPath();
} else {
} else if (StringUtils::checkFileExtension(APP_STATE.openEpubPath, ".epub")) {
// Handle EPUB file
Epub lastEpub(APP_STATE.openEpubPath, "/.crosspoint");
if (!lastEpub.load()) {
@ -242,6 +229,8 @@ void SleepActivity::renderCoverSleepScreen() const {
}
coverBmpPath = lastEpub.getCoverBmpPath();
} else {
return renderDefaultSleepScreen();
}
FsFile file;

View File

@ -12,6 +12,7 @@
#include "MappedInputManager.h"
#include "ScreenComponents.h"
#include "fontIds.h"
#include "util/StringUtils.h"
void HomeActivity::taskTrampoline(void* param) {
auto* self = static_cast<HomeActivity*>(param);
@ -44,10 +45,8 @@ void HomeActivity::onEnter() {
lastBookTitle = lastBookTitle.substr(lastSlash + 1);
}
const std::string ext4 = lastBookTitle.length() >= 4 ? lastBookTitle.substr(lastBookTitle.length() - 4) : "";
const std::string ext5 = lastBookTitle.length() >= 5 ? lastBookTitle.substr(lastBookTitle.length() - 5) : "";
// If epub, try to load the metadata for title/author
if (ext5 == ".epub") {
if (StringUtils::checkFileExtension(lastBookTitle, ".epub")) {
Epub epub(APP_STATE.openEpubPath, "/.crosspoint");
epub.load(false);
if (!epub.getTitle().empty()) {
@ -56,9 +55,9 @@ void HomeActivity::onEnter() {
if (!epub.getAuthor().empty()) {
lastBookAuthor = std::string(epub.getAuthor());
}
} else if (ext5 == ".xtch") {
} else if (StringUtils::checkFileExtension(lastBookTitle, ".xtch")) {
lastBookTitle.resize(lastBookTitle.length() - 5);
} else if (ext4 == ".xtc") {
} else if (StringUtils::checkFileExtension(lastBookTitle, ".xtc")) {
lastBookTitle.resize(lastBookTitle.length() - 4);
}
}

View File

@ -582,7 +582,7 @@ void CalibreWirelessActivity::handleSendBook(const std::string& data) {
// Sanitize and create full path
currentFilename = "/" + StringUtils::sanitizeFilename(filename);
if (currentFilename.find(".epub") == std::string::npos) {
if (!StringUtils::checkFileExtension(currentFilename, ".epub")) {
currentFilename += ".epub";
}
currentFileSize = length;

View File

@ -5,6 +5,7 @@
#include "MappedInputManager.h"
#include "fontIds.h"
#include "util/StringUtils.h"
namespace {
constexpr int PAGE_ITEMS = 23;
@ -50,9 +51,8 @@ void FileSelectionActivity::loadFiles() {
files.emplace_back(std::string(name) + "/");
} else {
auto filename = std::string(name);
std::string ext4 = filename.length() >= 4 ? filename.substr(filename.length() - 4) : "";
std::string ext5 = filename.length() >= 5 ? filename.substr(filename.length() - 5) : "";
if (ext5 == ".epub" || ext5 == ".xtch" || ext4 == ".xtc") {
if (StringUtils::checkFileExtension(filename, ".epub") || StringUtils::checkFileExtension(filename, ".xtch") ||
StringUtils::checkFileExtension(filename, ".xtc")) {
files.emplace_back(filename);
}
}

View File

@ -6,6 +6,7 @@
#include "Xtc.h"
#include "XtcReaderActivity.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('/');
@ -16,14 +17,7 @@ std::string ReaderActivity::extractFolderPath(const std::string& filePath) {
}
bool ReaderActivity::isXtcFile(const std::string& path) {
if (path.length() < 4) return false;
std::string ext4 = path.substr(path.length() - 4);
if (ext4 == ".xtc") return true;
if (path.length() >= 5) {
std::string ext5 = path.substr(path.length() - 5);
if (ext5 == ".xtch") return true;
}
return false;
return StringUtils::checkFileExtension(path, ".xtc") || StringUtils::checkFileExtension(path, ".xtch");
}
std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {

View File

@ -1,5 +1,7 @@
#include "StringUtils.h"
#include <cstring>
namespace StringUtils {
std::string sanitizeFilename(const std::string& name, size_t maxLength) {
@ -33,4 +35,18 @@ std::string sanitizeFilename(const std::string& name, size_t maxLength) {
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;
}
} // namespace StringUtils

View File

@ -1,4 +1,5 @@
#pragma once
#include <string>
namespace StringUtils {
@ -10,4 +11,9 @@ namespace StringUtils {
*/
std::string sanitizeFilename(const std::string& name, size_t maxLength = 100);
/**
* Check if the given filename ends with the specified extension (case-insensitive).
*/
bool checkFileExtension(const std::string& fileName, const char* extension);
} // namespace StringUtils