Minor adjustment for BOM strings

This commit is contained in:
jpirnay
2026-04-13 11:48:02 +02:00
parent 398a25c417
commit b907aa8ff7
+26 -26
View File
@@ -42,6 +42,21 @@ void beginRequest(const char* operation) {
KOReaderSyncClient::lastContigHeapAtFailure = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT); KOReaderSyncClient::lastContigHeapAtFailure = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT);
} }
// Skip a leading UTF-8 BOM (EF BB BF) and ASCII whitespace, returning a pointer
// to the first content character. Used by response-body checks that verify the
// payload starts with '{' (JSON) rather than '<' (HTML captive-portal page).
const char* skipBomAndWhitespace(const char* p) {
// UTF-8 BOM
if (static_cast<unsigned char>(p[0]) == 0xEF && static_cast<unsigned char>(p[1]) == 0xBB &&
static_cast<unsigned char>(p[2]) == 0xBF) {
p += 3;
}
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
p++;
}
return p;
}
// Device identifier for CrossPoint reader // Device identifier for CrossPoint reader
constexpr char DEVICE_NAME[] = "CrossPoint"; constexpr char DEVICE_NAME[] = "CrossPoint";
constexpr char DEVICE_ID[] = "crosspoint-reader"; constexpr char DEVICE_ID[] = "crosspoint-reader";
@@ -377,19 +392,8 @@ KOReaderSyncClient::Error KOReaderSyncClient::authenticate() {
if (err != ESP_OK) return NETWORK_ERROR; if (err != ESP_OK) return NETWORK_ERROR;
if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR; if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR;
if (httpCode == 200) { if (httpCode == 200) {
// The kosync auth response is always a JSON object. Guard against a reverse // Guard against a reverse proxy or captive portal returning HTTP 200 + HTML.
// proxy returning HTTP 200 + HTML (e.g. a login wall that followed all if (!activeBuf->data || *skipBomAndWhitespace(activeBuf->data) != '{') {
// redirects and landed on an auth page instead of the API endpoint).
// Skip leading whitespace before checking for '{' so servers that emit
// a BOM or indent their JSON don't get incorrectly rejected.
if (!activeBuf->data) {
return INVALID_RESPONSE;
}
const char* p = activeBuf->data;
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
p++;
}
if (*p != '{') {
return INVALID_RESPONSE; return INVALID_RESPONSE;
} }
return OK; return OK;
@@ -577,14 +581,10 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr
if (err != ESP_OK) return NETWORK_ERROR; if (err != ESP_OK) return NETWORK_ERROR;
if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR; if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR;
if (httpCode == 200 || httpCode == 202) { if (httpCode == 200 || httpCode == 202) {
// Guard against a reverse proxy or captive portal returning HTTP 200 + HTML // Guard against a reverse proxy or captive portal returning HTTP 200 + HTML.
// instead of the real API response, consistent with authenticate()'s check.
if (activeBuf->data) { if (activeBuf->data) {
const char* p = activeBuf->data; const char c = *skipBomAndWhitespace(activeBuf->data);
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { if (c != '\0' && c != '{') {
p++;
}
if (*p != '\0' && *p != '{') {
return INVALID_RESPONSE; return INVALID_RESPONSE;
} }
} }
@@ -609,13 +609,13 @@ const char* KOReaderSyncClient::lastFailureDetail() {
} }
// Network/TLS case: esp_http_client_perform() failed before getting a status code. // Network/TLS case: esp_http_client_perform() failed before getting a status code.
if (lastHttpCode == 0 && lastEspError != 0) { if (lastHttpCode == 0 && lastEspError != 0) {
// Detect TLS handshake failures on HTTPS URLs — likely caused by the server // HTTPS connect failures can be TLS version issues (ESP32 only supports up
// requiring TLS 1.3 which the ESP32 mbedTLS library does not support. // to TLS 1.2), but also DNS, cert, or plain network problems. Include the
// error name and heap stats so the user/bug-report has enough to triage.
if (lastEspError == ESP_ERR_HTTP_CONNECT && KOREADER_STORE.getBaseUrl().rfind("https", 0) == 0) { if (lastEspError == ESP_ERR_HTTP_CONNECT && KOREADER_STORE.getBaseUrl().rfind("https", 0) == 0) {
snprintf( snprintf(g_failureDetailBuf, sizeof(g_failureDetailBuf),
g_failureDetailBuf, sizeof(g_failureDetailBuf), "%s: connect failed — check network, DNS, certs, or TLS 1.2 compat (heap %u/%u contig)", lastOperation,
"%s: TLS handshake failed. Server may require TLS 1.3 (unsupported). Try a different server or use HTTP.", lastHeapAtFailure, lastContigHeapAtFailure);
lastOperation);
} else { } else {
snprintf(g_failureDetailBuf, sizeof(g_failureDetailBuf), "%s: %s (heap %u/%u contig)", lastOperation, snprintf(g_failureDetailBuf, sizeof(g_failureDetailBuf), "%s: %s (heap %u/%u contig)", lastOperation,
esp_err_to_name(lastEspError), lastHeapAtFailure, lastContigHeapAtFailure); esp_err_to_name(lastEspError), lastHeapAtFailure, lastContigHeapAtFailure);