]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/webfs/fs.c
git/branch: somewhere in the syncing, the fix for junk files was lost
[plan9front.git] / sys / src / cmd / webfs / fs.c
index 8e8cabbf927f84d6dd531a99366062325e9710f1..e4e08670daba7be2e4feda2f99bcd79cb3428360 100644 (file)
@@ -76,12 +76,15 @@ static char *nametab[] = {
                        nil,
 };
 
+static char *mtpt;
+static char *service;
 static long time0;
 static char *user;
+static char *agent;
 static Client client[64];
 static int nclient;
 
-#define        CLIENTID(c)     (((Client*)(c)) - client)
+#define        CLIENTID(c)     ((int)(((Client*)(c)) - client))
 
 Client*
 newclient(void)
@@ -166,7 +169,7 @@ fsmkqid(Qid *q, int level, void *aux)
        case Qclient:
                q->type = QTDIR;
        default:
-               q->path = (level<<24) | (((ulong)aux ^ time0) & 0x00ffffff);
+               q->path = (level<<24) | (((uintptr)aux ^ time0) & 0x00ffffff);
        }
 }
 
@@ -211,7 +214,7 @@ fsmkdir(Dir *d, int level, void *aux)
        d->uid = estrdup(user);
        d->gid = estrdup(user);
        d->muid = estrdup(user);
-       if(d->qid.type == QTDIR)
+       if(d->qid.type & QTDIR)
                d->mode |= DMDIR | 0111;
        switch(level){
        case Qheader:
@@ -219,7 +222,7 @@ fsmkdir(Dir *d, int level, void *aux)
                d->length = strlen(((Key*)aux)->val);
                break;
        case Qclient:
-               snprint(buf, sizeof(buf), "%ld", CLIENTID(aux));
+               snprint(buf, sizeof(buf), "%d", CLIENTID(aux));
                d->name = estrdup(buf);
                break;
        case Qctl:
@@ -309,7 +312,7 @@ fswalk1(Fid *fid, char *name, Qid *qid)
                                Key *k;
 
                                for(k = f->client->qbody->hdr; k; k = k->next){
-                                       strncpy(buf, k->key, sizeof(buf));
+                                       nstrcpy(buf, k->key, sizeof(buf));
                                        if(!strcmp(name, fshdrname(buf)))
                                                break;
                                }
@@ -396,10 +399,20 @@ fsopen(Req *r)
                                m = "GET";
                        if(cl->request[0])
                                m = cl->request;
+
+                       /*
+                        * some sites give a 403 Forbidden if we dont include
+                        * a meaningless Accept header in the request.
+                        */
+                       if(!lookkey(cl->hdr, "Accept"))
+                               cl->hdr = addkey(cl->hdr, "Accept", "*/*");
+
                        if(!lookkey(cl->hdr, "Connection"))
                                cl->hdr = addkey(cl->hdr, "Connection", "keep-alive");
-                       if(!lookkey(cl->hdr, "User-Agent"))
-                               cl->hdr = addkey(cl->hdr, "User-Agent", "webfs/0.1 (Plan 9 Front)");
+
+                       if(agent && !lookkey(cl->hdr, "User-Agent"))
+                               cl->hdr = addkey(cl->hdr, "User-Agent", agent);
+
                        http(m, cl->url, cl->hdr, cl->qbody, f->buq);
                        cl->request[0] = 0;
                        cl->url = nil;
@@ -484,13 +497,13 @@ fsread(Req *r)
                respond(r, nil);
                return;
        case Qrctl:
-               buf[0] = 0;
+               snprint(buf, sizeof(buf), "useragent %s\ntimeout %d\n", agent, timeout);
        String:
                readstr(r, buf);
                respond(r, nil);
                return;
        case Qctl:
-               snprint(buf, sizeof(buf), "%ld\n", CLIENTID(f->client));
+               snprint(buf, sizeof(buf), "%d\n", CLIENTID(f->client));
                goto String;
        case Qheader:
                snprint(buf, sizeof(buf), "%s", f->key->val);
@@ -514,13 +527,22 @@ fsread(Req *r)
 }
 
 static char*
-rootctl(char *ctl, char *arg)
+rootctl(Srv *fs, char *ctl, char *arg)
 {
        Url *u;
 
        if(debug)
                fprint(2, "rootctl: %q %q\n", ctl, arg);
 
+       if(!strcmp(ctl, "useragent")){
+               free(agent);
+               if(arg && *arg)
+                       agent = estrdup(arg);
+               else
+                       agent = nil;
+               return nil;
+       }
+
        if(!strcmp(ctl, "flushauth")){
                u = nil;
                if(arg && *arg)
@@ -529,6 +551,39 @@ rootctl(char *ctl, char *arg)
                freeurl(u);
                return nil;
        }
+
+       if(!strcmp(ctl, "timeout")){
+               if(arg && *arg)
+                       timeout = atoi(arg);
+               else
+                       timeout = 0;
+               if(timeout < 0)
+                       timeout = 0;
+               return nil;
+       }
+
+       /* ppreemptive authentication only basic
+        * auth supported, ctl message of the form:
+        *    preauth url realm
+        */
+       if(!strcmp(ctl, "preauth")){
+               char *a[3], buf[256];
+               int rc;
+
+               if(tokenize(arg, a, nelem(a)) != 2)
+                       return "preauth - bad field count";
+               if((u = saneurl(url(a[0], 0))) == nil)
+                       return "preauth - malformed url";
+               snprint(buf, sizeof(buf), "BASIC realm=\"%s\"", a[1]);
+               srvrelease(fs);
+               rc = authenticate(u, u, "GET", buf);
+               srvacquire(fs);
+               freeurl(u);
+               if(rc == -1)
+                       return "preauth failed";
+               return nil;
+       }
+
        return "bad ctl message";
 }
 
