From b32bf51f0ac5d062f157ce8e6de9a7f497f77beb Mon Sep 17 00:00:00 2001 From: Justin Mitchell Date: Wed, 14 Jan 2026 11:57:07 -0500 Subject: [PATCH] Allows koreader sync to run over http --- lib/KOReaderSync/KOReaderCredentialStore.cpp | 4 +- lib/KOReaderSync/KOReaderCredentialStore.h | 2 +- lib/KOReaderSync/KOReaderSyncClient.cpp | 61 +++++++++++++------ .../settings/KOReaderSettingsActivity.cpp | 10 ++- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/lib/KOReaderSync/KOReaderCredentialStore.cpp b/lib/KOReaderSync/KOReaderCredentialStore.cpp index f73cc325..c5737809 100644 --- a/lib/KOReaderSync/KOReaderCredentialStore.cpp +++ b/lib/KOReaderSync/KOReaderCredentialStore.cpp @@ -153,9 +153,9 @@ std::string KOReaderCredentialStore::getBaseUrl() const { return DEFAULT_SERVER_URL; } - // Normalize URL: add https:// if no protocol specified + // Normalize URL: add http:// if no protocol specified (local servers typically don't have SSL) if (serverUrl.find("://") == std::string::npos) { - return "https://" + serverUrl; + return "http://" + serverUrl; } return serverUrl; diff --git a/lib/KOReaderSync/KOReaderCredentialStore.h b/lib/KOReaderSync/KOReaderCredentialStore.h index d1709660..998101a2 100644 --- a/lib/KOReaderSync/KOReaderCredentialStore.h +++ b/lib/KOReaderSync/KOReaderCredentialStore.h @@ -57,7 +57,7 @@ class KOReaderCredentialStore { void setServerUrl(const std::string& url); const std::string& getServerUrl() const { return serverUrl; } - // Get base URL for API calls (with https:// normalization, falls back to default) + // Get base URL for API calls (with http:// normalization if no protocol, falls back to default) std::string getBaseUrl() const; // Document matching method diff --git a/lib/KOReaderSync/KOReaderSyncClient.cpp b/lib/KOReaderSync/KOReaderSyncClient.cpp index 91515cd9..32379f28 100644 --- a/lib/KOReaderSync/KOReaderSyncClient.cpp +++ b/lib/KOReaderSync/KOReaderSyncClient.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -19,6 +20,10 @@ void addAuthHeaders(HTTPClient& http) { http.addHeader("x-auth-user", KOREADER_STORE.getUsername().c_str()); http.addHeader("x-auth-key", KOREADER_STORE.getMd5Password().c_str()); } + +bool isHttpsUrl(const std::string& url) { + return url.rfind("https://", 0) == 0; +} } // namespace KOReaderSyncClient::Error KOReaderSyncClient::authenticate() { @@ -27,14 +32,20 @@ KOReaderSyncClient::Error KOReaderSyncClient::authenticate() { return NO_CREDENTIALS; } - const std::unique_ptr client(new WiFiClientSecure); - client->setInsecure(); - HTTPClient http; - std::string url = KOREADER_STORE.getBaseUrl() + "/users/auth"; Serial.printf("[%lu] [KOSync] Authenticating: %s\n", millis(), url.c_str()); - http.begin(*client, url.c_str()); + HTTPClient http; + std::unique_ptr secureClient; + WiFiClient plainClient; + + if (isHttpsUrl(url)) { + secureClient.reset(new WiFiClientSecure); + secureClient->setInsecure(); + http.begin(*secureClient, url.c_str()); + } else { + http.begin(plainClient, url.c_str()); + } addAuthHeaders(http); const int httpCode = http.GET(); @@ -59,24 +70,32 @@ KOReaderSyncClient::Error KOReaderSyncClient::getProgress(const std::string& doc return NO_CREDENTIALS; } - const std::unique_ptr client(new WiFiClientSecure); - client->setInsecure(); - HTTPClient http; - std::string url = KOREADER_STORE.getBaseUrl() + "/syncs/progress/" + documentHash; Serial.printf("[%lu] [KOSync] Getting progress: %s\n", millis(), url.c_str()); - http.begin(*client, url.c_str()); + HTTPClient http; + std::unique_ptr secureClient; + WiFiClient plainClient; + + if (isHttpsUrl(url)) { + secureClient.reset(new WiFiClientSecure); + secureClient->setInsecure(); + http.begin(*secureClient, url.c_str()); + } else { + http.begin(plainClient, url.c_str()); + } addAuthHeaders(http); const int httpCode = http.GET(); if (httpCode == 200) { - // Parse JSON response - JsonDocument doc; - const DeserializationError error = deserializeJson(doc, *client); + // Parse JSON response from response string + String responseBody = http.getString(); http.end(); + JsonDocument doc; + const DeserializationError error = deserializeJson(doc, responseBody); + if (error) { Serial.printf("[%lu] [KOSync] JSON parse failed: %s\n", millis(), error.c_str()); return JSON_ERROR; @@ -114,14 +133,20 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr return NO_CREDENTIALS; } - const std::unique_ptr client(new WiFiClientSecure); - client->setInsecure(); - HTTPClient http; - std::string url = KOREADER_STORE.getBaseUrl() + "/syncs/progress"; Serial.printf("[%lu] [KOSync] Updating progress: %s\n", millis(), url.c_str()); - http.begin(*client, url.c_str()); + HTTPClient http; + std::unique_ptr secureClient; + WiFiClient plainClient; + + if (isHttpsUrl(url)) { + secureClient.reset(new WiFiClientSecure); + secureClient->setInsecure(); + http.begin(*secureClient, url.c_str()); + } else { + http.begin(plainClient, url.c_str()); + } addAuthHeaders(http); http.addHeader("Content-Type", "application/json"); diff --git a/src/activities/settings/KOReaderSettingsActivity.cpp b/src/activities/settings/KOReaderSettingsActivity.cpp index 1ede2cda..6eb22c8e 100644 --- a/src/activities/settings/KOReaderSettingsActivity.cpp +++ b/src/activities/settings/KOReaderSettingsActivity.cpp @@ -112,14 +112,18 @@ void KOReaderSettingsActivity::handleSelection() { updateRequired = true; })); } else if (selectedIndex == 2) { - // Sync Server URL + // Sync Server URL - prefill with https:// if empty to save typing + const std::string currentUrl = KOREADER_STORE.getServerUrl(); + const std::string prefillUrl = currentUrl.empty() ? "https://" : currentUrl; exitActivity(); enterNewActivity(new KeyboardEntryActivity( - renderer, mappedInput, "Sync Server URL", KOREADER_STORE.getServerUrl(), 10, + renderer, mappedInput, "Sync Server URL", prefillUrl, 10, 128, // maxLength - URLs can be long false, // not password [this](const std::string& url) { - KOREADER_STORE.setServerUrl(url); + // Clear if user just left the prefilled https:// + const std::string urlToSave = (url == "https://" || url == "http://") ? "" : url; + KOREADER_STORE.setServerUrl(urlToSave); KOREADER_STORE.saveToFile(); exitActivity(); updateRequired = true;