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