1
0
mirror of https://git.sr.ht/~sircmpwn/gmni synced 2024-11-23 00:42:15 +01:00

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.
This commit is contained in:
Ondřej Fiala 2022-07-02 06:59:16 +02:00 committed by Drew DeVault
parent 584544ff7f
commit 74d0652125
2 changed files with 48 additions and 5 deletions

@ -22,6 +22,9 @@ gmnlm - Gemini line-mode browser
*-P* *-P*
Disable pagination. Disable pagination.
*-R* _redirs_
Sets the maximum number of redirects, negative argument disables limit.
*-U* *-U*
Disable conservative use of Unicode symbols to render Gemini layout Disable conservative use of Unicode symbols to render Gemini layout
features. features.

@ -33,9 +33,13 @@ struct history {
struct history *prev, *next; struct history *prev, *next;
}; };
#define REDIRS_UNLIMITED -1
#define REDIRS_ASK -2
struct browser { struct browser {
bool pagination, unicode; bool pagination, unicode;
int max_width; int max_width;
int max_redirs;
struct gemini_options opts; struct gemini_options opts;
struct gemini_tofu tofu; struct gemini_tofu tofu;
enum tofu_action tofu_mode; enum tofu_action tofu_mode;
@ -92,7 +96,7 @@ const char *help_msg =
static void static void
usage(const char *argv_0) usage(const char *argv_0)
{ {
fprintf(stderr, "usage: %s [-PU] [-j mode] [-W width] [gemini://...]\n", argv_0); fprintf(stderr, "usage: %s [-PU] [-j mode] [-R redirs] [-W width] [gemini://...]\n", argv_0);
} }
static void static void
@ -368,7 +372,7 @@ do_requests(struct browser *browser, struct gemini_response *resp)
int nredir = 0; int nredir = 0;
bool requesting = true; bool requesting = true;
enum gemini_result res; enum gemini_result res;
char *scheme; char *scheme;
CURLUcode uc = curl_url_get(browser->url, CURLUcode uc = curl_url_get(browser->url,
CURLUPART_SCHEME, &scheme, 0); CURLUPART_SCHEME, &scheme, 0);
@ -483,9 +487,40 @@ do_requests(struct browser *browser, struct gemini_response *resp)
free(new_url); free(new_url);
break; break;
case GEMINI_STATUS_CLASS_REDIRECT: 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; requesting = false;
fprintf(stderr, "Error: maximum redirects (5) exceeded\n"); fprintf(stderr, "Error: maximum redirects (%d) exceeded\n",
browser->max_redirs);
break; break;
} }
set_url(browser, resp->meta, NULL); set_url(browser, resp->meta, NULL);
@ -1185,10 +1220,11 @@ main(int argc, char *argv[])
.url = curl_url(), .url = curl_url(),
.tty = fopen("/dev/tty", "w+"), .tty = fopen("/dev/tty", "w+"),
.meta = NULL, .meta = NULL,
.max_redirs = REDIRS_ASK,
}; };
int c; int c;
while ((c = getopt(argc, argv, "hj:PUW:")) != -1) { while ((c = getopt(argc, argv, "hj:PR:UW:")) != -1) {
switch (c) { switch (c) {
case 'h': case 'h':
usage(argv[0]); usage(argv[0]);
@ -1208,6 +1244,10 @@ main(int argc, char *argv[])
case 'P': case 'P':
browser.pagination = false; browser.pagination = false;
break; break;
case 'R':;
int mr = strtol(optarg, NULL, 10);
browser.max_redirs = mr < 0 ? REDIRS_UNLIMITED : mr;
break;
case 'U': case 'U':
browser.unicode = false; browser.unicode = false;
break; break;