From cfcd27c3e8d4152fed6ed738e09a3e0b3a6d57c0 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Fri, 6 Dec 2024 15:14:41 +0100 Subject: [PATCH] [gemini] Show query dialog box for codes 10 and 11. Refs #121 11 is for passwords, but now is shown in plain text. --- src/protocol/gemini/Makefile | 2 +- src/protocol/gemini/codes.c | 6 +-- src/protocol/gemini/dialog.c | 70 +++++++++++++++++++++++++++++++++ src/protocol/gemini/dialog.h | 15 +++++++ src/protocol/gemini/gemini.c | 38 ++++++++++++------ src/protocol/gemini/gemini.h | 15 ++++++- src/protocol/gemini/meson.build | 2 +- 7 files changed, 129 insertions(+), 19 deletions(-) create mode 100644 src/protocol/gemini/dialog.c create mode 100644 src/protocol/gemini/dialog.h diff --git a/src/protocol/gemini/Makefile b/src/protocol/gemini/Makefile index 017f769c2..9ee744dbb 100644 --- a/src/protocol/gemini/Makefile +++ b/src/protocol/gemini/Makefile @@ -1,6 +1,6 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config -OBJS = codes.o gemini.o +OBJS = codes.o dialog.o gemini.o include $(top_srcdir)/Makefile.lib diff --git a/src/protocol/gemini/codes.c b/src/protocol/gemini/codes.c index 86d95f5a6..814e7dfe1 100644 --- a/src/protocol/gemini/codes.c +++ b/src/protocol/gemini/codes.c @@ -18,6 +18,7 @@ #include "intl/libintl.h" #include "network/connection.h" #include "protocol/gemini/codes.h" +#include "protocol/gemini/gemini.h" #include "protocol/uri.h" #include "session/session.h" #include "session/task.h" @@ -125,11 +126,6 @@ get_gemini_error_document(struct terminal *term, struct uri *uri, int code) return string.source; } -struct gemini_error_info { - int code; - struct uri *uri; -}; - static void show_gemini_error_document(struct session *ses, void *data) { diff --git a/src/protocol/gemini/dialog.c b/src/protocol/gemini/dialog.c new file mode 100644 index 000000000..e0e283182 --- /dev/null +++ b/src/protocol/gemini/dialog.c @@ -0,0 +1,70 @@ +/* Gemini query dialog stuff */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "elinks.h" + +#include "bfu/dialog.h" +#include "bfu/inpfield.h" +#include "intl/libintl.h" +#include "main/object.h" +#include "protocol/gemini/dialog.h" +#include "protocol/gemini/gemini.h" +#include "protocol/uri.h" +#include "session/location.h" +#include "session/session.h" +#include "session/task.h" +#include "terminal/terminal.h" +#include "util/color.h" +#include "util/lists.h" +#include "util/memory.h" +#include "util/snprintf.h" +#include "util/string.h" + +static void +query_ok(void *d, const char *data) +{ + struct gemini_error_info *info = (struct gemini_error_info *)d; + + char *url = get_uri_string(info->uri, URI_PROTOCOL | URI_HOST | URI_PORT | URI_DATA); + char *url2 = straconcat(url, "?", data, NULL); + + mem_free_if(url); + + if (!url2) { + return; + } + goto_url_with_hook(info->ses, url2); + mem_free(url2); + done_uri(info->uri); + mem_free(info->prompt); + mem_free(info); +} + +static void +query_cancel(void *d) +{ + struct gemini_error_info *info = (struct gemini_error_info *)d; + + done_uri(info->uri); + mem_free(info->prompt); + mem_free(info); +} + +void +do_gemini_query_dialog(struct session *ses, void *data) +{ + struct gemini_error_info *info = (struct gemini_error_info *)data; + info->ses = ses; + + input_dialog(ses->tab->term, NULL, + info->prompt, N_("Enter text"), + info, NULL, + MAX_STR_LEN, info->value, 0, 0, NULL, + (void (*)(void *, char *))query_ok, + query_cancel); +} diff --git a/src/protocol/gemini/dialog.h b/src/protocol/gemini/dialog.h new file mode 100644 index 000000000..e56ec5a4d --- /dev/null +++ b/src/protocol/gemini/dialog.h @@ -0,0 +1,15 @@ +#ifndef EL__PROTOCOL_GEMINI_DIALOG_H +#define EL__PROTOCOL_GEMINI_DIALOG_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct session; +void do_gemini_query_dialog(struct session *ses, void *data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/protocol/gemini/gemini.c b/src/protocol/gemini/gemini.c index 79bf6328d..4545f7c73 100644 --- a/src/protocol/gemini/gemini.c +++ b/src/protocol/gemini/gemini.c @@ -30,6 +30,7 @@ #include "osdep/sysname.h" #include "protocol/date.h" #include "protocol/gemini/codes.h" +#include "protocol/gemini/dialog.h" #include "protocol/gemini/gemini.h" #include "protocol/header.h" #include "protocol/uri.h" @@ -60,10 +61,6 @@ done_gemini(struct module *mod) { } -struct gemini_connection_info { - int code; -}; - static void gemini_end_request(struct connection *conn, struct connection_state state, int notrunc) @@ -85,6 +82,7 @@ done_gemini_connection(struct connection *conn) { struct gemini_connection_info *gemini = (struct gemini_connection_info *)conn->info; + mem_free_if(gemini->prompt); mem_free(gemini); conn->info = NULL; conn->done = NULL; @@ -167,6 +165,18 @@ read_gemini_data_done(struct connection *conn) if (!conn->from) { if (gemini->code >= 40) { gemini_error_document(conn, gemini->code); + } else if (gemini->code == 10 || gemini->code == 11) { + struct gemini_error_info *info; + assert(conn && conn->uri); + info = (struct gemini_error_info *)mem_calloc(1, sizeof(*info)); + + if (!info) { + return; + } + info->code = gemini->code; + info->uri = get_uri_reference(conn->uri); + info->prompt = null_or_stracpy(gemini->prompt); + add_questions_entry(do_gemini_query_dialog, info); } else { /* This is not an error, thus fine. No need generate any * document, as this may be empty and it's not a problem. @@ -314,15 +324,21 @@ gemini_got_header(struct socket *socket, struct read_buffer *rb) if (!init_string(&head_string)) { return; } - add_to_string(&head_string, "\nContent-Type: "); - add_bytes_to_string(&head_string, rb->data + 3, a - 2); - if (!conn->cached) { - done_string(&head_string); - abort_connection(conn, connection_state(S_OUT_OF_MEM)); - return; + if (h == 10 || h == 11) { + add_bytes_to_string(&head_string, rb->data + 3, a - 4); + mem_free_set(&gemini->prompt, head_string.source); + } else { + add_to_string(&head_string, "\nContent-Type: "); + add_bytes_to_string(&head_string, rb->data + 3, a - 2); + + if (!conn->cached) { + done_string(&head_string); + abort_connection(conn, connection_state(S_OUT_OF_MEM)); + return; + } + mem_free_set(&conn->cached->head, head_string.source); } - mem_free_set(&conn->cached->head, head_string.source); kill_buffer_data(rb, a + 1); read_gemini_data(socket, rb); diff --git a/src/protocol/gemini/gemini.h b/src/protocol/gemini/gemini.h index be5a10c01..9e9132d46 100644 --- a/src/protocol/gemini/gemini.h +++ b/src/protocol/gemini/gemini.h @@ -1,4 +1,3 @@ - #ifndef EL__PROTOCOL_GEMINI_GEMINI_H #define EL__PROTOCOL_GEMINI_GEMINI_H @@ -11,8 +10,22 @@ extern "C" { struct connection; struct read_buffer; +struct session; struct socket; +struct gemini_connection_info { + char *prompt; + int code; +}; + +struct gemini_error_info { + int code; + struct uri *uri; + struct session *ses; + char *prompt; + char value[MAX_STR_LEN]; +}; + extern struct module gemini_protocol_module; #ifdef CONFIG_GEMINI diff --git a/src/protocol/gemini/meson.build b/src/protocol/gemini/meson.build index a51eccfdd..ab13cbd66 100644 --- a/src/protocol/gemini/meson.build +++ b/src/protocol/gemini/meson.build @@ -1 +1 @@ -srcs += files('codes.c', 'gemini.c') +srcs += files('codes.c', 'dialog.c', 'gemini.c')