shithub: gemnine

Download patch

ref: 3a91d0da6accefe72f46e3c7d149ef3d5cfd759e
parent: 54f4cf61dada165e94b3cd61f72a7003092e9867
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Aug 24 07:29:07 EDT 2020

fix queries, split request/response code

--- a/gemnine.h
+++ b/gemnine.h
@@ -1,7 +1,15 @@
+typedef struct Response Response;
 typedef struct Url Url;
 
-struct Url
-{
+struct Response {
+	Url *url;
+	char *mime;
+	char *prompt;
+	int status;
+	int fd;
+};
+
+struct Url {
 	char *full;
 	char *scheme;
 	char *user;
@@ -13,8 +21,21 @@
 	char *fragment;
 };
 
+typedef struct {
+	char *s1;
+	char *s2;
+}Str2;
+
 #pragma varargck type "U" Url*
+#pragma varargck type "E" Str2
+#pragma varargck type "N" char*
+#pragma varargck type "]" char*
 
+/* req.c */
+Response *request(Url *url);
+void freeresponse(Response *r);
+
+/* url.c */
 int	Efmt(Fmt*);
 int	Nfmt(Fmt*);
 int	Mfmt(Fmt*);
@@ -24,5 +45,6 @@
 void freeurl(Url *u);
 char *Upath(Url *u);
 
+/* util.c */
 void *emalloc(int n);
 char *estrdup(char *s);
--- a/main.c
+++ b/main.c
@@ -1,132 +1,10 @@
 #include <u.h>
 #include <libc.h>
-#include <libsec.h>
 #include <bio.h>
-#include <ctype.h>
 #include <plumb.h>
+#include <ctype.h>
 #include "gemnine.h"
 
-typedef struct Response Response;
-
-struct Response {
-	Url *url;
-	char *mime;
-	char *prompt;
-	int status;
-	int fd;
-};
-
-#pragma varargck type "E" char*
-
-void
-freeresponse(Response *r)
-{
-	if(r != nil){
-		close(r->fd);
-		freeurl(r->url);
-		free(r->mime);
-		free(r->prompt);
-		free(r);
-	}
-}
-
-Response *
-request(Url *url)
-{
-	Thumbprint *th;
-	Response *r;
-	char *s, buf[1024], *port;
-	TLSconn conn;
-	int i, ok, len, oldfd;
-	Url *u;
-
-	r = calloc(1, sizeof(*r));
-	r->fd = -1;
-	r->url = url;
-
-	if((port = url->port) == nil)
-		port = "1965";
-	if((r->fd = dial(netmkaddr(url->host, "tcp", port), nil, nil, nil)) < 0){
-		werrstr("dial: %r");
-		goto err;
-	}
-	th = initThumbprints("/sys/lib/ssl/gemini", nil, "x509");
-	memset(&conn, 0, sizeof(conn));
-	conn.serverName = r->url->host;
-	oldfd = r->fd;
-	r->fd = tlsClient(oldfd, &conn);
-	close(oldfd);
-	if(r->fd < 0){
-		werrstr("tls: %r");
-		goto err;
-	}
-
-	/* FIXME find a way to trust on the first run */
-	if(th != nil){
-		ok = okCertificate(conn.cert, conn.certlen, th);
-		freeThumbprints(th);
-		if(!ok){
-			//fprint(2, "echo 'x509 %r server=%s' >>/sys/lib/ssl/gemini\n", r->url->server);
-			//werrstr("untrusted cert");
-			//goto err;
-		}
-	}
-
-	fprint(r->fd, "%s\r\n", r->url->full);
-	for(len = 0; len < sizeof(buf)-1; len++){
-		if((i = read(r->fd, buf+len, 1)) < 0){
-			werrstr("read: %r");
-			goto err;
-		}
-		if(i == 0 || buf[len] == '\n')
-			break;
-	}
-
-	s = buf;
-	s[len] = 0;
-	for(len--; len >= 0 && (s[len] == '\r' || s[len] == '\n'); len--)
-		s[len] = 0;
-	if(s[0] < '0' || s[0] > '9' || s[1] < '0' || s[1] > '9'){
-		werrstr("invalid status");
-		goto err;
-	}
-	r->status = 10*(int)(s[0]-'0') + s[1] - '0';
-	s += 2;
-	while(isspace(*s))
-		s++;
-
-	if(r->status >= 10 && r->status < 20){ /* input */
-		r->prompt = estrdup(s);
-	}else if(r->status >= 20 && r->status < 30){ /* success */
-		r->mime = estrdup(s[0] ? s : "text/gemini");
-	}else if(r->status >= 30 && r->status < 40){ /* redirect */
-		if((u = urlparse(r->url, s)) == nil){
-			werrstr("invalid redirect url");
-			goto err;
-		}
-		freeresponse(r);
-		if((r = request(u)) == nil)
-			freeurl(u);
-	}else if(r->status >= 40 && r->status < 50){
-		werrstr("temporary failure: %s", s);
-		goto err;
-	}else if(r->status >= 50 && r->status < 60){
-		werrstr("permanent failure: %s", s);
-		goto err;
-	}else if(r->status >= 60 && r->status < 70){
-		werrstr("client cert required: %s", s);
-		goto err;
-	}
-
-	return r;
-
-err:
-	if(r != nil && r->url != nil)
-		werrstr("%U: %r", r->url);
-	freeresponse(r);
-	return nil;
-}
-
 char *
 readall(int fd)
 {
@@ -249,7 +127,7 @@
 				print("%s\n", r->prompt);
 				s = readall(0);
 				free(url);
-				t = smprint("%s?%E", r->url->full, s);
+				t = smprint("%s?%E", r->url->full, (Str2){s, "/:@ \n"});
 				free(s);
 				url = urlparse(nil, t);
 				free(t);
--- a/mkfile
+++ b/mkfile
@@ -9,6 +9,7 @@
 
 OFILES=\
 	main.$O\
+	req.$O\
 	url.$O\
 	util.$O\
 
--- /dev/null
+++ b/req.c
@@ -1,0 +1,114 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+#include <ctype.h>
+#include "gemnine.h"
+
+Response *
+request(Url *url)
+{
+	Thumbprint *th;
+	Response *r;
+	char *s, buf[1024], *port;
+	TLSconn conn;
+	int i, ok, len, oldfd;
+	Url *u;
+
+	r = calloc(1, sizeof(*r));
+	r->fd = -1;
+	r->url = url;
+
+	if((port = url->port) == nil)
+		port = "1965";
+	if((r->fd = dial(netmkaddr(url->host, "tcp", port), nil, nil, nil)) < 0){
+		werrstr("dial: %r");
+		goto err;
+	}
+	th = initThumbprints("/sys/lib/ssl/gemini", nil, "x509");
+	memset(&conn, 0, sizeof(conn));
+	conn.serverName = r->url->host;
+	oldfd = r->fd;
+	r->fd = tlsClient(oldfd, &conn);
+	close(oldfd);
+	if(r->fd < 0){
+		werrstr("tls: %r");
+		goto err;
+	}
+
+	/* FIXME find a way to trust on the first run */
+	if(th != nil){
+		ok = okCertificate(conn.cert, conn.certlen, th);
+		freeThumbprints(th);
+		if(!ok){
+			//fprint(2, "echo 'x509 %r server=%s' >>/sys/lib/ssl/gemini\n", r->url->server);
+			//werrstr("untrusted cert");
+			//goto err;
+		}
+	}
+
+	fprint(r->fd, "%s\r\n", r->url->full);
+	for(len = 0; len < sizeof(buf)-1; len++){
+		if((i = read(r->fd, buf+len, 1)) < 0){
+			werrstr("read: %r");
+			goto err;
+		}
+		if(i == 0 || buf[len] == '\n')
+			break;
+	}
+
+	s = buf;
+	s[len] = 0;
+	for(len--; len >= 0 && (s[len] == '\r' || s[len] == '\n'); len--)
+		s[len] = 0;
+	if(s[0] < '0' || s[0] > '9' || s[1] < '0' || s[1] > '9'){
+		werrstr("invalid status");
+		goto err;
+	}
+	r->status = 10*(int)(s[0]-'0') + s[1] - '0';
+	s += 2;
+	while(isspace(*s))
+		s++;
+
+	if(r->status >= 10 && r->status < 20){ /* input */
+		r->prompt = estrdup(s);
+	}else if(r->status >= 20 && r->status < 30){ /* success */
+		r->mime = estrdup(s[0] ? s : "text/gemini");
+	}else if(r->status >= 30 && r->status < 40){ /* redirect */
+		if((u = urlparse(r->url, s)) == nil){
+			werrstr("invalid redirect url");
+			goto err;
+		}
+		freeresponse(r);
+		if((r = request(u)) == nil)
+			freeurl(u);
+	}else if(r->status >= 40 && r->status < 50){
+		werrstr("temporary failure: %s", s);
+		goto err;
+	}else if(r->status >= 50 && r->status < 60){
+		werrstr("permanent failure: %s", s);
+		goto err;
+	}else if(r->status >= 60 && r->status < 70){
+		werrstr("client cert required: %s", s);
+		goto err;
+	}
+
+	return r;
+
+err:
+	if(r != nil && r->url != nil)
+		werrstr("%U: %r", r->url);
+	freeresponse(r);
+	return nil;
+}
+
+void
+freeresponse(Response *r)
+{
+	if(r != nil){
+		close(r->fd);
+		freeurl(r->url);
+		free(r->mime);
+		free(r->prompt);
+		free(r);
+	}
+}
--- a/url.c
+++ b/url.c
@@ -8,15 +8,6 @@
 	Domlen = 256,
 };
 
-typedef struct {
-	char *s1;
-	char *s2;
-}Str2;
-
-#pragma varargck type "E" Str2
-#pragma varargck type "N" char*
-#pragma varargck type "]" char*
-
 static char reserved[] = "%:/?#[]@!$&'()*+,;=";
 
 static int