diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-09-05 03:29:26 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-09-05 03:29:26 +0200 |
commit | aa9097b4bbf566504c80689fa45b2e82aad56c36 (patch) | |
tree | bf17b5710a4c7d21e20457e9ac218096677d59ef | |
parent | 1a10c36b88d9acdd7edcb33a09525b74875cc1fa (diff) |
mothra: remove ftp,gopher,file and http code and use /mnt/web instead
-rw-r--r-- | sys/src/cmd/mothra/auth.c | 68 | ||||
-rw-r--r-- | sys/src/cmd/mothra/cistr.c | 29 | ||||
-rw-r--r-- | sys/src/cmd/mothra/crackurl.c | 188 | ||||
-rw-r--r-- | sys/src/cmd/mothra/file.c | 48 | ||||
-rw-r--r-- | sys/src/cmd/mothra/filetype.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/mothra/forms.c | 22 | ||||
-rw-r--r-- | sys/src/cmd/mothra/ftp.c | 428 | ||||
-rw-r--r-- | sys/src/cmd/mothra/getpix.c | 49 | ||||
-rw-r--r-- | sys/src/cmd/mothra/gopher.c | 38 | ||||
-rw-r--r-- | sys/src/cmd/mothra/gopher2html.c | 230 | ||||
-rw-r--r-- | sys/src/cmd/mothra/help.html | 78 | ||||
-rw-r--r-- | sys/src/cmd/mothra/http.c | 486 | ||||
-rw-r--r-- | sys/src/cmd/mothra/libpanel/mem.c | 1 | ||||
-rw-r--r-- | sys/src/cmd/mothra/mkfile | 7 | ||||
-rw-r--r-- | sys/src/cmd/mothra/mothra.c | 251 | ||||
-rw-r--r-- | sys/src/cmd/mothra/mothra.h | 39 | ||||
-rw-r--r-- | sys/src/cmd/mothra/rdhtml.c | 7 | ||||
-rw-r--r-- | sys/src/cmd/mothra/urlcanon.c | 70 | ||||
-rw-r--r-- | sys/src/cmd/mothra/version.c | 2 |
19 files changed, 162 insertions, 1881 deletions
diff --git a/sys/src/cmd/mothra/auth.c b/sys/src/cmd/mothra/auth.c deleted file mode 100644 index 3e99e6324..000000000 --- a/sys/src/cmd/mothra/auth.c +++ /dev/null @@ -1,68 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <event.h> -#include <panel.h> -#include <bio.h> -#include "mothra.h" - -static int -basicauth(char *arg, char *str, int n) -{ - int i; - char *p; - char buf[1024]; - Biobuf *b; - - if(strncmp(arg, "realm=", 6) == 0) - arg += 6; - if(*arg == '"'){ - arg++; - for(p = arg; *p && *p != '"'; p++); - *p = 0; - } else { - for(p = arg; *p && *p != ' ' && *p != '\t'; p++); - *p = 0; - } - - p = getenv("home"); - if(p == 0){ - werrstr("$home not set"); - return -1; - } - snprint(buf, sizeof(buf), "%s/lib/mothra/insecurity", p); - b = Bopen(buf, OREAD); - if(b == 0){ - werrstr("www password file %s: %r", buf); - return -1; - } - - i = strlen(arg); - while(p = Brdline(b, '\n')) - if(strncmp(arg, p, i) == 0 && p[i] == '\t') - break; - if(p == 0){ - Bterm(b); - werrstr("no basic password for domain `%s'", arg); - return -1; - } - - p[Blinelen(b)-1] = 0; - for(p += i; *p == '\t'; p++); - if (enc64(buf, sizeof buf, (uchar*)p, strlen(p)) < 0) { - Bterm(b); - werrstr("password too long: %s", p); - return -1; - } - snprint(str, n, "Authorization: Basic %s\r\n", buf); - return 0; -} - -int -auth(Url *url, char *str, int n) -{ - if(cistrcmp(url->authtype, "basic") == 0) - return basicauth(url->autharg, str, n); - werrstr("unknown auth method %s", url->authtype); - return -1; -} diff --git a/sys/src/cmd/mothra/cistr.c b/sys/src/cmd/mothra/cistr.c deleted file mode 100644 index f6aec8681..000000000 --- a/sys/src/cmd/mothra/cistr.c +++ /dev/null @@ -1,29 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <event.h> -#include <panel.h> -#include <ctype.h> -#include "mothra.h" -int cistrcmp(char *s1, char *s2){ - int c1, c2; - - for(; *s1; s1++, s2++){ - c1 = isupper(*s1) ? tolower(*s1) : *s1; - c2 = isupper(*s2) ? tolower(*s2) : *s2; - if (c1 < c2) return -1; - if (c1 > c2) return 1; - } - return 0; -} -int cistrncmp(char *s1, char *s2, int n){ - int c1, c2; - - for(; *s1 && n!=0; s1++, s2++, --n){ - c1 = isupper(*s1) ? tolower(*s1) : *s1; - c2 = isupper(*s2) ? tolower(*s2) : *s2; - if (c1 < c2) return -1; - if (c1 > c2) return 1; - } - return 0; -} diff --git a/sys/src/cmd/mothra/crackurl.c b/sys/src/cmd/mothra/crackurl.c deleted file mode 100644 index f04f42575..000000000 --- a/sys/src/cmd/mothra/crackurl.c +++ /dev/null @@ -1,188 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <event.h> -#include <panel.h> -#include <ctype.h> -#include "mothra.h" -enum{ - IP=1, /* url can contain //ipaddress[:port] */ - REL=2, /* fill in ip address & root of name from current, if necessary */ - SSL=4, /* use SSL/TLS encryption */ -}; -Scheme scheme[]={ - "http:", HTTP, IP|REL, 80, - "https:", HTTP, IP|REL|SSL, 443, - "ftp:", FTP, IP|REL, 21, - "file:", FILE, REL, 0, - "telnet:", TELNET, IP, 0, - "mailto:", MAILTO, 0, 0, - "gopher:", GOPHER, IP, 70, - 0, HTTP, IP|REL, 80, -}; -int endaddr(int c){ - return c=='/' || c==':' || c=='?' || c=='#' || c=='\0'; -} -/* - * Remove ., mu/.. and empty components from path names. - * Empty last components of urls are significant, and - * therefore preserved. - */ -void urlcanon(char *name){ - char *s, *t; - char **comp, **p, **q; - int rooted; - rooted=name[0]=='/'; - /* - * Break the name into a list of components - */ - comp=emalloc((strlen(name)+2)*sizeof(char *)); - p=comp; - *p++=name; - for(s=name;;s++){ - if(*s=='/'){ - *p++=s+1; - *s='\0'; - } - else if(*s=='\0' || *s=='?') - break; - } - *p=0; - /* - * go through the component list, deleting components that are empty (except - * the last component) or ., and any .. and its non-.. predecessor. - */ - p=q=comp; - while(*p){ - if(strcmp(*p, "")==0 && p[1]!=0 - || strcmp(*p, ".")==0) - p++; - else if(strcmp(*p, "..")==0 && q!=comp && strcmp(q[-1], "..")!=0){ - --q; - p++; - } - else - *q++=*p++; - } - *q=0; - /* - * rebuild the path name - */ - s=name; - if(rooted) *s++='/'; - for(p=comp;*p;p++){ - t=*p; - while(*t) *s++=*t++; - if(p[1]!=0) *s++='/'; - } - *s='\0'; - free(comp); -} -/* - * True url parsing is a nightmare. - * This assumes that there are two basic syntaxes - * for url's -- with and without an ip address. - * If the type identifier or the ip address and port number - * or the relative address is missing from urlname or is empty, - * it is copied from cur. - */ -void crackurl(Url *url, char *urlname, Url *cur){ - char *relp, *tagp, *httpname; - int len; - Scheme *up; - char buf[30]; - /* - * The following lines `fix' the most egregious urlname syntax errors - */ - while(*urlname==' ' || *urlname=='\t' || *urlname=='\n') urlname++; - relp=strchr(urlname, '\n'); - if(relp) *relp='\0'; - /* - * In emulation of Netscape, attach a free "http://" - * to names beginning with "www.". - */ - if(strncmp(urlname, "www.", 4)==0){ - httpname=emalloc(strlen(urlname)+8); - strcpy(httpname, "http://"); - strcat(httpname, urlname); - crackurl(url, httpname, cur); - free(httpname); - return; - } - url->port=cur->port; - strncpy(url->ipaddr, cur->ipaddr, sizeof(url->ipaddr)); - strncpy(url->reltext, cur->reltext, sizeof(url->reltext)); - if(strchr(urlname, ':')==0){ - up=cur->scheme; - if(up==0){ - up=&scheme[0]; - cur->scheme=up; - } - } - else{ - for(up=scheme;up->name;up++){ - len=strlen(up->name); - if(strncmp(urlname, up->name, len)==0){ - urlname+=len; - break; - } - } - if(up->name==0) up=&scheme[0]; /* default to http: */ - } - url->access=up->type; - url->scheme=up; - if(up!=cur->scheme) - url->reltext[0]='\0'; - if(up->flags&IP && strncmp(urlname, "//", 2)==0){ - urlname+=2; - for(relp=urlname;!endaddr(*relp);relp++); - len=relp-urlname; - strncpy(url->ipaddr, urlname, len); - url->ipaddr[len]='\0'; - urlname=relp; - if(*urlname==':'){ - urlname++; - url->port=atoi(urlname); - while(!endaddr(*urlname)) urlname++; - } - else - url->port=up->port; - if(*urlname=='\0') urlname="/"; - } - url->ssl = up->flags&SSL; - - tagp=strchr(urlname, '#'); - if(tagp){ - *tagp='\0'; - strncpy(url->tag, tagp+1, sizeof(url->tag)); - } - else - url->tag[0]='\0'; - if(!(up->flags&REL) || *urlname=='/') - strncpy(url->reltext, urlname, sizeof(url->reltext)); - else if(urlname[0]){ - relp=strrchr(url->reltext, '/'); - if(relp==0) - strncpy(url->reltext, urlname, sizeof(url->reltext)); - else - strcpy(relp+1, urlname); - } - urlcanon(url->reltext); - if(tagp) *tagp='#'; - /* - * The following mess of strcpys and strcats - * can't be changed to a few sprints because - * urls are not necessarily composed of legal utf - */ - strcpy(url->fullname, up->name); - if(up->flags&IP){ - strncat(url->fullname, "//", sizeof(url->fullname)); - strncat(url->fullname, url->ipaddr, sizeof(url->fullname)); - if(url->port!=up->port){ - snprint(buf, sizeof(buf), ":%d", url->port); - strncat(url->fullname, buf, sizeof(url->fullname)); - } - } - strcat(url->fullname, url->reltext); - url->map=0; -} diff --git a/sys/src/cmd/mothra/file.c b/sys/src/cmd/mothra/file.c deleted file mode 100644 index 50ae60f25..000000000 --- a/sys/src/cmd/mothra/file.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <event.h> -#include <panel.h> -#include "mothra.h" -/* - * fd is the result of a successful open(name, OREAD), - * where name is the name of a directory. We convert - * this into an html page containing links to the files - * in the directory. - */ -int dir2html(char *name, int fd){ - int p[2], first; - Dir *dir; - int i, n; - if(pipe(p)==-1){ - close(fd); - return -1; - } - switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ - case -1: - close(fd); - return -1; - case 0: - close(p[1]); - fprint(p[0], "<head>\n"); - fprint(p[0], "<title>Directory %s</title>\n", name); - fprint(p[0], "</head>\n"); - fprint(p[0], "<body>\n"); - fprint(p[0], "<h1>%s</h1>\n", name); - fprint(p[0], "<ul>\n"); - first=1; - while((n = dirread(fd, &dir)) > 0) { - for (i = 0; i < n; i++) - fprint(p[0], "<li><a href=\"%s/%s\">%s%s</a>\n", name, dir[i].name, dir[i].name, - dir[i].mode&DMDIR?"/":""); - free(dir); - } - fprint(p[0], "</ul>\n"); - fprint(p[0], "</body>\n"); - _exits(0); - default: - close(fd); - close(p[0]); - return p[1]; - } -} diff --git a/sys/src/cmd/mothra/filetype.c b/sys/src/cmd/mothra/filetype.c index 71ae92bed..c71e87726 100644 --- a/sys/src/cmd/mothra/filetype.c +++ b/sys/src/cmd/mothra/filetype.c @@ -86,7 +86,7 @@ Kind content[]={ "application/pdf", PDF, "application/octet-stream", SUFFIX, "application/zip", ZIP, - 0, HTML + 0, SUFFIX }; int content2type(char *s, char *name){ int type; diff --git a/sys/src/cmd/mothra/forms.c b/sys/src/cmd/mothra/forms.c index 5e08a3242..6e0775759 100644 --- a/sys/src/cmd/mothra/forms.c +++ b/sys/src/cmd/mothra/forms.c @@ -12,7 +12,7 @@ typedef struct Field Field; typedef struct Option Option; struct Form{ int method; - Url *action; + char *action; Field *fields, *efields; Form *next; }; @@ -98,12 +98,8 @@ void rdform(Hglob *g){ break; } g->form=emallocz(sizeof(Form), 1); - g->form->action=emalloc(sizeof(Url)); s=pl_getattr(g->attr, "action"); - if(s==0) - *g->form->action=*g->dst->url; - else - crackurl(g->form->action, s, g->dst->base); + g->form->action=strdup((s && s[0]) ? s : g->dst->url->fullname); s=pl_getattr(g->attr, "method"); if(s==0) g->form->method=GET; @@ -268,12 +264,8 @@ void rdform(Hglob *g){ form=emalloc(sizeof(Form)); form->fields=0; form->efields=0; - form->action=emalloc(sizeof(Url)); s=pl_getattr(g->attr, "action"); - if(s==0) - *form->action=*g->dst->url; - else - crackurl(form->action, s, g->dst->base); + form->action=strdup((s && s[0]) ? s : g->dst->url->fullname); form->method=GET; form->fields=0; f=newfield(form); @@ -537,7 +529,7 @@ void h_submitinput(Panel *p, int){ Field *f; Option *o; form=((Field *)p->userp)->form; - if(form->method==GET) size=ulen(form->action->fullname)+1; + if(form->method==GET) size=ulen(form->action)+1; else size=1; for(f=form->fields;f;f=f->next) switch(f->type){ case TYPEIN: @@ -564,7 +556,7 @@ void h_submitinput(Panel *p, int){ } buf=emalloc(size); if(form->method==GET){ - strcpy(buf, form->action->fullname); + strcpy(buf, form->action); sep='?'; } else{ @@ -623,8 +615,8 @@ fprint(2, "GET %s\n", buf); geturl(buf, GET, 0, 0, 0); } else{ -fprint(2, "POST %s: %s\n", form->action->fullname, buf); - geturl(form->action->fullname, POST, buf, 0, 0); +fprint(2, "POST %s: %s\n", form->action, buf); + geturl(form->action, POST, buf, 0, 0); } free(buf); } diff --git a/sys/src/cmd/mothra/ftp.c b/sys/src/cmd/mothra/ftp.c deleted file mode 100644 index 78c3ab5da..000000000 --- a/sys/src/cmd/mothra/ftp.c +++ /dev/null @@ -1,428 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <event.h> -#include <panel.h> -#include <bio.h> -#include <ndb.h> -#include <ctype.h> -#include <ip.h> -#include "mothra.h" - -enum -{ - /* return codes */ - Extra= 1, - Success= 2, - Incomplete= 3, - TempFail= 4, - PermFail= 5, - - NAMELEN= 28, - Nnetdir= 3*NAMELEN, /* max length of network directory paths */ - Ndialstr= 64, /* max length of dial strings */ -}; - -typedef struct Ftp Ftp; -struct Ftp -{ - char net[Nnetdir]; - Biobuf *ftpctl; - Url *u; -}; - -static int ftpdebug; - - -/* - * read from biobuf turning cr/nl into nl - */ -char* -getcrnl(Biobuf *b) -{ - char *p, *ep; - - p = Brdline(b, '\n'); - if(p == nil) - return nil; - ep = p + Blinelen(b) - 1; - if(*(ep-1) == '\r') - ep--; - *ep = 0; - return p; -} - -char* -readfile(char *file, char *buf, int len) -{ - int n, fd; - - fd = open(file, OREAD); - if(fd < 0) - return nil; - n = read(fd, buf, len-1); - close(fd); - if(n <= 0) - return nil; - buf[n] = 0; - return buf; -} - -char* -sysname(void) -{ - static char sys[Ndbvlen]; - char *p; - - p = readfile("/dev/sysname", sys, sizeof(sys)); - if(p == nil) - return "unknown"; - return p; -} - -char* -domainname(void) -{ - static char domain[Ndbvlen]; - Ndbtuple *t; - - if(*domain) - return domain; - - t = csgetval(0, "sys", sysname(), "dom", domain); - if(t){ - ndbfree(t); - return domain; - } else - return sysname(); -} - -static int -sendrequest(Biobuf *b, char *fmt, ...) -{ - char buf[2*1024], *s; - va_list args; - - va_start(args, fmt); - s = buf + vsnprint(buf, (sizeof(buf)-4) / sizeof(*buf), fmt, args); - va_end(args); - *s++ = '\r'; - *s++ = '\n'; - if(write(Bfildes(b), buf, s - buf) != s - buf) - return -1; - if(ftpdebug) - write(2, buf, s - buf); - return 0; -} - -static int -getreply(Biobuf *b, char *msg, int len) -{ - char *line; - int rv; - int i, n; - - while(line = getcrnl(b)){ - /* add line to message buffer, strip off \r */ - n = Blinelen(b); - if(ftpdebug) - write(2, line, n); - if(n > len - 1) - i = len - 1; - else - i = n; - if(i > 0){ - memmove(msg, line, i); - msg += i; - len -= i; - *msg = 0; - } - - /* stop if not a continuation */ - rv = atoi(line); - if(rv >= 100 && rv < 600 && (n == 4 || (n > 4 && line[3] == ' '))) - return rv/100; - } - - return -1; -} - -int -terminateftp(Ftp *d) -{ - if(d->ftpctl){ - close(Bfildes(d->ftpctl)); - Bterm(d->ftpctl); - free(d->ftpctl); - d->ftpctl = nil; - } - free(d); - return -1; -} - -Biobuf* -hello(Ftp *d) -{ - int fd; - char *p; - Biobuf *b; - char msg[1024]; - char ndir[Nnetdir]; - - snprint(msg, sizeof msg, "tcp!%s!%d", d->u->ipaddr, d->u->port); - fd = dial(msg, 0, ndir, 0); - if(fd < 0){ - d->ftpctl = nil; - return nil; - } - b = emalloc(sizeof(Biobuf)); - Binit(b, fd, OREAD); - d->ftpctl = b; - - /* remember network for the data connections */ - p = strrchr(ndir, '/'); - if(p == 0){ - fprint(2, "dial is out of date\n"); - return nil; - } - *p = 0; - strcpy(d->net, ndir); - - /* wait for hello from other side */ - if(getreply(b, msg, sizeof(msg)) != Success){ - fprint(2, "instead of hello: %s\n", msg); - return nil; - } - return b; -} - -int -logon(Ftp *d) -{ - char msg[1024]; - - /* login anonymous */ - sendrequest(d->ftpctl, "USER anonymous"); - switch(getreply(d->ftpctl, msg, sizeof(msg))){ - case Success: - return 0; - case Incomplete: - break; /* need password */ - default: - fprint(2, "login failed: %s\n", msg); - werrstr(msg); - return -1; - } - - /* send user id as password */ - sprint(msg, "%s@", getuser()); - sendrequest(d->ftpctl, "PASS %s", msg); - if(getreply(d->ftpctl, msg, sizeof(msg)) != Success){ - fprint(2, "login failed: %s\n", msg); - werrstr(msg); - return -1; - } - - return 0; -} - -int -xfertype(Ftp *d, char *t) -{ - char msg[1024]; - - sendrequest(d->ftpctl, "TYPE %s", t); - if(getreply(d->ftpctl, msg, sizeof(msg)) != Success){ - fprint(2, "can't set type %s: %s\n", t, msg); - werrstr(msg); - return -1; - } - return 0; -} - -int -passive(Ftp *d) -{ - char msg[1024]; - char dialstr[Ndialstr]; - char *f[6]; - char *p; - int fd; - - sendrequest(d->ftpctl, "PASV"); - if(getreply(d->ftpctl, msg, sizeof(msg)) != Success) - return -1; - - /* get address and port number from reply, this is AI */ - p = strchr(msg, '('); - if(p == nil){ - for(p = msg+3; *p; p++) - if(isdigit(*p)) - break; - } else - p++; - if(getfields(p, f, 6, 0, ",") < 6){ - fprint(2, "passive mode protocol botch: %s\n", msg); - werrstr("ftp protocol botch"); - return -1; - } - snprint(dialstr, sizeof(dialstr), "%s!%s.%s.%s.%s!%d", d->net, - f[0], f[1], f[2], f[3], - ((atoi(f[4])&0xff)<<8) + (atoi(f[5])&0xff)); - - - /* open data connection */ - fd = dial(dialstr, 0, 0, 0); - if(fd < 0){ - fprint(2, "passive mode connect to %s failed: %r\n", dialstr); - return -1; - } - - /* tell remote to send a file */ - sendrequest(d->ftpctl, "RETR %s", d->u->reltext); - if(getreply(d->ftpctl, msg, sizeof(msg)) != Extra){ - fprint(2, "passive mode retrieve failed: %s\n", msg); - werrstr(msg); - return -1; - } - return fd; -} - -int -active(Ftp *d) -{ - char msg[1024]; - char buf[Ndialstr]; - char netdir[Nnetdir]; - char newdir[Nnetdir]; - uchar ipaddr[4]; - int dfd, cfd, listenfd; - char *p; - int port; - - /* get a channel to listen on, let kernel pick the port number */ - sprint(buf, "%s!*!0", d->net); - listenfd = announce(buf, netdir); - if(listenfd < 0){ - fprint(2, "can't listen for ftp callback: %r\n", buf); - return -1; - } - - /* get the local address and port number */ - sprint(newdir, "%s/local", netdir); - readfile(newdir, buf, sizeof buf); - p = strchr(buf, '!')+1; - parseip(ipaddr, buf); - port = atoi(p); - - /* tell remote side address and port*/ - sendrequest(d->ftpctl, "PORT %d,%d,%d,%d,%d,%d", ipaddr[0], ipaddr[1], ipaddr[2], - ipaddr[3], port>>8, port&0xff); - if(getreply(d->ftpctl, msg, sizeof(msg)) != Success){ - close(listenfd); - werrstr("ftp protocol botch"); - fprint(2, "active mode connect failed %s\n", msg); - return -1; - } - - /* tell remote to send a file */ - sendrequest(d->ftpctl, "RETR %s", d->u->reltext); - if(getreply(d->ftpctl, msg, sizeof(msg)) != Extra){ - close(listenfd); - fprint(2, "active mode connect failed: %s\n", msg); - werrstr(msg); - return -1; - } - - /* wait for a new call */ - cfd = listen(netdir, newdir); - close(listenfd); - if(cfd < 0){ - fprint(2, "active mode connect failed: %r\n"); - return -1; - } - - /* open the data connection and close the control connection */ - dfd = accept(cfd, newdir); - close(cfd); - if(dfd < 0){ - fprint(2, "active mode connect failed: %r\n"); - werrstr("ftp protocol botch"); - return -1; - } - - return dfd; -} - -/* - * Given a url, return a file descriptor on which caller can - * read an ftp document. - * The caller is responsible for processing redirection loops. - */ -int -ftp(Url *url) -{ - int n; - int data; - Ftp *d; - int pfd[2]; - char buf[2048]; - - if(url->type == 0) - url->type = PLAIN; - - d = (Ftp*)emalloc(sizeof(Ftp)); - d->u = url; - d->ftpctl = nil; - - if(hello(d) == nil) - return terminateftp(d); - if(logon(d) < 0) - return terminateftp(d); - - switch(url->type){ - case PLAIN: - case HTML: - if(xfertype(d, "A") < 0) - return terminateftp(d); - break; - default: - if(xfertype(d, "I") < 0) - return terminateftp(d); - break; - } - - /* first try passive mode, then active */ - data = passive(d); - if(data < 0){ - if(d->ftpctl == nil) - return -1; - data = active(d); - if(data < 0) - return -1; - } - - if(pipe(pfd) < 0) - return -1; - - switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ - case -1: - werrstr("Can't fork"); - close(pfd[0]); - close(pfd[1]); - return terminateftp(d); - case 0: - close(pfd[0]); - while((n=read(data, buf, sizeof(buf)))>0) - write(pfd[1], buf, n); - if(n<0) - fprint(2, "ftp: %s: %r\n", url->fullname); - _exits(0); - default: - close(pfd[1]); - close(data); - terminateftp(d); - return pfd[0]; - } - return -1; -} diff --git a/sys/src/cmd/mothra/getpix.c b/sys/src/cmd/mothra/getpix.c index 19e2b8b23..10e7b7467 100644 --- a/sys/src/cmd/mothra/getpix.c +++ b/sys/src/cmd/mothra/getpix.c @@ -39,7 +39,7 @@ void getimage(Rtext *t, Www *w){ Pix *p; ap=t->user; - crackurl(&url, ap->image, w->base); + seturl(&url, ap->image, w->url->fullname); for(p=w->pix;p!=nil; p=p->next) if(strcmp(ap->image, p->name)==0 && ap->width==p->width && ap->height==p->height){ storebitmap(t, p->b); @@ -105,12 +105,55 @@ void getimage(Rtext *t, Www *w){ } void getpix(Rtext *t, Www *w){ + int i, pid, nworker, worker[NXPROC]; Action *ap; + nworker = 0; + for(i=0; i<nelem(worker); i++) + worker[i] = -1; + for(;t!=0;t=t->next){ ap=t->user; - if(ap && ap->image) - getimage(t, w); + if(ap && ap->image){ + pid = rfork(RFFDG|RFPROC|RFMEM); + switch(pid){ + case -1: + fprint(2, "fork: %r\n"); + break; + case 0: + getimage(t, w); + exits(0); + default: + for(i=0; i<nelem(worker); i++) + if(worker[i] == -1){ + worker[i] = pid; + nworker++; + break; + } + + while(nworker == nelem(worker)){ + if((pid = waitpid()) < 0) + break; + for(i=0; i<nelem(worker); i++) + if(worker[i] == pid){ + worker[i] = -1; + nworker--; + break; + } + } + } + + } + } + while(nworker > 0){ + if((pid = waitpid()) < 0) + break; + for(i=0; i<nelem(worker); i++) + if(worker[i] == pid){ + worker[i] = -1; + nworker--; + break; + } } } diff --git a/sys/src/cmd/mothra/gopher.c b/sys/src/cmd/mothra/gopher.c deleted file mode 100644 index 2e231eae6..000000000 --- a/sys/src/cmd/mothra/gopher.c +++ /dev/null @@ -1,38 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <event.h> -#include <panel.h> -#include "mothra.h" -void httpheader(Url *, char *); -/* - * Given a url, return a file descriptor on which caller can - * read a gopher document. - */ -int gopher(Url *url){ - int pfd[2]; - char port[30]; - if(pipe(pfd)==-1) return -1; - switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ - case -1: - close(pfd[0]); - close(pfd[1]); - return -1; - case 0: - dup(pfd[1], 1); - close(pfd[0]); - close(pfd[1]); - sprint(port, "%d", url->port); - execl("/bin/aux/gopher2html", - "gopher2html", url->ipaddr, port, url->reltext+1, 0); - fprint(2, "Can't exec aux/gopher2html!\n"); - print("<head><title>Mothra error</title></head>\n"); - print("<body><h1>Mothra error</h1>\n"); - print("Can't exec aux/gopher2html!</body>\n"); - exits("no exec"); - default: - close(pfd[1]); - url->type=HTML; - return pfd[0]; - } -} diff --git a/sys/src/cmd/mothra/gopher2html.c b/sys/src/cmd/mothra/gopher2html.c deleted file mode 100644 index e0c57d736..000000000 --- a/sys/src/cmd/mothra/gopher2html.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Reads gopher output from a TCP port, outputs - * html on standard output. - * Usage: gopher2html gopher-string - * where gopher-string is the string sent to - * the gopher server to get the document. - * - * Gopher protocol is described in rfc1436 - */ -#include <u.h> -#include <libc.h> -char *cmd; -int ifd; -void errexit(char *s, ...){ - static char buf[1024]; - char *out; - va_list args; - va_start(args, s); - out = doprint(buf, buf+sizeof(buf), s, args); - va_end(args); - *out='\0'; - print("<head><title>%s error</title></head>\n", cmd); - print("<body><h1>%s error</h1>\n", cmd); - print("%s</body>\n", buf); - exits("gopher error"); -} -void wtext(char *buf, char *ebuf){ - char *bp; - for(bp=buf;bp!=ebuf;bp++){ - if(*bp=='<' || *bp=='>' || *bp=='&' || *bp=='"'){ - if(bp!=buf) write(1, buf, bp-buf); - buf=bp+1; - switch(*bp){ - case '<': print("<"); break; - case '>': print(">"); break; - case '&': print("&"); break; - case '"': print("""); break; - } - } - } - if(bp!=buf) write(1, buf, bp-buf); -} -void savefile(char *name, char *type){ - int fd, n; - char save[30], buf[1024]; - for(n=1;;n++){ - if(n==100) errexit("can't save binary file %s: %r", name); - sprint(save, "gopher.save.%d", n); - fd=create(save, OWRITE, 0444); - if(fd!=-1) break; - } - print("<head><title>%s</title></head\n", name); - print("<body><h1>%s</h1><p>\n", name); - print("Saving %s file %s in <tt>%s</tt>...\n", type, name, save); - while((n=read(ifd, buf, sizeof buf))>0) write(fd, buf, n); - close(fd); - print("done</body>\n"); -} -void copyfile(char *title){ - char buf[1024]; - int n; - print("<head><title>%s</title></head>\n", title); - print("<body><h1>%s</h1><pre>\n", title); - while((n=read(ifd, buf, sizeof buf))>0) wtext(buf, buf+n); - print("</pre></body>\n"); -} -/* - * A directory entry contains - * type name selector host port - * all tab separated, except type and name (type is one character) - */ -char ibuf[1024], *ibp, *eibuf; -#define EOF (-1) -int get(void){ - int n; -Again: - if(ibp==eibuf){ - n=read(ifd, ibuf, sizeof(ibuf)); - if(n<=0) return EOF; - eibuf=ibuf+n; - ibp=ibuf; - } - if(*ibp=='\r'){ - ibp++; - goto Again; - } - return *ibp++&255; -} -char *escape(char *in){ - static char out[516]; - char *op, *eop; - eop=out+512; - op=out; - for(;*in;in++){ - if(op<eop){ - if(strchr("/$-_@.&!*'(),", *in) - || 'a'<=*in && *in<='z' - || 'A'<=*in && *in<='Z' - || '0'<=*in && *in<='9') - *op++=*in; - else{ - sprint(op, "%%%.2X", *in&255); - op+=3; - } - } - } - *op='\0'; - return out; -} -void copydir(char *title){ - int type, c; - char name[513], *ename; - char selector[513]; - char host[513]; - char port[513]; - char *bp; - print("<head><title>%s</title></head>\n", title); - print("<body><h1>%s</h1><ul>\n", title); - for(;;){ - type=get(); - if(type==EOF || type=='.') break; - bp=name; - while((c=get())!=EOF && c!='\t') if(bp!=&name[512]) *bp++=c; - ename=bp; - bp=selector; - while((c=get())!=EOF && c!='\t') if(bp!=&selector[512]) *bp++=c; - *bp='\0'; - bp=host; - while((c=get())!=EOF && c!='\t') if(bp!=&host[512]) *bp++=c; - *bp='\0'; - bp=port; - while((c=get())!=EOF && c!='\t' && c!='\n') if(bp!=&port[512]) *bp++=c; - while(c!=EOF && c!='\n') c=get(); - *bp='\0'; - switch(type){ - case '3': - print("<li>"); - wtext(name, ename); - break; - case '7': - print("<li><isindex action=\"gopher://%s:%s/%c%s\">", - host, port, type, escape(selector)); - wtext(name, ename); - break; - default: - print("<li><a href=\"gopher://%s:%s/%c%s\">", - host, port, type, escape(selector)); - wtext(name, ename); - print("</a>\n"); - break; - } - } - print("</ul></body>\n"); -} -int hexdigit(int c){ - if('0'<=c && c<='9') return c-'0'; - if('a'<=c && c<='f') return c-'a'+10; - if('A'<=c && c<='F') return c-'A'+10; - return -1; -} -void unescape(char *s){ - char *t; - int hi, lo; - t=s; - while(*s){ - if(*s=='%' - && (hi=hexdigit(s[1]))>=0 - && (lo=hexdigit(s[2]))>=0){ - *t++=hi*16+lo; - s+=3; - } - else *t++=*s++; - } - *t='\0'; -} -void main(int argc, char *argv[]){ - char dialstr[1024]; - char *name; - cmd=argv[0]; - if(argc!=4) errexit("Usage: %s host port selector", argv[0]); - sprint(dialstr, "tcp!%s!%s", argv[1], argv[2]); - ifd=dial(dialstr, 0, 0, 0); - if(ifd==-1) errexit("can't call %s:%s", argv[1], argv[2]); - unescape(argv[3]); - switch(argv[3][0]){ - case '/': - fprint(ifd, "\r\n"); - copydir(argv[3]); - break; - case '\0': - fprint(ifd, "\r\n"); - copydir(argv[1]); - break; - case '7': /* index query */ - name=strchr(argv[3], '?'); - if(name!=0){ - if(name==argv[3]+1){ - argv[3][1]=argv[3][0]; - argv[3]++; - } - else - *name='\t'; - name++; - } - else - name=argv[3]; - fprint(ifd, "%s\r\n", argv[3]+1); - copydir(name); - break; - default: - fprint(ifd, "%s\r\n", argv[3]+1); - name=strrchr(argv[3], '/'); - if(name==0) name=argv[3]; - else name++; - switch(argv[3][0]){ - default: errexit("sorry, can't handle %s (type %c)", - argv[3]+1, argv[3][0]); - case '0': copyfile(name); break; - case '1': copydir(name); break; - case '4': savefile(name, "Macintosh BINHEX"); break; - case '5': savefile(name, "DOS binary"); break; - case '6': savefile(name, "uuencoded"); break; - case '9': savefile(name, "binary"); break; - case 'g': savefile(name, "GIF"); break; - case 'I': savefile(name, "some sort of image"); break; - } - break; - } - exits(0); -} diff --git a/sys/src/cmd/mothra/help.html b/sys/src/cmd/mothra/help.html deleted file mode 100644 index 771f4b138..000000000 --- a/sys/src/cmd/mothra/help.html +++ /dev/null @@ -1,78 +0,0 @@ -<html><head><title>Mothra help</title> -</head> -<body> -<H1>Mothra Help</H1> -<p> -Mothra is a World-wide Web browser. Its display looks like this: -<p><img src="file:display.pic" alt="[mothra display]"> -<p>The display's regions, from top to bottom, are: -<ul> -<li>Error messages and other information. -<li>A text input window in which <a href="#commands">commands</a> can be typed. -<li>A scrollable list of titles of previously visited documents, with the most recent first. -Pointing at one of these lines with mouse button 1 revisits the document. -<li>The title of the currently-displayed document. -<li>The URL of the currently-displayed document. -<li>The scrollable document display. Underlined text and -images surrounded by boxes may be pointed at with button 1 to -visit the files that they refer to. Files that are not -HTML documents (for example images or mailto: urls) cause -<i>9v</i> or <i>mail</i> to pop up in a new 8½ window. -</ul> -<h4>Mouse Action</H4> -<p>Pointing with button -2 instead of button 1 selects a url without following it; -the url will be displayed in the selection: area and commands -will refer to the url, but it will not be drawn in the document display. -Button 3 pops up a command menu that contains -<ul> -<li><b>alt display</b><br>switches to (or from) the alternate display, which shows only -the scrollable document display area. This might be useful when running mothra -in a small window. -<li><b>snarf url</b><br>copies the selected url into the snarf buffer. -<li><b>paste</b><br>appends the snarf buffer to the command window. -<li><b>inline pix</b><br>turn off/on loading of inline images. Image maps cannot be disabled. -<li><b>fix cmap</b><br>reload the default plan 9 colormap -<li><b>save hit</b><br>appends the selected url to file:$home/lib/hit.html -<li><b>hit list</b><br>displays file:$home/lib/hit.html -<li><b>exit</b> -</ul> -<a name="#commands"><h4>Commands</h4></a> -<p>The commands you can type are: -<ul> -<li>g [url]<br>get the page with the given url (default, the selection.) -<li>r [url]<br>refresh the display if the URL changes. -Otherwise, you will probably see a cached version. -<li>s file<br>save the current page in the given file. -<li>w file<br>write a bitmap image of the document display area in the given file. -<li>q<br>exit. -<li>?<br>get help. -<li>h<br>get help. -</ul> -<p> -<h4>Configuration</h4> -Mothra gets configuration information from the environment. -<ul> -<li>$url<br>The default <i>url</i> displayed when mothra starts. -A <i>url</i> given on the command line overrides this. -The default is <b>/sys/lib/mothra/start.html</b> -<li>$httpproxy<br>The network address of an http proxy server, -in the format expected by dial(2). If $httpproxy is not set -or is null, no proxy server is used. -</ul> -<h4>Command line</h4> -If the mothra command has an argument, it is the name of a <i>url</i> to visit -instead of the startup page. Giving mothra the <b>-i</b> flag disables loading -of inline images. The <b>inline pix</b> menu item will reset this option. -<h4>Files</h4> -Mothra creates several files in $home/lib/mothra. -<ul> -<li>mothra.log<br>a list of all the url's visited -<li>mothra.err<br>a log of error messages, mostly uninteresting -<li>hit.html<br>the hit list used by the <b>save hit</b> -and <b>hit list</b> commands. Since <b>save hit</b> only -adds new urls to the end of this file, it is safe to edit it -to add annotation or sort the saved urls. -</ul> -</body> -</html> diff --git a/sys/src/cmd/mothra/http.c b/sys/src/cmd/mothra/http.c deleted file mode 100644 index deb36f391..000000000 --- a/sys/src/cmd/mothra/http.c +++ /dev/null @@ -1,486 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <draw.h> -#include <event.h> -#include <panel.h> - -#include <libsec.h> /* tlsClient */ - -#include "mothra.h" -typedef struct Cache Cache; -struct Cache{ - int fd; /* file descriptor on which to write cached data */ - ulong hash; /* hash of url, used to compute cache file name */ - int modtime; /* time at which cache entry was created */ - int type; /* url->type of cached entry */ -}; -void httpheader(Url *, char *); -int httpresponse(char *); -static char *proxyserver; /* name of proxy server */ -void exitnow(void*, char*){ - noted(NDFLT); -} -void hashname(char *name, int n, char *stem, Cache *c){ - snprint(name, n, "/sys/lib/mothra/cache/%s.%.8lux", stem, c->hash); -} -// #define CacheEnabled -/* - * Returns fd of cached file, if found (else -1) - * Fills in Cache data structure for caller - * If stale is set, caller has determined that the existing - * cache entry for this url is stale, so we shouldn't bother re-examining it. - */ -int cacheopen(Url *url, Cache *c, int stale){ -#ifdef CacheEnabled - int fd, n; - char name[NNAME+1], *s, *l; - /* - * If we're using a proxy server or the url contains a ? or =, - * don't even bother. - */ - if(proxyserver || strchr(url->reltext, '?')!=0 || strchr(url->reltext, '=')!=0){ - c->fd=-1; - return -1; - } - c->hash=0; - for(s=url->fullname,n=0;*s;s++,n++) c->hash=c->hash*n+(*s&255); - if(stale) - fd=-1; - else{ - hashname(name, sizeof(name), "cache", c); - fd=open(name, OREAD); - } - if(fd==-1){ - hashname(name, sizeof(name), "write", c); - c->fd=create(name, OWRITE, 0444); - if(c->fd!=-1) - fprint(c->fd, "%s %10ld\n", url->fullname, time(0)); - return -1; - } - c->fd=-1; - for(l=name;l!=&name[NNAME];l+=n){ - n=&name[NNAME]-l; - n=read(fd, l, n); - if(n<=0) break; - } - *l='\0'; - s=strchr(name, ' '); - if(s==0){ - close(fd); - return -1; - } - *s='\0'; - if(strcmp(url->fullname, name)!=0){ - close(fd); - return -1; - } - c->modtime=atol(++s); - s=strchr(s, '\n'); - if(s==0){ - close(fd); - return -1; - } - s++; - if(strncmp(s, "type ", 5)!=0){ - close(fd); - return -1; - } - c->type=atoi(s+5); - s=strchr(s+5, '\n'); - if(s==0){ - close(fd); - return -1; - } - - seek(fd, s-name+1, 0); - return fd; -#else - c->fd=-1; - return -1; -#endif -} -/* - * Close url->fd and either rename the cache file or - * remove it, depending on success - */ -void cacheclose(Cache *c, int success){ - char wname[NNAME+1], cname[NNAME+1], *celem; - Dir *wdir; - if(c->fd==-1) return; - close(c->fd); - hashname(wname, sizeof(wname), "write", c); - if(!success){ - remove(wname); - return; - } - if((wdir = dirstat(wname)) == 0) - return; - hashname(cname, sizeof(cname), "cache", c); - if(access(cname, 0) == 0){ - if(remove(cname)==-1){ - remove(wname); - free(wdir); - return; - } - /* - * This looks implausible, but it's what the mv command does - */ - do; while(remove(cname)!=-1); - } - celem=strrchr(cname, '/'); - if(celem==0) celem=cname; - else celem++; - strcpy(wdir->name, celem); - if(dirwstat(wname, wdir)==-1) - remove(wname); - free(wdir); -} -static char *wkday[]={ - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; -static char *month[]={ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; -/* - * Sun, 06 Nov 1994 08:49:38 GMT - * 123456789 123456789 123456789 - */ -char *rfc1123date(long time){ - static char buf[50]; - Tm *t; - t=gmtime(time); - snprint(buf, sizeof(buf), "%s, %2.2d %s %4.4d %2.2d:%2.2d:%2.2d GMT", - wkday[t->wday], t->mday, month[t->mon], t->year+1900, - t->hour, t->min, t->sec); - return buf; -} -/* - * Given a url, return a file descriptor on which caller can - * read an http document. As a side effect, we parse the - * http header and fill in some fields in the url. - * The caller is responsible for processing redirection loops. - * Method can be either GET or POST. If method==post, body - * is the text to be posted. - */ -int http(Url *url, int method, char *body){ - char *addr, *com; - int fd, n, nnl, len; - int ncom, m; - int pfd[2]; - char buf[1024], *bp, *ebp; - char line[1024+1], *lp, *elp; - char authstr[NAUTH], *urlname; - int gotresponse; - int response; - Cache cache; - int cfd, cookiefd; - static int firsttime=1; - static int gotcookies; - - if(firsttime){ - proxyserver=getenv("httpproxy"); - gotcookies=(access("/mnt/webcookies/http", AREAD|AWRITE)==0); - firsttime=0; - } - *authstr = 0; -Authorize: - cfd=-1; - cookiefd=-1; - if(proxyserver && proxyserver[0]!='\0'){ - addr=strdup(proxyserver); - urlname=url->fullname; - } - else{ - addr=emalloc(strlen(url->ipaddr)+100); - sprint(addr, "tcp!%s!%d", url->ipaddr, url->port); - urlname=url->reltext; - } - fd=dial(addr, 0, 0, 0); - free(addr); - if(fd==-1) goto ErrReturn; - if(url->ssl){ - int tfd; - TLSconn conn; - - memset(&conn, 0, sizeof conn); - tfd = tlsClient(fd, &conn); - if(tfd < 0){ - close(fd); - goto ErrReturn; - } - /* BUG: check cert here? */ - if(conn.cert) - free(conn.cert); - close(fd); - fd = tfd; - } - ncom=strlen(urlname)+sizeof(buf); - com=emalloc(ncom+2); - cache.fd=-1; - switch(method){ - case GET: - cfd=cacheopen(url, &cache, 0); - if(cfd==-1) - n=sprint(com, - "GET %s HTTP/1.0\r\n%s" - "Accept: */*\r\n" - "User-agent: mothra/%s\r\n" - "Host: %s\r\n", - urlname, authstr, version, url->ipaddr); - else - n=sprint(com, - "GET %s HTTP/1.0\r\n%s" - "If-Modified-since: %s\r\n" - "Accept: */*\r\n" - "User-agent: mothra/%s\r\n" - "Host: %s\r\n", - urlname, authstr, rfc1123date(cache.modtime), version, url->ipaddr); - break; - case POST: - len=strlen(body); - n=sprint(com, - "POST %s HTTP/1.0\r\n%s" - "Content-type: application/x-www-form-urlencoded\r\n" - "Content-length: %d\r\n" - "User-agent: mothra/%s\r\n", - urlname, authstr, len, version); - break; - } - if(gotcookies && (cookiefd=open("/mnt/webcookies/http", ORDWR)) >= 0){ - if(fprint(cookiefd, "%s", url->fullname) > 0){ - while((m=read(cookiefd, buf, sizeof buf)) > 0){ - if(m+n>ncom){ - if(write(fd, com, n)!= n){ - free(com); - goto fdErrReturn; - } - n=0; - com[0] = '\0'; - } - strncat(com, buf, m); - n += m; - } - }else{ - close(cookiefd); - cookiefd=-1; - } - } - strcat(com, "\r\n"); - n += 2; - switch(method){ - case GET: - if(write(fd, com, n)!=n){ - free(com); - goto fdErrReturn; - } - break; - case POST: - if(write(fd, com, n)!=n - || write(fd, body, len)!=len){ - free(com); - goto fdErrReturn; - } - break; - } - free(com); - if(pipe(pfd)==-1) goto fdErrReturn; - n=read(fd, buf, 1024); - if(n<=0){ - EarlyEof: - if(n==0){ - fprint(2, "%s: EOF in header\n", url->fullname); - werrstr("EOF in header"); - } - pfdErrReturn: - close(pfd[0]); - close(pfd[1]); - fdErrReturn: - close(fd); - ErrReturn: - if(cookiefd>=0) - close(cookiefd); - cacheclose(&cache, 0); - return -1; - } - bp=buf; - ebp=buf+n; - url->type=0; - if(strncmp(buf, "HTTP/", 5)==0){ /* hack test for presence of header */ - SET(response); - gotresponse=0; - url->redirname[0]='\0'; - nnl=0; - lp=line; - elp=line+1024; - while(nnl!=2){ - if(bp==ebp){ - n=read(fd, buf, 1024); - if(n<=0) goto EarlyEof; - ebp=buf+n; - bp=buf; - } - if(*bp!='\r'){ - if(nnl==1 && (!gotresponse || (*bp!=' ' && *bp!='\t'))){ - *lp='\0'; - if(gotresponse){ - if(cookiefd>=0 && cistrncmp(line, "Set-Cookie:", 11) == 0) - fprint(cookiefd, "%s\n", line); - httpheader(url, line); - }else{ - response=httpresponse(line); - gotresponse=1; - } - lp=line; - } - if(*bp=='\n') nnl++; - else{ - nnl=0; - if(lp!=elp) *lp++=*bp; - } - } - bp++; - } - if(gotresponse) switch(response){ - case 200: /* OK */ - case 201: /* Created */ - case 202: /* Accepted */ - break; - case 204: /* No Content */ - werrstr("URL has no content"); - goto pfdErrReturn; - case 301: /* Moved Permanently */ - case 302: /* Moved Temporarily */ - if(url->redirname[0]){ - url->type=FORWARD; - werrstr("URL forwarded"); - goto pfdErrReturn; - } - break; - case 304: /* Not Modified */ - if(cfd!=-1){ - url->type=cache.type; - close(pfd[0]); - close(pfd[1]); - close(fd); - if(cookiefd>=0) - close(cookiefd); - return cfd; - } - werrstr("Not modified!"); - goto pfdErrReturn; - case 400: /* Bad Request */ - werrstr("Bad Request to server"); - goto pfdErrReturn; - case 401: /* Unauthorized */ - case 402: /* ??? */ - if(*authstr == 0){ - close(pfd[0]); - close(pfd[1]); - close(fd); - if(auth(url, authstr, sizeof(authstr)) == 0){ - if(cfd!=-1) - close(cfd); - goto Authorize; - } - goto ErrReturn; - } - break; - case 403: /* Forbidden */ - werrstr("Forbidden by server"); - goto pfdErrReturn; - case 404: /* Not Found */ - werrstr("Not found on server"); - goto pfdErrReturn; - case 500: /* Internal server error */ - werrstr("Server choked"); - goto pfdErrReturn; - case 501: /* Not implemented */ - werrstr("Server can't do it!"); - goto pfdErrReturn; - case 502: /* Bad gateway */ - werrstr("Bad gateway"); - goto pfdErrReturn; - case 503: /* Service unavailable */ - werrstr("Service unavailable"); - goto pfdErrReturn; - } - } - if(cfd!=-1){ - close(cfd); - cfd=cacheopen(url, &cache, 1); - } - if(cookiefd>=0){ - close(cookiefd); - cookiefd=-1; - } - if(url->type==0) - url->type=suffix2type(url->fullname); - if(cache.fd!=-1) fprint(cache.fd, "type %d\n", url->type); - switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ - case -1: - werrstr("Can't fork"); - goto pfdErrReturn; - case 0: - notify(exitnow); /* otherwise write on closed pipe below may cause havoc */ - close(pfd[0]); - if(bp!=ebp){ - write(pfd[1], bp, ebp-bp); - if(cache.fd!=-1) write(cache.fd, bp, ebp-bp); - } - while((n=read(fd, buf, 1024))>0){ - write(pfd[1], buf, n); - if(cache.fd!=-1) write(cache.fd, buf, n); - } - cacheclose(&cache, 1); - _exits(0); - default: - if(cache.fd!=-1) close(cache.fd); - close(pfd[1]); - close(fd); - return pfd[0]; - } -} -/* - * Process a header line for this url - */ -void httpheader(Url *url, char *line){ - char *name, *arg, *s, *arg2; - name=line; - while(*name==' ' || *name=='\t') name++; - for(s=name;*s!=':';s++) if(*s=='\0') return; - *s++='\0'; - while(*s==' ' || *s=='\t') s++; - arg=s; - while(*s!=' ' && *s!='\t' && *s!=';' && *s!='\0') s++; - while(*s == ' ' || *s == '\t' || *s == ';') - *s++ = '\0'; - arg2 = s; - if(cistrcmp(name, "Content-Type")==0){ - url->type|=content2type(arg, url->reltext); - if(cistrncmp(arg2, "charset=", 8) == 0){ - strncpy(url->charset, arg2+8, sizeof(url->charset)); - } else { - url->charset[0] = '\0'; - } - } - else if(cistrcmp(name, "Content-Encoding")==0) - url->type|=encoding2type(arg); - else if(cistrcmp(name, "WWW-authenticate")==0){ - strncpy(url->authtype, arg, sizeof(url->authtype)); - strncpy(url->autharg, arg2, sizeof(url->autharg)); - } - else if(cistrcmp(name, "URI")==0){ - if(*arg!='<') return; - ++arg; - for(s=arg;*s!='>';s++) if(*s=='\0') return; - *s='\0'; - strncpy(url->redirname, arg, sizeof(url->redirname)); - } - else if(cistrcmp(name, "Location")==0) - strncpy(url->redirname, arg, sizeof(url->redirname)); -} -int httpresponse(char *line){ - while(*line!=' ' && *line!='\t' && *line!='\0') line++; - return atoi(line); -} diff --git a/sys/src/cmd/mothra/libpanel/mem.c b/sys/src/cmd/mothra/libpanel/mem.c index 0155cc12b..84d9cb66b 100644 --- a/sys/src/cmd/mothra/libpanel/mem.c +++ b/sys/src/cmd/mothra/libpanel/mem.c @@ -11,6 +11,7 @@ void *pl_emalloc(int n){ fprint(2, "Can't malloc!\n"); exits("no mem"); } + setmalloctag(v, getcallerpc(&n)); return v; } void pl_unexpected(Panel *g, char *rou){ diff --git a/sys/src/cmd/mothra/mkfile b/sys/src/cmd/mothra/mkfile index 1b8542ce8..c770188a9 100644 --- a/sys/src/cmd/mothra/mkfile +++ b/sys/src/cmd/mothra/mkfile @@ -3,19 +3,12 @@ TARG=mothra LIB=libpanel/libpanel.$O.a CFILES= \ - cistr.c \ - crackurl.c \ - file.c \ filetype.c \ forms.c \ - ftp.c \ getpix.c \ - gopher.c \ html.syntax.c \ - http.c \ mothra.c \ rdhtml.c \ - auth.c \ OFILES=${CFILES:%.c=%.$O} version.$O HFILES=mothra.h html.h tcs.h libpanel/panel.h libpanel/rtext.h diff --git a/sys/src/cmd/mothra/mothra.c b/sys/src/cmd/mothra/mothra.c index cbb3ee7a1..47beaa79b 100644 --- a/sys/src/cmd/mothra/mothra.c +++ b/sys/src/cmd/mothra/mothra.c @@ -23,29 +23,22 @@ Panel *list; /* list of previously acquired www pages */ Panel *msg; /* message display */ Panel *menu3; /* button 3 menu */ Mouse mouse; /* current mouse data */ -char helpfile[] = "file:/sys/lib/mothra/help.html"; char mothra[] = "mothra!"; Url defurl={ - "http://plan9.bell-labs.com/", - 0, - "plan9.bell-labs.com", - "/", + "http://cat-v.org/", "", - "", "", "", - 80, - HTTP, - HTML + "http://cat-v.org/", + "", + "", + HTML, }; Url badurl={ + "", + "", "No file loaded", - 0, "", - "/dev/null", - "", "", "", "", - 0, - FILE, - HTML + HTML, }; Cursor patientcurs={ 0, 0, @@ -83,6 +76,7 @@ Cursor readingcurs={ 0x0E, 0x60, 0x1C, 0x00, 0x38, 0x00, 0x71, 0xB6, 0x61, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +char *mtpt="/mnt/web"; Www *current=0; Url *selection=0; int logfile; @@ -210,6 +204,7 @@ int mkmfile(char *stem, int mode){ sprint(home, "%s/lib/mothra", henv); f=create(home, OREAD, DMDIR|0777); if(f!=-1) close(f); + free(henv); } else strcpy(home, "/tmp"); @@ -231,6 +226,9 @@ void main(int argc, char *argv[]){ ARGBEGIN{ case 'd': debug++; break; case 'v': verbose=1; break; + case 'm': + if(mtpt = ARGF()) + break; default: goto Usage; }ARGEND @@ -243,12 +241,12 @@ void main(int argc, char *argv[]){ switch(argc){ default: Usage: - fprint(2, "Usage: %s [-d] [url]\n", argv[0]); + fprint(2, "Usage: %s [-d] [-m mtpt] [url]\n", argv[0]); exits("usage"); case 0: url=getenv("url"); if(url==0 || url[0]=='\0') - url="file:/sys/lib/mothra/start.html"; + url=defurl.fullname; break; case 1: url=argv[0]; break; } @@ -284,7 +282,6 @@ void main(int argc, char *argv[]){ fillellipse(bullet, Pt(4,4), 3, 3, display->black, ZP); new = www(-1); new->url=&badurl; - new->base=&badurl; strcpy(new->title, "See error message above"); plrtstr(&new->text, 0, 0, font, "See error message above", 0, 0); new->alldone=1; @@ -527,10 +524,6 @@ void docmd(Panel *p, char *s){ default: message("Unknown command %s, type h for help", s); break; - case '?': - case 'h': - geturl(helpfile, GET, 0, 1, 0); - break; case 'g': s=arg(s); if(*s=='\0'){ @@ -543,9 +536,8 @@ void docmd(Panel *p, char *s){ break; case 'r': s = arg(s); - if(*s == '\0') - s = selection ? selection->fullname : helpfile; - geturl(s, GET, 0, 0, 0); + if(*s == '\0' && selection) + geturl(selection->fullname, GET, 0, 0, 0); break; case 'W': s=arg(s); @@ -697,57 +689,79 @@ void popwin(char *cmd){ _exits(0); } } + +int readstr(char *buf, int nbuf, char *base, char *name) +{ + char path[128]; + int n, fd; + + snprint(path, sizeof path, "%s/%s", base, name); + if((fd = open(path, OREAD)) < 0){ + ErrOut: + memset(buf, 0, nbuf); + return 0; + } + n = read(fd, buf, nbuf-1); + close(fd); + if(n <= 0){ + close(fd); + goto ErrOut; + } + buf[n] = 0; + return n; +} + int urlopen(Url *url, int method, char *body){ - int fd; - Url prev; - int nredir; - Dir *dir; - nredir=0; -Again: - if(++nredir==NREDIR){ - werrstr("redir loop"); + int conn, ctlfd, fd, n; + char buf[1024+1]; + + snprint(buf, sizeof buf, "%s/clone", mtpt); + if((ctlfd = open(buf, ORDWR)) < 0) + return -1; + if((n = read(ctlfd, buf, sizeof buf-1)) <= 0){ + close(ctlfd); return -1; } - seek(logfile, 0, 2); - fprint(logfile, "%s\n", url->fullname); - switch(url->access){ - default: - werrstr("unknown access type"); + buf[n] = 0; + conn = atoi(buf); + + if(url->basename[0]){ + n = snprint(buf, sizeof buf, "baseurl %s", url->basename); + write(ctlfd, buf, n); + } + n = snprint(buf, sizeof buf, "url %s", url->reltext); + if(write(ctlfd, buf, n) != n){ + ErrOut: + close(ctlfd); return -1; - case FTP: - url->type = suffix2type(url->reltext); - return ftp(url); - case HTTP: - fd=http(url, method, body); - if(url->type==FORWARD){ - prev=*url; - crackurl(url, prev.redirname, &prev); + } - /* - * I'm not convinced that the following two lines are right, - * but once I got a redir loop because they were missing. - */ - method=GET; - body=0; - goto Again; - } - return fd; - case FILE: - url->type=suffix2type(url->reltext); - fd=open(url->reltext, OREAD); - if(fd!=-1){ - dir=dirfstat(fd); - if(dir->mode&DMDIR){ - url->type=HTML; - free(dir); - return dir2html(url->reltext, fd); - } - free(dir); + if(method == POST && body){ + snprint(buf, sizeof buf, "%s/%d/postbody", mtpt, conn); + if((fd = open(buf, OWRITE)) < 0) + goto ErrOut; + n = strlen(body); + if(write(fd, body, n) != n){ + close(fd); + goto ErrOut; } - return fd; - case GOPHER: - return gopher(url); + close(fd); } + + snprint(buf, sizeof buf, "%s/%d/body", mtpt, conn); + if((fd = open(buf, OREAD)) < 0) + goto ErrOut; + + snprint(buf, sizeof buf, "%s/%d/parsed", mtpt, conn); + readstr(url->fullname, sizeof(url->fullname), buf, "url"); + readstr(url->tag, sizeof(url->tag), buf, "fragment"); + + snprint(buf, sizeof buf, "%s/%d", mtpt, conn); + readstr(buf, sizeof buf, buf, "contenttype"); + url->type = content2type(buf, url->fullname); + + close(ctlfd); + return fd; } int pipeline(char *cmd, int fd) @@ -781,27 +795,21 @@ Err: /* * select the file at the given url */ +void seturl(Url *url, char *urlname, char *base){ + strncpy(url->reltext, urlname, sizeof(url->reltext)); + strcpy(url->basename, base); + url->fullname[0] = 0; + url->charset[0] = 0; + url->tag[0] = 0; + url->type = 0; + url->map = 0; +} + void selurl(char *urlname){ - Url *cur; static Url url; - if(current){ - cur=current->base; - /* - * I believe that the following test should never succeed - */ - if(cur==0){ - cur=current->url; - if(cur==0){ - fprint(2, "bad base & url, getting %s\n", urlname); - cur=&defurl; - } - else - fprint(2, "bad base, current %s, getting %s\n", - current->url->fullname, urlname); - } - } - else cur=&defurl; - crackurl(&url, urlname, cur); + seturl(&url, urlname, current? + current->url->fullname : + defurl.fullname); selection=&url; message("selected: %s", selection->fullname); } @@ -828,61 +836,15 @@ void geturl(char *urlname, int method, char *body, int cache, int map){ selurl(urlname); selection->map=map; - message("getting %s", selection->fullname); + message("getting %s", selection->reltext); esetcursor(&patientcurs); - switch(selection->access){ - default: - message("unknown access %d", selection->access); - break; - case TELNET: - sprint(cmd, "telnet %s", selection->reltext); - popwin(cmd); - break; - case MAILTO: - if(body){ - /* - * Undocumented Mozilla feature - */ - pipe(pfd); - switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ - case -1: - message("Can't fork!"); - break; - case 0: - close(0); - dup(pfd[1], 0); - close(pfd[1]); - close(pfd[0]); - execl("/bin/upas/send", - "sendmail", selection->reltext, 0); - message("Can't exec sendmail"); - _exits(0); - default: - close(pfd[1]); - fprint(pfd[0], - "Content-type: application/x-www-form-urlencoded\n" - "Subject: Form posted from Mothra\n" - "\n" - "%s\n", body); - close(pfd[0]); - break; - } - } - else{ - snprint(cmd, sizeof(cmd), "mail %s", selection->reltext); - popwin(cmd); - } - break; - case FTP: - case HTTP: - case FILE: - case GOPHER: - fd=urlopen(selection, method, body); - if(fd==-1){ + for(;;){ + if((fd=urlopen(selection, method, body)) < 0){ message("%r"); setcurrent(-1, 0); break; } + message("getting %s", selection->fullname); if(selection->type&COMPRESS) fd=pipeline("/bin/uncompress", fd); else if(selection->type&GUNZIP) @@ -908,19 +870,11 @@ void geturl(char *urlname, int method, char *body, int cache, int map){ freetext(w->text); freeform(w->form); freepix(w->pix); - if(w->base != w->url) - freeurl(w->base); freeurl(w->url); memset(w, 0, sizeof(*w)); } - if(selection->map){ - if(current && current->base) /* always succeeds */ - w->url=copyurl(current->base); - else{ - fprint(2, "no base for map!\n"); - w->url=copyurl(selection); - } - } + if(selection->map) + w->url=copyurl(current->url); else w->url=copyurl(selection); w->finished = 0; @@ -944,6 +898,7 @@ void geturl(char *urlname, int method, char *body, int cache, int map){ filter("fb/xbm2pic|fb/9v", fd); break; } + break; } donecurs(); } diff --git a/sys/src/cmd/mothra/mothra.h b/sys/src/cmd/mothra/mothra.h index 3fb97f87f..27ad5e13b 100644 --- a/sys/src/cmd/mothra/mothra.h +++ b/sys/src/cmd/mothra/mothra.h @@ -1,5 +1,6 @@ enum{ NWWW=64, /* # of pages we hold in the log */ + NXPROC=5, /* # of parallel procs loading the pix */ NNAME=512, NLINE=256, NAUTH=128, @@ -11,14 +12,7 @@ enum{ typedef struct Action Action; typedef struct Url Url; typedef struct Www Www; -typedef struct Scheme Scheme; typedef struct Field Field; -struct Scheme{ - char *name; - int type; - int flags; - int port; -}; struct Action{ char *image; Field *field; @@ -30,23 +24,15 @@ struct Action{ }; struct Url{ char fullname[NNAME]; - Scheme *scheme; - char ipaddr[NNAME]; + char basename[NNAME]; char reltext[NNAME]; char tag[NNAME]; - char redirname[NNAME]; - char autharg[NAUTH]; - char authtype[NTITLE]; char charset[NNAME]; - int port; - int access; int type; int map; /* is this an image map? */ - int ssl; }; struct Www{ Url *url; - Url *base; void *pix; void *form; char title[NTITLE]; @@ -83,18 +69,6 @@ enum{ }; /* - * url access types - */ -enum{ - HTTP=1, - FTP, - FILE, - TELNET, - MAILTO, - GOPHER, -}; - -/* * authentication types */ enum{ @@ -119,7 +93,7 @@ enum{ void plrdhtml(char *, int, Www *); void plrdplain(char *, int, Www *); void htmlerror(char *, int, char *, ...); /* user-supplied routine */ -void crackurl(Url *, char *, Url *); +void seturl(Url *, char *, char *); void getpix(Rtext *, Www *); int pipeline(char *, int); int urlopen(Url *, int, char *); @@ -128,16 +102,9 @@ void *emalloc(int); void *emallocz(int, int); void setbitmap(Rtext *); void message(char *, ...); -int ftp(Url *); -int http(Url *, int, char *); -int gopher(Url *); -int cistrcmp(char *, char *); -int cistrncmp(char *, char *, int); int suffix2type(char *); int content2type(char *, char *); int encoding2type(char *); void mkfieldpanel(Rtext *); void geturl(char *, int, char *, int, int); -int dir2html(char *, int); -int auth(Url*, char*, int); char version[]; diff --git a/sys/src/cmd/mothra/rdhtml.c b/sys/src/cmd/mothra/rdhtml.c index 7940f0309..168ecd49d 100644 --- a/sys/src/cmd/mothra/rdhtml.c +++ b/sys/src/cmd/mothra/rdhtml.c @@ -679,7 +679,6 @@ void plrdhtml(char *name, int fd, Www *dst){ g.tp=g.text; g.etext=g.text+NTITLE-1; dst->title[0]='\0'; - dst->base=dst->url; g.spacc=0; g.form=0; g.charset[0] = '\0'; @@ -796,12 +795,6 @@ void plrdhtml(char *name, int fd, Www *dst){ case Tag_strong: g.state->font=BOLD; break; - case Tag_base: - if(str=pl_getattr(g.attr, "href")){ - dst->base=emalloc(sizeof(Url)); - crackurl(dst->base, str, dst->url); - } - break; case Tag_blockquot: g.spacc=0; g.linebrk=1; diff --git a/sys/src/cmd/mothra/urlcanon.c b/sys/src/cmd/mothra/urlcanon.c deleted file mode 100644 index 2ffaeb750..000000000 --- a/sys/src/cmd/mothra/urlcanon.c +++ /dev/null @@ -1,70 +0,0 @@ -#include <u.h> -#include <libc.h> -void *emalloc(int n){ - void *p; - p=malloc(n); - if(p==0){ - fprint(2, "can't malloc\n"); - exits("no mem"); - } - return p; -} -void urlcanon(char *name){ - char *s, *t; - char **comp, **p, **q; - int rooted; - rooted=name[0]=='/'; - /* - * Break the name into a list of components - */ - comp=emalloc(strlen(name)*sizeof(char *)); - p=comp; - *p++=name; - for(s=name;;s++){ - if(*s=='/'){ - *p++=s+1; - *s='\0'; - } - else if(*s=='\0') - break; - } - *p=0; - /* - * go through the component list, deleting components that are empty (except - * the last component) or ., and any .. and its non-.. predecessor. - */ - p=q=comp; - while(*p){ - if(strcmp(*p, "")==0 && p[1]!=0 - || strcmp(*p, ".")==0) - p++; - else if(strcmp(*p, "..")==0 && q!=comp && strcmp(q[-1], "..")!=0){ - --q; - p++; - } - else - *q++=*p++; - } - *q=0; - /* - * rebuild the path name - */ - s=name; - if(rooted) *s++='/'; - for(p=comp;*p;p++){ - t=*p; - while(*t) *s++=*t++; - if(p[1]!=0) *s++='/'; - } - *s='\0'; - free(comp); -} -void main(int argc, char *argv[]){ - int i; - for(i=1;i!=argc;i++){ - print("%s: ", argv[i]); - urlcanon(argv[i]); - print("%s\n", argv[i]); - } - exits(0); -} diff --git a/sys/src/cmd/mothra/version.c b/sys/src/cmd/mothra/version.c index 1e8feb792..1da6deaf6 100644 --- a/sys/src/cmd/mothra/version.c +++ b/sys/src/cmd/mothra/version.c @@ -1 +1 @@ -char version[]="Sep-4-19:07:30-CET-2011"; +char version[]="Sep-5-03:25:57-CET-2011"; |