parse.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  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. * note: netscape and ie through versions 4.7 and 4
  513. * support only basic authorization, so that is all that is supported here
  514. *
  515. * "Authorization" ":" "Basic" base64-user-pass
  516. * where base64-user-pass is the base64 encoding of
  517. * username ":" password
  518. */
  519. static void
  520. mimeauthorization(Hlex *h, char *)
  521. {
  522. char *up, *p;
  523. int n;
  524. if(lex(h) != Word || cistrcmp(h->wordval, "basic") != 0)
  525. return;
  526. n = lexbase64(h);
  527. if(!n)
  528. return;
  529. /*
  530. * wipe out source for password, so it won't be logged.
  531. * it is replaced by a single =,
  532. * which is valid base64, but not ok for an auth reponse.
  533. * therefore future parses of the header field will not overwrite
  534. * authuser and authpass.
  535. */
  536. memmove(h->c->hpos - (n - 1), h->c->hpos, h->c->hstop - h->c->hpos);
  537. h->c->hstop -= n - 1;
  538. *h->c->hstop = '\0';
  539. h->c->hpos -= n - 1;
  540. h->c->hpos[-1] = '=';
  541. up = halloc(h->c, n + 1);
  542. n = dec64((uchar*)up, n, h->wordval, n);
  543. up[n] = '\0';
  544. p = strchr(up, ':');
  545. if(p != nil){
  546. *p++ = '\0';
  547. h->c->head.authuser = hstrdup(h->c, up);
  548. h->c->head.authpass = hstrdup(h->c, p);
  549. }
  550. }
  551. static void
  552. mimeagent(Hlex *h, char *)
  553. {
  554. lexhead(h);
  555. h->c->head.client = hstrdup(h->c, h->wordval);
  556. }
  557. static void
  558. mimefrom(Hlex *h, char *)
  559. {
  560. lexhead(h);
  561. }
  562. static void
  563. mimehost(Hlex *h, char *)
  564. {
  565. char *hd;
  566. lexhead(h);
  567. for(hd = h->wordval; *hd == ' ' || *hd == '\t'; hd++)
  568. ;
  569. h->c->head.host = hlower(hstrdup(h->c, hd));
  570. }
  571. /*
  572. * if present, implies that a message body follows the headers
  573. * "content-length" ":" digits
  574. */
  575. static void
  576. mimecontlen(Hlex *h, char *)
  577. {
  578. char *e;
  579. ulong v;
  580. if(lex(h) != Word)
  581. return;
  582. e = h->wordval;
  583. v = digtoul(e, &e);
  584. if(v == ~0UL || *e != '\0')
  585. return;
  586. h->c->head.contlen = v;
  587. }
  588. /*
  589. * mimexpect : "expect" ":" expects
  590. * expects : | expects "," expect
  591. * expect : "100-continue" | token | token "=" token expectparams | token "=" qstring expectparams
  592. * expectparams : ";" token | ";" token "=" token | token "=" qstring
  593. * for now, we merely parse "100-continue" or anything else.
  594. */
  595. static void
  596. mimeexpect(Hlex *h, char *)
  597. {
  598. if(lex(h) != Word || cistrcmp(h->wordval, "100-continue") != 0 || lex(h) != '\n')
  599. h->c->head.expectother = 1;
  600. h->c->head.expectcont = 1;
  601. }
  602. static void
  603. mimetransenc(Hlex *h, char *)
  604. {
  605. h->c->head.transenc = mimehfields(h);
  606. }
  607. static void
  608. mimecookie(Hlex *h, char *)
  609. {
  610. char *s;
  611. HSPairs *p;
  612. p = nil;
  613. for(;;){
  614. while(lex(h) != Word)
  615. if(h->tok != ';' && h->tok != ',')
  616. goto breakout;
  617. s = hstrdup(h->c, h->wordval);
  618. while (lex(h) != Word && h->tok != QString)
  619. if (h->tok != '=')
  620. goto breakout;
  621. p = hmkspairs(h->c, s, hstrdup(h->c, h->wordval), p);
  622. }
  623. breakout:
  624. h->c->head.cookie = hrevspairs(p);
  625. }
  626. static void
  627. mimefresh(Hlex *h, char *)
  628. {
  629. char *s;
  630. lexhead(h);
  631. for(s = h->wordval; *s && (*s==' ' || *s=='\t'); s++)
  632. ;
  633. if(strncmp(s, "pathstat/", 9) == 0)
  634. h->c->head.fresh_thresh = atoi(s+9);
  635. else if(strncmp(s, "have/", 5) == 0)
  636. h->c->head.fresh_have = atoi(s+5);
  637. }
  638. static void
  639. mimeignore(Hlex *h, char *)
  640. {
  641. lexhead(h);
  642. }
  643. static void
  644. parsejump(Hlex *h, char *k)
  645. {
  646. int l, r, m;
  647. l = 1;
  648. r = nelem(mimehead) - 1;
  649. while(l <= r){
  650. m = (r + l) >> 1;
  651. if(cistrcmp(mimehead[m].name, k) <= 0)
  652. l = m + 1;
  653. else
  654. r = m - 1;
  655. }
  656. m = l - 1;
  657. if(cistrcmp(mimehead[m].name, k) == 0 && !mimehead[m].ignore){
  658. mimehead[m].seen = 1;
  659. (*mimehead[m].parse)(h, k);
  660. }else
  661. mimeignore(h, k);
  662. }
  663. static int
  664. lex(Hlex *h)
  665. {
  666. return h->tok = lex1(h, 0);
  667. }
  668. static int
  669. lexbase64(Hlex *h)
  670. {
  671. int c, n;
  672. n = 0;
  673. lex1(h, 1);
  674. while((c = getc(h)) >= 0){
  675. if(!isalnum(c) && c != '+' && c != '/'){
  676. ungetc(h);
  677. break;
  678. }
  679. if(n < HMaxWord-1)
  680. h->wordval[n++] = c;
  681. }
  682. h->wordval[n] = '\0';
  683. return n;
  684. }
  685. /*
  686. * rfc 822/rfc 1521 lexical analyzer
  687. */
  688. static int
  689. lex1(Hlex *h, int skipwhite)
  690. {
  691. int level, c;
  692. if(h->eol)
  693. return '\n';
  694. top:
  695. c = getc(h);
  696. switch(c){
  697. case '(':
  698. level = 1;
  699. while((c = getc(h)) >= 0){
  700. if(c == '\\'){
  701. c = getc(h);
  702. if(c < 0)
  703. return '\n';
  704. continue;
  705. }
  706. if(c == '(')
  707. level++;
  708. else if(c == ')' && --level == 0)
  709. break;
  710. else if(c == '\n'){
  711. c = getc(h);
  712. if(c < 0)
  713. return '\n';
  714. if(c == ')' && --level == 0)
  715. break;
  716. if(c != ' ' && c != '\t'){
  717. ungetc(h);
  718. return '\n';
  719. }
  720. }
  721. }
  722. goto top;
  723. case ' ': case '\t':
  724. goto top;
  725. case '\r':
  726. c = getc(h);
  727. if(c != '\n'){
  728. ungetc(h);
  729. goto top;
  730. }
  731. case '\n':
  732. if(h->tok == '\n'){
  733. h->eol = 1;
  734. h->eoh = 1;
  735. return '\n';
  736. }
  737. c = getc(h);
  738. if(c < 0){
  739. h->eol = 1;
  740. return '\n';
  741. }
  742. if(c != ' ' && c != '\t'){
  743. ungetc(h);
  744. h->eol = 1;
  745. return '\n';
  746. }
  747. goto top;
  748. case ')':
  749. case '<': case '>':
  750. case '[': case ']':
  751. case '@': case '/':
  752. case ',': case ';': case ':': case '?': case '=':
  753. if(skipwhite){
  754. ungetc(h);
  755. return c;
  756. }
  757. return c;
  758. case '"':
  759. if(skipwhite){
  760. ungetc(h);
  761. return c;
  762. }
  763. word(h, "\"");
  764. getc(h); /* skip the closing quote */
  765. return QString;
  766. default:
  767. ungetc(h);
  768. if(skipwhite)
  769. return c;
  770. word(h, "\"(){}<>@,;:/[]?=\r\n \t");
  771. if(h->wordval[0] == '\0'){
  772. h->c->head.closeit = 1;
  773. hfail(h->c, HSyntax);
  774. longjmp(h->jmp, -1);
  775. }
  776. return Word;
  777. }
  778. /* not reached */
  779. }
  780. /*
  781. * return the rest of an rfc 822, including \n
  782. * do not map to lower case
  783. */
  784. static void
  785. lexhead(Hlex *h)
  786. {
  787. int c, n;
  788. n = 0;
  789. while((c = getc(h)) >= 0){
  790. if(c == '\r')
  791. c = wordcr(h);
  792. else if(c == '\n')
  793. c = wordnl(h);
  794. if(c == '\n')
  795. break;
  796. if(c == '\\'){
  797. c = getc(h);
  798. if(c < 0)
  799. break;
  800. }
  801. if(n < HMaxWord-1)
  802. h->wordval[n++] = c;
  803. }
  804. h->tok = '\n';
  805. h->eol = 1;
  806. h->wordval[n] = '\0';
  807. }
  808. static void
  809. word(Hlex *h, char *stop)
  810. {
  811. int c, n;
  812. n = 0;
  813. while((c = getc(h)) >= 0){
  814. if(c == '\r')
  815. c = wordcr(h);
  816. else if(c == '\n')
  817. c = wordnl(h);
  818. if(c == '\\'){
  819. c = getc(h);
  820. if(c < 0)
  821. break;
  822. }else if(c < 32 || strchr(stop, c) != nil){
  823. ungetc(h);
  824. break;
  825. }
  826. if(n < HMaxWord-1)
  827. h->wordval[n++] = c;
  828. }
  829. h->wordval[n] = '\0';
  830. }
  831. static int
  832. wordcr(Hlex *h)
  833. {
  834. int c;
  835. c = getc(h);
  836. if(c == '\n')
  837. return wordnl(h);
  838. ungetc(h);
  839. return ' ';
  840. }
  841. static int
  842. wordnl(Hlex *h)
  843. {
  844. int c;
  845. c = getc(h);
  846. if(c == ' ' || c == '\t')
  847. return c;
  848. ungetc(h);
  849. return '\n';
  850. }
  851. static int
  852. getc(Hlex *h)
  853. {
  854. if(h->eoh)
  855. return -1;
  856. if(h->c->hpos < h->c->hstop)
  857. return *h->c->hpos++;
  858. h->eoh = 1;
  859. h->eol = 1;
  860. return -1;
  861. }
  862. static void
  863. ungetc(Hlex *h)
  864. {
  865. if(h->eoh)
  866. return;
  867. h->c->hpos--;
  868. }
  869. static ulong
  870. digtoul(char *s, char **e)
  871. {
  872. ulong v;
  873. int c, ovfl;
  874. v = 0;
  875. ovfl = 0;
  876. for(;;){
  877. c = *s;
  878. if(c < '0' || c > '9')
  879. break;
  880. s++;
  881. c -= '0';
  882. if(v > UlongMax/10 || v == UlongMax/10 && c >= UlongMax%10)
  883. ovfl = 1;
  884. v = v * 10 + c;
  885. }
  886. if(e)
  887. *e = s;
  888. if(ovfl)
  889. return UlongMax;
  890. return v;
  891. }
  892. int
  893. http11(HConnect *c)
  894. {
  895. return c->req.vermaj > 1 || c->req.vermaj == 1 && c->req.vermin > 0;
  896. }
  897. char*
  898. hmkmimeboundary(HConnect *c)
  899. {
  900. char buf[32];
  901. int i;
  902. srand((time(0)<<16)|getpid());
  903. strcpy(buf, "upas-");
  904. for(i = 5; i < sizeof(buf)-1; i++)
  905. buf[i] = 'a' + nrand(26);
  906. buf[i] = 0;
  907. return hstrdup(c, buf);
  908. }
  909. HSPairs*
  910. hmkspairs(HConnect *c, char *s, char *t, HSPairs *next)
  911. {
  912. HSPairs *sp;
  913. sp = halloc(c, sizeof *sp);
  914. sp->s = s;
  915. sp->t = t;
  916. sp->next = next;
  917. return sp;
  918. }
  919. HSPairs*
  920. hrevspairs(HSPairs *sp)
  921. {
  922. HSPairs *last, *next;
  923. last = nil;
  924. for(; sp != nil; sp = next){
  925. next = sp->next;
  926. sp->next = last;
  927. last = sp;
  928. }
  929. return last;
  930. }
  931. HFields*
  932. hmkhfields(HConnect *c, char *s, HSPairs *p, HFields *next)
  933. {
  934. HFields *hf;
  935. hf = halloc(c, sizeof *hf);
  936. hf->s = s;
  937. hf->params = p;
  938. hf->next = next;
  939. return hf;
  940. }
  941. HFields*
  942. hrevhfields(HFields *hf)
  943. {
  944. HFields *last, *next;
  945. last = nil;
  946. for(; hf != nil; hf = next){
  947. next = hf->next;
  948. hf->next = last;
  949. last = hf;
  950. }
  951. return last;
  952. }
  953. HContent*
  954. hmkcontent(HConnect *c, char *generic, char *specific, HContent *next)
  955. {
  956. HContent *ct;
  957. ct = halloc(c, sizeof(HContent));
  958. ct->generic = generic;
  959. ct->specific = specific;
  960. ct->next = next;
  961. ct->q = 1;
  962. ct->mxb = 0;
  963. return ct;
  964. }