parse_to.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2001-2003 Fhg Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * ser is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * ---------
00024  * 2003-04-26 ZSW (jiri)
00025  * 2010-03-03  fix multi-token no-quotes display name (andrei)
00026  */
00027 
00033 #include "parse_to.h"
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include "../dprint.h"
00037 #include "msg_parser.h"
00038 #include "parse_uri.h"
00039 #include "../ut.h"
00040 #include "../mem/mem.h"
00041 
00042 
00043 enum {
00044         START_TO, DISPLAY_QUOTED, E_DISPLAY_QUOTED, DISPLAY_TOKEN,
00045         DISPLAY_TOKEN_SP, S_URI_ENCLOSED, URI_ENCLOSED, E_URI_ENCLOSED,
00046         URI_OR_TOKEN, MAYBE_URI_END, END, F_CR, F_LF, F_CRLF
00047 };
00048 
00049 
00050 enum {
00051         S_PARA_NAME=20, PARA_NAME, S_EQUAL, S_PARA_VALUE, TAG1, TAG2,
00052         TAG3, PARA_VALUE_TOKEN , PARA_VALUE_QUOTED, E_PARA_VALUE
00053 };
00054 
00055 
00056 
00057 #define add_param( _param , _body , _newparam ) \
00058         do{\
00059                 DBG("DEBUG: add_param: %.*s=%.*s\n",param->name.len,ZSW(param->name.s),\
00060                         param->value.len,ZSW(param->value.s));\
00061                 if (!(_body)->param_lst)  (_body)->param_lst=(_param);\
00062                 else (_body)->last_param->next=(_param);\
00063                 (_body)->last_param =(_param);\
00064                 if ((_param)->type==TAG_PARAM)\
00065                         memcpy(&((_body)->tag_value),&((_param)->value),sizeof(str));\
00066                 _newparam = 0;\
00067         }while(0);
00068 
00069 
00070 
00071 
00072 
00073 static /*inline*/ char* parse_to_param(char *buffer, char *end,
00074                                         struct to_body *to_b,
00075                                         int *returned_status)
00076 {
00077         struct to_param *param;
00078         struct to_param *newparam;
00079         int status;
00080         int saved_status;
00081         char  *tmp;
00082 
00083         param=0;
00084         newparam=0;
00085         status=E_PARA_VALUE;
00086         saved_status=E_PARA_VALUE;
00087         for( tmp=buffer; tmp<end; tmp++)
00088         {
00089                 switch(*tmp)
00090                 {
00091                         case ' ':
00092                         case '\t':
00093                                 switch (status)
00094                                 {
00095                                         case TAG3:
00096                                                 param->type=TAG_PARAM;
00097                                         case PARA_NAME:
00098                                         case TAG1:
00099                                         case TAG2:
00100                                                 param->name.len = tmp-param->name.s;
00101                                                 status = S_EQUAL;
00102                                                 break;
00103                                         case PARA_VALUE_TOKEN:
00104                                                 param->value.len = tmp-param->value.s;
00105                                                 status = E_PARA_VALUE;
00106                                                 add_param(param, to_b, newparam);
00107                                                 break;
00108                                         case F_CRLF:
00109                                         case F_LF:
00110                                         case F_CR:
00111                                                 /*previous=crlf and now =' '*/
00112                                                 status=saved_status;
00113                                                 break;
00114                                 }
00115                                 break;
00116                         case '\n':
00117                                 switch (status)
00118                                 {
00119                                         case S_PARA_NAME:
00120                                         case S_EQUAL:
00121                                         case S_PARA_VALUE:
00122                                         case E_PARA_VALUE:
00123                                                 saved_status=status;
00124                                                 status=F_LF;
00125                                                 break;
00126                                         case TAG3:
00127                                                 param->type=TAG_PARAM;
00128                                         case PARA_NAME:
00129                                         case TAG1:
00130                                         case TAG2:
00131                                                 param->name.len = tmp-param->name.s;
00132                                                 saved_status = S_EQUAL;
00133                                                 status = F_LF;
00134                                                 break;
00135                                         case PARA_VALUE_TOKEN:
00136                                                 param->value.len = tmp-param->value.s;
00137                                                 saved_status = E_PARA_VALUE;
00138                                                 status = F_LF;
00139                                                 add_param(param, to_b, newparam);
00140                                                 break;
00141                                         case F_CR:
00142                                                 status=F_CRLF;
00143                                                 break;
00144                                         case F_CRLF:
00145                                         case F_LF:
00146                                                 status=saved_status;
00147                                                 goto endofheader;
00148                                         default:
00149                                                 LOG( L_ERR , "ERROR: parse_to_param : "
00150                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00151                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00152                                                 goto error;
00153                                 }
00154                                 break;
00155                         case '\r':
00156                                 switch (status)
00157                                 {
00158                                         case S_PARA_NAME:
00159                                         case S_EQUAL:
00160                                         case S_PARA_VALUE:
00161                                         case E_PARA_VALUE:
00162                                                 saved_status=status;
00163                                                 status=F_CR;
00164                                                 break;
00165                                         case TAG3:
00166                                                 param->type=TAG_PARAM;
00167                                         case PARA_NAME:
00168                                         case TAG1:
00169                                         case TAG2:
00170                                                 param->name.len = tmp-param->name.s;
00171                                                 saved_status = S_EQUAL;
00172                                                 status = F_CR;
00173                                                 break;
00174                                         case PARA_VALUE_TOKEN:
00175                                                 param->value.len = tmp-param->value.s;
00176                                                 saved_status = E_PARA_VALUE;
00177                                                 status = F_CR;
00178                                                 add_param(param, to_b, newparam);
00179                                                 break;
00180                                         case F_CRLF:
00181                                         case F_CR:
00182                                         case F_LF:
00183                                                 status=saved_status;
00184                                                 goto endofheader;
00185                                         default:
00186                                                 LOG( L_ERR , "ERROR: parse_to_param : "
00187                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00188                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00189                                                 goto error;
00190                                 }
00191                                 break;
00192                         case 0:
00193                                 switch (status)
00194                                 {
00195                                         case TAG3:
00196                                                 param->type = TAG_PARAM;
00197                                         case PARA_NAME:
00198                                         case TAG1:
00199                                         case TAG2:
00200                                                 param->name.len = tmp-param->name.s;
00201                                                 status = S_EQUAL;
00202                                         case S_EQUAL:
00203                                         case S_PARA_VALUE:
00204                                                 saved_status=status;
00205                                                 goto endofheader;
00206                                         case PARA_VALUE_TOKEN:
00207                                                 status = E_PARA_VALUE;
00208                                                 param->value.len = tmp-param->value.s;
00209                                                 add_param(param , to_b, newparam);
00210                                         case E_PARA_VALUE:
00211                                                 saved_status = status;
00212                                                 goto endofheader;
00213                                                 break;
00214                                         default:
00215                                                 LOG( L_ERR , "ERROR: parse_to_param : "
00216                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00217                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00218                                                 goto error;
00219                                 }
00220                                 break;
00221                         case '\\':
00222                                 switch (status)
00223                                 {
00224                                         case PARA_VALUE_QUOTED:
00225                                                 switch (*(tmp+1))
00226                                                 {
00227                                                         case '\r':
00228                                                         case '\n':
00229                                                                 break;
00230                                                         default:
00231                                                                 tmp++;
00232                                                 }
00233                                         default:
00234                                                 LOG( L_ERR , "ERROR: parse_to_param : "
00235                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00236                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00237                                                 goto error;
00238                                 }
00239                                 break;
00240                         case '"':
00241                                 switch (status)
00242                                 {
00243                                         case S_PARA_VALUE:
00244                                                 param->value.s = tmp+1;
00245                                                 status = PARA_VALUE_QUOTED;
00246                                                 break;
00247                                         case PARA_VALUE_QUOTED:
00248                                                 param->value.len=tmp-param->value.s;
00249                                                 add_param(param, to_b, newparam);
00250                                                 status = E_PARA_VALUE;
00251                                                 break;
00252                                         case F_CRLF:
00253                                         case F_LF:
00254                                         case F_CR:
00255                                                 /*previous=crlf and now !=' '*/
00256                                                 goto endofheader;
00257                                         default:
00258                                                 LOG( L_ERR , "ERROR: parse_to_param :"
00259                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00260                                                         *tmp,status,(int)(tmp-buffer), ZSW(buffer));
00261                                                 goto error;
00262                                 }
00263                                 break;
00264                         case ';' :
00265                                 switch (status)
00266                                 {
00267                                         case PARA_VALUE_QUOTED:
00268                                                 break;
00269                                         case TAG3:
00270                                                 param->type = TAG_PARAM;
00271                                         case PARA_NAME:
00272                                         case TAG1:
00273                                         case TAG2:
00274                                                 param->name.len = tmp-param->name.s;
00275                                         case S_EQUAL:
00276                                                 param->value.s = 0;
00277                                                 param->value.len = 0;
00278                                                 goto semicolon_add_param;
00279                                         case S_PARA_VALUE:
00280                                                 param->value.s = tmp;
00281                                         case PARA_VALUE_TOKEN:
00282                                                 param->value.len=tmp-param->value.s;
00283 semicolon_add_param:
00284                                                 add_param(param, to_b, newparam);
00285                                         case E_PARA_VALUE:
00286                                                 param = (struct to_param*)
00287                                                         pkg_malloc(sizeof(struct to_param));
00288                                                 if (!param){
00289                                                         LOG( L_ERR , "ERROR: parse_to_param"
00290                                                         " - out of memory\n" );
00291                                                         goto error;
00292                                                 }
00293                                                 memset(param,0,sizeof(struct to_param));
00294                                                 param->type=GENERAL_PARAM;
00295                                                 status = S_PARA_NAME;
00296                                                 /* link to free mem if not added in to_body list */
00297                                                 newparam = param;
00298                                                 break;
00299                                         case F_CRLF:
00300                                         case F_LF:
00301                                         case F_CR:
00302                                                 /*previous=crlf and now !=' '*/
00303                                                 goto endofheader;
00304                                         default:
00305                                                 LOG( L_ERR , "ERROR: parse_to_param :"
00306                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00307                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00308                                                 goto error;
00309                                 }
00310                                 break;
00311                         case 'T':
00312                         case 't' :
00313                                 switch (status)
00314                                 {
00315                                         case PARA_VALUE_QUOTED:
00316                                         case PARA_VALUE_TOKEN:
00317                                         case PARA_NAME:
00318                                                 break;
00319                                         case S_PARA_NAME:
00320                                                 param->name.s = tmp;
00321                                                 status = TAG1;
00322                                                 break;
00323                                         case S_PARA_VALUE:
00324                                                 param->value.s = tmp;
00325                                                 status = PARA_VALUE_TOKEN;
00326                                                 break;
00327                                         case TAG1:
00328                                         case TAG2:
00329                                         case TAG3:
00330                                                 status = PARA_NAME;
00331                                                 break;
00332                                         case F_CRLF:
00333                                         case F_LF:
00334                                         case F_CR:
00335                                                 /*previous=crlf and now !=' '*/
00336                                                 goto endofheader;
00337                                         default:
00338                                                 LOG( L_ERR , "ERROR: parse_to_param :"
00339                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00340                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00341                                                 goto error;
00342                                 }
00343                                 break;
00344                         case 'A':
00345                         case 'a' :
00346                                 switch (status)
00347                                 {
00348                                         case PARA_VALUE_QUOTED:
00349                                         case PARA_VALUE_TOKEN:
00350                                         case PARA_NAME:
00351                                                 break;
00352                                         case S_PARA_NAME:
00353                                                 param->name.s = tmp;
00354                                                 status = PARA_NAME;
00355                                                 break;
00356                                         case S_PARA_VALUE:
00357                                                 param->value.s = tmp;
00358                                                 status = PARA_VALUE_TOKEN;
00359                                                 break;
00360                                         case TAG1:
00361                                                 status = TAG2;
00362                                                 break;
00363                                         case TAG2:
00364                                         case TAG3:
00365                                                 status = PARA_NAME;
00366                                                 break;
00367                                         case F_CRLF:
00368                                         case F_LF:
00369                                         case F_CR:
00370                                                 /*previous=crlf and now !=' '*/
00371                                                 goto endofheader;
00372                                         default:
00373                                                 LOG( L_ERR , "ERROR: parse_to_param : "
00374                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00375                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00376                                                 goto error;
00377                                 }
00378                                 break;
00379                         case 'G':
00380                         case 'g' :
00381                                 switch (status)
00382                                 {
00383                                         case PARA_VALUE_QUOTED:
00384                                         case PARA_VALUE_TOKEN:
00385                                         case PARA_NAME:
00386                                                 break;
00387                                         case S_PARA_NAME:
00388                                                 param->name.s = tmp;
00389                                                 status = PARA_NAME;
00390                                                 break;
00391                                         case S_PARA_VALUE:
00392                                                 param->value.s = tmp;
00393                                                 status = PARA_VALUE_TOKEN;
00394                                                 break;
00395                                         case TAG1:
00396                                         case TAG3:
00397                                                 status = PARA_NAME;
00398                                                 break;
00399                                         case TAG2:
00400                                                 status = TAG3;
00401                                                 break;
00402                                         case F_CRLF:
00403                                         case F_LF:
00404                                         case F_CR:
00405                                                 /*previous=crlf and now !=' '*/
00406                                                 goto endofheader;
00407                                         default:
00408                                                 LOG( L_ERR , "ERROR: parse_to_param : "
00409                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00410                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00411                                                 goto error;
00412                                 }
00413                                 break;
00414                         case '=':
00415                                 switch (status)
00416                                 {
00417                                         case PARA_VALUE_QUOTED:
00418                                                 break;
00419                                         case TAG3:
00420                                                 param->type=TAG_PARAM;
00421                                         case PARA_NAME:
00422                                         case TAG1:
00423                                         case TAG2:
00424                                                 param->name.len = tmp-param->name.s;
00425                                                 status = S_PARA_VALUE;
00426                                                 break;
00427                                         case S_EQUAL:
00428                                                 status = S_PARA_VALUE;
00429                                                 break;
00430                                         case F_CRLF:
00431                                         case F_LF:
00432                                         case F_CR:
00433                                                 /*previous=crlf and now !=' '*/
00434                                                 goto endofheader;
00435                                         default:
00436                                                 LOG( L_ERR , "ERROR: parse_to_param : "
00437                                                         "unexpected char [%c] in status %d: <<%.*s>> .\n",
00438                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00439                                                 goto error;
00440                                 }
00441                                 break;
00442                         default:
00443                                 switch (status)
00444                                 {
00445                                         case TAG1:
00446                                         case TAG2:
00447                                         case TAG3:
00448                                                 status = PARA_NAME;
00449                                                 break;
00450                                         case PARA_VALUE_TOKEN:
00451                                         case PARA_NAME:
00452                                         case PARA_VALUE_QUOTED:
00453                                                 break;
00454                                         case S_PARA_NAME:
00455                                                 param->name.s = tmp;
00456                                                 status = PARA_NAME;
00457                                                 break;
00458                                         case S_PARA_VALUE:
00459                                                 param->value.s = tmp;
00460                                                 status = PARA_VALUE_TOKEN;
00461                                                 break;
00462                                         case F_CRLF:
00463                                         case F_LF:
00464                                         case F_CR:
00465                                                 /*previous=crlf and now !=' '*/
00466                                                 goto endofheader;
00467                                         default:
00468                                                 LOG(L_ERR, "ERROR: parse_to_param: "
00469                                                         "spitting out [%c] in status %d\n",*tmp,status );
00470                                                 goto error;
00471                                 }
00472                 }/*switch*/
00473         }/*for*/
00474         if (!(status==F_CR || status==F_LF || status==F_CRLF))
00475                 saved_status=status;
00476 
00477 
00478 endofheader:
00479         switch(saved_status){
00480                 case TAG3:
00481                         param->type = TAG_PARAM; /* tag at the end */
00482                         /* no break */
00483                 case PARA_NAME:
00484                 case TAG1:
00485                 case TAG2:
00486                         param->name.len = tmp-param->name.s;
00487                         /* no break */
00488                 case S_EQUAL:
00489                         /* parameter without '=', e.g. foo */
00490                         param->value.s=0;
00491                         param->value.len=0;
00492                         add_param(param, to_b, newparam);
00493                         saved_status=E_PARA_VALUE;
00494                         break;
00495                 case S_PARA_VALUE:
00496                         /* parameter with null value, e.g. foo= */
00497                         param->value.s=tmp;
00498                         param->value.len=0;
00499                         add_param(param, to_b, newparam);
00500                         saved_status=E_PARA_VALUE;
00501                         break;
00502                 case PARA_VALUE_TOKEN:
00503                         param->value.len=tmp-param->value.s;
00504                         add_param(param, to_b, newparam);
00505                         saved_status=E_PARA_VALUE;
00506                         break;
00507                 case E_PARA_VALUE:
00508                         break;
00509                 default:
00510                         LOG( L_ERR , "ERROR: parse_to_param : unexpected end of header,"
00511                                                 " status %d: <<%.*s>> .\n",
00512                                                 saved_status, (int)(tmp-buffer), ZSW(buffer));
00513                         goto error;
00514         }
00515         *returned_status=saved_status;
00516         return tmp;
00517 
00518 error:
00519         if (newparam) pkg_free(newparam);
00520         to_b->error=PARSE_ERROR;
00521         *returned_status = status;
00522         return tmp;
00523 }
00524 
00525 
00526 
00527 
00528 char* parse_to(char* buffer, char *end, struct to_body *to_b)
00529 {
00530         int status;
00531         int saved_status;
00532         char  *tmp,*foo;
00533         
00534         saved_status=START_TO; /* fixes gcc 4.x warning */
00535         status=START_TO;
00536         memset(to_b, 0, sizeof(struct to_body));
00537         to_b->error=PARSE_OK;
00538         foo=0;
00539 
00540         for( tmp=buffer; tmp<end; tmp++)
00541         {
00542                 switch(*tmp)
00543                 {
00544                         case ' ':
00545                         case '\t':
00546                                 switch (status)
00547                                 {
00548                                         case F_CRLF:
00549                                         case F_LF:
00550                                         case F_CR:
00551                                                 /*previous=crlf and now =' '*/
00552                                                 status=saved_status;
00553                                                 break;
00554                                         case URI_ENCLOSED:
00555                                                 to_b->uri.len = tmp - to_b->uri.s;
00556                                                 status = E_URI_ENCLOSED;
00557                                                 break;
00558                                         case URI_OR_TOKEN:
00559                                                 foo = tmp;
00560                                                 status = MAYBE_URI_END;
00561                                                 break;
00562                                         case DISPLAY_TOKEN:
00563                                                 foo = tmp;
00564                                                 status = DISPLAY_TOKEN_SP;
00565                                                 break;
00566                                 }
00567                                 break;
00568                         case '\n':
00569                                 switch (status)
00570                                 {
00571                                         case URI_OR_TOKEN:
00572                                                 foo = tmp;
00573                                                 status = MAYBE_URI_END;
00574                                         case MAYBE_URI_END:
00575                                         case DISPLAY_TOKEN_SP:
00576                                         case E_DISPLAY_QUOTED:
00577                                         case END:
00578                                                 saved_status=status;
00579                                                 status=F_LF;
00580                                                 break;
00581                                         case DISPLAY_TOKEN:
00582                                                 foo=tmp;
00583                                                 saved_status=DISPLAY_TOKEN_SP;
00584                                                 status=F_LF;
00585                                                 break;
00586                                         case F_CR:
00587                                                 status=F_CRLF;
00588                                                 break;
00589                                         case F_CRLF:
00590                                         case F_LF:
00591                                                 status=saved_status;
00592                                                 goto endofheader;
00593                                         default:
00594                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00595                                                         "in status %d: <<%.*s>> .\n",
00596                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00597                                                 goto error;
00598                                 }
00599                                 break;
00600                         case '\r':
00601                                 switch (status)
00602                                 {
00603                                         case URI_OR_TOKEN:
00604                                                 foo = tmp;
00605                                                 status = MAYBE_URI_END;
00606                                         case MAYBE_URI_END:
00607                                         case DISPLAY_TOKEN_SP:
00608                                         case E_DISPLAY_QUOTED:
00609                                         case END:
00610                                                 saved_status=status;
00611                                                 status=F_CR;
00612                                                 break;
00613                                         case DISPLAY_TOKEN:
00614                                                 foo=tmp;
00615                                                 saved_status=DISPLAY_TOKEN_SP;
00616                                                 status=F_CR;
00617                                                 break;
00618                                         case F_CRLF:
00619                                         case F_CR:
00620                                         case F_LF:
00621                                                 status=saved_status;
00622                                                 goto endofheader;
00623                                         default:
00624                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00625                                                         "in status %d: <<%.*s>> .\n",
00626                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00627                                                 goto error;
00628                                 }
00629                                 break;
00630                         case 0:
00631                                 switch (status)
00632                                 {
00633                                         case URI_OR_TOKEN:
00634                                         case MAYBE_URI_END:
00635                                                 to_b->uri.len = tmp - to_b->uri.s;
00636                                         case END:
00637                                                 saved_status = status = END;
00638                                                 goto endofheader;
00639                                         default:
00640                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00641                                                         "in status %d: <<%.*s>> .\n",
00642                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00643                                                 goto error;
00644                                 }
00645                                 break;
00646                         case '\\':
00647                                 switch (status)
00648                                 {
00649                                         case DISPLAY_QUOTED:
00650                                                 tmp++; /* jump over next char */
00651                                                 break;
00652                                         default:
00653                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00654                                                         "in status %d: <<%.*s>> .\n",
00655                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00656                                                 goto error;
00657                                 }
00658                                 break;
00659                         case '<':
00660                                 switch (status)
00661                                 {
00662                                         case START_TO:
00663                                                 to_b->body.s=tmp;
00664                                                 status = S_URI_ENCLOSED;
00665                                                 break;
00666                                         case DISPLAY_QUOTED:
00667                                                 break;
00668                                         case E_DISPLAY_QUOTED:
00669                                                 status = S_URI_ENCLOSED;
00670                                                 break;
00671                                         case URI_OR_TOKEN:
00672                                         case DISPLAY_TOKEN:
00673                                                 to_b->display.len=tmp-to_b->display.s;
00674                                                 status = S_URI_ENCLOSED;
00675                                                 break;
00676                                         case DISPLAY_TOKEN_SP:
00677                                         case MAYBE_URI_END:
00678                                                 to_b->display.len=foo-to_b->display.s;
00679                                                 status = S_URI_ENCLOSED;
00680                                                 break;
00681                                         case F_CRLF:
00682                                         case F_LF:
00683                                         case F_CR:
00684                                                 /*previous=crlf and now !=' '*/
00685                                                 goto endofheader;
00686                                         default:
00687                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00688                                                         "in status %d: <<%.*s>> .\n",
00689                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00690                                                 goto error;
00691                                 }
00692                                 break;
00693                         case '>':
00694                                 switch (status)
00695                                 {
00696                                         case DISPLAY_QUOTED:
00697                                                 break;
00698                                         case URI_ENCLOSED:
00699                                                 to_b->uri.len = tmp - to_b->uri.s;
00700                                         case E_URI_ENCLOSED:
00701                                                 status = END;
00702                                                 foo = 0;
00703                                                 break;
00704                                         case F_CRLF:
00705                                         case F_LF:
00706                                         case F_CR:
00707                                                 /*previous=crlf and now !=' '*/
00708                                                 goto endofheader;
00709                                         default:
00710                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00711                                                         "in status %d: <<%.*s>> .\n",
00712                                                         *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00713                                                 goto error;
00714                                 }
00715                                 break;
00716                         case '"':
00717                                 switch (status)
00718                                 {
00719                                         case START_TO:
00720                                                 to_b->body.s = tmp;
00721                                                 to_b->display.s = tmp;
00722                                                 status = DISPLAY_QUOTED;
00723                                                 break;
00724                                         case DISPLAY_QUOTED:
00725                                                 status = E_DISPLAY_QUOTED;
00726                                                 to_b->display.len = tmp-to_b->display.s+1;
00727                                                 break;
00728                                         case F_CRLF:
00729                                         case F_LF:
00730                                         case F_CR:
00731                                                 /*previous=crlf and now !=' '*/
00732                                                 goto endofheader;
00733                                         default:
00734                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00735                                                         "in status %d: <<%.*s>> .\n",
00736                                                         *tmp,status, (int)(tmp-buffer), buffer);
00737                                                 goto error;
00738                                 }
00739                                 break;
00740                         case ';' :
00741                                 switch (status)
00742                                 {
00743                                         case DISPLAY_QUOTED:
00744                                         case URI_ENCLOSED:
00745                                                 break;
00746                                         case URI_OR_TOKEN:
00747                                                 foo = tmp;
00748                                         case MAYBE_URI_END:
00749                                                 to_b->uri.len = foo - to_b->uri.s;
00750                                         case END:
00751                                                 to_b->body.len = tmp-to_b->body.s;
00752                                                 tmp = parse_to_param(tmp,end,to_b,&saved_status);
00753                                                 goto endofheader;
00754                                         case F_CRLF:
00755                                         case F_LF:
00756                                         case F_CR:
00757                                                 /*previous=crlf and now !=' '*/
00758                                                 goto endofheader;
00759                                         default:
00760                                                 LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
00761                                                         "in status %d: <<%.*s>> .\n",
00762                                                         *tmp,status, (int)(tmp-buffer), buffer);
00763                                                 goto error;
00764                                 }
00765                                 break;
00766                         default:
00767                                 switch (status)
00768                                 {
00769                                         case START_TO:
00770                                                 to_b->uri.s = to_b->body.s = tmp;
00771                                                 status = URI_OR_TOKEN;
00772                                                 to_b->display.s=tmp;
00773                                                 break;
00774                                         case S_URI_ENCLOSED:
00775                                                 to_b->uri.s=tmp;
00776                                                 status=URI_ENCLOSED;
00777                                                 break;
00778                                         case MAYBE_URI_END:
00779                                         case DISPLAY_TOKEN_SP:
00780                                                 status = DISPLAY_TOKEN;
00781                                         case DISPLAY_QUOTED:
00782                                         case DISPLAY_TOKEN:
00783                                         case URI_ENCLOSED:
00784                                         case URI_OR_TOKEN:
00785                                                 break;
00786                                         case F_CRLF:
00787                                         case F_LF:
00788                                         case F_CR:
00789                                                 /*previous=crlf and now !=' '*/
00790                                                 goto endofheader;
00791                                         default:
00792                                                 DBG("DEBUG:parse_to: spitting out [%c] in status %d\n",
00793                                                 *tmp,status );
00794                                                 goto error;
00795                                 }
00796                 }/*char switch*/
00797         }/*for*/
00798 
00799 endofheader:
00800         if (to_b->display.len==0) to_b->display.s=0;
00801         status=saved_status;
00802         DBG("end of header reached, state=%d\n", status);
00803         /* check if error*/
00804         switch(status){
00805                 case MAYBE_URI_END:
00806                         to_b->uri.len = foo - to_b->uri.s;
00807                 case END:
00808                         to_b->body.len = tmp - to_b->body.s;
00809                 case E_PARA_VALUE:
00810                         break;
00811                 default:
00812                         LOG(L_ERR, "ERROR: parse_to: invalid To -  unexpected "
00813                                         "end of header in state %d\n", status);
00814                         goto error;
00815         }
00816         return tmp;
00817 
00818 error:
00819         to_b->error=PARSE_ERROR;
00820         return tmp;
00821 
00822 }
00823 
00824 
00825 void free_to_params(struct to_body* tb)
00826 {
00827         struct to_param *tp=tb->param_lst;
00828         struct to_param *foo;
00829         while (tp){
00830                 foo = tp->next;
00831                 pkg_free(tp);
00832                 tp=foo;
00833         }
00834 }
00835 
00836 
00837 void free_to(struct to_body* tb)
00838 {
00839         free_to_params(tb);
00840         pkg_free(tb);
00841 }
00842 
00843 
00844 int parse_to_header(struct sip_msg *msg)
00845 {
00846         if ( !msg->to && ( parse_headers(msg,HDR_TO_F,0)==-1 || !msg->to)) {
00847                 ERR("bad msg or missing TO header\n");
00848                 return -1;
00849         }
00850 
00851         // HDR_TO_T is automatically parsed (get_hdr_field in parser/msg_parser.c)
00852         // so check only ptr validity
00853         if (msg->to->parsed)
00854                 return 0;
00855         else
00856                 return -1;
00857 }
00858 
00859 sip_uri_t *parse_to_uri(sip_msg_t *msg)
00860 {
00861         to_body_t *tb = NULL;
00862         
00863         if(msg==NULL)
00864                 return NULL;
00865 
00866         if(parse_to_header(msg)<0)
00867         {
00868                 LM_ERR("cannot parse TO header\n");
00869                 return NULL;
00870         }
00871 
00872         if(msg->to==NULL || get_to(msg)==NULL)
00873                 return NULL;
00874 
00875         tb = get_to(msg);
00876         
00877         if(tb->parsed_uri.user.s!=NULL || tb->parsed_uri.host.s!=NULL)
00878                 return &tb->parsed_uri;
00879 
00880         if (parse_uri(tb->uri.s, tb->uri.len , &tb->parsed_uri)<0)
00881         {
00882                 LM_ERR("failed to parse To uri\n");
00883                 memset(&tb->parsed_uri, 0, sizeof(struct sip_uri));
00884                 return NULL;
00885         }
00886 
00887         return &tb->parsed_uri;
00888 }