Commit Diff


commit - 86395f5c1e1693b506e0e3e9087a073aeb694e86
commit + 0972d8b2a08f2c28e86b3cc310f9eac1be74766d
blob - f510a44129c6f2446a709f1546452e51701bbe85
blob + b9d7b8287a090c303ff1b6a8df20342f17075afb
--- gemini.c
+++ gemini.c
@@ -63,12 +63,14 @@ static void		 check_special_page(struct req*, const ch
 
 static void		 handle_get(struct imsg*, size_t);
 static void		 handle_cert_status(struct imsg*, size_t);
+static void		 handle_proceed(struct imsg*, size_t);
 static void		 handle_stop(struct imsg*, size_t);
 static void		 handle_quit(struct imsg*, size_t);
 
 static imsg_handlerfn *handlers[] = {
 	[IMSG_GET] = handle_get,
 	[IMSG_CERT_STATUS] = handle_cert_status,
+	[IMSG_PROCEED] = handle_proceed,
 	[IMSG_STOP] = handle_stop,
 	[IMSG_QUIT] = handle_quit,
 };
@@ -343,7 +345,6 @@ parse_reply(struct req *req)
 	    req->buf, len);
 	imsg_flush(ibuf);
 
-	yield_r(req, copy_body, NULL);
 	return;
 
 err:
@@ -377,27 +378,6 @@ copy_body(int fd, short ev, void *d)
 			break;
 		}
 	}
-}
-
-static int
-serve_special_page(struct req *req, const char *url)
-{
-	int		 code = 20;
-	const char	*meta = "text/gemini";
-
-	if (strcmp(url, "about:new"))
-		return 0;
-
-	imsg_compose(ibuf, IMSG_GOT_CODE, req->id, 0, -1, &code, sizeof(code));
-	imsg_compose(ibuf, IMSG_GOT_META, req->id, 0, -1, meta, strlen(meta)+1);
-	imsg_compose(ibuf, IMSG_BUF, req->id, 0, -1, about_new, strlen(about_new));
-	imsg_compose(ibuf, IMSG_EOF, req->id, 0, -1, NULL, 0);
-	imsg_flush(ibuf);
-
-	/* don't close_page here, since req is not added to requests
-	 * queue */
-	free(req);
-	return 1;
 }
 
 static void
@@ -417,9 +397,6 @@ handle_get(struct imsg *imsg, size_t datalen)
 
 	req->id = imsg->hdr.peerid;
 
-	if (serve_special_page(req, data))
-		return;
-
         if (!url_parse(imsg->data, &req->url, &e)) {
 		fprintf(stderr, "failed to parse url: %s\n", e);
 		close_with_err(req, e);
@@ -467,6 +444,15 @@ handle_cert_status(struct imsg *imsg, size_t datalen)
 }
 
 static void
