/* * parse a search string of the form * tag=val&tag1=val1... */ HSPairs* hparsequery(HConnect *c, char *search) { HSPairs *q; char *tag, *val, *s; while((s = strchr(search, '?')) != nil) search = s + 1; s = search; while((s = strchr(s, '+')) != nil) *s++ = ' '; q = nil; while(*search){ tag = search; while(*search != '='){ if(*search == '\0') return q; search++; } *search++ = 0; val = search; while(*search != '&'){ if(*search == '\0') return hmkspairs(c, hurlunesc(c, tag), hurlunesc(c, val), q); search++; } *search++ = '\0'; q = hmkspairs(c, hurlunesc(c, tag), hurlunesc(c, val), q); } return q; }
/* * Handle unpacking the request in the URI and * invoking the actual handler. */ static void dosearch(char *search) { if (strncmp(search, "dir=", 4) == 0){ search = hurlunesc(connect, search+4); dols(search); return; } /* * Otherwise, we've gotten an illegal request. * spit out a non-apologetic error. */ search = hurlunesc(connect, search); error("Bad directory listing request", "<p>Illegal formatted directory listing request:</p>\n" "<p>%H</p>", search); }
/* * find man pages mentioning the search string */ void dosearch(int vermaj, char *search) { int sect; char *p; if(strncmp(search, "man=", 4) == 0){ sect = 0; search = hurlunesc(connect, search+4); p = strchr(search, '&'); if(p != nil){ *p++ = 0; if(strncmp(p, "sect=", 5) == 0) sect = atoi(p+5); } man(search, sect, vermaj); return; } if(vermaj){ hokheaders(connect); hprint(hout, "Content-type: text/html\r\n"); hprint(hout, "\r\n"); } if(strncmp(search, "pat=", 4) == 0){ search = hurlunesc(connect, search+4); search = hlower(search); searchfor(search); return; } hprint(hout, "<head><title>illegal search</title></head>\n"); hprint(hout, "<body><p>Illegally formatted Plan 9 man page search</p>\n"); search = hurlunesc(connect, search); hprint(hout, "<body><p>%H</p>\n", search); hprint(hout, "</body>"); }
/* * parse the next request line * returns: * 1 ok * 0 eof * -1 error */ int hparsereq(HConnect *c, int timeout) { Strings ss; char *vs, *v, *search, *uri, *origuri, *extra; if(c->bin != nil){ hfail(c, HInternal); return -1; } /* * serve requests until a magic request. * later requests have to come quickly. * only works for http/1.1 or later. */ if(timeout) alarm(timeout); if(hgethead(c, 0) < 0) return -1; if(timeout) alarm(0); c->reqtime = time(nil); c->req.meth = getword(c); if(c->req.meth == nil){ hfail(c, HSyntax); return -1; } uri = getword(c); if(uri == nil || strlen(uri) == 0){ hfail(c, HSyntax); return -1; } v = getword(c); if(v == nil){ if(strcmp(c->req.meth, "GET") != 0){ hfail(c, HUnimp, c->req.meth); return -1; } c->req.vermaj = 0; c->req.vermin = 9; }else{ vs = v; if(strncmp(vs, "HTTP/", 5) != 0){ hfail(c, HUnkVers, vs); return -1; } vs += 5; c->req.vermaj = strtoul(vs, &vs, 10); if(*vs != '.' || c->req.vermaj != 1){ hfail(c, HUnkVers, vs); return -1; } vs++; c->req.vermin = strtoul(vs, &vs, 10); if(*vs != '\0'){ hfail(c, HUnkVers, vs); return -1; } extra = getword(c); if(extra != nil){ hfail(c, HSyntax); return -1; } } /* * the fragment is not supposed to be sent * strip it 'cause some clients send it */ origuri = uri; uri = strchr(origuri, '#'); if(uri != nil) *uri = 0; /* * http/1.1 requires the server to accept absolute * or relative uri's. convert to relative with an absolute path */ if(http11(c)){ ss = parseuri(c, origuri); uri = ss.s1; c->req.urihost = ss.s2; if(uri == nil){ hfail(c, HBadReq, uri); return -1; } origuri = uri; } /* * munge uri for search, protection, and magic */ ss = stripsearch(origuri); origuri = ss.s1; search = ss.s2; uri = hurlunesc(c, origuri); uri = abspath(c, uri, "/"); if(uri == nil || uri[0] == '\0'){ hfail(c, HNotFound, "no object specified"); return -1; } c->req.uri = uri; c->req.search = search; if(search) c->req.searchpairs = hparsequery(c, hstrdup(c, search)); return 1; }