jcs
/detritus
/amendments
/37
gemini: Support 1X input requests
jcs made amendment 37 about 1 year ago
--- gemini.c Mon Nov 11 23:12:07 2024
+++ gemini.c Fri Nov 15 11:43:02 2024
@@ -20,8 +20,6 @@
#include "detritus.h"
-#define GEMINI_PORT 1965
-
enum {
PARSE_STATE_HEADER,
PARSE_STATE_BODY,
@@ -60,7 +58,7 @@ gemini_request_init(page_handle pageh)
if (page->uri->port == 0)
page->uri->port = GEMINI_PORT;
-
+
output_len = strlen(page->uri->str) + 2;
output = xmalloc(output_len + 1);
if (page->request->output == NULL) {
@@ -351,15 +349,19 @@ gemini_reset(page_handle pageh)
/* restart at body */
page->parse_state = PARSE_STATE_BODY;
page->content_pos = page->header_len;
-
- browser_commit_to_loading_page(page->browser);
}
static bool
parse_header(struct page *page, char *str, size_t len)
{
- short status;
- char fail[32];
+ char fail[32], *newuri, *encoded, *query;
+ Str255 txt;
+ GrafPtr win;
+ DialogPtr dlg;
+ Handle ihandle;
+ Rect irect, dlgrect;
+ size_t tlen;
+ short status, hit, itype, ret, top;
BROWSER_DEBUGF((page->browser, "Received header: %s", str));
if (!(str[0] >= '0' && str[0] <= '9' &&
@@ -374,11 +376,78 @@ parse_header(struct page *page, char *str, size_t len)
fail[MIN(len, sizeof(fail) - 1)] = '\0';
if (page->server_status >= 10 && page->server_status <= 19) {
- /* input, not supported */
- browser_statusf(page->browser, "Error: Input not supported (%d)",
- page->server_status);
+ /* input requested */
+ GetPort(&win);
+
+ if ((dlg = GetNewDialog(INPUT_DLOG_ID, NULL,
+ (WindowPtr)-1)) == NULL) {
+ warn("Can't find DLOG %d", INPUT_DLOG_ID);
+ return false;
+ }
+ center_in_screen(dlg->portRect.right - dlg->portRect.left,
+ dlg->portRect.bottom - dlg->portRect.top, true, &dlgrect);
+ MoveWindow(dlg, dlgrect.left, dlgrect.top, true);
+
+ snprintf((char *)txt, sizeof(txt), "Input requested from %s",
+ page->uri->hostname);
+ CtoPstr(txt);
+ SetWTitle(dlg, txt);
+
+ GetDItem(dlg, INPUT_DLOG_PROMPT_ID, &itype, &ihandle, &irect);
+ tlen = len - 2;
+ if (tlen >= sizeof(txt))
+ tlen = sizeof(txt) - 1;
+ memcpy(txt + 1, str + 3, tlen);
+ txt[0] = tlen;
+ SetIText(ihandle, txt);
+
+ ShowWindow(dlg);
+ for (;;) {
+ ModalDialog(ModalDialogFilter, &hit);
+ if (hit == ok || hit == cancel)
+ break;
+ }
+
+ if (hit == ok) {
+ GetDItem(dlg, INPUT_DLOG_INPUT_ID, &itype, &ihandle, &irect);
+ GetIText(ihandle, txt);
+ PtoCstr(txt);
+ }
+
+ DisposDialog(dlg);
+
+ SetPort(win);
+
+ if (hit != ok) {
+ browser_statusf(page->browser, "Canceled input");
+ return false;
+ }
+
+ /* make a new uri with this same one but send input as query */
+ encoded = uri_encode(txt);
+ if (encoded == NULL) {
+ browser_statusf(page->browser, "Error: Out of memory");
+ return false;
+ }
+
+ tlen = 1 + strlen(encoded);
+ query = xmalloc(tlen + 1);
+ if (query == NULL) {
+ xfree(&encoded);
+ browser_statusf(page->browser, "Error: Out of memory");
+ }
+
+ snprintf(query, tlen + 1, "?%s", encoded);
+ xfree(&encoded);
+
+ page->redir_to = build_relative_uri(page->uri, query, tlen);
+ xfree(&query);
+ if (page->redir_to == NULL)
+ browser_statusf(page->browser, "Error: Out of memory");
+
return false;
}
+
if (page->server_status >= 20 && page->server_status <= 29) {
/* success */
if (len + 3 + 1 > sizeof(page->content_type))
@@ -387,30 +456,35 @@ parse_header(struct page *page, char *str, size_t len)
page->content_type[len - 2] = '\0';
return true;
}
+
if (page->server_status >= 30 && page->server_status <= 39) {
/* redirect */
page->redir_to = build_relative_uri(page->uri, str + 3, len - 2);
/* TODO: infinite loop detection */
return false;
}
+
if (page->server_status >= 40 && page->server_status <= 49) {
/* temp fail */
browser_statusf(page->browser, "Error: Server reported temporary "
"failure: %s", fail);
return false;
}
+
if (page->server_status >= 50 && page->server_status <= 59) {
/* perm fail */
browser_statusf(page->browser, "Error: Server reported "
"permanent failure: %s", fail);
return false;
}
+
if (page->server_status >= 60 && page->server_status <= 69) {
/* auth, not supported */
browser_statusf(page->browser, "Error: Auth not supported (%d)",
status);
return false;
}
+
browser_statusf(page->browser, "Error: Unsupported status: %s", fail);
return false;
}