parse.c 20 KB

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