+handle_proceed(struct imsg *imsg, size_t datalen)
+{
+	struct req	*req;
+
+	req = req_by_id(imsg->hdr.peerid);
+	yield_r(req, copy_body, NULL);
+}
+
+static void
 handle_stop(struct imsg *imsg, size_t datalen)
 {
 	struct req	*req;
blob - 70fa25871c6cf66971d840815d9da003ac15074c
blob + 44faf3c1699c6a9ef82a9c23ef26dbb275b44e64
--- pages.c
+++ pages.c
@@ -36,3 +36,22 @@ const char *about_new =
 	">quote\n"
 	"Id dolore aperiam voluptatem libero eaque omnis rerum nulla. Ullam sit voluptate accusamus molestiae enim minus. Fugit sequi quam dignissimos. Odio inventore vel sed. Voluptatem aut magni dignissimos."
 	;
+
+const char *err_pages[70] = {
+	[CANNOT_FETCH]		= "# Couldn't load the page\n",
+	[TOO_MUCH_REDIRECTS]	= "# Too much redirects\n",
+
+	[40] = "# Temporary failure\n",
+	[41] = "# Server unavailable\n",
+	[42] = "# CGI error\n",
+	[43] = "# Proxy error\n",
+	[44] = "# Slow down\n",
+	[50] = "# Permanent failure\n",
+	[51] = "# Not found\n",
+	[52] = "# Gone\n",
+	[53] = "# Proxy request refused\n",
+	[59] = "# Bad request\n",
+	[60] = "# Client certificate required\n",
+	[61] = "# Certificate not authorised\n",
+	[62] = "# Certificate not valid\n"
+};
blob - b22f1e2f3eac9a175081da9049cfea62e36b4da0
blob + ff93bcfbd3dbbff0d6f93cd7bbe960dfa6329146
--- telescope.c
+++ telescope.c
@@ -24,6 +24,9 @@ static void	handle_imsg_got_meta(struct imsg*, size_t)
 static void	handle_imsg_buf(struct imsg*, size_t);
 static void	handle_imsg_eof(struct imsg*, size_t);
 
+static void	load_page_from_str(struct tab*, const char*);
+static void	load_url(struct tab*, const char*);
+
 static imsg_handlerfn *handlers[] = {
 	[IMSG_ERR] = handle_imsg_err,
 	[IMSG_CHECK_CERT] = handle_imsg_check_cert,
@@ -72,36 +75,78 @@ handle_imsg_check_cert(struct imsg *imsg, size_t datal
 static void
 handle_imsg_got_code(struct imsg *imsg, size_t datalen)
 {
-	int code;
+	const char	*errpage;
+	struct tab	*tab;
 
-	if (sizeof(code) != datalen)
+	tab = tab_by_id(imsg->hdr.peerid);
+
+	if (sizeof(tab->code) != datalen)
 		die();
+	memcpy(&tab->code, imsg->data, sizeof(tab->code));
 
-	memcpy(&code, imsg->data, sizeof(code));
+        if (tab->code < 20) {
+		if (tab->code != 10 && tab->code != 11)
+			tab->code = 10;
+	} else if (tab->code < 30)
+		tab->code = 20;
+	else if (tab->code < 40)
+		tab->code = 30;
+	else if (tab->code < 50)
+		tab->code = 40;
+	else if (tab->code < 60)
+		tab->code = 50;
+	else
+		tab->code = 60;
 
-	/* fprintf(stderr, "got status code: %d\n", code); */
+	if (tab->code != 30)
+		tab->redirect_count = 0;
 }
 
 static void
 handle_imsg_got_meta(struct imsg *imsg, size_t datalen)
 {
-	/* fprintf(stderr, "got meta: "); */
-	/* fflush(stderr); */
-	/* write(2, imsg->data, datalen); */
-	/* fprintf(stderr, "\n"); */
+	struct tab	*tab;
+
+	tab = tab_by_id(imsg->hdr.peerid);
+
+	if (sizeof(tab->meta) <= datalen)
+		die();
+	memcpy(tab->meta, imsg->data, datalen);
+
+	/* TODO: parse the MIME type if it's 20 */
+	gemtext_initparser(&tab->page);
+
+	if (tab->code == 20) {
+		imsg_compose(ibuf, IMSG_PROCEED, tab->id, 0, -1, NULL, 0);
+		imsg_flush(ibuf);
+		return;
+	}
+
+	if (tab->code == 30)
+		die();
+
+	/* 4x, 5x or 6x */
+
+	if (!tab->page.parse(&tab->page, err_pages[tab->code],
+	    strlen(err_pages[tab->code])))
+		die();
+	if (!tab->page.free(&tab->page))
+		die();
+
+	ui_on_tab_refresh(tab);
 }
 
 static void
 handle_imsg_buf(struct imsg *imsg, size_t datalen)
 {
-	struct tab	*t;
+	struct tab	*tab;
 
-	t = tab_by_id(imsg->hdr.peerid);
+	tab = tab_by_id(imsg->hdr.peerid);
 
-	if (!t->page.parse(&t->page, imsg->data, datalen))
+	if (!tab->page.parse(&tab->page, imsg->data, datalen))
 		die();
 
-	ui_on_tab_refresh(t);
+	ui_on_tab_refresh(tab);
 }
 
 static void
@@ -145,12 +190,35 @@ dispatch_imsg(int fd, short ev, void *d)
 	}
 }
 
+static void
+load_page_from_str(struct tab *tab, const char *page)
+{
+	gemtext_initparser(&tab->page);
+	if (!tab->page.parse(&tab->page, about_new, strlen(about_new)))
+		die();
+	if (!tab->page.free(&tab->page))
+		die();
+	ui_on_tab_refresh(tab);
+}
+
+static void
+load_url(struct tab *tab, const char *url)
+{
+	if (!strcmp(url, "about:new")) {
+		load_page_from_str(tab, about_new);
+		return;
+	}
+
+	imsg_compose(ibuf, IMSG_GET, tab->id, 0, -1, url, strlen(url)+1);
+	imsg_flush(ibuf);
+}
+
 void
 new_tab(void)
 {
 	struct tab	*tab;
 	const char	*url = "about:new";
-	/* const char	*url = "gemini://localhost/cgi/slow-out"; */
+	/* const char	*url = "gemini://localhost.it/"; */
 
 	if ((tab = calloc(1, sizeof(*tab))) == NULL)
 		die();
@@ -159,12 +227,10 @@ new_tab(void)
 
 	tab->id = tab_counter++;
 	TAILQ_INIT(&tab->page.head);
-	gemtext_initparser(&tab->page);
 
-	imsg_compose(ibuf, IMSG_GET, tab->id, 0, -1, url, strlen(url)+1);
-	imsg_flush(ibuf);
-
 	ui_on_new_tab(tab);
+
+	load_url(tab, url);
 }
 
 int
blob - fba4108e1f8e0cf7637d6dce7f7e1c4d31f4f1dc
blob + 62c3fb3d9c04d0e9a9f20ab61f4ff9c1a0d92f87
--- telescope.h
+++ telescope.h
@@ -36,9 +36,10 @@ enum imsg_type {
 	IMSG_CERT_STATUS,
 	IMSG_GOT_CODE,
 	IMSG_GOT_META,
+	IMSG_PROCEED,
+	IMSG_STOP,
 	IMSG_BUF,
 	IMSG_EOF,
-	IMSG_STOP,
 	IMSG_QUIT,
 };
 
@@ -89,19 +90,27 @@ struct tab {
 	TAILQ_ENTRY(tab)	 tabs;
 	uint32_t		 id;
 	uint32_t		 flags;
+
+	int			 code;
+	char			 meta[GEMINI_URL_LEN];
+	int			 redirect_count;
 };
 
 extern struct event		 imsgev;
 
-/* about.c */
-extern const char	*about_new;
-
 /* gemini.c */
 int		 client_main(struct imsgbuf *b);
 
 /* gemtext.c */
 void		 gemtext_initparser(struct parser*);
 
+/* pages.c */
+extern const char	*about_new;
+
+#define CANNOT_FETCH		0
+#define TOO_MUCH_REDIRECTS	1
+extern const char	*err_pages[70];
+
 /* ui.c */
 int		 ui_init(void);
 void		 ui_on_new_tab(struct tab*);