parse_addr_spec.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. /*
  2. * Copyright (C) 2001-2003 Fhg Fokus
  3. *
  4. * This file is part of ser, a free SIP server.
  5. *
  6. * ser is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * ser is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. * History:
  21. * ---------
  22. * 2003-04-26 ZSW (jiri)
  23. * 2010-03-03 fix multi-token no-quotes display name (andrei)
  24. */
  25. /** Parser :: Parse To: header.
  26. * @file
  27. * @ingroup parser
  28. */
  29. #include "parse_to.h"
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include "../dprint.h"
  33. #include "msg_parser.h"
  34. #include "parse_uri.h"
  35. #include "../ut.h"
  36. #include "../mem/mem.h"
  37. enum {
  38. START_TO, DISPLAY_QUOTED, E_DISPLAY_QUOTED, DISPLAY_TOKEN,
  39. DISPLAY_TOKEN_SP, S_URI_ENCLOSED, URI_ENCLOSED, E_URI_ENCLOSED,
  40. URI_OR_TOKEN, MAYBE_URI_END, END, F_CR, F_LF, F_CRLF
  41. };
  42. enum {
  43. S_PARA_NAME=20, PARA_NAME, S_EQUAL, S_PARA_VALUE, TAG1, TAG2,
  44. TAG3, PARA_VALUE_TOKEN , PARA_VALUE_QUOTED, E_PARA_VALUE
  45. };
  46. #define add_param( _param , _body , _newparam ) \
  47. do{\
  48. DBG("DEBUG: add_param: %.*s=%.*s\n",param->name.len,ZSW(param->name.s),\
  49. param->value.len,ZSW(param->value.s));\
  50. if (!(_body)->param_lst) (_body)->param_lst=(_param);\
  51. else (_body)->last_param->next=(_param);\
  52. (_body)->last_param =(_param);\
  53. if ((_param)->type==TAG_PARAM)\
  54. memcpy(&((_body)->tag_value),&((_param)->value),sizeof(str));\
  55. _newparam = 0;\
  56. }while(0);
  57. static char* parse_to_param(char* const buffer, const char* const end,
  58. struct to_body* const to_b, const int allow_comma_sep,
  59. int* const returned_status)
  60. {
  61. struct to_param *param;
  62. struct to_param *newparam;
  63. int status;
  64. int saved_status;
  65. char *tmp;
  66. param=0;
  67. newparam=0;
  68. status=E_PARA_VALUE;
  69. saved_status=E_PARA_VALUE;
  70. for( tmp=buffer; tmp<end; tmp++)
  71. {
  72. switch(*tmp)
  73. {
  74. case ' ':
  75. case '\t':
  76. switch (status)
  77. {
  78. case TAG3:
  79. param->type=TAG_PARAM;
  80. case PARA_NAME:
  81. case TAG1:
  82. case TAG2:
  83. param->name.len = tmp-param->name.s;
  84. status = S_EQUAL;
  85. break;
  86. case PARA_VALUE_TOKEN:
  87. param->value.len = tmp-param->value.s;
  88. status = E_PARA_VALUE;
  89. add_param(param, to_b, newparam);
  90. break;
  91. case F_CRLF:
  92. case F_LF:
  93. case F_CR:
  94. /*previous=crlf and now =' '*/
  95. status=saved_status;
  96. break;
  97. }
  98. break;
  99. case '\n':
  100. switch (status)
  101. {
  102. case S_PARA_NAME:
  103. case S_EQUAL:
  104. case S_PARA_VALUE:
  105. case E_PARA_VALUE:
  106. saved_status=status;
  107. status=F_LF;
  108. break;
  109. case TAG3:
  110. param->type=TAG_PARAM;
  111. case PARA_NAME:
  112. case TAG1:
  113. case TAG2:
  114. param->name.len = tmp-param->name.s;
  115. saved_status = S_EQUAL;
  116. status = F_LF;
  117. break;
  118. case PARA_VALUE_TOKEN:
  119. param->value.len = tmp-param->value.s;
  120. saved_status = E_PARA_VALUE;
  121. status = F_LF;
  122. add_param(param, to_b, newparam);
  123. break;
  124. case F_CR:
  125. status=F_CRLF;
  126. break;
  127. case F_CRLF:
  128. case F_LF:
  129. status=saved_status;
  130. goto endofheader;
  131. default:
  132. LOG( L_ERR , "ERROR: parse_to_param : "
  133. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  134. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  135. goto error;
  136. }
  137. break;
  138. case '\r':
  139. switch (status)
  140. {
  141. case S_PARA_NAME:
  142. case S_EQUAL:
  143. case S_PARA_VALUE:
  144. case E_PARA_VALUE:
  145. saved_status=status;
  146. status=F_CR;
  147. break;
  148. case TAG3:
  149. param->type=TAG_PARAM;
  150. case PARA_NAME:
  151. case TAG1:
  152. case TAG2:
  153. param->name.len = tmp-param->name.s;
  154. saved_status = S_EQUAL;
  155. status = F_CR;
  156. break;
  157. case PARA_VALUE_TOKEN:
  158. param->value.len = tmp-param->value.s;
  159. saved_status = E_PARA_VALUE;
  160. status = F_CR;
  161. add_param(param, to_b, newparam);
  162. break;
  163. case F_CRLF:
  164. case F_CR:
  165. case F_LF:
  166. status=saved_status;
  167. goto endofheader;
  168. default:
  169. LOG( L_ERR , "ERROR: parse_to_param : "
  170. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  171. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  172. goto error;
  173. }
  174. break;
  175. case 0:
  176. switch (status)
  177. {
  178. case TAG3:
  179. param->type = TAG_PARAM;
  180. case PARA_NAME:
  181. case TAG1:
  182. case TAG2:
  183. param->name.len = tmp-param->name.s;
  184. status = S_EQUAL;
  185. case S_EQUAL:
  186. case S_PARA_VALUE:
  187. saved_status=status;
  188. goto endofheader;
  189. case PARA_VALUE_TOKEN:
  190. status = E_PARA_VALUE;
  191. param->value.len = tmp-param->value.s;
  192. add_param(param , to_b, newparam);
  193. case E_PARA_VALUE:
  194. saved_status = status;
  195. goto endofheader;
  196. break;
  197. default:
  198. LOG( L_ERR , "ERROR: parse_to_param : "
  199. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  200. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  201. goto error;
  202. }
  203. break;
  204. case '\\':
  205. switch (status)
  206. {
  207. case PARA_VALUE_QUOTED:
  208. switch (*(tmp+1))
  209. {
  210. case '\r':
  211. case '\n':
  212. break;
  213. default:
  214. tmp++;
  215. }
  216. default:
  217. LOG( L_ERR , "ERROR: parse_to_param : "
  218. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  219. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  220. goto error;
  221. }
  222. break;
  223. case '"':
  224. switch (status)
  225. {
  226. case S_PARA_VALUE:
  227. param->value.s = tmp+1;
  228. status = PARA_VALUE_QUOTED;
  229. break;
  230. case PARA_VALUE_QUOTED:
  231. param->value.len=tmp-param->value.s;
  232. add_param(param, to_b, newparam);
  233. status = E_PARA_VALUE;
  234. break;
  235. case F_CRLF:
  236. case F_LF:
  237. case F_CR:
  238. /*previous=crlf and now !=' '*/
  239. goto endofheader;
  240. default:
  241. LOG( L_ERR , "ERROR: parse_to_param :"
  242. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  243. *tmp,status,(int)(tmp-buffer), ZSW(buffer));
  244. goto error;
  245. }
  246. break;
  247. case ';' :
  248. switch (status)
  249. {
  250. case PARA_VALUE_QUOTED:
  251. break;
  252. case TAG3:
  253. param->type = TAG_PARAM;
  254. case PARA_NAME:
  255. case TAG1:
  256. case TAG2:
  257. param->name.len = tmp-param->name.s;
  258. case S_EQUAL:
  259. param->value.s = 0;
  260. param->value.len = 0;
  261. goto semicolon_add_param;
  262. case S_PARA_VALUE:
  263. param->value.s = tmp;
  264. case PARA_VALUE_TOKEN:
  265. param->value.len=tmp-param->value.s;
  266. semicolon_add_param:
  267. add_param(param, to_b, newparam);
  268. case E_PARA_VALUE:
  269. param = (struct to_param*)
  270. pkg_malloc(sizeof(struct to_param));
  271. if (!param){
  272. LOG( L_ERR , "ERROR: parse_to_param"
  273. " - out of memory\n" );
  274. goto error;
  275. }
  276. memset(param,0,sizeof(struct to_param));
  277. param->type=GENERAL_PARAM;
  278. status = S_PARA_NAME;
  279. /* link to free mem if not added in to_body list */
  280. newparam = param;
  281. break;
  282. case F_CRLF:
  283. case F_LF:
  284. case F_CR:
  285. /*previous=crlf and now !=' '*/
  286. goto endofheader;
  287. default:
  288. LOG( L_ERR , "ERROR: parse_to_param :"
  289. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  290. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  291. goto error;
  292. }
  293. break;
  294. case 'T':
  295. case 't' :
  296. switch (status)
  297. {
  298. case PARA_VALUE_QUOTED:
  299. case PARA_VALUE_TOKEN:
  300. case PARA_NAME:
  301. break;
  302. case S_PARA_NAME:
  303. param->name.s = tmp;
  304. status = TAG1;
  305. break;
  306. case S_PARA_VALUE:
  307. param->value.s = tmp;
  308. status = PARA_VALUE_TOKEN;
  309. break;
  310. case TAG1:
  311. case TAG2:
  312. case TAG3:
  313. status = PARA_NAME;
  314. break;
  315. case F_CRLF:
  316. case F_LF:
  317. case F_CR:
  318. /*previous=crlf and now !=' '*/
  319. goto endofheader;
  320. default:
  321. LOG( L_ERR , "ERROR: parse_to_param :"
  322. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  323. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  324. goto error;
  325. }
  326. break;
  327. case 'A':
  328. case 'a' :
  329. switch (status)
  330. {
  331. case PARA_VALUE_QUOTED:
  332. case PARA_VALUE_TOKEN:
  333. case PARA_NAME:
  334. break;
  335. case S_PARA_NAME:
  336. param->name.s = tmp;
  337. status = PARA_NAME;
  338. break;
  339. case S_PARA_VALUE:
  340. param->value.s = tmp;
  341. status = PARA_VALUE_TOKEN;
  342. break;
  343. case TAG1:
  344. status = TAG2;
  345. break;
  346. case TAG2:
  347. case TAG3:
  348. status = PARA_NAME;
  349. break;
  350. case F_CRLF:
  351. case F_LF:
  352. case F_CR:
  353. /*previous=crlf and now !=' '*/
  354. goto endofheader;
  355. default:
  356. LOG( L_ERR , "ERROR: parse_to_param : "
  357. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  358. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  359. goto error;
  360. }
  361. break;
  362. case 'G':
  363. case 'g' :
  364. switch (status)
  365. {
  366. case PARA_VALUE_QUOTED:
  367. case PARA_VALUE_TOKEN:
  368. case PARA_NAME:
  369. break;
  370. case S_PARA_NAME:
  371. param->name.s = tmp;
  372. status = PARA_NAME;
  373. break;
  374. case S_PARA_VALUE:
  375. param->value.s = tmp;
  376. status = PARA_VALUE_TOKEN;
  377. break;
  378. case TAG1:
  379. case TAG3:
  380. status = PARA_NAME;
  381. break;
  382. case TAG2:
  383. status = TAG3;
  384. break;
  385. case F_CRLF:
  386. case F_LF:
  387. case F_CR:
  388. /*previous=crlf and now !=' '*/
  389. goto endofheader;
  390. default:
  391. LOG( L_ERR , "ERROR: parse_to_param : "
  392. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  393. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  394. goto error;
  395. }
  396. break;
  397. case '=':
  398. switch (status)
  399. {
  400. case PARA_VALUE_QUOTED:
  401. break;
  402. case TAG3:
  403. param->type=TAG_PARAM;
  404. case PARA_NAME:
  405. case TAG1:
  406. case TAG2:
  407. param->name.len = tmp-param->name.s;
  408. status = S_PARA_VALUE;
  409. break;
  410. case S_EQUAL:
  411. status = S_PARA_VALUE;
  412. break;
  413. case F_CRLF:
  414. case F_LF:
  415. case F_CR:
  416. /*previous=crlf and now !=' '*/
  417. goto endofheader;
  418. default:
  419. LOG( L_ERR , "ERROR: parse_to_param : "
  420. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  421. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  422. goto error;
  423. }
  424. break;
  425. case ',':
  426. if(status==PARA_VALUE_QUOTED) {
  427. /* comma is allowed inside quoted values */
  428. break;
  429. }
  430. if (allow_comma_sep)
  431. {
  432. switch (status)
  433. {
  434. case S_PARA_NAME:
  435. case S_EQUAL:
  436. case S_PARA_VALUE:
  437. case E_PARA_VALUE:
  438. saved_status=status;
  439. status=E_PARA_VALUE;
  440. goto endofheader;
  441. case TAG3:
  442. param->type=TAG_PARAM;
  443. case PARA_NAME:
  444. case TAG1:
  445. case TAG2:
  446. param->name.len = tmp-param->name.s;
  447. saved_status = S_EQUAL;
  448. status = E_PARA_VALUE;
  449. goto endofheader;
  450. case PARA_VALUE_TOKEN:
  451. param->value.len = tmp-param->value.s;
  452. saved_status = E_PARA_VALUE;
  453. status = E_PARA_VALUE;
  454. add_param(param, to_b, newparam);
  455. goto endofheader;
  456. case F_CRLF:
  457. case F_CR:
  458. case F_LF:
  459. status=saved_status;
  460. goto endofheader;
  461. default:
  462. LOG( L_ERR , "ERROR: parse_to_param : "
  463. "unexpected char [%c] in status %d: <<%.*s>> .\n",
  464. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  465. goto error;
  466. }
  467. break;
  468. } else {
  469. if((status==S_PARA_VALUE || status==PARA_VALUE_TOKEN)
  470. && param->type==TAG_PARAM) {
  471. /* if comma is not separator, allow it as part of value
  472. * - some user agents use it */
  473. break;
  474. }
  475. LOG( L_ERR, "ERROR parse_to_param : "
  476. "invalid character ',' in status %d: <<%.*s>>\n",
  477. status, (int)(tmp-buffer), ZSW(buffer));
  478. }
  479. default:
  480. switch (status)
  481. {
  482. case TAG1:
  483. case TAG2:
  484. case TAG3:
  485. status = PARA_NAME;
  486. break;
  487. case PARA_VALUE_TOKEN:
  488. case PARA_NAME:
  489. case PARA_VALUE_QUOTED:
  490. break;
  491. case S_PARA_NAME:
  492. param->name.s = tmp;
  493. status = PARA_NAME;
  494. break;
  495. case S_PARA_VALUE:
  496. param->value.s = tmp;
  497. status = PARA_VALUE_TOKEN;
  498. break;
  499. case F_CRLF:
  500. case F_LF:
  501. case F_CR:
  502. /*previous=crlf and now !=' '*/
  503. goto endofheader;
  504. default:
  505. LOG(L_ERR, "ERROR: parse_to_param: "
  506. "spitting out [%c] in status %d\n",*tmp,status );
  507. goto error;
  508. }
  509. }/*switch*/
  510. }/*for*/
  511. if (!(status==F_CR || status==F_LF || status==F_CRLF))
  512. saved_status=status;
  513. endofheader:
  514. switch(saved_status){
  515. case TAG3:
  516. param->type = TAG_PARAM; /* tag at the end */
  517. /* no break */
  518. case PARA_NAME:
  519. case TAG1:
  520. case TAG2:
  521. param->name.len = tmp-param->name.s;
  522. /* no break */
  523. case S_EQUAL:
  524. /* parameter without '=', e.g. foo */
  525. param->value.s=0;
  526. param->value.len=0;
  527. add_param(param, to_b, newparam);
  528. saved_status=E_PARA_VALUE;
  529. break;
  530. case S_PARA_VALUE:
  531. /* parameter with null value, e.g. foo= */
  532. if ( status==F_CRLF )
  533. param->value.s=tmp-2;
  534. else if ( status==F_CR || status==F_LF )
  535. param->value.s=tmp-1;
  536. else
  537. param->value.s=tmp;
  538. param->value.len=0;
  539. add_param(param, to_b, newparam);
  540. saved_status=E_PARA_VALUE;
  541. break;
  542. case PARA_VALUE_TOKEN:
  543. param->value.len=tmp-param->value.s;
  544. add_param(param, to_b, newparam);
  545. saved_status=E_PARA_VALUE;
  546. break;
  547. case E_PARA_VALUE:
  548. break;
  549. default:
  550. LOG( L_ERR , "ERROR: parse_to_param : unexpected end of header,"
  551. " status %d: <<%.*s>> .\n",
  552. saved_status, (int)(tmp-buffer), ZSW(buffer));
  553. goto error;
  554. }
  555. *returned_status=saved_status;
  556. return tmp;
  557. error:
  558. if (newparam) pkg_free(newparam);
  559. to_b->error=PARSE_ERROR;
  560. *returned_status = status;
  561. return tmp;
  562. }
  563. char* parse_addr_spec(char* const buffer, const char* const end, struct to_body* const to_b, const int allow_comma_sep)
  564. {
  565. int status;
  566. int saved_status;
  567. char *tmp,*foo;
  568. saved_status=START_TO; /* fixes gcc 4.x warning */
  569. status=START_TO;
  570. memset(to_b, 0, sizeof(struct to_body));
  571. to_b->error=PARSE_OK;
  572. foo=0;
  573. for( tmp=buffer; tmp<end; tmp++)
  574. {
  575. switch(*tmp)
  576. {
  577. case ' ':
  578. case '\t':
  579. switch (status)
  580. {
  581. case F_CRLF:
  582. case F_LF:
  583. case F_CR:
  584. /*previous=crlf and now =' '*/
  585. status=saved_status;
  586. break;
  587. case URI_ENCLOSED:
  588. to_b->uri.len = tmp - to_b->uri.s;
  589. status = E_URI_ENCLOSED;
  590. break;
  591. case URI_OR_TOKEN:
  592. foo = tmp;
  593. status = MAYBE_URI_END;
  594. break;
  595. case DISPLAY_TOKEN:
  596. foo = tmp;
  597. status = DISPLAY_TOKEN_SP;
  598. break;
  599. }
  600. break;
  601. case '\n':
  602. switch (status)
  603. {
  604. case URI_OR_TOKEN:
  605. foo = tmp;
  606. status = MAYBE_URI_END;
  607. case MAYBE_URI_END:
  608. case DISPLAY_TOKEN_SP:
  609. case E_DISPLAY_QUOTED:
  610. case END:
  611. saved_status=status;
  612. status=F_LF;
  613. break;
  614. case DISPLAY_TOKEN:
  615. foo=tmp;
  616. saved_status=DISPLAY_TOKEN_SP;
  617. status=F_LF;
  618. break;
  619. case F_CR:
  620. status=F_CRLF;
  621. break;
  622. case F_CRLF:
  623. case F_LF:
  624. status=saved_status;
  625. goto endofheader;
  626. default:
  627. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  628. "in status %d: <<%.*s>> .\n",
  629. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  630. goto error;
  631. }
  632. break;
  633. case '\r':
  634. switch (status)
  635. {
  636. case URI_OR_TOKEN:
  637. foo = tmp;
  638. status = MAYBE_URI_END;
  639. case MAYBE_URI_END:
  640. case DISPLAY_TOKEN_SP:
  641. case E_DISPLAY_QUOTED:
  642. case END:
  643. saved_status=status;
  644. status=F_CR;
  645. break;
  646. case DISPLAY_TOKEN:
  647. foo=tmp;
  648. saved_status=DISPLAY_TOKEN_SP;
  649. status=F_CR;
  650. break;
  651. case F_CRLF:
  652. case F_CR:
  653. case F_LF:
  654. status=saved_status;
  655. goto endofheader;
  656. default:
  657. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  658. "in status %d: <<%.*s>> .\n",
  659. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  660. goto error;
  661. }
  662. break;
  663. case 0:
  664. switch (status)
  665. {
  666. case URI_OR_TOKEN:
  667. case MAYBE_URI_END:
  668. to_b->uri.len = tmp - to_b->uri.s;
  669. case END:
  670. saved_status = status = END;
  671. goto endofheader;
  672. default:
  673. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  674. "in status %d: <<%.*s>> .\n",
  675. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  676. goto error;
  677. }
  678. break;
  679. case '\\':
  680. switch (status)
  681. {
  682. case DISPLAY_QUOTED:
  683. tmp++; /* jump over next char */
  684. break;
  685. default:
  686. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  687. "in status %d: <<%.*s>> .\n",
  688. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  689. goto error;
  690. }
  691. break;
  692. case '<':
  693. switch (status)
  694. {
  695. case START_TO:
  696. to_b->body.s=tmp;
  697. status = S_URI_ENCLOSED;
  698. break;
  699. case DISPLAY_QUOTED:
  700. break;
  701. case E_DISPLAY_QUOTED:
  702. status = S_URI_ENCLOSED;
  703. break;
  704. case URI_OR_TOKEN:
  705. case DISPLAY_TOKEN:
  706. to_b->display.len=tmp-to_b->display.s;
  707. status = S_URI_ENCLOSED;
  708. break;
  709. case DISPLAY_TOKEN_SP:
  710. case MAYBE_URI_END:
  711. to_b->display.len=foo-to_b->display.s;
  712. status = S_URI_ENCLOSED;
  713. break;
  714. case F_CRLF:
  715. case F_LF:
  716. case F_CR:
  717. /*previous=crlf and now !=' '*/
  718. goto endofheader;
  719. default:
  720. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  721. "in status %d: <<%.*s>> .\n",
  722. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  723. goto error;
  724. }
  725. break;
  726. case '>':
  727. switch (status)
  728. {
  729. case DISPLAY_QUOTED:
  730. break;
  731. case URI_ENCLOSED:
  732. to_b->uri.len = tmp - to_b->uri.s;
  733. case E_URI_ENCLOSED:
  734. status = END;
  735. foo = 0;
  736. break;
  737. case F_CRLF:
  738. case F_LF:
  739. case F_CR:
  740. /*previous=crlf and now !=' '*/
  741. goto endofheader;
  742. default:
  743. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  744. "in status %d: <<%.*s>> .\n",
  745. *tmp,status, (int)(tmp-buffer), ZSW(buffer));
  746. goto error;
  747. }
  748. break;
  749. case '"':
  750. switch (status)
  751. {
  752. case START_TO:
  753. to_b->body.s = tmp;
  754. to_b->display.s = tmp;
  755. status = DISPLAY_QUOTED;
  756. break;
  757. case DISPLAY_QUOTED:
  758. status = E_DISPLAY_QUOTED;
  759. to_b->display.len = tmp-to_b->display.s+1;
  760. break;
  761. case F_CRLF:
  762. case F_LF:
  763. case F_CR:
  764. /*previous=crlf and now !=' '*/
  765. goto endofheader;
  766. default:
  767. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  768. "in status %d: <<%.*s>> .\n",
  769. *tmp,status, (int)(tmp-buffer), buffer);
  770. goto error;
  771. }
  772. break;
  773. case ';' :
  774. switch (status)
  775. {
  776. case DISPLAY_QUOTED:
  777. case URI_ENCLOSED:
  778. break;
  779. case URI_OR_TOKEN:
  780. foo = tmp;
  781. case MAYBE_URI_END:
  782. to_b->uri.len = foo - to_b->uri.s;
  783. case END:
  784. to_b->body.len = tmp-to_b->body.s;
  785. tmp = parse_to_param(tmp,end,to_b,allow_comma_sep,&saved_status);
  786. goto endofheader;
  787. case F_CRLF:
  788. case F_LF:
  789. case F_CR:
  790. /*previous=crlf and now !=' '*/
  791. goto endofheader;
  792. default:
  793. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  794. "in status %d: <<%.*s>> .\n",
  795. *tmp,status, (int)(tmp-buffer), buffer);
  796. goto error;
  797. }
  798. break;
  799. case ',' :
  800. if (allow_comma_sep)
  801. {
  802. switch (status)
  803. {
  804. case DISPLAY_QUOTED:
  805. case URI_ENCLOSED:
  806. break;
  807. case URI_OR_TOKEN:
  808. foo = tmp;
  809. case MAYBE_URI_END:
  810. to_b->uri.len = foo - to_b->uri.s;
  811. case END:
  812. to_b->body.len = tmp-to_b->body.s;
  813. saved_status = END;
  814. goto endofheader;
  815. case F_CRLF:
  816. case F_LF:
  817. case F_CR:
  818. /*previous=crlf and now !=' '*/
  819. goto endofheader;
  820. default:
  821. LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
  822. "in status %d: <<%.*s>> .\n",
  823. *tmp,status, (int)(tmp-buffer), buffer);
  824. goto error;
  825. }
  826. break;
  827. }
  828. /* If commas not allowed treat as a default character */
  829. default:
  830. switch (status)
  831. {
  832. case START_TO:
  833. to_b->uri.s = to_b->body.s = tmp;
  834. status = URI_OR_TOKEN;
  835. to_b->display.s=tmp;
  836. break;
  837. case S_URI_ENCLOSED:
  838. to_b->uri.s=tmp;
  839. status=URI_ENCLOSED;
  840. break;
  841. case MAYBE_URI_END:
  842. case DISPLAY_TOKEN_SP:
  843. status = DISPLAY_TOKEN;
  844. case DISPLAY_QUOTED:
  845. case DISPLAY_TOKEN:
  846. case URI_ENCLOSED:
  847. case URI_OR_TOKEN:
  848. break;
  849. case F_CRLF:
  850. case F_LF:
  851. case F_CR:
  852. /*previous=crlf and now !=' '*/
  853. goto endofheader;
  854. default:
  855. DBG("DEBUG:parse_to: spitting out [%c] in status %d\n",
  856. *tmp,status );
  857. goto error;
  858. }
  859. }/*char switch*/
  860. }/*for*/
  861. /* Reached end of buffer */
  862. switch (status)
  863. {
  864. case URI_OR_TOKEN:
  865. case MAYBE_URI_END:
  866. case END:
  867. saved_status = status;
  868. foo = tmp;
  869. }
  870. endofheader:
  871. if (to_b->display.len==0) to_b->display.s=0;
  872. status=saved_status;
  873. DBG("end of header reached, state=%d\n", status);
  874. /* check if error*/
  875. switch(status){
  876. case URI_OR_TOKEN:
  877. case MAYBE_URI_END:
  878. to_b->uri.len = foo - to_b->uri.s;
  879. case END:
  880. to_b->body.len = tmp - to_b->body.s;
  881. case E_PARA_VALUE:
  882. break;
  883. default:
  884. LOG(L_ERR, "ERROR: parse_to: invalid To - unexpected "
  885. "end of header in state %d\n", status);
  886. goto error;
  887. }
  888. return tmp;
  889. error:
  890. to_b->error=PARSE_ERROR;
  891. return tmp;
  892. }
  893. void free_to_params(struct to_body* const tb)
  894. {
  895. struct to_param *tp=tb->param_lst;
  896. struct to_param *foo;
  897. while (tp){
  898. foo = tp->next;
  899. pkg_free(tp);
  900. tp=foo;
  901. }
  902. tb->param_lst = NULL;
  903. }
  904. void free_to(struct to_body* const tb)
  905. {
  906. free_to_params(tb);
  907. pkg_free(tb);
  908. }