11 typedef struct Webfid Webfid;
12 typedef struct Client Client;
23 int obody; /* body opend */
24 int cbody; /* body closed */
33 Key *key; /* copy for Qheader */
34 Buq *buq; /* reference for Qbody, Qpost */
58 static char *nametab[] = {
81 static Client client[64];
84 #define CLIENTID(c) (((Client*)(c)) - client)
92 for(i = 0; i < nclient; i++)
93 if(client[i].ref == 0)
95 if(i >= nelem(client))
112 freeclient(Client *cl)
116 if(cl == nil || decref(cl))
119 buclose(cl->qbody, 0);
128 freeurl(cl->baseurl);
130 memset(cl, 0, sizeof(*cl));
134 clienturl(Client *cl)
138 if(cl->qbody && cl->qbody->url)
139 return cl->qbody->url;
148 if(f->level < Qclient)
150 else if(f->level < Qurl)
152 else if(f->level < Qheader)
153 return clienturl(f->client);
159 fsmkqid(Qid *q, int level, void *aux)
169 q->path = (level<<24) | (((ulong)aux ^ time0) & 0x00ffffff);
186 urlstr(char *buf, int nbuf, Url *u, int level)
191 return snprint(buf, nbuf, "%U", u);
192 if(level == Qurlpath)
193 return snprint(buf, nbuf, "%s", Upath(u));
194 if((s = (&u->scheme)[level - Qurlschm]) == nil){
198 return snprint(buf, nbuf, "%s", s);
203 fsmkdir(Dir *d, int level, void *aux)
207 memset(d, 0, sizeof(*d));
208 fsmkqid(&d->qid, level, aux);
210 d->atime = d->mtime = time0;
211 d->uid = estrdup(user);
212 d->gid = estrdup(user);
213 d->muid = estrdup(user);
214 if(d->qid.type & QTDIR)
215 d->mode |= DMDIR | 0111;
218 d->name = fshdrname(estrdup(((Key*)aux)->key));
219 d->length = strlen(((Key*)aux)->val);
222 snprint(buf, sizeof(buf), "%ld", CLIENTID(aux));
223 d->name = estrdup(buf);
234 d->name = estrdup(nametab[level]);
235 if(level >= Qurl && level <= Qurlfrag)
236 d->length = urlstr(buf, sizeof(buf), (Url*)aux, level);
245 if(r->ifcall.aname && r->ifcall.aname[0]){
246 respond(r, "invalid attach specifier");
249 f = emalloc(sizeof(*f));
251 fsmkqid(&r->fid->qid, f->level, wfaux(f));
252 r->ofcall.qid = r->fid->qid;
263 fsmkdir(&r->d, f->level, wfaux(f));
268 fswalk1(Fid *fid, char *name, Qid *qid)
273 if(!(fid->qid.type&QTDIR))
274 return "walk in non-directory";
277 if(strcmp(name, "..") == 0){
282 freeclient(f->client);
286 if(f->level > Qparsed)
292 for(i=f->level+1; i < nelem(nametab); i++){
294 if(strcmp(name, nametab[i]) == 0)
296 if(i == Qbody && strncmp(name, "body.", 5) == 0)
301 if(j >= 0 && j < nclient){
302 f->client = &client[j];
307 if(i == Qheader && f->client && f->client->qbody){
311 for(k = f->client->qbody->hdr; k; k = k->next){
312 strncpy(buf, k->key, sizeof(buf));
313 if(!strcmp(name, fshdrname(buf)))
317 /* need to copy as key is owned by qbody wich might go away */
318 f->key = addkey(0, k->key, k->val);
323 if(i >= nelem(nametab))
324 return "directory entry not found";
327 fsmkqid(qid, f->level, wfaux(f));
333 fsclone(Fid *oldfid, Fid *newfid)
338 if(o == nil || o->key || o->buq)
340 f = emalloc(sizeof(*f));
341 memmove(f, o, sizeof(*f));
358 if((cl = newclient()) == nil){
359 respond(r, "no more clients");
364 fsmkqid(&r->fid->qid, f->level, wfaux(f));
365 r->ofcall.qid = r->fid->qid;
368 if(cl->qbody && !cl->cbody){
370 respond(r, "client in use");
381 if(cl->qbody == nil){
385 respond(r, "no url set");
388 cl->qbody = bualloc(16*1024);
389 if(f->level != Qbody){
390 f->buq = bualloc(64*1024);
391 if(!lookkey(cl->hdr, "Content-Type"))
392 cl->hdr = addkey(cl->hdr, "Content-Type",
393 "application/x-www-form-urlencoded");
399 if(!lookkey(cl->hdr, "Connection"))
400 cl->hdr = addkey(cl->hdr, "Connection", "keep-alive");
401 if(!lookkey(cl->hdr, "User-Agent"))
402 cl->hdr = addkey(cl->hdr, "User-Agent", "webfs/0.1 (Plan 9 Front)");
403 http(m, cl->url, cl->hdr, cl->qbody, f->buq);
412 bureq(f->buq = cl->qbody, r);
419 rootgen(int i, Dir *d, void *)
428 fsmkdir(d, Qclient, &client[i]);
435 clientgen(int i, Dir *d, void *aux)
443 if(cl == nil || cl->qbody == nil)
445 for(k = cl->qbody->hdr; i > 0 && k; i--, k = k->next)
447 if(k == nil || i > 0)
457 parsedgen(int i, Dir *d, void *aux)
475 dirread9p(r, rootgen, nil);
479 dirread9p(r, clientgen, f->client);
483 dirread9p(r, parsedgen, clienturl(f->client));
493 snprint(buf, sizeof(buf), "%ld\n", CLIENTID(f->client));
496 snprint(buf, sizeof(buf), "%s", f->key->val);
507 urlstr(buf, sizeof(buf), clienturl(f->client), f->level);
513 respond(r, "not implemented");
517 rootctl(char *ctl, char *arg)
522 fprint(2, "rootctl: %q %q\n", ctl, arg);
524 if(!strcmp(ctl, "flushauth")){
527 u = saneurl(url(arg, 0));
532 return "bad ctl message";
536 clientctl(Client *cl, char *ctl, char *arg)
543 fprint(2, "clientctl: %q %q\n", ctl, arg);
545 if(!strcmp(ctl, "url")){
546 if((u = saneurl(url(arg, cl->baseurl))) == nil)
551 else if(!strcmp(ctl, "baseurl")){
552 if((u = url(arg, 0)) == nil)
553 return "bad baseurl";
554 freeurl(cl->baseurl);
557 else if(!strcmp(ctl, "request")){
559 strncpy(p, arg, sizeof(cl->request));
560 for(; *p && isalpha(*p); p++)
564 else if(!strcmp(ctl, "headers")){
567 while(*ctl && strchr("\r\n\t ", *ctl))
569 if(arg = strchr(ctl, '\n'))
571 if(k = parsehdr(ctl)){
579 static char *tab[] = {
584 for(t = tab; *t; t++){
585 strncpy(buf, *t, sizeof(buf));
586 if(!strcmp(ctl, fshdrname(buf))){
587 cl->hdr = delkey(cl->hdr, *t);
589 cl->hdr = addkey(cl->hdr, *t, arg);
594 return "bad ctl message";
610 n = r->ofcall.count = r->ifcall.count;
612 memmove(s, r->ifcall.data, n);
613 while(n > 0 && strchr("\r\n", s[n-1]))
617 while(*t && strchr("\r\n\t ", *t)==0)
619 while(*t && strchr("\r\n\t ", *t))
622 t = clientctl(f->client, s, t);
632 respond(r, "not implemented");
643 buflushreq(f->buq, o);
648 fsdestroyfid(Fid *fid)
656 if(f->client->qbody == f->buq){
657 f->client->obody = 0;
658 f->client->cbody = 1;
664 freeclient(f->client);
679 .destroyfid=fsdestroyfid,
685 fprint(2, "usage: %s [-D] [-m mtpt] [-s srv]\n", argv0);
690 main(int argc, char *argv[])
692 char *srv, *mtpt, *s;
695 fmtinstall('U', Ufmt);
696 fmtinstall('E', Efmt);
708 mtpt = EARGF(usage());
711 srv = EARGF(usage());
722 if(s = getenv("httpproxy")){
723 proxy = saneurl(url(s, 0));
727 postmountsrv(&fs, srv, mtpt, MREPL);