diff --git a/lib/Epub/Epub.cpp b/lib/Epub/Epub.cpp index 1477d72..a3edac8 100644 --- a/lib/Epub/Epub.cpp +++ b/lib/Epub/Epub.cpp @@ -322,6 +322,11 @@ int Epub::getTocItemsCount() const { return toc.size(); } // work out the section index for a toc index int Epub::getSpineIndexForTocIndex(const int tocIndex) const { + if (tocIndex < 0 || tocIndex >= toc.size()) { + Serial.printf("[%lu] [EBP] getSpineIndexForTocIndex: tocIndex %d out of range\n", millis(), tocIndex); + return 0; + } + // the toc entry should have an href that matches the spine item // so we can find the spine index by looking for the href for (int i = 0; i < spine.size(); i++) { @@ -336,6 +341,11 @@ int Epub::getSpineIndexForTocIndex(const int tocIndex) const { } int Epub::getTocIndexForSpineIndex(const int spineIndex) const { + if (spineIndex < 0 || spineIndex >= spine.size()) { + Serial.printf("[%lu] [EBP] getTocIndexForSpineIndex: spineIndex %d out of range\n", millis(), spineIndex); + return -1; + } + // the toc entry should have an href that matches the spine item // so we can find the toc index by looking for the href for (int i = 0; i < toc.size(); i++) { @@ -348,13 +358,21 @@ int Epub::getTocIndexForSpineIndex(const int spineIndex) const { return -1; } -size_t Epub::getBookSize() const { return getCumulativeSpineItemSize(getSpineItemsCount() - 1); } +size_t Epub::getBookSize() const { + if (spine.empty()) { + return 0; + } + return getCumulativeSpineItemSize(getSpineItemsCount() - 1); +} // Calculate progress in book uint8_t Epub::calculateProgress(const int currentSpineIndex, const float currentSpineRead) { + size_t bookSize = getBookSize(); + if (bookSize == 0) { + return 0; + } size_t prevChapterSize = (currentSpineIndex >= 1) ? getCumulativeSpineItemSize(currentSpineIndex - 1) : 0; size_t curChapterSize = getCumulativeSpineItemSize(currentSpineIndex) - prevChapterSize; - size_t bookSize = getBookSize(); size_t sectionProgSize = currentSpineRead * curChapterSize; return round(static_cast(prevChapterSize + sectionProgSize) / bookSize * 100.0); } diff --git a/lib/ZipFile/ZipFile.cpp b/lib/ZipFile/ZipFile.cpp index 30b44f8..f55bb85 100644 --- a/lib/ZipFile/ZipFile.cpp +++ b/lib/ZipFile/ZipFile.cpp @@ -62,6 +62,10 @@ long ZipFile::getDataOffset(const mz_zip_archive_file_stat& fileStat) const { const uint64_t fileOffset = fileStat.m_local_header_ofs; FILE* file = fopen(filePath.c_str(), "r"); + if (!file) { + Serial.printf("[%lu] [ZIP] Failed to open file for reading local header\n", millis()); + return -1; + } fseek(file, fileOffset, SEEK_SET); const size_t read = fread(pLocalHeader, 1, localHeaderSize, file); fclose(file); @@ -104,6 +108,10 @@ uint8_t* ZipFile::readFileToMemory(const char* filename, size_t* size, const boo } FILE* file = fopen(filePath.c_str(), "rb"); + if (!file) { + Serial.printf("[%lu] [ZIP] Failed to open file for reading\n", millis()); + return nullptr; + } fseek(file, fileOffset, SEEK_SET); const auto deflatedDataSize = static_cast(fileStat.m_comp_size); @@ -175,6 +183,10 @@ bool ZipFile::readFileToStream(const char* filename, Print& out, const size_t ch } FILE* file = fopen(filePath.c_str(), "rb"); + if (!file) { + Serial.printf("[%lu] [ZIP] Failed to open file for streaming\n", millis()); + return false; + } fseek(file, fileOffset, SEEK_SET); const auto deflatedDataSize = static_cast(fileStat.m_comp_size); diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index f4e4536..dd6dd04 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -33,13 +33,14 @@ void EpubReaderActivity::onEnter() { epub->setupCacheDir(); - if (SD.exists((epub->getCachePath() + "/progress.bin").c_str())) { - File f = SD.open((epub->getCachePath() + "/progress.bin").c_str()); + File f = SD.open((epub->getCachePath() + "/progress.bin").c_str()); + if (f) { uint8_t data[4]; - f.read(data, 4); - currentSpineIndex = data[0] + (data[1] << 8); - nextPageNumber = data[2] + (data[3] << 8); - Serial.printf("[%lu] [ERS] Loaded cache: %d, %d\n", millis(), currentSpineIndex, nextPageNumber); + if (f.read(data, 4) == 4) { + currentSpineIndex = data[0] + (data[1] << 8); + nextPageNumber = data[2] + (data[3] << 8); + Serial.printf("[%lu] [ERS] Loaded cache: %d, %d\n", millis(), currentSpineIndex, nextPageNumber); + } f.close(); } @@ -382,7 +383,7 @@ void EpubReaderActivity::renderStatusBar() const { const auto tocItem = epub->getTocItem(tocIndex); title = tocItem.title; titleWidth = renderer.getTextWidth(SMALL_FONT_ID, title.c_str()); - while (titleWidth > availableTextWidth) { + while (titleWidth > availableTextWidth && title.length() > 11) { title = title.substr(0, title.length() - 8) + "..."; titleWidth = renderer.getTextWidth(SMALL_FONT_ID, title.c_str()); } diff --git a/src/main.cpp b/src/main.cpp index 9f25569..a518201 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -159,7 +159,12 @@ void setup() { SPI.begin(EPD_SCLK, SD_SPI_MISO, EPD_MOSI, EPD_CS); // SD Card Initialization - SD.begin(SD_SPI_CS, SPI, SPI_FQ); + if (!SD.begin(SD_SPI_CS, SPI, SPI_FQ)) { + Serial.printf("[%lu] [ ] SD card initialization failed\n", millis()); + exitActivity(); + enterNewActivity(new FullScreenMessageActivity(renderer, inputManager, "SD card error", BOLD)); + return; + } SETTINGS.loadFromFile();