parse.c 18 KB

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