cgmnlm

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

commit dcc2b34d434d8e0f695e43a1f775759846e60417
parent ea595cdb2ba9d1e443c7ccdccf3842e49e7162a8
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 20 Sep 2020 19:14:47 -0400

gmnlm: implement redirects

Diffstat:
Msrc/gmnlm.c | 80+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 48 insertions(+), 32 deletions(-)

diff --git a/src/gmnlm.c b/src/gmnlm.c @@ -217,50 +217,66 @@ main(int argc, char *argv[]) while (run) { struct link *links; static char prompt[4096]; - char *plain_url; - CURLUcode uc = curl_url_get(url, CURLUPART_URL, &plain_url, 0); - assert(uc == CURLUE_OK); // Invariant - snprintf(prompt, sizeof(prompt), "\nat %s\n" - "[n]: follow Nth link; [o <url>]: open URL; " - "[b]ack; [f]orward; " - "[q]uit\n" - "=> ", plain_url); + int nredir = 0; + bool requesting = true; + while (requesting) { + CURLUcode uc = curl_url_get(url, CURLUPART_URL, &plain_url, 0); + assert(uc == CURLUE_OK); // Invariant + + enum gemini_result res = gemini_request( + plain_url, &opts, &resp); + if (res != GEMINI_OK) { + fprintf(stderr, "Error: %s\n", + gemini_strerr(res, &resp)); + requesting = false; + break; + } + + switch (gemini_response_class(resp.status)) { + case GEMINI_STATUS_CLASS_INPUT: + assert(0); // TODO + case GEMINI_STATUS_CLASS_REDIRECT: + if (++nredir >= 5) { + requesting = false; + fprintf(stderr, "Error: maximum redirects (5) exceeded"); + break; + } + fprintf(stderr, + "Following redirect to %s\n", resp.meta); + set_url(url, resp.meta, NULL); + break; + case GEMINI_STATUS_CLASS_CLIENT_CERTIFICATE_REQUIRED: + assert(0); // TODO + case GEMINI_STATUS_CLASS_TEMPORARY_FAILURE: + case GEMINI_STATUS_CLASS_PERMANENT_FAILURE: + requesting = false; + fprintf(stderr, "Server returned %s %d %s\n", + resp.status / 10 == 4 ? + "TEMPORARY FAILURE" : "PERMANENT FALIURE", + resp.status, resp.meta); + break; + case GEMINI_STATUS_CLASS_SUCCESS: + requesting = false; + display_response(tty, &resp, &links, pagination); + break; + } - enum gemini_result res = gemini_request(plain_url, &opts, &resp); - if (res != GEMINI_OK) { - fprintf(stderr, "Error: %s\n", gemini_strerr(res, &resp)); - assert(0); // TODO: Prompt + if (requesting) { + gemini_response_finish(&resp); + } } - snprintf(prompt, sizeof(prompt), "\n%s at %s\n" + snprintf(prompt, sizeof(prompt), "\n%s%s at %s\n" "[n]: follow Nth link; [o <url>]: open URL; " "[b]ack; [f]orward; " "[q]uit\n" "=> ", + resp.status == GEMINI_STATUS_SUCCESS ? " " : "", resp.status == GEMINI_STATUS_SUCCESS ? resp.meta : "", plain_url); - switch (gemini_response_class(resp.status)) { - case GEMINI_STATUS_CLASS_INPUT: - assert(0); // TODO - case GEMINI_STATUS_CLASS_REDIRECT: - assert(0); // TODO - case GEMINI_STATUS_CLASS_CLIENT_CERTIFICATE_REQUIRED: - assert(0); // TODO - case GEMINI_STATUS_CLASS_TEMPORARY_FAILURE: - case GEMINI_STATUS_CLASS_PERMANENT_FAILURE: - fprintf(stderr, "Server returned %s %d %s\n", - resp.status / 10 == 4 ? - "TEMPORARY FAILURE" : "PERMANENT FALIURE", - resp.status, resp.meta); - break; - case GEMINI_STATUS_CLASS_SUCCESS: - display_response(tty, &resp, &links, pagination); - break; - } - gemini_response_finish(&resp); bool prompting = true;