## Problem
Three `fopen()` calls in ZipFile.cpp did not check for NULL before using
the file handle. If files cannot be opened, `fseek`/`fread`/`fclose`
receive NULL and crash.
## Fix
Added NULL checks with appropriate error logging and early returns for
all three locations:
- `getDataOffset()`
- `readFileToMemory()`
- `readFileToStream()`
## Testing
- Builds successfully with `pio run`
- Affects: `lib/ZipFile/ZipFile.cpp`
## Problem
- `getBookSize()` calls `getCumulativeSpineItemSize(getSpineItemsCount()
- 1)` which passes -1 when spine is empty
- `calculateProgress()` then divides by zero when book size is 0
## Fix
- Return 0 from `getBookSize()` if spine is empty
- Return 0 from `calculateProgress()` if book size is 0
## Testing
- Builds successfully with `pio run`
- Affects: `lib/Epub/Epub.cpp`
## Problem
Reading progress.bin used `SD.exists()` then `SD.open()` without
checking if open succeeded. Race conditions or SD errors could cause
file handle to be invalid.
## Fix
- Removed redundant `SD.exists()` check
- Check if file opened successfully before reading
- Verify correct number of bytes were read
## Testing
- Builds successfully with `pio run`
- Affects: `src/activities/reader/EpubReaderActivity.cpp`
## Problem
`SD.begin()` return value was ignored. If the SD card fails to
initialize, the device continues and crashes when trying to load
settings/state.
## Fix
Check return value and display "SD card error" message instead of
proceeding with undefined state.
## Testing
- Builds successfully with `pio run`
- Affects: `src/main.cpp`
## Problem
The status bar title truncation loop crashes when the chapter title is
shorter than 8 characters.
```cpp
// title.length() - 8 underflows when length < 8 (size_t is unsigned)
title = title.substr(0, title.length() - 8) + "...";
```
## Fix
Added a length guard to skip truncation for titles that are too short to
truncate safely.
## Testing
- Builds successfully with `pio run`
- Affects: `src/activities/reader/EpubReaderActivity.cpp`
## Problem
`getSpineIndexForTocIndex()` and `getTocIndexForSpineIndex()` access
`toc[tocIndex]` and `spine[spineIndex]` without validating indices are
within bounds. Malformed EPUBs or edge cases could trigger out-of-bounds
access.
## Fix
Added bounds validation at the start of both functions before accessing
the arrays.
## Testing
- Builds successfully with `pio run`
- Affects: `lib/Epub/Epub.cpp`