133 lines · 2.8 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <libsec.h>#include <ctype.h>#include "gemnine.h" static char *statuses[] = {	[Cinput] = "input",	[Cinputnoecho] = "sensitive input",	[Csuccess] = "success",	[Credirtmp] = "redirect - temporary",	[Credirperm] = "redirect - permanent",	[Cfailtmp] = "temporary failure",	[Cunavail] = "server unavailable",	[Ccgierr] = "cgi error",	[Cproxyerr] = "proxy error",	[Cslowdown] = "slow down",	[Cfailperm] = "permanent failure",	[Cnotfound] = "not found",	[Cgone] = "gone",	[Cnoproxy] = "proxy request refused",	[Cbadrequest] = "bad request",	[Ccertrequired] = "client certificate required",	[Ccertnotauth] = "certificate not authorized",	[Ccertinvalid] = "certificate not valid",}; 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);		free(conn.cert);		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->code = 10*(int)(s[0]-'0') + s[1] - '0';	s += 2;	while(isspace(*s))		s++; 	if(r->code < nelem(statuses))		r->status = statuses[r->code];	if(r->status == nil)		r->status = "???"; 	if(r->code >= 10 && r->code < 20){ /* input */		r->prompt = estrdup(s);	}else if(r->code >= 20 && r->code < 30){ /* success */		r->mime = estrdup(s[0] ? s : "text/gemini");	}else if(r->code >= 30 && r->code < 40){ /* redirect */		if((u = urlparse(r->url, s)) == nil){			werrstr("invalid redirect");			goto err;		}		u->free = 1;		freeresponse(r);		r = request(u);	}else{		r->meta = estrdup(s);		werrstr(r->status);		goto err;	} err:	return r;} voidfreeresponse(Response *r){	if(r == nil)		return;	close(r->fd);	if(r->url->free)		freeurl(r->url);	free(r->mime);	free(r->prompt);	free(r->meta);	free(r);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t