diff --git a/src/gmnlm.c b/src/gmnlm.c
index 2375151c7f5fced09a80e41d26809730827f8925..4b844200eeb4318d694566d7a84eb3e64c7c7668 100644
--- a/src/gmnlm.c
+++ b/src/gmnlm.c
@@ -82,6 +82,7 @@ if (curl_url_set(browser->url, CURLUPART_URL, new_url, 0) != CURLUE_OK) {
fprintf(stderr, "Error: invalid URL\n");
return false;
}
+ curl_url_get(browser->url, CURLUPART_URL, &browser->plain_url, 0);
if (history) {
struct history *next = calloc(1, sizeof(struct history));
curl_url_get(browser->url, CURLUPART_URL, &next->url, 0);
@@ -118,19 +119,23 @@ case '\0':
result = PROMPT_MORE;
goto exit;
case 'q':
+ if (in[1]) break;
result = PROMPT_QUIT;
goto exit;
case 'b':
+ if (in[1]) break;
if (!browser->history->prev) {
fprintf(stderr, "At beginning of history\n");
result = PROMPT_AGAIN;
goto exit;
}
+ if (in[1]) break;
browser->history = browser->history->prev;
set_url(browser, browser->history->url, NULL);
result = PROMPT_ANSWERED;
goto exit;
case 'f':
+ if (in[1]) break;
if (!browser->history->next) {
fprintf(stderr, "At end of history\n");
result = PROMPT_AGAIN;
@@ -141,6 +146,7 @@ set_url(browser, browser->history->url, NULL);
result = PROMPT_ANSWERED;
goto exit;
case '/':
+ if (in[1]) break;
if ((r = regcomp(&browser->regex, &in[1], REG_EXTENDED)) != 0) {
static char buf[1024];
r = regerror(r, &browser->regex, buf, sizeof(buf));
@@ -153,6 +159,7 @@ result = PROMPT_ANSWERED;
}
goto exit_re;
case 'n':
+ if (in[1]) break;
if (browser->searching) {
result = PROMPT_NEXT;
goto exit_re;
@@ -162,6 +169,7 @@ result = PROMPT_AGAIN;
goto exit;
}
case '?':
+ if (in[1]) break;
fprintf(browser->tty, "%s", help_msg);
result = PROMPT_AGAIN;
goto exit;
@@ -465,6 +473,17 @@ }
return input;
}
+static bool
+has_suffix(char *str, char *suff)
+{
+ size_t suffl = strlen(suff);
+ size_t strl = strlen(str);
+ if (strl < suffl) {
+ return false;
+ }
+ return strcmp(&str[strl - suffl], suff) == 0;
+}
+
// Returns true to skip prompting
static bool
do_requests(struct browser *browser, struct gemini_response *resp)
@@ -472,9 +491,40 @@ {
int nredir = 0;
bool requesting = true;
while (requesting) {
+ char *scheme;
CURLUcode uc = curl_url_get(browser->url,
- CURLUPART_URL, &browser->plain_url, 0);
+ CURLUPART_SCHEME, &scheme, 0);
assert(uc == CURLUE_OK); // Invariant
+ if (strcmp(scheme, "file") == 0) {
+ requesting = false;
+
+ char *path;
+ uc = curl_url_get(browser->url,
+ CURLUPART_PATH, &path, 0);
+ if (uc != CURLUE_OK) {
+ resp->status = GEMINI_STATUS_BAD_REQUEST;
+ break;
+ }
+
+ FILE *fp = fopen(path, "r");
+ if (!fp) {
+ resp->status = GEMINI_STATUS_NOT_FOUND;
+ break;
+ }
+
+ BIO *file = BIO_new_fp(fp, BIO_CLOSE);
+ resp->bio = BIO_new(BIO_f_buffer());
+ BIO_push(resp->bio, file);
+ if (has_suffix(path, ".gmi") || has_suffix(path, ".gemini")) {
+ resp->meta = strdup("text/gemini");
+ } else if (has_suffix(path, ".txt")) {
+ resp->meta = strdup("text/plain");
+ } else {
+ resp->meta = strdup("application/x-octet-stream");
+ }
+ resp->status = GEMINI_STATUS_SUCCESS;
+ return display_response(browser, resp);
+ }
enum gemini_result res = gemini_request(browser->plain_url,
&browser->opts, resp);