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