parse.c 20 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ctype.h>
  4. #include <libsec.h>
  5. #include <bin.h>
  6. #include <httpd.h>
  7. #include "escape.h"
  8. typedef struct Hlex Hlex;
  9. typedef struct MimeHead MimeHead;
  10. enum
  11. {
  12. /*
  13. * tokens
  14. */
  15. Word = 1,
  16. QString,
  17. };
  18. #define UlongMax 4294967295UL
  19. struct Hlex
  20. {
  21. int tok;
  22. int eoh;
  23. int eol; /* end of header line encountered? */
  24. uchar *hstart; /* start of header */
  25. jmp_buf jmp; /* jmp here to parse header */
  26. char wordval[HMaxWord];
  27. HConnect *c;
  28. };
  29. struct MimeHead
  30. {
  31. char *name;
  32. void (*parse)(Hlex*, char*);
  33. uchar seen;
  34. uchar ignore;
  35. };
  36. static void mimeaccept(Hlex*, char*);
  37. static void mimeacceptchar(Hlex*, char*);
  38. static void mimeacceptenc(Hlex*, char*);
  39. static void mimeacceptlang(Hlex*, char*);
  40. static void mimeagent(Hlex*, char*);
  41. static void mimeauthorization(Hlex*, char*);
  42. static void mimeconnection(Hlex*, char*);
  43. static void mimecontlen(Hlex*, char*);
  44. static void mimecookie(Hlex*, char*);
  45. static void mimeexpect(Hlex*, char*);
  46. static void mimefresh(Hlex*, char*);
  47. static void mimefrom(Hlex*, char*);
  48. static void mimehost(Hlex*, char*);
  49. static void mimeifrange(Hlex*, char*);
  50. static void mimeignore(Hlex*, char*);
  51. static void mimematch(Hlex*, char*);
  52. static void mimemodified(Hlex*, char*);
  53. static void mimenomatch(Hlex*, char*);
  54. static void mimerange(Hlex*, char*);
  55. static void mimetransenc(Hlex*, char*);
  56. static void mimeunmodified(Hlex*, char*);
  57. /*
  58. * headers seen also include
  59. * allow cache-control chargeto
  60. * content-encoding content-language content-location content-md5 content-range content-type
  61. * date etag expires forwarded last-modified max-forwards pragma
  62. * proxy-agent proxy-authorization proxy-connection
  63. * ua-color ua-cpu ua-os ua-pixels
  64. * upgrade via x-afs-tokens x-serial-number
  65. */
  66. static MimeHead mimehead[] =
  67. {
  68. {"accept", mimeaccept},
  69. {"accept-charset", mimeacceptchar},
  70. {"accept-encoding", mimeacceptenc},
  71. {"accept-language", mimeacceptlang},
  72. {"authorization", mimeauthorization},
  73. {"connection", mimeconnection},
  74. {"content-length", mimecontlen},
  75. {"cookie", mimecookie},
  76. {"expect", mimeexpect},
  77. {"fresh", mimefresh},
  78. {"from", mimefrom},
  79. {"host", mimehost},
  80. {"if-match", mimematch},
  81. {"if-modified-since", mimemodified},
  82. {"if-none-match", mimenomatch},
  83. {"if-range", mimeifrange},
  84. {"if-unmodified-since", mimeunmodified},
  85. {"range", mimerange},
  86. {"transfer-encoding", mimetransenc},
  87. {"user-agent", mimeagent},
  88. };
  89. char* hmydomain;
  90. char* hversion = "HTTP/1.1";
  91. static void lexhead(Hlex*);
  92. static void parsejump(Hlex*, char*);
  93. static int getc(Hlex*);
  94. static void ungetc(Hlex*);
  95. static int wordcr(Hlex*);
  96. static int wordnl(Hlex*);
  97. static void word(Hlex*, char*);
  98. static int lex1(Hlex*, int);
  99. static int lex(Hlex*);
  100. static int lexbase64(Hlex*);
  101. static ulong digtoul(char *s, char **e);
  102. /*
  103. * flush and clean up junk from a request
  104. */
  105. void
  106. hreqcleanup(HConnect *c)
  107. {
  108. int i;
  109. hxferenc(&c->hout, 0);
  110. memset(&c->req, 0, sizeof(c->req));
  111. memset(&c->head, 0, sizeof(c->head));
  112. c->hpos = c->header;
  113. c->hstop = c->header;
  114. binfree(&c->bin);
  115. for(i = 0; i < nelem(mimehead); i++){
  116. mimehead[i].seen = 0;
  117. mimehead[i].ignore = 0;
  118. }
  119. }
  120. /*
  121. * list of tokens
  122. * if the client is HTTP/1.0,
  123. * ignore headers which match one of the tokens.
  124. * restarts parsing if necessary.
  125. */
  126. static void
  127. mimeconnection(Hlex *h, char *)
  128. {
  129. char *u, *p;
  130. int reparse, i;
  131. reparse = 0;
  132. for(;;){
  133. while(lex(h) != Word)
  134. if(h->tok != ',')
  135. goto breakout;
  136. if(cistrcmp(h->wordval, "keep-alive") == 0)
  137. h->c->head.persist = 1;
  138. else if(cistrcmp(h->wordval, "close") == 0)
  139. h->c->head.closeit = 1;
  140. else if(!http11(h->c)){
  141. for(i = 0; i < nelem(mimehead); i++){
  142. if(cistrcmp(mimehead[i].name, h->wordval) == 0){
  143. reparse = mimehead[i].seen && !mimehead[i].ignore;
  144. mimehead[i].ignore = 1;
  145. if(cistrcmp(mimehead[i].name, "authorization") == 0){
  146. h->c->head.authuser = nil;
  147. h->c->head.authpass = nil;
  148. }
  149. }
  150. }
  151. }
  152. if(lex(h) != ',')
  153. break;
  154. }
  155. breakout:;
  156. /*
  157. * if need to ignore headers we've already parsed,
  158. * reset & start over. need to save authorization
  159. * info because it's written over when parsed.
  160. */
  161. if(reparse){
  162. u = h->c->head.authuser;
  163. p = h->c->head.authpass;
  164. memset(&h->c->head, 0, sizeof(h->c->head));
  165. h->c->head.authuser = u;
  166. h->c->head.authpass = p;
  167. h->c->hpos = h->hstart;
  168. longjmp(h->jmp, 1);
  169. }
  170. }
  171. int
  172. hparseheaders(HConnect *c, int timeout)
  173. {
  174. Hlex h;
  175. c->head.fresh_thresh = 0;
  176. c->head.fresh_have = 0;
  177. c->head.persist = 0;
  178. if(c->req.vermaj == 0){
  179. c->head.host = hmydomain;
  180. return 1;
  181. }
  182. memset(&h, 0, sizeof(h));
  183. h.c = c;
  184. if(timeout)
  185. alarm(timeout);
  186. if(hgethead(c, 1) < 0)
  187. return -1;
  188. if(timeout)
  189. alarm(0);
  190. h.hstart = c->hpos;
  191. if(setjmp(h.jmp) == -1)
  192. return -1;
  193. h.eol = 0;
  194. h.eoh = 0;
  195. h.tok = '\n';
  196. while(lex(&h) != '\n'){
  197. if(h.tok == Word && lex(&h) == ':')
  198. parsejump(&h, hstrdup(c, h.wordval));
  199. while(h.tok != '\n')
  200. lex(&h);
  201. h.eol = h.eoh;
  202. }
  203. if(http11(c)){
  204. /*
  205. * according to the http/1.1 spec,
  206. * these rules must be followed
  207. */
  208. if(c->head.host == nil){
  209. hfail(c, HBadReq, nil);
  210. return -1;
  211. }
  212. if(c->req.urihost != nil)
  213. c->head.host = c->req.urihost;
  214. /*
  215. * also need to check host is actually this one
  216. */
  217. }else if(c->head.host == nil)
  218. c->head.host = hmydomain;
  219. return 1;
  220. }
  221. /*
  222. * mimeparams : | mimeparams ";" mimepara
  223. * mimeparam : token "=" token | token "=" qstring
  224. */
  225. static HSPairs*
  226. mimeparams(Hlex *h)
  227. {
  228. HSPairs *p;
  229. char *s;
  230. p = nil;
  231. for(;;){
  232. if(lex(h) != Word)
  233. break;
  234. s = hstrdup(h->c, h->wordval);
  235. if(lex(h) != Word && h->tok != QString)
  236. break;
  237. p = hmkspairs(h->c, s, hstrdup(h->c, h->wordval), p);
  238. }
  239. return hrevspairs(p);
  240. }
  241. /*
  242. * mimehfields : mimehfield | mimehfields commas mimehfield
  243. * mimehfield : token mimeparams
  244. * commas : "," | commas ","
  245. */
  246. static HFields*
  247. mimehfields(Hlex *h)
  248. {
  249. HFields *f;
  250. f = nil;
  251. for(;;){
  252. while(lex(h) != Word)
  253. if(h->tok != ',')
  254. goto breakout;
  255. f = hmkhfields(h->c, hstrdup(h->c, h->wordval), nil, f);
  256. if(lex(h) == ';')
  257. f->params = mimeparams(h);
  258. if(h->tok != ',')
  259. break;
  260. }
  261. breakout:;
  262. return hrevhfields(f);
  263. }
  264. /*
  265. * parse a list of acceptable types, encodings, languages, etc.
  266. */
  267. static HContent*
  268. mimeok(Hlex *h, char *name, int multipart, HContent *head)
  269. {
  270. char *generic, *specific, *s;
  271. float v;
  272. /*
  273. * each type is separated by one or more commas
  274. */
  275. while(lex(h) != Word)
  276. if(h->tok != ',')
  277. return head;
  278. generic = hstrdup(h->c, h->wordval);
  279. lex(h);
  280. if(h->tok == '/' || multipart){
  281. /*
  282. * at one time, IE5 improperly said '*' for single types
  283. */
  284. if(h->tok != '/')
  285. return nil;
  286. if(lex(h) != Word)
  287. return head;
  288. specific = hstrdup(h->c, h->wordval);
  289. if(!multipart && strcmp(specific, "*") != 0)
  290. return head;
  291. lex(h);
  292. }else
  293. specific = nil;
  294. head = hmkcontent(h->c, generic, specific, head);
  295. for(;;){
  296. switch(h->tok){
  297. case ';':
  298. /*
  299. * should make a list of these params
  300. * for accept, they fall into two classes:
  301. * up to a q=..., they modify the media type.
  302. * afterwards, they acceptance criteria
  303. */
  304. if(lex(h) == Word){
  305. s = hstrdup(h->c, h->wordval);
  306. if(lex(h) != '=' || lex(h) != Word && h->tok != QString)
  307. return head;
  308. v = strtod(h->wordval, nil);
  309. if(strcmp(s, "q") == 0)
  310. head->q = v;
  311. else if(strcmp(s, "mxb") == 0)
  312. head->mxb = v;
  313. else{
  314. /* cope with accept: application/xhtml+xml; profile=http://www.wapforum.org/xhtml, */
  315. while(lex(h) == Word || (h->tok != ',' && h->eol == 0) )
  316. ;
  317. return mimeok(h, name, multipart, head);
  318. }
  319. }
  320. break;
  321. case ',':
  322. return mimeok(h, name, multipart, head);
  323. default:
  324. return head;
  325. }
  326. lex(h);
  327. }
  328. }
  329. /*
  330. * parse a list of entity tags
  331. * 1#entity-tag
  332. * entity-tag = [weak] opaque-tag
  333. * weak = "W/"
  334. * opaque-tag = quoted-string
  335. */
  336. static HETag*
  337. mimeetag(Hlex *h, HETag *head)
  338. {
  339. HETag *e;
  340. int weak;
  341. for(;;){
  342. while(lex(h) != Word && h->tok != QString)
  343. if(h->tok != ',')
  344. return head;
  345. weak = 0;
  346. if(h->tok == Word && strcmp(h->wordval, "*") != 0){
  347. if(strcmp(h->wordval, "W") != 0)
  348. return head;
  349. if(lex(h) != '/' || lex(h) != QString)
  350. return head;
  351. weak = 1;
  352. }
  353. e = halloc(h->c, sizeof(HETag));
  354. e->etag = hstrdup(h->c, h->wordval);
  355. e->weak = weak;
  356. e->next = head;
  357. head = e;
  358. if(lex(h) != ',')
  359. return head;
  360. }
  361. }
  362. /*
  363. * ranges-specifier = byte-ranges-specifier
  364. * byte-ranges-specifier = "bytes" "=" byte-range-set
  365. * byte-range-set = 1#(byte-range-spec|suffix-byte-range-spec)
  366. * byte-range-spec = byte-pos "-" [byte-pos]
  367. * byte-pos = 1*DIGIT
  368. * suffix-byte-range-spec = "-" suffix-length
  369. * suffix-length = 1*DIGIT
  370. *
  371. * syntactically invalid range specifiers cause the
  372. * entire header field to be ignored.
  373. * it is syntactically incorrect for the second byte pos
  374. * to be smaller than the first byte pos
  375. */
  376. static HRange*
  377. mimeranges(Hlex *h, HRange *head)
  378. {
  379. HRange *r, *rh, *tail;
  380. char *w;
  381. ulong start, stop;
  382. int suf;
  383. if(lex(h) != Word || strcmp(h->wordval, "bytes") != 0 || lex(h) != '=')
  384. return head;
  385. rh = nil;
  386. tail = nil;
  387. for(;;){
  388. while(lex(h) != Word){
  389. if(h->tok != ','){
  390. if(h->tok == '\n')
  391. goto breakout;
  392. return head;
  393. }
  394. }
  395. w = h->wordval;
  396. start = 0;
  397. suf = 1;
  398. if(w[0] != '-'){
  399. suf = 0;
  400. start = digtoul(w, &w);
  401. if(w[0] != '-')
  402. return head;
  403. }
  404. w++;
  405. stop = ~0UL;
  406. if(w[0] != '\0'){
  407. stop = digtoul(w, &w);
  408. if(w[0] != '\0')
  409. return head;
  410. if(!suf && stop < start)
  411. return head;
  412. }
  413. r = halloc(h->c, sizeof(HRange));
  414. r->suffix = suf;
  415. r->start = start;
  416. r->stop = stop;
  417. r->next = nil;
  418. if(rh == nil)
  419. rh = r;
  420. else
  421. tail->next = r;
  422. tail = r;
  423. if(lex(h) != ','){
  424. if(h->tok == '\n')
  425. break;
  426. return head;
  427. }
  428. }
  429. breakout:;
  430. if(head == nil)
  431. return rh;
  432. for(tail = head; tail->next != nil; tail = tail->next)
  433. ;
  434. tail->next = rh;
  435. return head;
  436. }
  437. static void
  438. mimeaccept(Hlex *h, char *name)
  439. {
  440. h->c->head.oktype = mimeok(h, name, 1, h->c->head.oktype);
  441. }
  442. static void
  443. mimeacceptchar(Hlex *h, char *name)
  444. {
  445. h->c->head.okchar = mimeok(h, name, 0, h->c->head.okchar);
  446. }
  447. static void
  448. mimeacceptenc(Hlex *h, char *name)
  449. {
  450. h->c->head.okencode = mimeok(h, name, 0, h->c->head.okencode);
  451. }
  452. static void
  453. mimeacceptlang(Hlex *h, char *name)
  454. {
  455. h->c->head.oklang = mimeok(h, name, 0, h->c->head.oklang);
  456. }
  457. static void
  458. mimemodified(Hlex *h, char *)
  459. {
  460. lexhead(h);
  461. h->c->head.ifmodsince = hdate2sec(h->wordval);
  462. }
  463. static void
  464. mimeunmodified(Hlex *h, char *)
  465. {
  466. lexhead(h);
  467. h->c->head.ifunmodsince = hdate2sec(h->wordval);
  468. }
  469. static void
  470. mimematch(Hlex *h, char *)
  471. {
  472. h->c->head.ifmatch = mimeetag(h, h->c->head.ifmatch);
  473. }
  474. static void
  475. mimenomatch(Hlex *h, char *)
  476. {
  477. h->c->head.ifnomatch = mimeetag(h, h->c->head.ifnomatch);
  478. }
  479. /*
  480. * argument is either etag or date
  481. */
  482. static void
  483. mimeifrange(Hlex *h, char *)
  484. {
  485. int c, d, et;
  486. et = 0;
  487. c = getc(h);
  488. while(c == ' ' || c == '\t')
  489. c = getc(h);
  490. if(c == '"')
  491. et = 1;
  492. else if(c == 'W'){
  493. d = getc(h);
  494. if(d == '/')
  495. et = 1;
  496. ungetc(h);
  497. }
  498. ungetc(h);
  499. if(et){
  500. h->c->head.ifrangeetag = mimeetag(h, h->c->head.ifrangeetag);
  501. }else{
  502. lexhead(h);
  503. h->c->head.ifrangedate = hdate2sec(h->wordval);
  504. }
  505. }
  506. static void
  507. mimerange(Hlex *h, char *)
  508. {
  509. h->c->head.range = mimeranges(h, h->c->head.range);
  510. }
  511. /*
  512. * parse it like cookies
  513. */
  514. static void
  515. authdigest(Hlex *h, char *)
  516. {
  517. char *s;
  518. HSPairs *p;
  519. p = nil;
  520. for(;;){
  521. while(lex(h) != Word)
  522. if(h->tok != ';' && h->tok != ',')
  523. goto breakout;
  524. s = hstrdup(h->c, h->wordval);
  525. while (lex(h) != Word && h->tok != QString)
  526. if (h->tok != '=')
  527. goto breakout;
  528. p = hmkspairs(h->c, s, hstrdup(h->c, h->wordval), p);
  529. }
  530. breakout:
  531. h->c->head.authinfo = hrevspairs(p);
  532. }
  533. /*
  534. * note: netscape and ie through versions 4.7 and 4
  535. * support only basic authorization, so that is all that is supported here
  536. *
  537. * "Authorization" ":" "Basic" base64-user-pass
  538. * where base64-user-pass is the base64 encoding of
  539. * username ":" password
  540. */
  541. static void
  542. authbasic(Hlex *h, char *)
  543. {
  544. char *up, *p;
  545. int n;
  546. n = lexbase64(h);
  547. if(!n)
  548. return;
  549. /*
  550. * wipe out source for password, so it won't be logged.
  551. * it is replaced by a single =,
  552. * which is valid base64, but not ok for an auth reponse.
  553. * therefore future parses of the header field will not overwrite
  554. * authuser and authpass.
  555. */
  556. memmove(h->c->hpos - (n - 1), h->c->hpos, h->c->hstop - h->c->hpos);
  557. h->c->hstop -= n - 1;
  558. *h->c->hstop = '\0';
  559. h->c->hpos -= n - 1;
  560. h->c->hpos[-1] = '=';
  561. up = halloc(h->c, n + 1);
  562. n = dec64((uchar*)up, n, h->wordval, n);
  563. up[n] = '\0';
  564. p = strchr(up, ':');
  565. if(p != nil){
  566. *p++ = '\0';
  567. h->c->head.authuser = hstrdup(h->c, up);
  568. h->c->head.authpass = hstrdup(h->c, p);
  569. }
  570. }
  571. /*
  572. * "Authorization" ":" "Basic" | "Digest" ...
  573. */
  574. static void
  575. mimeauthorization(Hlex *h, char *)
  576. {
  577. int i;
  578. static MimeHead authparser[] = {
  579. { "basic", authbasic },
  580. { "digest", authdigest },
  581. };
  582. if(lex(h) != Word)
  583. return;
  584. for (i = 0; i < nelem(authparser); i++)
  585. if (cistrcmp(h->wordval, authparser[i].name) == 0) {
  586. (*authparser[i].parse)(h, nil);
  587. break;
  588. }
  589. }
  590. static void
  591. mimeagent(Hlex *h, char *)
  592. {
  593. lexhead(h);
  594. h->c->head.client = hstrdup(h->c, h->wordval);
  595. }
  596. static void
  597. mimefrom(Hlex *h, char *)
  598. {
  599. lexhead(h);
  600. }
  601. static void
  602. mimehost(Hlex *h, char *)
  603. {
  604. char *hd;
  605. lexhead(h);
  606. for(hd = h->wordval; *hd == ' ' || *hd == '\t'; hd++)
  607. ;
  608. h->c->head.host = hlower(hstrdup(h->c, hd));
  609. }
  610. /*
  611. * if present, implies that a message body follows the headers
  612. * "content-length" ":" digits
  613. */
  614. static void
  615. mimecontlen(Hlex *h, char *)
  616. {
  617. char *e;
  618. ulong v;
  619. if(lex(h) != Word)
  620. return;
  621. e = h->wordval;
  622. v = digtoul(e, &e);
  623. if(v == ~0UL || *e != '\0')
  624. return;
  625. h->c->head.contlen = v;
  626. }
  627. /*
  628. * mimexpect : "expect" ":" expects
  629. * expects : | expects "," expect
  630. * expect : "100-continue" | token | token "=" token expectparams | token "=" qstring expectparams
  631. * expectparams : ";" token | ";" token "=" token | token "=" qstring
  632. * for now, we merely parse "100-continue" or anything else.
  633. */
  634. static void
  635. mimeexpect(Hlex *h, char *)
  636. {
  637. if(lex(h) != Word || cistrcmp(h->wordval, "100-continue") != 0 || lex(h) != '\n')
  638. h->c->head.expectother = 1;
  639. h->c->head.expectcont = 1;
  640. }
  641. static void
  642. mimetransenc(Hlex *h, char *)
  643. {
  644. h->c->head.transenc = mimehfields(h);
  645. }
  646. static void
  647. mimecookie(Hlex *h, char *)
  648. {
  649. char *s;
  650. HSPairs *p;
  651. p = nil;
  652. for(;;){
  653. while(lex(h) != Word)
  654. if(h->tok != ';' && h->tok != ',')
  655. goto breakout;
  656. s = hstrdup(h->c, h->wordval);
  657. while (lex(h) != Word && h->tok != QString)
  658. if (h->tok != '=')
  659. goto breakout;
  660. p = hmkspairs(h->c, s, hstrdup(h->c, h->wordval), p);
  661. }
  662. breakout:
  663. h->c->head.cookie = hrevspairs(p);
  664. }
  665. static void
  666. mimefresh(Hlex *h, char *)
  667. {
  668. char *s;
  669. lexhead(h);
  670. for(s = h->wordval; *s && (*s==' ' || *s=='\t'); s++)
  671. ;
  672. if(strncmp(s, "pathstat/", 9) == 0)
  673. h->c->head.fresh_thresh = atoi(s+9);
  674. else if(strncmp(s, "have/", 5) == 0)
  675. h->c->head.fresh_have = atoi(s+5);
  676. }
  677. static void
  678. mimeignore(Hlex *h, char *)
  679. {
  680. lexhead(h);
  681. }
  682. static void
  683. parsejump(Hlex *h, char *k)
  684. {
  685. int l, r, m;
  686. l = 1;
  687. r = nelem(mimehead) - 1;
  688. while(l <= r){
  689. m = (r + l) >> 1;
  690. if(cistrcmp(mimehead[m].name, k) <= 0)
  691. l = m + 1;
  692. else
  693. r = m - 1;
  694. }
  695. m = l - 1;
  696. if(cistrcmp(mimehead[m].name, k) == 0 && !mimehead[m].ignore){
  697. mimehead[m].seen = 1;
  698. (*mimehead[m].parse)(h, k);
  699. }else
  700. mimeignore(h, k);
  701. }
  702. static int
  703. lex(Hlex *h)
  704. {
  705. return h->tok = lex1(h, 0);
  706. }
  707. static int
  708. lexbase64(Hlex *h)
  709. {
  710. int c, n;
  711. n = 0;
  712. lex1(h, 1);
  713. while((c = getc(h)) >= 0){
  714. if(!isalnum(c) && c != '+' && c != '/'){
  715. ungetc(h);
  716. break;
  717. }
  718. if(n < HMaxWord-1)
  719. h->wordval[n++] = c;
  720. }
  721. h->wordval[n] = '\0';
  722. return n;
  723. }
  724. /*
  725. * rfc 822/rfc 1521 lexical analyzer
  726. */
  727. static int
  728. lex1(Hlex *h, int skipwhite)
  729. {
  730. int level, c;
  731. if(h->eol)
  732. return '\n';
  733. top:
  734. c = getc(h);
  735. switch(c){
  736. case '(':
  737. level = 1;
  738. while((c = getc(h)) >= 0){
  739. if(c == '\\'){
  740. c = getc(h);
  741. if(c < 0)
  742. return '\n';
  743. continue;
  744. }
  745. if(c == '(')
  746. level++;
  747. else if(c == ')' && --level == 0)
  748. break;
  749. else if(c == '\n'){
  750. c = getc(h);
  751. if(c < 0)
  752. return '\n';
  753. if(c == ')' && --level == 0)
  754. break;
  755. if(c != ' ' && c != '\t'){
  756. ungetc(h);
  757. return '\n';
  758. }
  759. }
  760. }
  761. goto top;
  762. case ' ': case '\t':
  763. goto top;
  764. case '\r':
  765. c = getc(h);
  766. if(c != '\n'){
  767. ungetc(h);
  768. goto top;
  769. }
  770. case '\n':
  771. if(h->tok == '\n'){
  772. h->eol = 1;
  773. h->eoh = 1;
  774. return '\n';
  775. }
  776. c = getc(h);
  777. if(c < 0){
  778. h->eol = 1;
  779. return '\n';
  780. }
  781. if(c != ' ' && c != '\t'){
  782. ungetc(h);
  783. h->eol = 1;
  784. return '\n';
  785. }
  786. goto top;
  787. case ')':
  788. case '<': case '>':
  789. case '[': case ']':
  790. case '@': case '/':
  791. case ',': case ';': case ':': case '?': case '=':
  792. if(skipwhite){
  793. ungetc(h);
  794. return c;
  795. }
  796. return c;
  797. case '"':
  798. if(skipwhite){
  799. ungetc(h);
  800. return c;
  801. }
  802. word(h, "\"");
  803. getc(h); /* skip the closing quote */
  804. return QString;
  805. default:
  806. ungetc(h);
  807. if(skipwhite)
  808. return c;
  809. word(h, "\"(){}<>@,;:/[]?=\r\n \t");
  810. if(h->wordval[0] == '\0'){
  811. h->c->head.closeit = 1;
  812. hfail(h->c, HSyntax);
  813. longjmp(h->jmp, -1);
  814. }
  815. return Word;
  816. }
  817. /* not reached */
  818. }
  819. /*
  820. * return the rest of an rfc 822, including \n
  821. * do not map to lower case
  822. */
  823. static void
  824. lexhead(Hlex *h)
  825. {
  826. int c, n;
  827. n = 0;
  828. while((c = getc(h)) >= 0){
  829. if(c == '\r')
  830. c = wordcr(h);
  831. else if(c == '\n')
  832. c = wordnl(h);
  833. if(c == '\n')
  834. break;
  835. if(c == '\\'){
  836. c = getc(h);
  837. if(c < 0)
  838. break;
  839. }
  840. if(n < HMaxWord-1)
  841. h->wordval[n++] = c;
  842. }
  843. h->tok = '\n';
  844. h->eol = 1;
  845. h->wordval[n] = '\0';
  846. }
  847. static void
  848. word(Hlex *h, char *stop)
  849. {
  850. int c, n;
  851. n = 0;
  852. while((c = getc(h)) >= 0){
  853. if(c == '\r')
  854. c = wordcr(h);
  855. else if(c == '\n')
  856. c = wordnl(h);
  857. if(c == '\\'){
  858. c = getc(h);
  859. if(c < 0)
  860. break;
  861. }else if(c < 32 || strchr(stop, c) != nil){
  862. ungetc(h);
  863. break;
  864. }
  865. if(n < HMaxWord-1)
  866. h->wordval[n++] = c;
  867. }
  868. h->wordval[n] = '\0';
  869. }
  870. static int
  871. wordcr(Hlex *h)
  872. {
  873. int c;
  874. c = getc(h);
  875. if(c == '\n')
  876. return wordnl(h);
  877. ungetc(h);
  878. return ' ';
  879. }
  880. static int
  881. wordnl(Hlex *h)
  882. {
  883. int c;
  884. c = getc(h);
  885. if(c == ' ' || c == '\t')
  886. return c;
  887. ungetc(h);
  888. return '\n';
  889. }
  890. static int
  891. getc(Hlex *h)
  892. {
  893. if(h->eoh)
  894. return -1;
  895. if(h->c->hpos < h->c->hstop)
  896. return *h->c->hpos++;
  897. h->eoh = 1;
  898. h->eol = 1;
  899. return -1;
  900. }
  901. static void
  902. ungetc(Hlex *h)
  903. {
  904. if(h->eoh)
  905. return;
  906. h->c->hpos--;
  907. }
  908. static ulong
  909. digtoul(char *s, char **e)
  910. {
  911. ulong v;
  912. int c, ovfl;
  913. v = 0;
  914. ovfl = 0;
  915. for(;;){
  916. c = *s;
  917. if(c < '0' || c > '9')
  918. break;
  919. s++;
  920. c -= '0';
  921. if(v > UlongMax/10 || v == UlongMax/10 && c >= UlongMax%10)
  922. ovfl = 1;
  923. v = v * 10 + c;
  924. }
  925. if(e)
  926. *e = s;
  927. if(ovfl)
  928. return UlongMax;
  929. return v;
  930. }
  931. int
  932. http11(HConnect *c)
  933. {
  934. return c->req.vermaj > 1 || c->req.vermaj == 1 && c->req.vermin > 0;
  935. }
  936. char*
  937. hmkmimeboundary(HConnect *c)
  938. {
  939. char buf[32];
  940. int i;
  941. srand((time(0)<<16)|getpid());
  942. strcpy(buf, "upas-");
  943. for(i = 5; i < sizeof(buf)-1; i++)
  944. buf[i] = 'a' + nrand(26);
  945. buf[i] = 0;
  946. return hstrdup(c, buf);
  947. }
  948. HSPairs*
  949. hmkspairs(HConnect *c, char *s, char *t, HSPairs *next)
  950. {
  951. HSPairs *sp;
  952. sp = halloc(c, sizeof *sp);
  953. sp->s = s;
  954. sp->t = t;
  955. sp->next = next;
  956. return sp;
  957. }
  958. HSPairs*
  959. hrevspairs(HSPairs *sp)
  960. {
  961. HSPairs *last, *next;
  962. last = nil;
  963. for(; sp != nil; sp = next){
  964. next = sp->next;
  965. sp->next = last;
  966. last = sp;
  967. }
  968. return last;
  969. }
  970. HFields*
  971. hmkhfields(HConnect *c, char *s, HSPairs *p, HFields *next)
  972. {
  973. HFields *hf;
  974. hf = halloc(c, sizeof *hf);
  975. hf->s = s;
  976. hf->params = p;
  977. hf->next = next;
  978. return hf;
  979. }
  980. HFields*
  981. hrevhfields(HFields *hf)
  982. {
  983. HFields *last, *next;
  984. last = nil;
  985. for(; hf != nil; hf = next){
  986. next = hf->next;
  987. hf->next = last;
  988. last = hf;
  989. }
  990. return last;
  991. }
  992. HContent*
  993. hmkcontent(HConnect *c, char *generic, char *specific, HContent *next)
  994. {
  995. HContent *ct;
  996. ct = halloc(c, sizeof(HContent));
  997. ct->generic = generic;
  998. ct->specific = specific;
  999. ct->next = next;
  1000. ct->q = 1;
  1001. ct->mxb = 0;
  1002. return ct;
  1003. }