parse.c 18 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  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. else{
  309. /* cope with accept: application/xhtml+xml; profile=http://www.wapforum.org/xhtml, */
  310. while(lex(h) == Word || (h->tok != ',' && h->eol == 0) )
  311. ;
  312. return mimeok(h, name, multipart, head);
  313. }
  314. }
  315. break;
  316. case ',':
  317. return mimeok(h, name, multipart, head);
  318. default:
  319. return head;
  320. }
  321. lex(h);
  322. }
  323. return head;
  324. }
  325. /*
  326. * parse a list of entity tags
  327. * 1#entity-tag
  328. * entity-tag = [weak] opaque-tag
  329. * weak = "W/"
  330. * opaque-tag = quoted-string
  331. */
  332. static HETag*
  333. mimeetag(Hlex *h, HETag *head)
  334. {
  335. HETag *e;
  336. int weak;
  337. for(;;){
  338. while(lex(h) != Word && h->tok != QString)
  339. if(h->tok != ',')
  340. return head;
  341. weak = 0;
  342. if(h->tok == Word && strcmp(h->wordval, "*") != 0){
  343. if(strcmp(h->wordval, "W") != 0)
  344. return head;
  345. if(lex(h) != '/' || lex(h) != QString)
  346. return head;
  347. weak = 1;
  348. }
  349. e = halloc(h->c, sizeof(HETag));
  350. e->etag = hstrdup(h->c, h->wordval);
  351. e->weak = weak;
  352. e->next = head;
  353. head = e;
  354. if(lex(h) != ',')
  355. return head;
  356. }
  357. return head;
  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. goto top;
  760. return 0;
  761. }
  762. /*
  763. * return the rest of an rfc 822, including \n
  764. * do not map to lower case
  765. */
  766. static void
  767. lexhead(Hlex *h)
  768. {
  769. int c, n;
  770. n = 0;
  771. while((c = getc(h)) >= 0){
  772. if(c == '\r')
  773. c = wordcr(h);
  774. else if(c == '\n')
  775. c = wordnl(h);
  776. if(c == '\n')
  777. break;
  778. if(c == '\\'){
  779. c = getc(h);
  780. if(c < 0)
  781. break;
  782. }
  783. if(n < HMaxWord-1)
  784. h->wordval[n++] = c;
  785. }
  786. h->tok = '\n';
  787. h->eol = 1;
  788. h->wordval[n] = '\0';
  789. }
  790. static void
  791. word(Hlex *h, char *stop)
  792. {
  793. int c, n;
  794. n = 0;
  795. while((c = getc(h)) >= 0){
  796. if(c == '\r')
  797. c = wordcr(h);
  798. else if(c == '\n')
  799. c = wordnl(h);
  800. if(c == '\\'){
  801. c = getc(h);
  802. if(c < 0)
  803. break;
  804. }else if(c < 32 || strchr(stop, c) != nil){
  805. ungetc(h);
  806. break;
  807. }
  808. if(n < HMaxWord-1)
  809. h->wordval[n++] = c;
  810. }
  811. h->wordval[n] = '\0';
  812. }
  813. static int
  814. wordcr(Hlex *h)
  815. {
  816. int c;
  817. c = getc(h);
  818. if(c == '\n')
  819. return wordnl(h);
  820. ungetc(h);
  821. return ' ';
  822. }
  823. static int
  824. wordnl(Hlex *h)
  825. {
  826. int c;
  827. c = getc(h);
  828. if(c == ' ' || c == '\t')
  829. return c;
  830. ungetc(h);
  831. return '\n';
  832. }
  833. static int
  834. getc(Hlex *h)
  835. {
  836. if(h->eoh)
  837. return -1;
  838. if(h->c->hpos < h->c->hstop)
  839. return *h->c->hpos++;
  840. h->eoh = 1;
  841. h->eol = 1;
  842. return -1;
  843. }
  844. static void
  845. ungetc(Hlex *h)
  846. {
  847. if(h->eoh)
  848. return;
  849. h->c->hpos--;
  850. }
  851. static ulong
  852. digtoul(char *s, char **e)
  853. {
  854. ulong v;
  855. int c, ovfl;
  856. v = 0;
  857. ovfl = 0;
  858. for(;;){
  859. c = *s;
  860. if(c < '0' || c > '9')
  861. break;
  862. s++;
  863. c -= '0';
  864. if(v > UlongMax/10 || v == UlongMax/10 && c >= UlongMax%10)
  865. ovfl = 1;
  866. v = v * 10 + c;
  867. }
  868. if(e)
  869. *e = s;
  870. if(ovfl)
  871. return UlongMax;
  872. return v;
  873. }
  874. int
  875. http11(HConnect *c)
  876. {
  877. return c->req.vermaj > 1 || c->req.vermaj == 1 && c->req.vermin > 0;
  878. }
  879. char*
  880. hmkmimeboundary(HConnect *c)
  881. {
  882. char buf[32];
  883. int i;
  884. srand((time(0)<<16)|getpid());
  885. strcpy(buf, "upas-");
  886. for(i = 5; i < sizeof(buf)-1; i++)
  887. buf[i] = 'a' + nrand(26);
  888. buf[i] = 0;
  889. return hstrdup(c, buf);
  890. }
  891. HSPairs*
  892. hmkspairs(HConnect *c, char *s, char *t, HSPairs *next)
  893. {
  894. HSPairs *sp;
  895. sp = halloc(c, sizeof *sp);
  896. sp->s = s;
  897. sp->t = t;
  898. sp->next = next;
  899. return sp;
  900. }
  901. HSPairs*
  902. hrevspairs(HSPairs *sp)
  903. {
  904. HSPairs *last, *next;
  905. last = nil;
  906. for(; sp != nil; sp = next){
  907. next = sp->next;
  908. sp->next = last;
  909. last = sp;
  910. }
  911. return last;
  912. }
  913. HFields*
  914. hmkhfields(HConnect *c, char *s, HSPairs *p, HFields *next)
  915. {
  916. HFields *hf;
  917. hf = halloc(c, sizeof *hf);
  918. hf->s = s;
  919. hf->params = p;
  920. hf->next = next;
  921. return hf;
  922. }
  923. HFields*
  924. hrevhfields(HFields *hf)
  925. {
  926. HFields *last, *next;
  927. last = nil;
  928. for(; hf != nil; hf = next){
  929. next = hf->next;
  930. hf->next = last;
  931. last = hf;
  932. }
  933. return last;
  934. }
  935. HContent*
  936. hmkcontent(HConnect *c, char *generic, char *specific, HContent *next)
  937. {
  938. HContent *ct;
  939. ct = halloc(c, sizeof(HContent));
  940. ct->generic = generic;
  941. ct->specific = specific;
  942. ct->next = next;
  943. ct->q = 1;
  944. ct->mxb = 0;
  945. return ct;
  946. }