parse.c 18 KB

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