ref: 594e3fdedb7a4d4fc78641199d764cefd4b43a2e
parent: 782b239c64d827cd98cfd9f1deb3cdbf1d818d75
author: grobe0ba <grobe0ba@tcp80.org>
date: Mon Aug 1 16:10:12 EDT 2022
integrate phil9s tcp80x
--- a/tcp80.c
+++ b/tcp80.c
@@ -2,6 +2,8 @@
#include <libc.h>
#include <ctype.h>
#include <auth.h>
+#include <bio.h>
+#include <regexp.h>
typedef struct Pair Pair;
typedef struct Ctype Ctype;
@@ -39,6 +41,53 @@
".css", "text/css;charset=utf-8",
};
+char *findrule(char *rulesfile, char *path) {
+ Biobuf *bio;
+ char *s, *p, *d, *r;
+ Reprog *re;
+ Resub m[16];
+
+ if ((bio = Bopen(rulesfile, OREAD)) == nil) sysfatal("open: %r");
+ while (s = Brdstr(bio, '\n', 1)) {
+ p = s;
+ while (strchr("\t ", *p)) p++;
+ d = nil;
+ if (*p != '#') {
+ if (d = strchr(p, '\t'))
+ *d++ = 0;
+ else if (d = strchr(p, ' '))
+ *d++ = 0;
+ }
+ if (d == nil) {
+ free(s);
+ continue;
+ }
+ while (strchr("\t ", *d)) d++;
+
+ if (re = regcomp(p)) {
+ memset(m, 0, sizeof(m));
+ if (regexec(re, path, m, nelem(m))) {
+ r = malloc(1024);
+ regsub(d, r, 1024, m, nelem(m));
+ free(s);
+ Bterm(bio);
+ return r;
+ }
+ }
+ free(s);
+ }
+ Bterm(bio);
+ return nil;
+}
+
+void dispatchrule(char *cmd) {
+ if (rfork(RFPROC | RFNOWAIT | RFFDG | RFREND) == 0) {
+ execl("/bin/rc", "rc", "-c", cmd, nil);
+ exits("exec");
+ }
+ exits(nil);
+}
+
Pair*
findhdr(Pair *h, char *key)
{
@@ -260,7 +309,7 @@
static char buf[1024];
snprint(buf, sizeof(buf), "%s%s%s%s%s%s",
- host ? "http://" : "", host ? host : "",
+ host ? "http://" : "", host ? host : "",
path ? path : "/", name ? name : "",
query ? "?" : "", query ? query : "");
return buf;
@@ -289,7 +338,7 @@
status = "405 Method Not Allowed";
Error:
if(!nobody)
- n = snprint(buf, sizeof(buf),
+ n = snprint(buf, sizeof(buf),
"<html><head><title>%s</title></head>\n"
"<body><h1>%s</h1><pre>%r</pre></body></html>\n",
status, status);
@@ -355,7 +404,7 @@
p = strchr(location, '?');
s = fullurl(h ? h->val : nil, urlenc(tmp, buf, sizeof(tmp)), "/", p ? p+1 : nil);
if(!nobody)
- n = snprint(buf, sizeof(buf),
+ n = snprint(buf, sizeof(buf),
"<html><head><title>%s</title></head>\n"
"<body><h1>%s</h1><pre>Moved to <a href=\"%s\">%s</a></pre></body></html>\n",
status, status, s, s);
@@ -391,12 +440,12 @@
goto Out;
print( "<html><head><title>%s</title></head><body>"
- "<pre>\n<a href=\"/%s\">/</a>",
+ "<pre>\n<a href=\"/%s\">/</a>",
buf, noindex ? "?noindex" : "");
for(p = buf+1; *p; p = s+1){
if(s = strchr(p, '/'))
*s = 0;
- print( "<a href=\"%s/%s\">%s</a>/",
+ print( "<a href=\"%s/%s\">%s</a>/",
urlenc(tmp, buf, sizeof(tmp)), noindex ? "?noindex" : "", p);
if(s == nil)
break;
@@ -409,7 +458,7 @@
if((n = dirreadall(fd, &d)) > 0){
qsort(d, n, sizeof d[0], (int (*)(void*, void*))dircmp);
for(i=0; i<n; i++)
- print("<a href=\"%s%s\">%s</a>%s\n",
+ print("<a href=\"%s%s\">%s</a>%s\n",
urlenc(tmp, d[i].name, sizeof(tmp)),
(d[i].qid.type & QTDIR) ? (noindex ? "/?noindex" : "/") : "",
d[i].name,
@@ -528,18 +577,74 @@
return s;
}
+int parsequery(void) {
+ static char buf[1024], line[1024];
+ char *p, *e, *k, *x, *s;
+ int lineno, n;
+ Pair *h;
+
+ naheader = 0;
+ lineno = 0;
+ *line = 0;
+ p = buf;
+ e = buf + sizeof(buf);
+ while ((n = read(0, p, e - p)) > 0) {
+ p += n;
+ while ((p > buf) && (e = memchr(buf, '\n', p - buf))) {
+ if ((e > buf) && (e[-1] == '\r')) e[-1] = 0;
+ *e++ = 0;
+ if (*buf != ' ' && *buf != '\t' && *line) {
+ if (lineno++ == 0) {
+ nstrcpy(method, token(line, "\t ", &s), sizeof(method));
+ nstrcpy(location, token(s, "\t ", nil), sizeof(location));
+ } else {
+ if (lineno > 100) return -1;
+ k = token(line, ":", &s);
+ while (*s) {
+ if (naheader >= nelem(aheader)) return -1;
+ x = token(s, ",", &s);
+ h = aheader + naheader++;
+ nstrcpy(h->key, k, sizeof(h->key));
+ nstrcpy(h->val, x, sizeof(h->val));
+ if (x = strchr(h->val, ';')) {
+ *x++ = 0;
+ x = token(x, ";", nil);
+ }
+ h->att = x;
+ h->next = header;
+ header = h;
+ }
+ }
+ }
+ nstrcpy(line, buf, sizeof(line));
+ p -= e - buf;
+ if (p > buf) memmove(buf, e, p - buf);
+ if (*line == 0) {
+ if (method[0] == 0) return -1;
+ return 0;
+ }
+ }
+ e = buf + sizeof(buf);
+ }
+ return -1;
+}
+
void
main(int argc, char **argv)
{
static char buf[1024], line[1024];
- char *p, *e, *k, *x, *s;
+ char *p, *e, *k, *x, *s, *r, *c;
int lineno, n;
Pair *h;
+ r = nil;
ARGBEGIN {
- case 't':
- trusted++;
- break;
+ case 'r':
+ r = ARGF();
+ break;
+ case 't':
+ trusted++;
+ break;
} ARGEND
time(0);
@@ -557,6 +662,25 @@
}
if(remote[0] == 0)
strcpy(remote, "-");
+
+ if(parsequery() < 0){
+ respond("400 Bad Request");
+ return;
+ }
+
+ if(r){
+ c = findrule(r, location);
+ if(c){
+ if(cistrcmp(method, "GET") != 0){
+ respond("405 Method Not Allowed");
+ return;
+ }
+ dispatchrule(c);
+ free(c);
+ return;
+ }
+ }
+
if(!trusted){
if(addns("none", "/lib/namespace.httpd") < 0)
return;
@@ -565,6 +689,7 @@
if(rfork(RFNOMNT) < 0)
return;
}
+
naheader = 0;
lineno = 0;
*line = 0;