180ee5cbfSDavid du Colombier #include <u.h> 280ee5cbfSDavid du Colombier #include <libc.h> 32bef681aSDavid du Colombier #include <ctype.h> 480ee5cbfSDavid du Colombier #include <libsec.h> 580ee5cbfSDavid du Colombier #include <bin.h> 680ee5cbfSDavid du Colombier #include <httpd.h> 780ee5cbfSDavid du Colombier #include "escape.h" 880ee5cbfSDavid du Colombier 980ee5cbfSDavid du Colombier typedef struct Hlex Hlex; 1080ee5cbfSDavid du Colombier typedef struct MimeHead MimeHead; 1180ee5cbfSDavid du Colombier 1280ee5cbfSDavid du Colombier enum 1380ee5cbfSDavid du Colombier { 1480ee5cbfSDavid du Colombier /* 1580ee5cbfSDavid du Colombier * tokens 1680ee5cbfSDavid du Colombier */ 1780ee5cbfSDavid du Colombier Word = 1, 1880ee5cbfSDavid du Colombier QString, 1980ee5cbfSDavid du Colombier }; 2080ee5cbfSDavid du Colombier 2180ee5cbfSDavid du Colombier #define UlongMax 4294967295UL 2280ee5cbfSDavid du Colombier 2380ee5cbfSDavid du Colombier struct Hlex 2480ee5cbfSDavid du Colombier { 2580ee5cbfSDavid du Colombier int tok; 2680ee5cbfSDavid du Colombier int eoh; 2780ee5cbfSDavid du Colombier int eol; /* end of header line encountered? */ 2880ee5cbfSDavid du Colombier uchar *hstart; /* start of header */ 2980ee5cbfSDavid du Colombier jmp_buf jmp; /* jmp here to parse header */ 3080ee5cbfSDavid du Colombier char wordval[HMaxWord]; 3180ee5cbfSDavid du Colombier HConnect *c; 3280ee5cbfSDavid du Colombier }; 3380ee5cbfSDavid du Colombier 3480ee5cbfSDavid du Colombier struct MimeHead 3580ee5cbfSDavid du Colombier { 3680ee5cbfSDavid du Colombier char *name; 3780ee5cbfSDavid du Colombier void (*parse)(Hlex*, char*); 3880ee5cbfSDavid du Colombier uchar seen; 3980ee5cbfSDavid du Colombier uchar ignore; 4080ee5cbfSDavid du Colombier }; 4180ee5cbfSDavid du Colombier 4280ee5cbfSDavid du Colombier static void mimeaccept(Hlex*, char*); 4380ee5cbfSDavid du Colombier static void mimeacceptchar(Hlex*, char*); 4480ee5cbfSDavid du Colombier static void mimeacceptenc(Hlex*, char*); 4580ee5cbfSDavid du Colombier static void mimeacceptlang(Hlex*, char*); 4680ee5cbfSDavid du Colombier static void mimeagent(Hlex*, char*); 4780ee5cbfSDavid du Colombier static void mimeauthorization(Hlex*, char*); 4880ee5cbfSDavid du Colombier static void mimeconnection(Hlex*, char*); 4980ee5cbfSDavid du Colombier static void mimecontlen(Hlex*, char*); 502bef681aSDavid du Colombier static void mimecookie(Hlex*, char*); 5180ee5cbfSDavid du Colombier static void mimeexpect(Hlex*, char*); 5280ee5cbfSDavid du Colombier static void mimefresh(Hlex*, char*); 5380ee5cbfSDavid du Colombier static void mimefrom(Hlex*, char*); 5480ee5cbfSDavid du Colombier static void mimehost(Hlex*, char*); 5580ee5cbfSDavid du Colombier static void mimeifrange(Hlex*, char*); 5680ee5cbfSDavid du Colombier static void mimeignore(Hlex*, char*); 5780ee5cbfSDavid du Colombier static void mimematch(Hlex*, char*); 5880ee5cbfSDavid du Colombier static void mimemodified(Hlex*, char*); 5980ee5cbfSDavid du Colombier static void mimenomatch(Hlex*, char*); 6080ee5cbfSDavid du Colombier static void mimerange(Hlex*, char*); 6180ee5cbfSDavid du Colombier static void mimetransenc(Hlex*, char*); 6280ee5cbfSDavid du Colombier static void mimeunmodified(Hlex*, char*); 6380ee5cbfSDavid du Colombier 6480ee5cbfSDavid du Colombier /* 6580ee5cbfSDavid du Colombier * headers seen also include 6680ee5cbfSDavid du Colombier * allow cache-control chargeto 6780ee5cbfSDavid du Colombier * content-encoding content-language content-location content-md5 content-range content-type 6880ee5cbfSDavid du Colombier * date etag expires forwarded last-modified max-forwards pragma 6980ee5cbfSDavid du Colombier * proxy-agent proxy-authorization proxy-connection 7080ee5cbfSDavid du Colombier * ua-color ua-cpu ua-os ua-pixels 7180ee5cbfSDavid du Colombier * upgrade via x-afs-tokens x-serial-number 7280ee5cbfSDavid du Colombier */ 7380ee5cbfSDavid du Colombier static MimeHead mimehead[] = 7480ee5cbfSDavid du Colombier { 7580ee5cbfSDavid du Colombier {"accept", mimeaccept}, 7680ee5cbfSDavid du Colombier {"accept-charset", mimeacceptchar}, 7780ee5cbfSDavid du Colombier {"accept-encoding", mimeacceptenc}, 7880ee5cbfSDavid du Colombier {"accept-language", mimeacceptlang}, 7980ee5cbfSDavid du Colombier {"authorization", mimeauthorization}, 8080ee5cbfSDavid du Colombier {"connection", mimeconnection}, 8180ee5cbfSDavid du Colombier {"content-length", mimecontlen}, 822bef681aSDavid du Colombier {"cookie", mimecookie}, 8380ee5cbfSDavid du Colombier {"expect", mimeexpect}, 8480ee5cbfSDavid du Colombier {"fresh", mimefresh}, 8580ee5cbfSDavid du Colombier {"from", mimefrom}, 8680ee5cbfSDavid du Colombier {"host", mimehost}, 8780ee5cbfSDavid du Colombier {"if-match", mimematch}, 8880ee5cbfSDavid du Colombier {"if-modified-since", mimemodified}, 8980ee5cbfSDavid du Colombier {"if-none-match", mimenomatch}, 9080ee5cbfSDavid du Colombier {"if-range", mimeifrange}, 9180ee5cbfSDavid du Colombier {"if-unmodified-since", mimeunmodified}, 9280ee5cbfSDavid du Colombier {"range", mimerange}, 9380ee5cbfSDavid du Colombier {"transfer-encoding", mimetransenc}, 9480ee5cbfSDavid du Colombier {"user-agent", mimeagent}, 9580ee5cbfSDavid du Colombier }; 9680ee5cbfSDavid du Colombier 9780ee5cbfSDavid du Colombier char* hmydomain; 9880ee5cbfSDavid du Colombier char* hversion = "HTTP/1.1"; 9980ee5cbfSDavid du Colombier 10080ee5cbfSDavid du Colombier static void lexhead(Hlex*); 10180ee5cbfSDavid du Colombier static void parsejump(Hlex*, char*); 10280ee5cbfSDavid du Colombier static int getc(Hlex*); 10380ee5cbfSDavid du Colombier static void ungetc(Hlex*); 10480ee5cbfSDavid du Colombier static int wordcr(Hlex*); 10580ee5cbfSDavid du Colombier static int wordnl(Hlex*); 10680ee5cbfSDavid du Colombier static void word(Hlex*, char*); 10780ee5cbfSDavid du Colombier static int lex1(Hlex*, int); 10880ee5cbfSDavid du Colombier static int lex(Hlex*); 10980ee5cbfSDavid du Colombier static int lexbase64(Hlex*); 11080ee5cbfSDavid du Colombier static ulong digtoul(char *s, char **e); 11180ee5cbfSDavid du Colombier 11280ee5cbfSDavid du Colombier /* 113*f9e1cf08SDavid du Colombier * flush and clean up junk from a request 11480ee5cbfSDavid du Colombier */ 11580ee5cbfSDavid du Colombier void 11680ee5cbfSDavid du Colombier hreqcleanup(HConnect *c) 11780ee5cbfSDavid du Colombier { 11880ee5cbfSDavid du Colombier int i; 11980ee5cbfSDavid du Colombier 12080ee5cbfSDavid du Colombier hxferenc(&c->hout, 0); 12180ee5cbfSDavid du Colombier memset(&c->req, 0, sizeof(c->req)); 12280ee5cbfSDavid du Colombier memset(&c->head, 0, sizeof(c->head)); 12380ee5cbfSDavid du Colombier c->hpos = c->header; 12480ee5cbfSDavid du Colombier c->hstop = c->header; 12580ee5cbfSDavid du Colombier binfree(&c->bin); 12680ee5cbfSDavid du Colombier for(i = 0; i < nelem(mimehead); i++){ 12780ee5cbfSDavid du Colombier mimehead[i].seen = 0; 12880ee5cbfSDavid du Colombier mimehead[i].ignore = 0; 12980ee5cbfSDavid du Colombier } 13080ee5cbfSDavid du Colombier } 13180ee5cbfSDavid du Colombier 13280ee5cbfSDavid du Colombier /* 13380ee5cbfSDavid du Colombier * list of tokens 13480ee5cbfSDavid du Colombier * if the client is HTTP/1.0, 13580ee5cbfSDavid du Colombier * ignore headers which match one of the tokens. 13680ee5cbfSDavid du Colombier * restarts parsing if necessary. 13780ee5cbfSDavid du Colombier */ 13880ee5cbfSDavid du Colombier static void 13980ee5cbfSDavid du Colombier mimeconnection(Hlex *h, char *) 14080ee5cbfSDavid du Colombier { 14180ee5cbfSDavid du Colombier char *u, *p; 14280ee5cbfSDavid du Colombier int reparse, i; 14380ee5cbfSDavid du Colombier 14480ee5cbfSDavid du Colombier reparse = 0; 14580ee5cbfSDavid du Colombier for(;;){ 14680ee5cbfSDavid du Colombier while(lex(h) != Word) 14780ee5cbfSDavid du Colombier if(h->tok != ',') 14880ee5cbfSDavid du Colombier goto breakout; 14980ee5cbfSDavid du Colombier 15080ee5cbfSDavid du Colombier if(cistrcmp(h->wordval, "keep-alive") == 0) 15180ee5cbfSDavid du Colombier h->c->head.persist = 1; 15280ee5cbfSDavid du Colombier else if(cistrcmp(h->wordval, "close") == 0) 15380ee5cbfSDavid du Colombier h->c->head.closeit = 1; 15480ee5cbfSDavid du Colombier else if(!http11(h->c)){ 15580ee5cbfSDavid du Colombier for(i = 0; i < nelem(mimehead); i++){ 15680ee5cbfSDavid du Colombier if(cistrcmp(mimehead[i].name, h->wordval) == 0){ 15780ee5cbfSDavid du Colombier reparse = mimehead[i].seen && !mimehead[i].ignore; 15880ee5cbfSDavid du Colombier mimehead[i].ignore = 1; 15980ee5cbfSDavid du Colombier if(cistrcmp(mimehead[i].name, "authorization") == 0){ 16080ee5cbfSDavid du Colombier h->c->head.authuser = nil; 16180ee5cbfSDavid du Colombier h->c->head.authpass = nil; 16280ee5cbfSDavid du Colombier } 16380ee5cbfSDavid du Colombier } 16480ee5cbfSDavid du Colombier } 16580ee5cbfSDavid du Colombier } 16680ee5cbfSDavid du Colombier 16780ee5cbfSDavid du Colombier if(lex(h) != ',') 16880ee5cbfSDavid du Colombier break; 16980ee5cbfSDavid du Colombier } 17080ee5cbfSDavid du Colombier 17180ee5cbfSDavid du Colombier breakout:; 17280ee5cbfSDavid du Colombier /* 17380ee5cbfSDavid du Colombier * if need to ignore headers we've already parsed, 17480ee5cbfSDavid du Colombier * reset & start over. need to save authorization 17580ee5cbfSDavid du Colombier * info because it's written over when parsed. 17680ee5cbfSDavid du Colombier */ 17780ee5cbfSDavid du Colombier if(reparse){ 17880ee5cbfSDavid du Colombier u = h->c->head.authuser; 17980ee5cbfSDavid du Colombier p = h->c->head.authpass; 18080ee5cbfSDavid du Colombier memset(&h->c->head, 0, sizeof(h->c->head)); 18180ee5cbfSDavid du Colombier h->c->head.authuser = u; 18280ee5cbfSDavid du Colombier h->c->head.authpass = p; 18380ee5cbfSDavid du Colombier 18480ee5cbfSDavid du Colombier h->c->hpos = h->hstart; 18580ee5cbfSDavid du Colombier longjmp(h->jmp, 1); 18680ee5cbfSDavid du Colombier } 18780ee5cbfSDavid du Colombier } 18880ee5cbfSDavid du Colombier 18980ee5cbfSDavid du Colombier int 19080ee5cbfSDavid du Colombier hparseheaders(HConnect *c, int timeout) 19180ee5cbfSDavid du Colombier { 19280ee5cbfSDavid du Colombier Hlex h; 19380ee5cbfSDavid du Colombier 19480ee5cbfSDavid du Colombier c->head.fresh_thresh = 0; 19580ee5cbfSDavid du Colombier c->head.fresh_have = 0; 19680ee5cbfSDavid du Colombier c->head.persist = 0; 19780ee5cbfSDavid du Colombier if(c->req.vermaj == 0){ 19880ee5cbfSDavid du Colombier c->head.host = hmydomain; 19980ee5cbfSDavid du Colombier return 1; 20080ee5cbfSDavid du Colombier } 20180ee5cbfSDavid du Colombier 20280ee5cbfSDavid du Colombier memset(&h, 0, sizeof(h)); 20380ee5cbfSDavid du Colombier h.c = c; 204e059317eSDavid du Colombier if(timeout) 20580ee5cbfSDavid du Colombier alarm(timeout); 206e059317eSDavid du Colombier if(hgethead(c, 1) < 0) 2079a747e4fSDavid du Colombier return -1; 208e059317eSDavid du Colombier if(timeout) 20980ee5cbfSDavid du Colombier alarm(0); 21080ee5cbfSDavid du Colombier h.hstart = c->hpos; 21180ee5cbfSDavid du Colombier 21280ee5cbfSDavid du Colombier if(setjmp(h.jmp) == -1) 21380ee5cbfSDavid du Colombier return -1; 21480ee5cbfSDavid du Colombier 21580ee5cbfSDavid du Colombier h.eol = 0; 21680ee5cbfSDavid du Colombier h.eoh = 0; 21780ee5cbfSDavid du Colombier h.tok = '\n'; 21880ee5cbfSDavid du Colombier while(lex(&h) != '\n'){ 21980ee5cbfSDavid du Colombier if(h.tok == Word && lex(&h) == ':') 22080ee5cbfSDavid du Colombier parsejump(&h, hstrdup(c, h.wordval)); 22180ee5cbfSDavid du Colombier while(h.tok != '\n') 22280ee5cbfSDavid du Colombier lex(&h); 22380ee5cbfSDavid du Colombier h.eol = h.eoh; 22480ee5cbfSDavid du Colombier } 22580ee5cbfSDavid du Colombier 22680ee5cbfSDavid du Colombier if(http11(c)){ 22780ee5cbfSDavid du Colombier /* 22880ee5cbfSDavid du Colombier * according to the http/1.1 spec, 22980ee5cbfSDavid du Colombier * these rules must be followed 23080ee5cbfSDavid du Colombier */ 23180ee5cbfSDavid du Colombier if(c->head.host == nil){ 23280ee5cbfSDavid du Colombier hfail(c, HBadReq, nil); 23380ee5cbfSDavid du Colombier return -1; 23480ee5cbfSDavid du Colombier } 23580ee5cbfSDavid du Colombier if(c->req.urihost != nil) 23680ee5cbfSDavid du Colombier c->head.host = c->req.urihost; 23780ee5cbfSDavid du Colombier /* 23880ee5cbfSDavid du Colombier * also need to check host is actually this one 23980ee5cbfSDavid du Colombier */ 24080ee5cbfSDavid du Colombier }else if(c->head.host == nil) 24180ee5cbfSDavid du Colombier c->head.host = hmydomain; 24280ee5cbfSDavid du Colombier return 1; 24380ee5cbfSDavid du Colombier } 24480ee5cbfSDavid du Colombier 24580ee5cbfSDavid du Colombier /* 24680ee5cbfSDavid du Colombier * mimeparams : | mimeparams ";" mimepara 24780ee5cbfSDavid du Colombier * mimeparam : token "=" token | token "=" qstring 24880ee5cbfSDavid du Colombier */ 24980ee5cbfSDavid du Colombier static HSPairs* 25080ee5cbfSDavid du Colombier mimeparams(Hlex *h) 25180ee5cbfSDavid du Colombier { 25280ee5cbfSDavid du Colombier HSPairs *p; 25380ee5cbfSDavid du Colombier char *s; 25480ee5cbfSDavid du Colombier 25580ee5cbfSDavid du Colombier p = nil; 25680ee5cbfSDavid du Colombier for(;;){ 25780ee5cbfSDavid du Colombier if(lex(h) != Word) 25880ee5cbfSDavid du Colombier break; 25980ee5cbfSDavid du Colombier s = hstrdup(h->c, h->wordval); 26080ee5cbfSDavid du Colombier if(lex(h) != Word && h->tok != QString) 26180ee5cbfSDavid du Colombier break; 26280ee5cbfSDavid du Colombier p = hmkspairs(h->c, s, hstrdup(h->c, h->wordval), p); 26380ee5cbfSDavid du Colombier } 26480ee5cbfSDavid du Colombier return hrevspairs(p); 26580ee5cbfSDavid du Colombier } 26680ee5cbfSDavid du Colombier 26780ee5cbfSDavid du Colombier /* 26880ee5cbfSDavid du Colombier * mimehfields : mimehfield | mimehfields commas mimehfield 26980ee5cbfSDavid du Colombier * mimehfield : token mimeparams 27080ee5cbfSDavid du Colombier * commas : "," | commas "," 27180ee5cbfSDavid du Colombier */ 27280ee5cbfSDavid du Colombier static HFields* 27380ee5cbfSDavid du Colombier mimehfields(Hlex *h) 27480ee5cbfSDavid du Colombier { 27580ee5cbfSDavid du Colombier HFields *f; 27680ee5cbfSDavid du Colombier 27780ee5cbfSDavid du Colombier f = nil; 27880ee5cbfSDavid du Colombier for(;;){ 27980ee5cbfSDavid du Colombier while(lex(h) != Word) 28080ee5cbfSDavid du Colombier if(h->tok != ',') 28180ee5cbfSDavid du Colombier goto breakout; 28280ee5cbfSDavid du Colombier 28380ee5cbfSDavid du Colombier f = hmkhfields(h->c, hstrdup(h->c, h->wordval), nil, f); 28480ee5cbfSDavid du Colombier 28580ee5cbfSDavid du Colombier if(lex(h) == ';') 28680ee5cbfSDavid du Colombier f->params = mimeparams(h); 28780ee5cbfSDavid du Colombier if(h->tok != ',') 28880ee5cbfSDavid du Colombier break; 28980ee5cbfSDavid du Colombier } 29080ee5cbfSDavid du Colombier breakout:; 29180ee5cbfSDavid du Colombier return hrevhfields(f); 29280ee5cbfSDavid du Colombier } 29380ee5cbfSDavid du Colombier 29480ee5cbfSDavid du Colombier /* 29580ee5cbfSDavid du Colombier * parse a list of acceptable types, encodings, languages, etc. 29680ee5cbfSDavid du Colombier */ 29780ee5cbfSDavid du Colombier static HContent* 29880ee5cbfSDavid du Colombier mimeok(Hlex *h, char *name, int multipart, HContent *head) 29980ee5cbfSDavid du Colombier { 30080ee5cbfSDavid du Colombier char *generic, *specific, *s; 30180ee5cbfSDavid du Colombier float v; 30280ee5cbfSDavid du Colombier 30380ee5cbfSDavid du Colombier /* 30480ee5cbfSDavid du Colombier * each type is separated by one or more commas 30580ee5cbfSDavid du Colombier */ 30680ee5cbfSDavid du Colombier while(lex(h) != Word) 30780ee5cbfSDavid du Colombier if(h->tok != ',') 30880ee5cbfSDavid du Colombier return head; 30980ee5cbfSDavid du Colombier 31080ee5cbfSDavid du Colombier generic = hstrdup(h->c, h->wordval); 31180ee5cbfSDavid du Colombier lex(h); 31280ee5cbfSDavid du Colombier if(h->tok == '/' || multipart){ 31380ee5cbfSDavid du Colombier /* 31480ee5cbfSDavid du Colombier * at one time, IE5 improperly said '*' for single types 31580ee5cbfSDavid du Colombier */ 31680ee5cbfSDavid du Colombier if(h->tok != '/') 31780ee5cbfSDavid du Colombier return nil; 31880ee5cbfSDavid du Colombier if(lex(h) != Word) 31980ee5cbfSDavid du Colombier return head; 32080ee5cbfSDavid du Colombier specific = hstrdup(h->c, h->wordval); 32180ee5cbfSDavid du Colombier if(!multipart && strcmp(specific, "*") != 0) 32280ee5cbfSDavid du Colombier return head; 32380ee5cbfSDavid du Colombier lex(h); 32480ee5cbfSDavid du Colombier }else 32580ee5cbfSDavid du Colombier specific = nil; 32680ee5cbfSDavid du Colombier head = hmkcontent(h->c, generic, specific, head); 32780ee5cbfSDavid du Colombier 32880ee5cbfSDavid du Colombier for(;;){ 32980ee5cbfSDavid du Colombier switch(h->tok){ 33080ee5cbfSDavid du Colombier case ';': 33180ee5cbfSDavid du Colombier /* 33280ee5cbfSDavid du Colombier * should make a list of these params 33380ee5cbfSDavid du Colombier * for accept, they fall into two classes: 33480ee5cbfSDavid du Colombier * up to a q=..., they modify the media type. 33580ee5cbfSDavid du Colombier * afterwards, they acceptance criteria 33680ee5cbfSDavid du Colombier */ 33780ee5cbfSDavid du Colombier if(lex(h) == Word){ 33880ee5cbfSDavid du Colombier s = hstrdup(h->c, h->wordval); 33980ee5cbfSDavid du Colombier if(lex(h) != '=' || lex(h) != Word && h->tok != QString) 34080ee5cbfSDavid du Colombier return head; 34180ee5cbfSDavid du Colombier v = strtod(h->wordval, nil); 34280ee5cbfSDavid du Colombier if(strcmp(s, "q") == 0) 34380ee5cbfSDavid du Colombier head->q = v; 34480ee5cbfSDavid du Colombier else if(strcmp(s, "mxb") == 0) 34580ee5cbfSDavid du Colombier head->mxb = v; 34651711cb6SDavid du Colombier else{ 34751711cb6SDavid du Colombier /* cope with accept: application/xhtml+xml; profile=http://www.wapforum.org/xhtml, */ 34851711cb6SDavid du Colombier while(lex(h) == Word || (h->tok != ',' && h->eol == 0) ) 34951711cb6SDavid du Colombier ; 35051711cb6SDavid du Colombier return mimeok(h, name, multipart, head); 35151711cb6SDavid du Colombier } 35280ee5cbfSDavid du Colombier } 35380ee5cbfSDavid du Colombier break; 35480ee5cbfSDavid du Colombier case ',': 35580ee5cbfSDavid du Colombier return mimeok(h, name, multipart, head); 35680ee5cbfSDavid du Colombier default: 35780ee5cbfSDavid du Colombier return head; 35880ee5cbfSDavid du Colombier } 35980ee5cbfSDavid du Colombier lex(h); 36080ee5cbfSDavid du Colombier } 36180ee5cbfSDavid du Colombier } 36280ee5cbfSDavid du Colombier 36380ee5cbfSDavid du Colombier /* 36480ee5cbfSDavid du Colombier * parse a list of entity tags 36580ee5cbfSDavid du Colombier * 1#entity-tag 36680ee5cbfSDavid du Colombier * entity-tag = [weak] opaque-tag 36780ee5cbfSDavid du Colombier * weak = "W/" 36880ee5cbfSDavid du Colombier * opaque-tag = quoted-string 36980ee5cbfSDavid du Colombier */ 37080ee5cbfSDavid du Colombier static HETag* 37180ee5cbfSDavid du Colombier mimeetag(Hlex *h, HETag *head) 37280ee5cbfSDavid du Colombier { 37380ee5cbfSDavid du Colombier HETag *e; 37480ee5cbfSDavid du Colombier int weak; 37580ee5cbfSDavid du Colombier 37680ee5cbfSDavid du Colombier for(;;){ 37780ee5cbfSDavid du Colombier while(lex(h) != Word && h->tok != QString) 37880ee5cbfSDavid du Colombier if(h->tok != ',') 37980ee5cbfSDavid du Colombier return head; 38080ee5cbfSDavid du Colombier 38180ee5cbfSDavid du Colombier weak = 0; 38280ee5cbfSDavid du Colombier if(h->tok == Word && strcmp(h->wordval, "*") != 0){ 38380ee5cbfSDavid du Colombier if(strcmp(h->wordval, "W") != 0) 38480ee5cbfSDavid du Colombier return head; 38580ee5cbfSDavid du Colombier if(lex(h) != '/' || lex(h) != QString) 38680ee5cbfSDavid du Colombier return head; 38780ee5cbfSDavid du Colombier weak = 1; 38880ee5cbfSDavid du Colombier } 38980ee5cbfSDavid du Colombier 39080ee5cbfSDavid du Colombier e = halloc(h->c, sizeof(HETag)); 39180ee5cbfSDavid du Colombier e->etag = hstrdup(h->c, h->wordval); 39280ee5cbfSDavid du Colombier e->weak = weak; 39380ee5cbfSDavid du Colombier e->next = head; 39480ee5cbfSDavid du Colombier head = e; 39580ee5cbfSDavid du Colombier 39680ee5cbfSDavid du Colombier if(lex(h) != ',') 39780ee5cbfSDavid du Colombier return head; 39880ee5cbfSDavid du Colombier } 39980ee5cbfSDavid du Colombier } 40080ee5cbfSDavid du Colombier 40180ee5cbfSDavid du Colombier /* 40280ee5cbfSDavid du Colombier * ranges-specifier = byte-ranges-specifier 40380ee5cbfSDavid du Colombier * byte-ranges-specifier = "bytes" "=" byte-range-set 40480ee5cbfSDavid du Colombier * byte-range-set = 1#(byte-range-spec|suffix-byte-range-spec) 40580ee5cbfSDavid du Colombier * byte-range-spec = byte-pos "-" [byte-pos] 40680ee5cbfSDavid du Colombier * byte-pos = 1*DIGIT 40780ee5cbfSDavid du Colombier * suffix-byte-range-spec = "-" suffix-length 40880ee5cbfSDavid du Colombier * suffix-length = 1*DIGIT 40980ee5cbfSDavid du Colombier * 41080ee5cbfSDavid du Colombier * syntactically invalid range specifiers cause the 41180ee5cbfSDavid du Colombier * entire header field to be ignored. 41280ee5cbfSDavid du Colombier * it is syntactically incorrect for the second byte pos 41380ee5cbfSDavid du Colombier * to be smaller than the first byte pos 41480ee5cbfSDavid du Colombier */ 41580ee5cbfSDavid du Colombier static HRange* 41680ee5cbfSDavid du Colombier mimeranges(Hlex *h, HRange *head) 41780ee5cbfSDavid du Colombier { 41880ee5cbfSDavid du Colombier HRange *r, *rh, *tail; 41980ee5cbfSDavid du Colombier char *w; 42080ee5cbfSDavid du Colombier ulong start, stop; 42180ee5cbfSDavid du Colombier int suf; 42280ee5cbfSDavid du Colombier 42380ee5cbfSDavid du Colombier if(lex(h) != Word || strcmp(h->wordval, "bytes") != 0 || lex(h) != '=') 42480ee5cbfSDavid du Colombier return head; 42580ee5cbfSDavid du Colombier 42680ee5cbfSDavid du Colombier rh = nil; 42780ee5cbfSDavid du Colombier tail = nil; 42880ee5cbfSDavid du Colombier for(;;){ 42980ee5cbfSDavid du Colombier while(lex(h) != Word){ 43080ee5cbfSDavid du Colombier if(h->tok != ','){ 43180ee5cbfSDavid du Colombier if(h->tok == '\n') 43280ee5cbfSDavid du Colombier goto breakout; 43380ee5cbfSDavid du Colombier return head; 43480ee5cbfSDavid du Colombier } 43580ee5cbfSDavid du Colombier } 43680ee5cbfSDavid du Colombier 43780ee5cbfSDavid du Colombier w = h->wordval; 43880ee5cbfSDavid du Colombier start = 0; 43980ee5cbfSDavid du Colombier suf = 1; 44080ee5cbfSDavid du Colombier if(w[0] != '-'){ 44180ee5cbfSDavid du Colombier suf = 0; 44280ee5cbfSDavid du Colombier start = digtoul(w, &w); 44380ee5cbfSDavid du Colombier if(w[0] != '-') 44480ee5cbfSDavid du Colombier return head; 44580ee5cbfSDavid du Colombier } 44680ee5cbfSDavid du Colombier w++; 44780ee5cbfSDavid du Colombier stop = ~0UL; 44880ee5cbfSDavid du Colombier if(w[0] != '\0'){ 44980ee5cbfSDavid du Colombier stop = digtoul(w, &w); 45080ee5cbfSDavid du Colombier if(w[0] != '\0') 45180ee5cbfSDavid du Colombier return head; 45280ee5cbfSDavid du Colombier if(!suf && stop < start) 45380ee5cbfSDavid du Colombier return head; 45480ee5cbfSDavid du Colombier } 45580ee5cbfSDavid du Colombier 45680ee5cbfSDavid du Colombier r = halloc(h->c, sizeof(HRange)); 45780ee5cbfSDavid du Colombier r->suffix = suf; 45880ee5cbfSDavid du Colombier r->start = start; 45980ee5cbfSDavid du Colombier r->stop = stop; 46080ee5cbfSDavid du Colombier r->next = nil; 46180ee5cbfSDavid du Colombier if(rh == nil) 46280ee5cbfSDavid du Colombier rh = r; 46380ee5cbfSDavid du Colombier else 46480ee5cbfSDavid du Colombier tail->next = r; 46580ee5cbfSDavid du Colombier tail = r; 46680ee5cbfSDavid du Colombier 46780ee5cbfSDavid du Colombier if(lex(h) != ','){ 46880ee5cbfSDavid du Colombier if(h->tok == '\n') 46980ee5cbfSDavid du Colombier break; 47080ee5cbfSDavid du Colombier return head; 47180ee5cbfSDavid du Colombier } 47280ee5cbfSDavid du Colombier } 47380ee5cbfSDavid du Colombier breakout:; 47480ee5cbfSDavid du Colombier 47580ee5cbfSDavid du Colombier if(head == nil) 47680ee5cbfSDavid du Colombier return rh; 47780ee5cbfSDavid du Colombier 47880ee5cbfSDavid du Colombier for(tail = head; tail->next != nil; tail = tail->next) 47980ee5cbfSDavid du Colombier ; 48080ee5cbfSDavid du Colombier tail->next = rh; 48180ee5cbfSDavid du Colombier return head; 48280ee5cbfSDavid du Colombier } 48380ee5cbfSDavid du Colombier 48480ee5cbfSDavid du Colombier static void 48580ee5cbfSDavid du Colombier mimeaccept(Hlex *h, char *name) 48680ee5cbfSDavid du Colombier { 48780ee5cbfSDavid du Colombier h->c->head.oktype = mimeok(h, name, 1, h->c->head.oktype); 48880ee5cbfSDavid du Colombier } 48980ee5cbfSDavid du Colombier 49080ee5cbfSDavid du Colombier static void 49180ee5cbfSDavid du Colombier mimeacceptchar(Hlex *h, char *name) 49280ee5cbfSDavid du Colombier { 49380ee5cbfSDavid du Colombier h->c->head.okchar = mimeok(h, name, 0, h->c->head.okchar); 49480ee5cbfSDavid du Colombier } 49580ee5cbfSDavid du Colombier 49680ee5cbfSDavid du Colombier static void 49780ee5cbfSDavid du Colombier mimeacceptenc(Hlex *h, char *name) 49880ee5cbfSDavid du Colombier { 49980ee5cbfSDavid du Colombier h->c->head.okencode = mimeok(h, name, 0, h->c->head.okencode); 50080ee5cbfSDavid du Colombier } 50180ee5cbfSDavid du Colombier 50280ee5cbfSDavid du Colombier static void 50380ee5cbfSDavid du Colombier mimeacceptlang(Hlex *h, char *name) 50480ee5cbfSDavid du Colombier { 50580ee5cbfSDavid du Colombier h->c->head.oklang = mimeok(h, name, 0, h->c->head.oklang); 50680ee5cbfSDavid du Colombier } 50780ee5cbfSDavid du Colombier 50880ee5cbfSDavid du Colombier static void 50980ee5cbfSDavid du Colombier mimemodified(Hlex *h, char *) 51080ee5cbfSDavid du Colombier { 51180ee5cbfSDavid du Colombier lexhead(h); 51280ee5cbfSDavid du Colombier h->c->head.ifmodsince = hdate2sec(h->wordval); 51380ee5cbfSDavid du Colombier } 51480ee5cbfSDavid du Colombier 51580ee5cbfSDavid du Colombier static void 51680ee5cbfSDavid du Colombier mimeunmodified(Hlex *h, char *) 51780ee5cbfSDavid du Colombier { 51880ee5cbfSDavid du Colombier lexhead(h); 51980ee5cbfSDavid du Colombier h->c->head.ifunmodsince = hdate2sec(h->wordval); 52080ee5cbfSDavid du Colombier } 52180ee5cbfSDavid du Colombier 52280ee5cbfSDavid du Colombier static void 52380ee5cbfSDavid du Colombier mimematch(Hlex *h, char *) 52480ee5cbfSDavid du Colombier { 52580ee5cbfSDavid du Colombier h->c->head.ifmatch = mimeetag(h, h->c->head.ifmatch); 52680ee5cbfSDavid du Colombier } 52780ee5cbfSDavid du Colombier 52880ee5cbfSDavid du Colombier static void 52980ee5cbfSDavid du Colombier mimenomatch(Hlex *h, char *) 53080ee5cbfSDavid du Colombier { 53180ee5cbfSDavid du Colombier h->c->head.ifnomatch = mimeetag(h, h->c->head.ifnomatch); 53280ee5cbfSDavid du Colombier } 53380ee5cbfSDavid du Colombier 53480ee5cbfSDavid du Colombier /* 53580ee5cbfSDavid du Colombier * argument is either etag or date 53680ee5cbfSDavid du Colombier */ 53780ee5cbfSDavid du Colombier static void 53880ee5cbfSDavid du Colombier mimeifrange(Hlex *h, char *) 53980ee5cbfSDavid du Colombier { 54080ee5cbfSDavid du Colombier int c, d, et; 54180ee5cbfSDavid du Colombier 54280ee5cbfSDavid du Colombier et = 0; 54380ee5cbfSDavid du Colombier c = getc(h); 54480ee5cbfSDavid du Colombier while(c == ' ' || c == '\t') 54580ee5cbfSDavid du Colombier c = getc(h); 54680ee5cbfSDavid du Colombier if(c == '"') 54780ee5cbfSDavid du Colombier et = 1; 54880ee5cbfSDavid du Colombier else if(c == 'W'){ 54980ee5cbfSDavid du Colombier d = getc(h); 55080ee5cbfSDavid du Colombier if(d == '/') 55180ee5cbfSDavid du Colombier et = 1; 55280ee5cbfSDavid du Colombier ungetc(h); 55380ee5cbfSDavid du Colombier } 55480ee5cbfSDavid du Colombier ungetc(h); 55580ee5cbfSDavid du Colombier if(et){ 55680ee5cbfSDavid du Colombier h->c->head.ifrangeetag = mimeetag(h, h->c->head.ifrangeetag); 55780ee5cbfSDavid du Colombier }else{ 55880ee5cbfSDavid du Colombier lexhead(h); 55980ee5cbfSDavid du Colombier h->c->head.ifrangedate = hdate2sec(h->wordval); 56080ee5cbfSDavid du Colombier } 56180ee5cbfSDavid du Colombier } 56280ee5cbfSDavid du Colombier 56380ee5cbfSDavid du Colombier static void 56480ee5cbfSDavid du Colombier mimerange(Hlex *h, char *) 56580ee5cbfSDavid du Colombier { 56680ee5cbfSDavid du Colombier h->c->head.range = mimeranges(h, h->c->head.range); 56780ee5cbfSDavid du Colombier } 56880ee5cbfSDavid du Colombier 56980ee5cbfSDavid du Colombier /* 57080ee5cbfSDavid du Colombier * note: netscape and ie through versions 4.7 and 4 57180ee5cbfSDavid du Colombier * support only basic authorization, so that is all that is supported here 57280ee5cbfSDavid du Colombier * 57380ee5cbfSDavid du Colombier * "Authorization" ":" "Basic" base64-user-pass 57480ee5cbfSDavid du Colombier * where base64-user-pass is the base64 encoding of 57580ee5cbfSDavid du Colombier * username ":" password 57680ee5cbfSDavid du Colombier */ 57780ee5cbfSDavid du Colombier static void 57880ee5cbfSDavid du Colombier mimeauthorization(Hlex *h, char *) 57980ee5cbfSDavid du Colombier { 58080ee5cbfSDavid du Colombier char *up, *p; 58180ee5cbfSDavid du Colombier int n; 58280ee5cbfSDavid du Colombier 58380ee5cbfSDavid du Colombier if(lex(h) != Word || cistrcmp(h->wordval, "basic") != 0) 58480ee5cbfSDavid du Colombier return; 58580ee5cbfSDavid du Colombier 58680ee5cbfSDavid du Colombier n = lexbase64(h); 58780ee5cbfSDavid du Colombier if(!n) 58880ee5cbfSDavid du Colombier return; 58980ee5cbfSDavid du Colombier 59080ee5cbfSDavid du Colombier /* 59180ee5cbfSDavid du Colombier * wipe out source for password, so it won't be logged. 59280ee5cbfSDavid du Colombier * it is replaced by a single =, 59380ee5cbfSDavid du Colombier * which is valid base64, but not ok for an auth reponse. 59480ee5cbfSDavid du Colombier * therefore future parses of the header field will not overwrite 59580ee5cbfSDavid du Colombier * authuser and authpass. 59680ee5cbfSDavid du Colombier */ 59780ee5cbfSDavid du Colombier memmove(h->c->hpos - (n - 1), h->c->hpos, h->c->hstop - h->c->hpos); 59880ee5cbfSDavid du Colombier h->c->hstop -= n - 1; 59980ee5cbfSDavid du Colombier *h->c->hstop = '\0'; 60080ee5cbfSDavid du Colombier h->c->hpos -= n - 1; 60180ee5cbfSDavid du Colombier h->c->hpos[-1] = '='; 60280ee5cbfSDavid du Colombier 60380ee5cbfSDavid du Colombier up = halloc(h->c, n + 1); 60480ee5cbfSDavid du Colombier n = dec64((uchar*)up, n, h->wordval, n); 60580ee5cbfSDavid du Colombier up[n] = '\0'; 60680ee5cbfSDavid du Colombier p = strchr(up, ':'); 60780ee5cbfSDavid du Colombier if(p != nil){ 60880ee5cbfSDavid du Colombier *p++ = '\0'; 60980ee5cbfSDavid du Colombier h->c->head.authuser = hstrdup(h->c, up); 61080ee5cbfSDavid du Colombier h->c->head.authpass = hstrdup(h->c, p); 61180ee5cbfSDavid du Colombier } 61280ee5cbfSDavid du Colombier } 61380ee5cbfSDavid du Colombier 61480ee5cbfSDavid du Colombier static void 61580ee5cbfSDavid du Colombier mimeagent(Hlex *h, char *) 61680ee5cbfSDavid du Colombier { 61780ee5cbfSDavid du Colombier lexhead(h); 61880ee5cbfSDavid du Colombier h->c->head.client = hstrdup(h->c, h->wordval); 61980ee5cbfSDavid du Colombier } 62080ee5cbfSDavid du Colombier 62180ee5cbfSDavid du Colombier static void 62280ee5cbfSDavid du Colombier mimefrom(Hlex *h, char *) 62380ee5cbfSDavid du Colombier { 62480ee5cbfSDavid du Colombier lexhead(h); 62580ee5cbfSDavid du Colombier } 62680ee5cbfSDavid du Colombier 62780ee5cbfSDavid du Colombier static void 62880ee5cbfSDavid du Colombier mimehost(Hlex *h, char *) 62980ee5cbfSDavid du Colombier { 63080ee5cbfSDavid du Colombier char *hd; 63180ee5cbfSDavid du Colombier 63280ee5cbfSDavid du Colombier lexhead(h); 63380ee5cbfSDavid du Colombier for(hd = h->wordval; *hd == ' ' || *hd == '\t'; hd++) 63480ee5cbfSDavid du Colombier ; 63580ee5cbfSDavid du Colombier h->c->head.host = hlower(hstrdup(h->c, hd)); 63680ee5cbfSDavid du Colombier } 63780ee5cbfSDavid du Colombier 63880ee5cbfSDavid du Colombier /* 63980ee5cbfSDavid du Colombier * if present, implies that a message body follows the headers 64080ee5cbfSDavid du Colombier * "content-length" ":" digits 64180ee5cbfSDavid du Colombier */ 64280ee5cbfSDavid du Colombier static void 64380ee5cbfSDavid du Colombier mimecontlen(Hlex *h, char *) 64480ee5cbfSDavid du Colombier { 64580ee5cbfSDavid du Colombier char *e; 64680ee5cbfSDavid du Colombier ulong v; 64780ee5cbfSDavid du Colombier 64880ee5cbfSDavid du Colombier if(lex(h) != Word) 64980ee5cbfSDavid du Colombier return; 65080ee5cbfSDavid du Colombier e = h->wordval; 65180ee5cbfSDavid du Colombier v = digtoul(e, &e); 65280ee5cbfSDavid du Colombier if(v == ~0UL || *e != '\0') 65380ee5cbfSDavid du Colombier return; 65480ee5cbfSDavid du Colombier h->c->head.contlen = v; 65580ee5cbfSDavid du Colombier } 65680ee5cbfSDavid du Colombier 65780ee5cbfSDavid du Colombier /* 65880ee5cbfSDavid du Colombier * mimexpect : "expect" ":" expects 65980ee5cbfSDavid du Colombier * expects : | expects "," expect 66080ee5cbfSDavid du Colombier * expect : "100-continue" | token | token "=" token expectparams | token "=" qstring expectparams 66180ee5cbfSDavid du Colombier * expectparams : ";" token | ";" token "=" token | token "=" qstring 66280ee5cbfSDavid du Colombier * for now, we merely parse "100-continue" or anything else. 66380ee5cbfSDavid du Colombier */ 66480ee5cbfSDavid du Colombier static void 66580ee5cbfSDavid du Colombier mimeexpect(Hlex *h, char *) 66680ee5cbfSDavid du Colombier { 66780ee5cbfSDavid du Colombier if(lex(h) != Word || cistrcmp(h->wordval, "100-continue") != 0 || lex(h) != '\n') 66880ee5cbfSDavid du Colombier h->c->head.expectother = 1; 66980ee5cbfSDavid du Colombier h->c->head.expectcont = 1; 67080ee5cbfSDavid du Colombier } 67180ee5cbfSDavid du Colombier 67280ee5cbfSDavid du Colombier static void 67380ee5cbfSDavid du Colombier mimetransenc(Hlex *h, char *) 67480ee5cbfSDavid du Colombier { 67580ee5cbfSDavid du Colombier h->c->head.transenc = mimehfields(h); 67680ee5cbfSDavid du Colombier } 67780ee5cbfSDavid du Colombier 67880ee5cbfSDavid du Colombier static void 6792bef681aSDavid du Colombier mimecookie(Hlex *h, char *) 6802bef681aSDavid du Colombier { 6812bef681aSDavid du Colombier char *s; 6822bef681aSDavid du Colombier HSPairs *p; 6832bef681aSDavid du Colombier 6842bef681aSDavid du Colombier p = nil; 6852bef681aSDavid du Colombier for(;;){ 6862bef681aSDavid du Colombier while(lex(h) != Word) 6872bef681aSDavid du Colombier if(h->tok != ';' && h->tok != ',') 6882bef681aSDavid du Colombier goto breakout; 6892bef681aSDavid du Colombier s = hstrdup(h->c, h->wordval); 6902bef681aSDavid du Colombier while (lex(h) != Word && h->tok != QString) 6912bef681aSDavid du Colombier if (h->tok != '=') 6922bef681aSDavid du Colombier goto breakout; 6932bef681aSDavid du Colombier p = hmkspairs(h->c, s, hstrdup(h->c, h->wordval), p); 6942bef681aSDavid du Colombier } 6952bef681aSDavid du Colombier breakout: 6962bef681aSDavid du Colombier h->c->head.cookie = hrevspairs(p); 6972bef681aSDavid du Colombier } 6982bef681aSDavid du Colombier 6992bef681aSDavid du Colombier static void 70080ee5cbfSDavid du Colombier mimefresh(Hlex *h, char *) 70180ee5cbfSDavid du Colombier { 70280ee5cbfSDavid du Colombier char *s; 70380ee5cbfSDavid du Colombier 70480ee5cbfSDavid du Colombier lexhead(h); 70580ee5cbfSDavid du Colombier for(s = h->wordval; *s && (*s==' ' || *s=='\t'); s++) 70680ee5cbfSDavid du Colombier ; 70780ee5cbfSDavid du Colombier if(strncmp(s, "pathstat/", 9) == 0) 70880ee5cbfSDavid du Colombier h->c->head.fresh_thresh = atoi(s+9); 70980ee5cbfSDavid du Colombier else if(strncmp(s, "have/", 5) == 0) 71080ee5cbfSDavid du Colombier h->c->head.fresh_have = atoi(s+5); 71180ee5cbfSDavid du Colombier } 71280ee5cbfSDavid du Colombier 71380ee5cbfSDavid du Colombier static void 71480ee5cbfSDavid du Colombier mimeignore(Hlex *h, char *) 71580ee5cbfSDavid du Colombier { 71680ee5cbfSDavid du Colombier lexhead(h); 71780ee5cbfSDavid du Colombier } 71880ee5cbfSDavid du Colombier 71980ee5cbfSDavid du Colombier static void 72080ee5cbfSDavid du Colombier parsejump(Hlex *h, char *k) 72180ee5cbfSDavid du Colombier { 72280ee5cbfSDavid du Colombier int l, r, m; 72380ee5cbfSDavid du Colombier 72480ee5cbfSDavid du Colombier l = 1; 72580ee5cbfSDavid du Colombier r = nelem(mimehead) - 1; 72680ee5cbfSDavid du Colombier while(l <= r){ 72780ee5cbfSDavid du Colombier m = (r + l) >> 1; 72880ee5cbfSDavid du Colombier if(cistrcmp(mimehead[m].name, k) <= 0) 72980ee5cbfSDavid du Colombier l = m + 1; 73080ee5cbfSDavid du Colombier else 73180ee5cbfSDavid du Colombier r = m - 1; 73280ee5cbfSDavid du Colombier } 73380ee5cbfSDavid du Colombier m = l - 1; 73480ee5cbfSDavid du Colombier if(cistrcmp(mimehead[m].name, k) == 0 && !mimehead[m].ignore){ 73580ee5cbfSDavid du Colombier mimehead[m].seen = 1; 73680ee5cbfSDavid du Colombier (*mimehead[m].parse)(h, k); 73780ee5cbfSDavid du Colombier }else 73880ee5cbfSDavid du Colombier mimeignore(h, k); 73980ee5cbfSDavid du Colombier } 74080ee5cbfSDavid du Colombier 74180ee5cbfSDavid du Colombier static int 74280ee5cbfSDavid du Colombier lex(Hlex *h) 74380ee5cbfSDavid du Colombier { 74480ee5cbfSDavid du Colombier return h->tok = lex1(h, 0); 74580ee5cbfSDavid du Colombier } 74680ee5cbfSDavid du Colombier 74780ee5cbfSDavid du Colombier static int 74880ee5cbfSDavid du Colombier lexbase64(Hlex *h) 74980ee5cbfSDavid du Colombier { 75080ee5cbfSDavid du Colombier int c, n; 75180ee5cbfSDavid du Colombier 75280ee5cbfSDavid du Colombier n = 0; 75380ee5cbfSDavid du Colombier lex1(h, 1); 75480ee5cbfSDavid du Colombier 75580ee5cbfSDavid du Colombier while((c = getc(h)) >= 0){ 756*f9e1cf08SDavid du Colombier if(!isalnum(c) && c != '+' && c != '/'){ 75780ee5cbfSDavid du Colombier ungetc(h); 75880ee5cbfSDavid du Colombier break; 75980ee5cbfSDavid du Colombier } 76080ee5cbfSDavid du Colombier if(n < HMaxWord-1) 76180ee5cbfSDavid du Colombier h->wordval[n++] = c; 76280ee5cbfSDavid du Colombier } 76380ee5cbfSDavid du Colombier h->wordval[n] = '\0'; 76480ee5cbfSDavid du Colombier return n; 76580ee5cbfSDavid du Colombier } 76680ee5cbfSDavid du Colombier 76780ee5cbfSDavid du Colombier /* 76880ee5cbfSDavid du Colombier * rfc 822/rfc 1521 lexical analyzer 76980ee5cbfSDavid du Colombier */ 77080ee5cbfSDavid du Colombier static int 77180ee5cbfSDavid du Colombier lex1(Hlex *h, int skipwhite) 77280ee5cbfSDavid du Colombier { 77380ee5cbfSDavid du Colombier int level, c; 77480ee5cbfSDavid du Colombier 77580ee5cbfSDavid du Colombier if(h->eol) 77680ee5cbfSDavid du Colombier return '\n'; 77780ee5cbfSDavid du Colombier 77880ee5cbfSDavid du Colombier top: 77980ee5cbfSDavid du Colombier c = getc(h); 78080ee5cbfSDavid du Colombier switch(c){ 78180ee5cbfSDavid du Colombier case '(': 78280ee5cbfSDavid du Colombier level = 1; 78380ee5cbfSDavid du Colombier while((c = getc(h)) >= 0){ 78480ee5cbfSDavid du Colombier if(c == '\\'){ 78580ee5cbfSDavid du Colombier c = getc(h); 78680ee5cbfSDavid du Colombier if(c < 0) 78780ee5cbfSDavid du Colombier return '\n'; 78880ee5cbfSDavid du Colombier continue; 78980ee5cbfSDavid du Colombier } 79080ee5cbfSDavid du Colombier if(c == '(') 79180ee5cbfSDavid du Colombier level++; 79280ee5cbfSDavid du Colombier else if(c == ')' && --level == 0) 79380ee5cbfSDavid du Colombier break; 79480ee5cbfSDavid du Colombier else if(c == '\n'){ 79580ee5cbfSDavid du Colombier c = getc(h); 79680ee5cbfSDavid du Colombier if(c < 0) 79780ee5cbfSDavid du Colombier return '\n'; 79880ee5cbfSDavid du Colombier if(c == ')' && --level == 0) 79980ee5cbfSDavid du Colombier break; 80080ee5cbfSDavid du Colombier if(c != ' ' && c != '\t'){ 80180ee5cbfSDavid du Colombier ungetc(h); 80280ee5cbfSDavid du Colombier return '\n'; 80380ee5cbfSDavid du Colombier } 80480ee5cbfSDavid du Colombier } 80580ee5cbfSDavid du Colombier } 80680ee5cbfSDavid du Colombier goto top; 80780ee5cbfSDavid du Colombier 80880ee5cbfSDavid du Colombier case ' ': case '\t': 80980ee5cbfSDavid du Colombier goto top; 81080ee5cbfSDavid du Colombier 81180ee5cbfSDavid du Colombier case '\r': 81280ee5cbfSDavid du Colombier c = getc(h); 81380ee5cbfSDavid du Colombier if(c != '\n'){ 81480ee5cbfSDavid du Colombier ungetc(h); 81580ee5cbfSDavid du Colombier goto top; 81680ee5cbfSDavid du Colombier } 81780ee5cbfSDavid du Colombier 81880ee5cbfSDavid du Colombier case '\n': 81980ee5cbfSDavid du Colombier if(h->tok == '\n'){ 82080ee5cbfSDavid du Colombier h->eol = 1; 82180ee5cbfSDavid du Colombier h->eoh = 1; 82280ee5cbfSDavid du Colombier return '\n'; 82380ee5cbfSDavid du Colombier } 82480ee5cbfSDavid du Colombier c = getc(h); 82580ee5cbfSDavid du Colombier if(c < 0){ 82680ee5cbfSDavid du Colombier h->eol = 1; 82780ee5cbfSDavid du Colombier return '\n'; 82880ee5cbfSDavid du Colombier } 82980ee5cbfSDavid du Colombier if(c != ' ' && c != '\t'){ 83080ee5cbfSDavid du Colombier ungetc(h); 83180ee5cbfSDavid du Colombier h->eol = 1; 83280ee5cbfSDavid du Colombier return '\n'; 83380ee5cbfSDavid du Colombier } 83480ee5cbfSDavid du Colombier goto top; 83580ee5cbfSDavid du Colombier 83680ee5cbfSDavid du Colombier case ')': 83780ee5cbfSDavid du Colombier case '<': case '>': 83880ee5cbfSDavid du Colombier case '[': case ']': 83980ee5cbfSDavid du Colombier case '@': case '/': 84080ee5cbfSDavid du Colombier case ',': case ';': case ':': case '?': case '=': 84180ee5cbfSDavid du Colombier if(skipwhite){ 84280ee5cbfSDavid du Colombier ungetc(h); 84380ee5cbfSDavid du Colombier return c; 84480ee5cbfSDavid du Colombier } 84580ee5cbfSDavid du Colombier return c; 84680ee5cbfSDavid du Colombier 84780ee5cbfSDavid du Colombier case '"': 84880ee5cbfSDavid du Colombier if(skipwhite){ 84980ee5cbfSDavid du Colombier ungetc(h); 85080ee5cbfSDavid du Colombier return c; 85180ee5cbfSDavid du Colombier } 85280ee5cbfSDavid du Colombier word(h, "\""); 85380ee5cbfSDavid du Colombier getc(h); /* skip the closing quote */ 85480ee5cbfSDavid du Colombier return QString; 85580ee5cbfSDavid du Colombier 85680ee5cbfSDavid du Colombier default: 85780ee5cbfSDavid du Colombier ungetc(h); 85880ee5cbfSDavid du Colombier if(skipwhite) 85980ee5cbfSDavid du Colombier return c; 86080ee5cbfSDavid du Colombier word(h, "\"(){}<>@,;:/[]?=\r\n \t"); 86180ee5cbfSDavid du Colombier if(h->wordval[0] == '\0'){ 86280ee5cbfSDavid du Colombier h->c->head.closeit = 1; 86380ee5cbfSDavid du Colombier hfail(h->c, HSyntax); 86480ee5cbfSDavid du Colombier longjmp(h->jmp, -1); 86580ee5cbfSDavid du Colombier } 86680ee5cbfSDavid du Colombier return Word; 86780ee5cbfSDavid du Colombier } 868b85a8364SDavid du Colombier /* not reached */ 86980ee5cbfSDavid du Colombier } 87080ee5cbfSDavid du Colombier 87180ee5cbfSDavid du Colombier /* 87280ee5cbfSDavid du Colombier * return the rest of an rfc 822, including \n 87380ee5cbfSDavid du Colombier * do not map to lower case 87480ee5cbfSDavid du Colombier */ 87580ee5cbfSDavid du Colombier static void 87680ee5cbfSDavid du Colombier lexhead(Hlex *h) 87780ee5cbfSDavid du Colombier { 87880ee5cbfSDavid du Colombier int c, n; 87980ee5cbfSDavid du Colombier 88080ee5cbfSDavid du Colombier n = 0; 88180ee5cbfSDavid du Colombier while((c = getc(h)) >= 0){ 88280ee5cbfSDavid du Colombier if(c == '\r') 88380ee5cbfSDavid du Colombier c = wordcr(h); 88480ee5cbfSDavid du Colombier else if(c == '\n') 88580ee5cbfSDavid du Colombier c = wordnl(h); 88680ee5cbfSDavid du Colombier if(c == '\n') 88780ee5cbfSDavid du Colombier break; 88880ee5cbfSDavid du Colombier if(c == '\\'){ 88980ee5cbfSDavid du Colombier c = getc(h); 89080ee5cbfSDavid du Colombier if(c < 0) 89180ee5cbfSDavid du Colombier break; 89280ee5cbfSDavid du Colombier } 89380ee5cbfSDavid du Colombier 89480ee5cbfSDavid du Colombier if(n < HMaxWord-1) 89580ee5cbfSDavid du Colombier h->wordval[n++] = c; 89680ee5cbfSDavid du Colombier } 89780ee5cbfSDavid du Colombier h->tok = '\n'; 89880ee5cbfSDavid du Colombier h->eol = 1; 89980ee5cbfSDavid du Colombier h->wordval[n] = '\0'; 90080ee5cbfSDavid du Colombier } 90180ee5cbfSDavid du Colombier 90280ee5cbfSDavid du Colombier static void 90380ee5cbfSDavid du Colombier word(Hlex *h, char *stop) 90480ee5cbfSDavid du Colombier { 90580ee5cbfSDavid du Colombier int c, n; 90680ee5cbfSDavid du Colombier 90780ee5cbfSDavid du Colombier n = 0; 90880ee5cbfSDavid du Colombier while((c = getc(h)) >= 0){ 90980ee5cbfSDavid du Colombier if(c == '\r') 91080ee5cbfSDavid du Colombier c = wordcr(h); 91180ee5cbfSDavid du Colombier else if(c == '\n') 91280ee5cbfSDavid du Colombier c = wordnl(h); 91380ee5cbfSDavid du Colombier if(c == '\\'){ 91480ee5cbfSDavid du Colombier c = getc(h); 91580ee5cbfSDavid du Colombier if(c < 0) 91680ee5cbfSDavid du Colombier break; 91780ee5cbfSDavid du Colombier }else if(c < 32 || strchr(stop, c) != nil){ 91880ee5cbfSDavid du Colombier ungetc(h); 91980ee5cbfSDavid du Colombier break; 92080ee5cbfSDavid du Colombier } 92180ee5cbfSDavid du Colombier 92280ee5cbfSDavid du Colombier if(n < HMaxWord-1) 92380ee5cbfSDavid du Colombier h->wordval[n++] = c; 92480ee5cbfSDavid du Colombier } 92580ee5cbfSDavid du Colombier h->wordval[n] = '\0'; 92680ee5cbfSDavid du Colombier } 92780ee5cbfSDavid du Colombier 92880ee5cbfSDavid du Colombier static int 92980ee5cbfSDavid du Colombier wordcr(Hlex *h) 93080ee5cbfSDavid du Colombier { 93180ee5cbfSDavid du Colombier int c; 93280ee5cbfSDavid du Colombier 93380ee5cbfSDavid du Colombier c = getc(h); 93480ee5cbfSDavid du Colombier if(c == '\n') 93580ee5cbfSDavid du Colombier return wordnl(h); 93680ee5cbfSDavid du Colombier ungetc(h); 93780ee5cbfSDavid du Colombier return ' '; 93880ee5cbfSDavid du Colombier } 93980ee5cbfSDavid du Colombier 94080ee5cbfSDavid du Colombier static int 94180ee5cbfSDavid du Colombier wordnl(Hlex *h) 94280ee5cbfSDavid du Colombier { 94380ee5cbfSDavid du Colombier int c; 94480ee5cbfSDavid du Colombier 94580ee5cbfSDavid du Colombier c = getc(h); 94680ee5cbfSDavid du Colombier if(c == ' ' || c == '\t') 94780ee5cbfSDavid du Colombier return c; 94880ee5cbfSDavid du Colombier ungetc(h); 94980ee5cbfSDavid du Colombier 95080ee5cbfSDavid du Colombier return '\n'; 95180ee5cbfSDavid du Colombier } 95280ee5cbfSDavid du Colombier 95380ee5cbfSDavid du Colombier static int 95480ee5cbfSDavid du Colombier getc(Hlex *h) 95580ee5cbfSDavid du Colombier { 95680ee5cbfSDavid du Colombier if(h->eoh) 95780ee5cbfSDavid du Colombier return -1; 95880ee5cbfSDavid du Colombier if(h->c->hpos < h->c->hstop) 95980ee5cbfSDavid du Colombier return *h->c->hpos++; 96080ee5cbfSDavid du Colombier h->eoh = 1; 96180ee5cbfSDavid du Colombier h->eol = 1; 96280ee5cbfSDavid du Colombier return -1; 96380ee5cbfSDavid du Colombier } 96480ee5cbfSDavid du Colombier 96580ee5cbfSDavid du Colombier static void 96680ee5cbfSDavid du Colombier ungetc(Hlex *h) 96780ee5cbfSDavid du Colombier { 96880ee5cbfSDavid du Colombier if(h->eoh) 96980ee5cbfSDavid du Colombier return; 97080ee5cbfSDavid du Colombier h->c->hpos--; 97180ee5cbfSDavid du Colombier } 97280ee5cbfSDavid du Colombier 97380ee5cbfSDavid du Colombier static ulong 97480ee5cbfSDavid du Colombier digtoul(char *s, char **e) 97580ee5cbfSDavid du Colombier { 97680ee5cbfSDavid du Colombier ulong v; 97780ee5cbfSDavid du Colombier int c, ovfl; 97880ee5cbfSDavid du Colombier 97980ee5cbfSDavid du Colombier v = 0; 98080ee5cbfSDavid du Colombier ovfl = 0; 98180ee5cbfSDavid du Colombier for(;;){ 98280ee5cbfSDavid du Colombier c = *s; 98380ee5cbfSDavid du Colombier if(c < '0' || c > '9') 98480ee5cbfSDavid du Colombier break; 98580ee5cbfSDavid du Colombier s++; 98680ee5cbfSDavid du Colombier c -= '0'; 98780ee5cbfSDavid du Colombier if(v > UlongMax/10 || v == UlongMax/10 && c >= UlongMax%10) 98880ee5cbfSDavid du Colombier ovfl = 1; 98980ee5cbfSDavid du Colombier v = v * 10 + c; 99080ee5cbfSDavid du Colombier } 99180ee5cbfSDavid du Colombier 99280ee5cbfSDavid du Colombier if(e) 99380ee5cbfSDavid du Colombier *e = s; 99480ee5cbfSDavid du Colombier if(ovfl) 99580ee5cbfSDavid du Colombier return UlongMax; 99680ee5cbfSDavid du Colombier return v; 99780ee5cbfSDavid du Colombier } 99880ee5cbfSDavid du Colombier 99980ee5cbfSDavid du Colombier int 100080ee5cbfSDavid du Colombier http11(HConnect *c) 100180ee5cbfSDavid du Colombier { 100280ee5cbfSDavid du Colombier return c->req.vermaj > 1 || c->req.vermaj == 1 && c->req.vermin > 0; 100380ee5cbfSDavid du Colombier } 100480ee5cbfSDavid du Colombier 100580ee5cbfSDavid du Colombier char* 100680ee5cbfSDavid du Colombier hmkmimeboundary(HConnect *c) 100780ee5cbfSDavid du Colombier { 100880ee5cbfSDavid du Colombier char buf[32]; 100980ee5cbfSDavid du Colombier int i; 101080ee5cbfSDavid du Colombier 101180ee5cbfSDavid du Colombier srand((time(0)<<16)|getpid()); 101280ee5cbfSDavid du Colombier strcpy(buf, "upas-"); 101380ee5cbfSDavid du Colombier for(i = 5; i < sizeof(buf)-1; i++) 101480ee5cbfSDavid du Colombier buf[i] = 'a' + nrand(26); 101580ee5cbfSDavid du Colombier buf[i] = 0; 101680ee5cbfSDavid du Colombier return hstrdup(c, buf); 101780ee5cbfSDavid du Colombier } 101880ee5cbfSDavid du Colombier 101980ee5cbfSDavid du Colombier HSPairs* 102080ee5cbfSDavid du Colombier hmkspairs(HConnect *c, char *s, char *t, HSPairs *next) 102180ee5cbfSDavid du Colombier { 102280ee5cbfSDavid du Colombier HSPairs *sp; 102380ee5cbfSDavid du Colombier 102480ee5cbfSDavid du Colombier sp = halloc(c, sizeof *sp); 102580ee5cbfSDavid du Colombier sp->s = s; 102680ee5cbfSDavid du Colombier sp->t = t; 102780ee5cbfSDavid du Colombier sp->next = next; 102880ee5cbfSDavid du Colombier return sp; 102980ee5cbfSDavid du Colombier } 103080ee5cbfSDavid du Colombier 103180ee5cbfSDavid du Colombier HSPairs* 103280ee5cbfSDavid du Colombier hrevspairs(HSPairs *sp) 103380ee5cbfSDavid du Colombier { 103480ee5cbfSDavid du Colombier HSPairs *last, *next; 103580ee5cbfSDavid du Colombier 103680ee5cbfSDavid du Colombier last = nil; 103780ee5cbfSDavid du Colombier for(; sp != nil; sp = next){ 103880ee5cbfSDavid du Colombier next = sp->next; 103980ee5cbfSDavid du Colombier sp->next = last; 104080ee5cbfSDavid du Colombier last = sp; 104180ee5cbfSDavid du Colombier } 104280ee5cbfSDavid du Colombier return last; 104380ee5cbfSDavid du Colombier } 104480ee5cbfSDavid du Colombier 104580ee5cbfSDavid du Colombier HFields* 104680ee5cbfSDavid du Colombier hmkhfields(HConnect *c, char *s, HSPairs *p, HFields *next) 104780ee5cbfSDavid du Colombier { 104880ee5cbfSDavid du Colombier HFields *hf; 104980ee5cbfSDavid du Colombier 105080ee5cbfSDavid du Colombier hf = halloc(c, sizeof *hf); 105180ee5cbfSDavid du Colombier hf->s = s; 105280ee5cbfSDavid du Colombier hf->params = p; 105380ee5cbfSDavid du Colombier hf->next = next; 105480ee5cbfSDavid du Colombier return hf; 105580ee5cbfSDavid du Colombier } 105680ee5cbfSDavid du Colombier 105780ee5cbfSDavid du Colombier HFields* 105880ee5cbfSDavid du Colombier hrevhfields(HFields *hf) 105980ee5cbfSDavid du Colombier { 106080ee5cbfSDavid du Colombier HFields *last, *next; 106180ee5cbfSDavid du Colombier 106280ee5cbfSDavid du Colombier last = nil; 106380ee5cbfSDavid du Colombier for(; hf != nil; hf = next){ 106480ee5cbfSDavid du Colombier next = hf->next; 106580ee5cbfSDavid du Colombier hf->next = last; 106680ee5cbfSDavid du Colombier last = hf; 106780ee5cbfSDavid du Colombier } 106880ee5cbfSDavid du Colombier return last; 106980ee5cbfSDavid du Colombier } 107080ee5cbfSDavid du Colombier 107180ee5cbfSDavid du Colombier HContent* 107280ee5cbfSDavid du Colombier hmkcontent(HConnect *c, char *generic, char *specific, HContent *next) 107380ee5cbfSDavid du Colombier { 107480ee5cbfSDavid du Colombier HContent *ct; 107580ee5cbfSDavid du Colombier 107680ee5cbfSDavid du Colombier ct = halloc(c, sizeof(HContent)); 107780ee5cbfSDavid du Colombier ct->generic = generic; 107880ee5cbfSDavid du Colombier ct->specific = specific; 107980ee5cbfSDavid du Colombier ct->next = next; 108080ee5cbfSDavid du Colombier ct->q = 1; 108180ee5cbfSDavid du Colombier ct->mxb = 0; 108280ee5cbfSDavid du Colombier return ct; 108380ee5cbfSDavid du Colombier } 1084