Sanitize config values and surface the URL on connection errors

curl error 1 (unsupported protocol) was caused by invisible junk in
the config: leading whitespace, tabs or a UTF-8 BOM around the server
URL. Trim all of it, default to http:// when no scheme is given,
validate the scheme with the parsed value shown on screen, and include
the attempted URL in the first-connection error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Sads
2026-06-11 23:44:20 +02:00
co-authored by Claude Fable 5
parent b7ac3768a8
commit 65d772aae5
+31 -10
View File
@@ -142,11 +142,19 @@ static void fatal_error(const char *detail, const char *fmt, ...)
/* config */ /* config */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static void strip_eol(char *s) /* trim whitespace on both ends and a UTF-8 BOM; editors sneak these in,
* and any of them makes curl fail with "unsupported protocol" */
static char *clean_line(char *s)
{ {
if (!strncmp(s, "\xEF\xBB\xBF", 3))
s += 3;
while (*s == ' ' || *s == '\t')
s++;
size_t n = strlen(s); size_t n = strlen(s);
while (n > 0 && (s[n - 1] == '\n' || s[n - 1] == '\r' || s[n - 1] == ' ')) while (n > 0 && (s[n - 1] == '\n' || s[n - 1] == '\r' ||
s[n - 1] == ' ' || s[n - 1] == '\t'))
s[--n] = '\0'; s[--n] = '\0';
return s;
} }
static int load_config(void) static int load_config(void)
@@ -165,11 +173,11 @@ static int load_config(void)
char line[512]; char line[512];
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
strip_eol(line); char *s = clean_line(line);
if (!strncmp(line, "server=", 7)) if (!strncmp(s, "server=", 7))
snprintf(g_server, sizeof(g_server), "%s", line + 7); snprintf(g_server, sizeof(g_server), "%s", clean_line(s + 7));
else if (!strncmp(line, "apikey=", 7)) else if (!strncmp(s, "apikey=", 7))
snprintf(g_apikey, sizeof(g_apikey), "%s", line + 7); snprintf(g_apikey, sizeof(g_apikey), "%s", clean_line(s + 7));
} }
fclose(f); fclose(f);
@@ -180,6 +188,16 @@ static int load_config(void)
if (!g_server[0] || !g_apikey[0] || strstr(g_apikey, "PASTE_YOUR")) if (!g_server[0] || !g_apikey[0] || strstr(g_apikey, "PASTE_YOUR"))
return -1; return -1;
/* default to http:// when no scheme is given */
if (!strstr(g_server, "://")) {
char tmp[512];
snprintf(tmp, sizeof(tmp), "http://%s", g_server);
snprintf(g_server, sizeof(g_server), "%s", tmp);
}
if (strncasecmp(g_server, "http://", 7) && strncasecmp(g_server, "https://", 8))
fatal_error(g_server,
"Bad server URL in config (must start with http:// or https://):");
return 0; return 0;
} }
@@ -548,9 +566,12 @@ static int fetch_page(int is_first)
long code; long code;
CURLcode res = http_request(url, body, &buf, &code, NULL, 0); CURLcode res = http_request(url, body, &buf, &code, NULL, 0);
if (res != CURLE_OK) { if (res != CURLE_OK) {
if (is_first) if (is_first) {
fatal_error(curl_easy_strerror(res), char det[700];
"Connection failed (curl error %d)", res); snprintf(det, sizeof(det), "%s -- URL: %s",
curl_easy_strerror(res), url);
fatal_error(det, "Connection failed (curl error %d)", res);
}
log_line("page %d: curl error %d", g_next_page, res); log_line("page %d: curl error %d", g_next_page, res);
g_next_page = 0; g_next_page = 0;
free(buf.data); free(buf.data);