readr

Minimal Terminal RSS Reader
Log | Files | Refs | README | LICENSE

commit 2fc6e232da14d8a8d4d3b910d6a5613ab6d0608a
parent 18d6254c3ab9a711c55d91cd68ab3e800626d6dd
Author: citbl <citbl@citbl.org>
Date:   Thu, 16 Jul 2026 23:34:32 +1000

1.12 bug fixes and somewhat better support for reddit with netnewswire user-agent

Diffstat:
Msrc/config.h | 8+++-----
Msrc/feeds.c | 2++
Msrc/http.c | 17+++++++++++++++--
3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/config.h b/src/config.h @@ -1,11 +1,9 @@ #pragma once -#define VERSION "v1.11" +#define VERSION "v1.12" -// recommended, pass as chrome for reddit feeds -#define USER_AGENT \ - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 " \ - "Safari/537.36" +// Some feed servers reject fake browser UAs; identify as a feed reader instead. +#define USER_AGENT "NetNewsWire (RSS Reader; https://netnewswire.com/)" // seconds timeout for feed HTTP fetch #define TIMEOUT 15 diff --git a/src/feeds.c b/src/feeds.c @@ -81,6 +81,8 @@ parse_feed(feed_t* feed, char* url, char* http_body) *feed = (feed_t) { .url = url }; feed->title = (char*)ecalloc(FEED_CAP, sizeof(char)); + if (!http_body) return; + /* process feed from given buffer */ mrss_error_t rc = mrss_parse_buffer(http_body, strlen(http_body), &rss); diff --git a/src/http.c b/src/http.c @@ -1,4 +1,4 @@ -#include <string.h> +#include <curl/curl.h> #include <mrss.h> #include <string.h> #include <pthread.h> @@ -7,6 +7,8 @@ #include "utils.h" #include "config.h" +#define ACCEPT_FEED_TYPES "Accept: application/rss+xml, application/atom+xml, application/xml;q=0.9, text/xml;q=0.8, */*;q=0.1" + size_t http_write(char* ptr, size_t size, size_t nmemb, void* userdata) { @@ -24,7 +26,7 @@ http_write(char* ptr, size_t size, size_t nmemb, void* userdata) void* /* http contents */ threaded_fetch(void* url) { - char curl_errbuf[CURL_ERROR_SIZE]; + char curl_errbuf[CURL_ERROR_SIZE] = { 0 }; CURL* curl = curl_easy_init(); if (!curl) { return NULL; } @@ -34,11 +36,20 @@ threaded_fetch(void* url) return NULL; } + struct curl_slist* headers = curl_slist_append(NULL, ACCEPT_FEED_TYPES); + if (!headers) { + free(blob); + curl_easy_cleanup(curl); + return NULL; + } + curl_easy_setopt(curl, CURLOPT_URL, (char*)url); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, VERIFY_SSL_PEER ? 1L : 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, VERIFY_SSL_HOST ? 1L : 0L); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_write); curl_easy_setopt(curl, CURLOPT_WRITEDATA, blob); @@ -53,6 +64,7 @@ threaded_fetch(void* url) curl_errbuf[0] ? curl_errbuf : curl_easy_strerror(res)); free(blob->data); free(blob); + curl_slist_free_all(headers); curl_easy_cleanup(curl); return NULL; } @@ -63,6 +75,7 @@ threaded_fetch(void* url) blob->ctype = strdup(ct); } + curl_slist_free_all(headers); curl_easy_cleanup(curl); return blob; }