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