commit de2a69bb424696abd9b1be5232fb7a89fa5f8767 from: Omar Polo date: Mon May 17 10:13:17 2021 UTC ask to save a page when it can't be rendered it's good for thing like images and text with weird encodings. commit - 87e40628fa517c12135d3edee522705522042f79 commit + de2a69bb424696abd9b1be5232fb7a89fa5f8767 blob - d4aec734906480b830fa6a47629c715a4f34f6fd blob + 66bce07c12d5faa0dd877834c78b5b4e27585366 --- ChangeLog +++ ChangeLog @@ -1,3 +1,7 @@ +2021-05-17 Omar Polo + + * telescope.c (handle_imsg_got_meta): ask the user to save a page when it can't be rendered + 2021-05-13 Omar Polo * gemtext.c (gemtext_free): heuristic to obtain the page title: if no h1 found, try with h2s and h3s blob - 2b96509fdd0337da41b701583d79bb641267d74e blob + ba64ad31f7f56325498038b378b001f58c186aea --- fs.c +++ fs.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,7 @@ static void handle_quit(struct imsg*, size_t); static void handle_bookmark_page(struct imsg*, size_t); static void handle_save_cert(struct imsg*, size_t); static void handle_update_cert(struct imsg*, size_t); +static void handle_file_open(struct imsg*, size_t); static void handle_session_start(struct imsg*, size_t); static void handle_session_tab(struct imsg*, size_t); static void handle_session_end(struct imsg*, size_t); @@ -58,6 +60,7 @@ static imsg_handlerfn *handlers[] = { [IMSG_BOOKMARK_PAGE] = handle_bookmark_page, [IMSG_SAVE_CERT] = handle_save_cert, [IMSG_UPDATE_CERT] = handle_update_cert, + [IMSG_FILE_OPEN] = handle_file_open, [IMSG_SESSION_START] = handle_session_start, [IMSG_SESSION_TAB] = handle_session_tab, [IMSG_SESSION_END] = handle_session_end, @@ -243,6 +246,27 @@ handle_update_cert(struct imsg *imsg, size_t datalen) end: imsg_compose(ibuf, IMSG_UPDATE_CERT_OK, imsg->hdr.peerid, 0, -1, &res, sizeof(res)); + imsg_flush(ibuf); +} + +static void +handle_file_open(struct imsg *imsg, size_t datalen) +{ + char *path, *e; + int fd; + + path = imsg->data; + if (path[datalen-1] != '\0') + die(); + + if ((fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0644)) == -1) { + e = strerror(errno); + imsg_compose(ibuf, IMSG_FILE_OPENED, imsg->hdr.peerid, 0, -1, + e, strlen(e)+1); + } else + imsg_compose(ibuf, IMSG_FILE_OPENED, imsg->hdr.peerid, 0, fd, + NULL, 0); + imsg_flush(ibuf); } blob - b993a5dde66ce6b28485127813fbd24171780b1f blob + 3a18f3c466982fafb2d0d4480a63006e8548207b --- sandbox.c +++ sandbox.c @@ -33,7 +33,7 @@ sandbox_network_process(void) void sandbox_ui_process(void) { - if (pledge("stdio tty", NULL) == -1) + if (pledge("stdio tty recvfd", NULL) == -1) err(1, "pledge"); } @@ -42,7 +42,7 @@ sandbox_fs_process(void) { char path[PATH_MAX]; - if (unveil("/tmp", "r") == -1) + if (unveil("/tmp", "rwc") == -1) err(1, "unveil"); strlcpy(path, getenv("HOME"), sizeof(path)); @@ -55,7 +55,7 @@ sandbox_fs_process(void) if (unveil(path, "rwc") == -1) err(1, "unveil"); - if (pledge("stdio rpath wpath cpath", NULL) == -1) + if (pledge("stdio rpath wpath cpath sendfd", NULL) == -1) err(1, "pledge"); } blob - 90a6debb5669b160daddb376844cec7410a01f0e blob + 1eee5e55de6e7494f46e248eec4d0c7c1e2e74f9 --- telescope.c +++ telescope.c @@ -29,6 +29,9 @@ static void handle_check_cert_user_choice(int, unsig static void handle_maybe_save_new_cert(int, unsigned int); static void handle_imsg_got_code(struct imsg*, size_t); static void handle_imsg_got_meta(struct imsg*, size_t); +static void handle_maybe_save_page(int, unsigned int); +static void handle_save_page_path(const char *, unsigned int); +static void handle_imsg_file_opened(struct imsg*, size_t); static void handle_imsg_buf(struct imsg*, size_t); static void handle_imsg_eof(struct imsg*, size_t); static void handle_imsg_bookmark_ok(struct imsg*, size_t); @@ -48,6 +51,7 @@ static imsg_handlerfn *handlers[] = { [IMSG_BOOKMARK_OK] = handle_imsg_bookmark_ok, [IMSG_SAVE_CERT_OK] = handle_imsg_save_cert_ok, [IMSG_UPDATE_CERT_OK] = handle_imsg_update_cert_ok, + [IMSG_FILE_OPENED] = handle_imsg_file_opened, }; static struct ohash certs; @@ -261,6 +265,8 @@ handle_imsg_got_meta(struct imsg *imsg, size_t datalen imsg_flush(netibuf); } else { load_page_from_str(tab, err_pages[UNKNOWN_TYPE_OR_CSET]); + ui_yornp("Can't display page, wanna save?", + handle_maybe_save_page, tab->id); } } else if (tab->code < 40) { /* 3x */ tab->redirect_count++; @@ -274,17 +280,87 @@ handle_imsg_got_meta(struct imsg *imsg, size_t datalen } else { /* 4x, 5x & 6x */ load_page_from_str(tab, err_pages[tab->code]); } +} + +static void +handle_maybe_save_page(int dosave, unsigned int tabid) +{ + if (dosave) + ui_read("Save to path", handle_save_page_path, tabid); + else + stop_tab(tab_by_id(tabid)); +} + +static void +handle_save_page_path(const char *path, unsigned int tabid) +{ + struct tab *tab; + + if (path == NULL) { + stop_tab(tab_by_id(tabid)); + return; + } + + tab = tab_by_id(tabid); + tab->path = strdup(path); + + imsg_compose(fsibuf, IMSG_FILE_OPEN, tabid, 0, -1, path, strlen(path)+1); + imsg_flush(fsibuf); } static void +handle_imsg_file_opened(struct imsg *imsg, size_t datalen) +{ + struct tab *tab; + char *page; + const char *e; + int l; + + tab = tab_by_id(imsg->hdr.peerid); + + if (imsg->fd == -1) { + stop_tab(tab); + + e = imsg->data; + if (e[datalen-1] != '\0') + die(); + l = asprintf(&page, "# Can't open file\n\n> %s: %s\n", + tab->path, e); + if (l == -1) + die(); + load_page_from_str(tab, page); + free(page); + } else { + tab->fd = imsg->fd; + imsg_compose(netibuf, IMSG_PROCEED, tab->id, 0, -1, NULL, 0); + imsg_flush(netibuf); + } +} + +static void handle_imsg_buf(struct imsg *imsg, size_t datalen) { struct tab *tab; + int l; + char *page; tab = tab_by_id(imsg->hdr.peerid); - if (!tab->window.page.parse(&tab->window.page, imsg->data, datalen)) - die(); + tab->bytes += datalen; + if (tab->fd == -1) { + if (!tab->window.page.parse(&tab->window.page, + imsg->data, datalen)) + die(); + } else { + write(tab->fd, imsg->data, datalen); + l = asprintf(&page, "Writing \"%s\"... (%zu bytes)\n", + tab->path, + tab->bytes); + if (l == -1) + die(); + load_page_from_str(tab, page); + free(page); + } ui_on_tab_refresh(tab); } @@ -293,11 +369,29 @@ static void handle_imsg_eof(struct imsg *imsg, size_t datalen) { struct tab *tab; + int l; + char *page; tab = tab_by_id(imsg->hdr.peerid); - if (!tab->window.page.free(&tab->window.page)) - die(); + + if (tab->fd == -1) { + if (!tab->window.page.free(&tab->window.page)) + die(); + } else { + l = asprintf(&page, "Wrote %s (%zu bytes)\n", + tab->path, + tab->bytes); + if (l == -1) + die(); + load_page_from_str(tab, page); + free(page); + close(tab->fd); + tab->fd = -1; + free(tab->path); + tab->path = NULL; + } + ui_on_tab_refresh(tab); ui_on_tab_loaded(tab); } @@ -395,6 +489,13 @@ do_load_url(struct tab *tab, const char *url) struct phos_uri uri; struct proto *p; char *t; + + if (tab->fd != -1) { + close(tab->fd); + tab->fd = -1; + free(tab->path); + tab->path = NULL; + } tab->trust = TS_UNKNOWN; @@ -467,6 +568,14 @@ stop_tab(struct tab *tab) { imsg_compose(netibuf, IMSG_STOP, tab->id, 0, -1, NULL, 0); imsg_flush(netibuf); + + if (tab->fd != -1) { + close(tab->fd); + tab->fd = -1; + free(tab->path); + tab->path = NULL; + load_page_from_str(tab, "Stopped.\n"); + } } void blob - 6aaa32596257531a4c76d8aa7119178979bc477f blob + 0d150af562162b1190f37e5c5f9b35276daf95be --- telescope.h +++ telescope.h @@ -50,6 +50,9 @@ enum imsg_type { IMSG_UPDATE_CERT, IMSG_UPDATE_CERT_OK, + IMSG_FILE_OPEN, + IMSG_FILE_OPENED, + IMSG_SESSION_START, IMSG_SESSION_TAB, IMSG_SESSION_END, @@ -168,6 +171,10 @@ struct tab { short loading_anim; short loading_anim_step; struct event loadingev; + + int fd; + size_t bytes; + char *path; }; struct proto { @@ -264,6 +271,7 @@ int ui_init(int, char * const*); void ui_on_tab_loaded(struct tab*); void ui_on_tab_refresh(struct tab*); void ui_require_input(struct tab*, int); +void ui_read(const char*, void(*)(const char*, unsigned int), unsigned int); void ui_yornp(const char*, void (*)(int, unsigned int), unsigned int); void ui_notify(const char*, ...) __attribute__((format(printf, 1, 2))); void ui_end(void); blob - e9a5a08e440f3bfa00e5e6c38f60412caa0a5da2 blob + dd0d3ccaeec27d5f8b16a8cb253e518622c2c3b5 --- ui.c +++ ui.c @@ -68,6 +68,9 @@ static void lu_select(void); static void bp_select(void); static void yornp_self_insert(void); static void yornp_abort(void); +static void read_self_insert(void); +static void read_abort(void); +static void read_select(void); static struct vline *nth_line(struct window*, size_t); static struct tab *current_tab(void); @@ -127,6 +130,9 @@ static char keybuf[64]; static void (*yornp_cb)(int, unsigned int); static unsigned int yornp_data; +static void (*read_cb)(const char*, unsigned int); +static unsigned int read_data; + struct kmap global_map, minibuffer_map, *current_map, @@ -134,7 +140,8 @@ struct kmap global_map, static struct histhead eecmd_history, ir_history, - lu_history; + lu_history, + read_history; static int in_minibuffer; @@ -1121,6 +1128,32 @@ yornp_abort(void) { exit_minibuffer(); yornp_cb(0, yornp_data); +} + +static void +read_self_insert(void) +{ + if (thiskey.meta || !unicode_isgraph(thiskey.cp)) { + global_key_unbound(); + return; + } + + minibuffer_self_insert(); +} + +static void +read_abort(void) +{ + exit_minibuffer(); + read_cb(NULL, read_data); +} + +static void +read_select(void) +{ + exit_minibuffer(); + minibuffer_hist_save_entry(); + read_cb(ministate.buf, read_data); } static struct vline * @@ -1872,6 +1905,7 @@ new_tab(const char *url) event_loopbreak(); return NULL; } + tab->fd = -1; TAILQ_INIT(&tab->hist.head); @@ -2045,6 +2079,26 @@ ui_yornp(const char *prompt, void (*fn)(int, unsigned } void +ui_read(const char *prompt, void (*fn)(const char*, unsigned int), + unsigned int data) +{ + size_t len; + + if (in_minibuffer) + return; + + read_cb = fn; + read_data = data; + enter_minibuffer(read_self_insert, read_select, read_abort, + &read_history); + + len = sizeof(ministate.prompt); + strlcpy(ministate.prompt, prompt, len); + strlcat(ministate.prompt, ": ", len); + redraw_tab(current_tab()); +} + +void ui_notify(const char *fmt, ...) { va_list ap;