@@ -556,7 +611,7 @@ clientctl(Client *cl, char *ctl, char *arg)
        }
        else if(!strcmp(ctl, "request")){
                p = cl->request;
-               strncpy(p, arg, sizeof(cl->request));
+               nstrcpy(p, arg, sizeof(cl->request));
                for(; *p && isalpha(*p); p++)
                        *p = toupper(*p);
                *p = 0;
@@ -564,7 +619,7 @@ clientctl(Client *cl, char *ctl, char *arg)
        else if(!strcmp(ctl, "headers")){
                while(arg && *arg){
                        ctl = arg;
-                       while(*ctl && strchr("\r\n\t ", *ctl))
+                       while(*ctl && strchr(whitespace, *ctl))
                                ctl++;
                        if(arg = strchr(ctl, '\n'))
                                *arg++ = 0;
@@ -582,7 +637,7 @@ clientctl(Client *cl, char *ctl, char *arg)
                        nil,
                };
                for(t = tab; *t; t++){
-                       strncpy(buf, *t, sizeof(buf));
+                       nstrcpy(buf, *t, sizeof(buf));
                        if(!strcmp(ctl, fshdrname(buf))){
                                cl->hdr = delkey(cl->hdr, *t);
                                if(arg && *arg)
@@ -614,14 +669,14 @@ fswrite(Req *r)
                        n--;
                s[n] = 0;
                t = s;
-               while(*t && strchr("\r\n\t ", *t)==0)
+               while(*t && strchr(whitespace, *t)==0)
                        t++;
-               while(*t && strchr("\r\n\t ", *t))
+               while(*t && strchr(whitespace, *t))
                        *t++ = 0;
                if(f->level == Qctl)
                        t = clientctl(f->client, s, t);
                else
-                       t = rootctl(s, t);
+                       t = rootctl(r->srv, s, t);
                free(s);
                respond(r, t);
                return;
@@ -666,8 +721,24 @@ fsdestroyfid(Fid *fid)
        }
 }
 
+static void
+fsstart(Srv*)
+{
+       /* drop reference to old webfs mount */
+       if(mtpt != nil)
+               unmount(nil, mtpt);
+}
+
+static void
+fsend(Srv*)
+{
+       postnote(PNGROUP, getpid(), "shutdown");
+       exits(nil);
+}
+
 Srv fs = 
 {
+       .start=fsstart,
        .attach=fsattach,
        .stat=fsstat,
        .walk1=fswalk1,
@@ -677,38 +748,51 @@ Srv fs =
        .write=fswrite,
        .flush=fsflush,
        .destroyfid=fsdestroyfid,
+       .end=fsend,
 };
 
 void
 usage(void)
 {
-       fprint(2, "usage: %s [-D] [-m mtpt] [-s srv]\n", argv0);
+       fprint(2, "usage: %s [-Dd] [-A useragent] [-T timeout] [-m mtpt] [-s service]\n", argv0);
        exits("usage");
 }
 
 void
 main(int argc, char *argv[])
 {
-       char *srv, *mtpt, *s;
+       char *s;
 
        quotefmtinstall();
        fmtinstall('U', Ufmt);
+       fmtinstall('N', Nfmt);
+       fmtinstall(']', Mfmt);
        fmtinstall('E', Efmt);
+       fmtinstall('[', encodefmt);
+       fmtinstall('H', encodefmt);
 
-       srv = nil;
        mtpt = "/mnt/web";
        user = getuser();
        time0 = time(0);
+       timeout = 10000;
 
        ARGBEGIN {
        case 'D':
                chatty9p++;
                break;
+       case 'A':
+               agent = EARGF(usage());
+               break;
+       case 'T':
+               timeout = atoi(EARGF(usage()));
+               if(timeout < 0)
+                       timeout = 0;
+               break;
        case 'm':
                mtpt = EARGF(usage());
                break;
        case 's':
-               srv = EARGF(usage());
+               service = EARGF(usage());
                break;
        case 'd':
                debug++;
@@ -719,10 +803,17 @@ main(int argc, char *argv[])
 
        rfork(RFNOTEG);
 
+       if(agent == nil)
+               agent = "Mozilla/5.0 (compatible; hjdicks)";
+       agent = estrdup(agent);
+
        if(s = getenv("httpproxy")){
                proxy = saneurl(url(s, 0));
+               if(proxy == nil || strcmp(proxy->scheme, "http") && strcmp(proxy->scheme, "https"))
+                       sysfatal("invalid httpproxy url: %s", s);
                free(s);
        }
 
-       postmountsrv(&fs, srv, mtpt, MREPL);
+       postmountsrv(&fs, service, mtpt, MREPL);
+       exits(nil);
 }