cgmnlm

colorful gemini line mode browser
git clone https://git.clttr.info/cgmnlm.git
Log (Feed) | Files | Refs (Tags) | README | LICENSE

commit d145754cf4cd3feea8e58a602b36323bbc8db0bb
parent c9cabb467f939bdc0482ba50e1bef970de1bfce6
Author: Ondřej Fiala <temp.xanomes@volny.cz>
Date:   Sat,  2 Jul 2022 06:59:16 +0200

gmnlm: prompt for redirects, make max redirects configurable

Redirects are currently the most reliable way of tracking users in
geminispace. To mitigate this, similar approach as used with server
certificates is adopted -- users are prompted by default, but this
can be easily overriden with a command line flag if convenience is
preferred to tracking-resistance.

Diffstat:
Mdoc/cgmnlm.scd | 3+++
Msrc/gmnlm.c | 50+++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/doc/cgmnlm.scd b/doc/cgmnlm.scd @@ -22,6 +22,9 @@ cgmnlm - colored Gemini line-mode browser *-P* Disable pagination. +*-R* _redirs_ + Sets the maximum number of redirects, negative argument disables limit. + *-U* Disable conservative use of Unicode symbols to render Gemini layout features. diff --git a/src/gmnlm.c b/src/gmnlm.c @@ -44,9 +44,13 @@ struct history { struct history *prev, *next; }; +#define REDIRS_UNLIMITED -1 +#define REDIRS_ASK -2 + struct browser { bool pagination, unicode, alttext, autoopen; int max_width; + int max_redirs; struct gemini_options opts; struct gemini_tofu tofu; enum tofu_action tofu_mode; @@ -114,7 +118,7 @@ const char *help_msg = static void usage(const char *argv_0) { - fprintf(stderr, "usage: %s [-PUAT] [-j mode] [-W width] [gemini://...]\n", argv_0); + fprintf(stderr, "usage: %s [-PUAT] [-j mode] [-R redirs] [-W width] [gemini://...]\n", argv_0); } static void @@ -434,7 +438,7 @@ do_requests(struct browser *browser, struct gemini_response *resp) int nredir = 0; bool requesting = true; enum gemini_result res; - + char *scheme; CURLUcode uc = curl_url_get(browser->url, CURLUPART_SCHEME, &scheme, 0); @@ -549,9 +553,40 @@ do_requests(struct browser *browser, struct gemini_response *resp) free(new_url); break; case GEMINI_STATUS_CLASS_REDIRECT: - if (++nredir >= 5) { + if (browser->max_redirs == REDIRS_ASK) { +again: + fprintf(browser->tty, + "The host %s is redirecting to:\n" + "%s\n\n" + "[f]ollow redirect; [a]bort\n" + "=> ", host, resp->meta); + + size_t sz = 0; + char *line = NULL; + if (getline(&line, &sz, browser->tty) == -1) { + free(line); + requesting = false; + break; + } + if (line[1] != '\n') { + free(line); + goto again; + } + + char c = line[0]; + free(line); + + if (c == 'a') { + requesting = false; + break; + } else if (c != 'f') { + goto again; + } + } else if (browser->max_redirs != REDIRS_UNLIMITED + && ++nredir >= browser->max_redirs) { requesting = false; - fprintf(stderr, "Error: maximum redirects (5) exceeded\n"); + fprintf(stderr, "Error: maximum redirects (%d) exceeded\n", + browser->max_redirs); break; } set_url(browser, resp->meta, NULL); @@ -1322,10 +1357,11 @@ main(int argc, char *argv[]) .url = curl_url(), .tty = fopen("/dev/tty", "w+"), .meta = NULL, + .max_redirs = REDIRS_ASK, }; int c; - while ((c = getopt(argc, argv, "hj:PTAUW:")) != -1) { + while ((c = getopt(argc, argv, "hj:PR:UW:TA")) != -1) { switch (c) { case 'h': usage(argv[0]); @@ -1351,6 +1387,10 @@ main(int argc, char *argv[]) case 'P': browser.pagination = false; break; + case 'R':; + int mr = strtol(optarg, NULL, 10); + browser.max_redirs = mr < 0 ? REDIRS_UNLIMITED : mr; + break; case 'U': browser.unicode = false; break;