commit - 87e40628fa517c12135d3edee522705522042f79
commit + de2a69bb424696abd9b1be5232fb7a89fa5f8767
blob - d4aec734906480b830fa6a47629c715a4f34f6fd
blob + 66bce07c12d5faa0dd877834c78b5b4e27585366
--- ChangeLog
+++ ChangeLog
+2021-05-17 Omar Polo <op@omarpolo.com>
+
+ * telescope.c (handle_imsg_got_meta): ask the user to save a page when it can't be rendered
+
2021-05-13 Omar Polo <op@omarpolo.com>
* 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
#include <sys/stat.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
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);
[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,
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
void
sandbox_ui_process(void)
{
- if (pledge("stdio tty", NULL) == -1)
+ if (pledge("stdio tty recvfd", NULL) == -1)
err(1, "pledge");
}
{
char path[PATH_MAX];
- if (unveil("/tmp", "r") == -1)
+ if (unveil("/tmp", "rwc") == -1)
err(1, "unveil");
strlcpy(path, getenv("HOME"), sizeof(path));
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
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);
[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;
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++;
} 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);
}
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);
}
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;
{
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
IMSG_UPDATE_CERT,
IMSG_UPDATE_CERT_OK,
+ IMSG_FILE_OPEN,
+ IMSG_FILE_OPENED,
+
IMSG_SESSION_START,
IMSG_SESSION_TAB,
IMSG_SESSION_END,
short loading_anim;
short loading_anim_step;
struct event loadingev;
+
+ int fd;
+ size_t bytes;
+ char *path;
};
struct proto {
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
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);
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,
static struct histhead eecmd_history,
ir_history,
- lu_history;
+ lu_history,
+ read_history;
static int in_minibuffer;
{
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 *
event_loopbreak();
return NULL;
}
+ tab->fd = -1;
TAILQ_INIT(&tab->hist.head);
}
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;