parse_to.c

Go to the documentation of this file.
00001 /*
00002  * $Id: parse_to.c 6032 2010-07-27 20:42:20Z miconda $
00003  *
00004  * Copyright (C) 2001-2003 Fhg Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio 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  * Kamailio 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  * 2006-05-29 removed the NO_PINGTEL_TAG_HACK - it's conflicting the RFC 3261;
00025  *            TAG parameter must have value; other parameters are accepted
00026  *            without value (bogdan)
00027  */
00028 
00029 /*!
00030  * \file
00031  * \brief To header parser
00032  * \ingroup parser
00033  */
00034 
00035 #include "parse_to.h"
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include "../dprint.h"
00039 #include "msg_parser.h"
00040 #include "parse_uri.h"
00041 #include "../ut.h"
00042 #include "../mem/mem.h"
00043 #include "../errinfo.h"
00044 
00045 
00046 enum {
00047    START_TO, DISPLAY_QUOTED, E_DISPLAY_QUOTED, DISPLAY_TOKEN, DISPLAY_TOKEN2,
00048    S_URI_ENCLOSED, URI_ENCLOSED, E_URI_ENCLOSED,
00049    URI_OR_TOKEN, MAYBE_URI_END, END, F_CR, F_LF, F_CRLF
00050 };
00051 
00052 
00053 enum {
00054    S_PARA_NAME=20, PARA_NAME, S_EQUAL, S_PARA_VALUE, TAG1, TAG2,
00055    TAG3, PARA_VALUE_TOKEN , PARA_VALUE_QUOTED, E_PARA_VALUE
00056 };
00057 
00058 
00059 
00060 #define add_param( _param , _body ) \
00061    do{\
00062       LM_DBG("%.*s=%.*s\n",param->name.len,ZSW(param->name.s),\
00063          param->value.len,ZSW(param->value.s));\
00064       if (!(_body)->param_lst)  (_body)->param_lst=(_param);\
00065       else (_body)->last_param->next=(_param);\
00066       (_body)->last_param =(_param);\
00067       if ((_param)->type==TAG_PARAM)\
00068          memcpy(&((_body)->tag_value),&((_param)->value),sizeof(str));\
00069       (_param) = 0;\
00070    }while(0);
00071 
00072 
00073 
00074 inline static void free_to_params(struct to_body* tb)
00075 {
00076    struct to_param *tp=tb->param_lst;
00077    struct to_param *foo;
00078    while (tp){
00079       foo = tp->next;
00080       pkg_free(tp);
00081       tp=foo;
00082    }
00083 }
00084 
00085 
00086 void free_to(struct to_body* tb)
00087 {
00088    free_to_params(tb);
00089    pkg_free(tb);
00090 }
00091 
00092 void destroy_to(struct to_body* tb)
00093 {
00094    free_to_params(tb);
00095 }
00096 
00097 
00098 
00099 static inline char* parse_to_param(char *buffer, char *end,
00100                struct to_body *to_b,
00101                int *returned_status)
00102 {
00103    struct to_param *param;
00104    int status;
00105    int saved_status;
00106    char  *tmp;
00107 
00108    param=0;
00109    status=E_PARA_VALUE;
00110    saved_status=E_PARA_VALUE;
00111    for( tmp=buffer; tmp<end; tmp++)
00112    {
00113       switch(*tmp)
00114       {
00115          case ' ':
00116          case '\t':
00117             switch (status)
00118             {
00119                case TAG3:
00120                   param->type=TAG_PARAM;
00121                case PARA_NAME:
00122                case TAG1:
00123                case TAG2:
00124                   param->name.len = tmp-param->name.s;
00125                   status = S_EQUAL;
00126                   break;
00127                case PARA_VALUE_TOKEN:
00128                   param->value.len = tmp-param->value.s;
00129                   status = E_PARA_VALUE;
00130                   add_param( param , to_b );
00131                   break;
00132                case F_CRLF:
00133                case F_LF:
00134                case F_CR:
00135                   /*previous=crlf and now =' '*/
00136                   status=saved_status;
00137                   break;
00138             }
00139             break;
00140          case '\n':
00141             switch (status)
00142             {
00143                case S_PARA_NAME:
00144                case S_EQUAL:
00145                case S_PARA_VALUE:
00146                case E_PARA_VALUE:
00147                   saved_status=status;
00148                   status=F_LF;
00149                   break;
00150                case TAG3:
00151                   param->type=TAG_PARAM;
00152                case PARA_NAME:
00153                case TAG1:
00154                case TAG2:
00155                   param->name.len = tmp-param->name.s;
00156                   saved_status = S_EQUAL;
00157                   status = F_LF;
00158                   break;
00159                case PARA_VALUE_TOKEN:
00160                   param->value.len = tmp-param->value.s;
00161                   saved_status = E_PARA_VALUE;
00162                   status = F_LF;
00163                   add_param( param , to_b );
00164                   break;
00165                case F_CR:
00166                   status=F_CRLF;
00167                   break;
00168                case F_CRLF:
00169                case F_LF:
00170                   status=saved_status;
00171                   goto endofheader;
00172                default:
00173                   goto parse_error;
00174             }
00175             break;
00176          case '\r':
00177             switch (status)
00178             {
00179                case S_PARA_NAME:
00180                case S_EQUAL:
00181                case S_PARA_VALUE:
00182                case E_PARA_VALUE:
00183                   saved_status=status;
00184                   status=F_CR;
00185                   break;
00186                case TAG3:
00187                   param->type=TAG_PARAM;
00188                case PARA_NAME:
00189                case TAG1:
00190                case TAG2:
00191                   param->name.len = tmp-param->name.s;
00192                   saved_status = S_EQUAL;
00193                   status = F_CR;
00194                   break;
00195                case PARA_VALUE_TOKEN:
00196                   param->value.len = tmp-param->value.s;
00197                   saved_status = E_PARA_VALUE;
00198                   status = F_CR;
00199                   add_param( param , to_b );
00200                   break;
00201                case F_CRLF:
00202                case F_CR:
00203                case F_LF:
00204                   status=saved_status;
00205                   goto endofheader;
00206                default:
00207                   goto parse_error;
00208             }
00209             break;
00210          case 0:
00211             switch (status)
00212             {
00213                case PARA_NAME:
00214                   param->name.len = tmp-param->name.s;
00215                case S_EQUAL:
00216                case S_PARA_VALUE:
00217                   if (param->type==TAG_PARAM)
00218                      goto parse_error;
00219                   param->value.s = tmp;
00220                case PARA_VALUE_TOKEN:
00221                   status = E_PARA_VALUE;
00222                   param->value.len = tmp-param->value.s;
00223                   add_param( param , to_b );
00224                case E_PARA_VALUE:
00225                   saved_status = status;
00226                   goto endofheader;
00227                   break;
00228                default:
00229                   goto parse_error;
00230             }
00231             break;
00232          case '\\':
00233             switch (status)
00234             {
00235                case PARA_VALUE_QUOTED:
00236                   switch (*(tmp+1))
00237                   {
00238                      case '\r':
00239                      case '\n':
00240                         break;
00241                      default:
00242                         tmp++;
00243                   }
00244                default:
00245                   goto parse_error;
00246             }
00247             break;
00248          case '"':
00249             switch (status)
00250             {
00251                case S_PARA_VALUE:
00252                   param->value.s = tmp+1;
00253                   status = PARA_VALUE_QUOTED;
00254                   break;
00255                case PARA_VALUE_QUOTED:
00256                   param->value.len=tmp-param->value.s-1 ;
00257                   add_param( param , to_b );
00258                   status = E_PARA_VALUE;
00259                   break;
00260                case F_CRLF:
00261                case F_LF:
00262                case F_CR:
00263                   /*previous=crlf and now !=' '*/
00264                   goto endofheader;
00265                default:
00266                   goto parse_error;
00267             }
00268             break;
00269          case ';' :
00270             switch (status)
00271             {
00272                case PARA_VALUE_QUOTED:
00273                   break;
00274                case PARA_NAME:
00275                   param->name.len = tmp-param->name.s;
00276                case S_EQUAL:
00277                case S_PARA_VALUE:
00278                   if (param->type==TAG_PARAM)
00279                      goto parse_error;
00280                   param->value.s = tmp;
00281                case PARA_VALUE_TOKEN:
00282                   param->value.len=tmp-param->value.s;
00283                   add_param(param,to_b);
00284                case E_PARA_VALUE:
00285                   param = (struct to_param*)
00286                      pkg_malloc(sizeof(struct to_param));
00287                   if (!param){
00288                      LM_ERR("out of pkg memory\n" );
00289                      goto error;
00290                   }
00291                   memset(param,0,sizeof(struct to_param));
00292                   param->type=GENERAL_PARAM;
00293                   status = S_PARA_NAME;
00294                   break;
00295                case F_CRLF:
00296                case F_LF:
00297                case F_CR:
00298                   /*previous=crlf and now !=' '*/
00299                   goto endofheader;
00300                default:
00301                   goto parse_error;
00302             }
00303             break;
00304          case 'T':
00305          case 't' :
00306             switch (status)
00307             {
00308                case PARA_VALUE_QUOTED:
00309                case PARA_VALUE_TOKEN:
00310                case PARA_NAME:
00311                   break;
00312                case S_PARA_NAME:
00313                   param->name.s = tmp;
00314                   status = TAG1;
00315                   break;
00316                case S_PARA_VALUE:
00317                   param->value.s = tmp;
00318                   status = PARA_VALUE_TOKEN;
00319                   break;
00320                case TAG1:
00321                case TAG2:
00322                case TAG3:
00323                   status = PARA_NAME;
00324                   break;
00325                case F_CRLF:
00326                case F_LF:
00327                case F_CR:
00328                   /*previous=crlf and now !=' '*/
00329                   goto endofheader;
00330                default:
00331                   goto parse_error;
00332             }
00333             break;
00334          case 'A':
00335          case 'a' :
00336             switch (status)
00337             {
00338                case PARA_VALUE_QUOTED:
00339                case PARA_VALUE_TOKEN:
00340                case PARA_NAME:
00341                   break;
00342                case S_PARA_NAME:
00343                   param->name.s = tmp;
00344                   status = PARA_NAME;
00345                   break;
00346                case S_PARA_VALUE:
00347                   param->value.s = tmp;
00348                   status = PARA_VALUE_TOKEN;
00349                   break;
00350                case TAG1:
00351                   status = TAG2;
00352                   break;
00353                case TAG2:
00354                case TAG3:
00355                   status = PARA_NAME;
00356                   break;
00357                case F_CRLF:
00358                case F_LF:
00359                case F_CR:
00360                   /*previous=crlf and now !=' '*/
00361                   goto endofheader;
00362                default:
00363                   goto parse_error;
00364             }
00365             break;
00366          case 'G':
00367          case 'g' :
00368             switch (status)
00369             {
00370                case PARA_VALUE_QUOTED:
00371                case PARA_VALUE_TOKEN:
00372                case PARA_NAME:
00373                   break;
00374                case S_PARA_NAME:
00375                   param->name.s = tmp;
00376                   status = PARA_NAME;
00377                   break;
00378                case S_PARA_VALUE:
00379                   param->value.s = tmp;
00380                   status = PARA_VALUE_TOKEN;
00381                   break;
00382                case TAG1:
00383                case TAG3:
00384                   status = PARA_NAME;
00385                   break;
00386                case TAG2:
00387                   status = TAG3;
00388                   break;
00389                case F_CRLF:
00390                case F_LF:
00391                case F_CR:
00392                   /*previous=crlf and now !=' '*/
00393                   goto endofheader;
00394                default:
00395                   goto parse_error;
00396             }
00397             break;
00398          case '=':
00399             switch (status)
00400             {
00401                case PARA_VALUE_QUOTED:
00402                   break;
00403                case TAG3:
00404                   param->type=TAG_PARAM;
00405                case PARA_NAME:
00406                case TAG1:
00407                case TAG2:
00408                   param->name.len = tmp-param->name.s;
00409                   status = S_PARA_VALUE;
00410                   break;
00411                case S_EQUAL:
00412                   status = S_PARA_VALUE;
00413                   break;
00414                case F_CRLF:
00415                case F_LF:
00416                case F_CR:
00417                   /*previous=crlf and now !=' '*/
00418                   goto endofheader;
00419                default:
00420                   goto parse_error;
00421             }
00422             break;
00423          default:
00424             switch (status)
00425             {
00426                case TAG1:
00427                case TAG2:
00428                case TAG3:
00429                   status = PARA_NAME;
00430                   break;
00431                case PARA_VALUE_TOKEN:
00432                case PARA_NAME:
00433                case PARA_VALUE_QUOTED:
00434                   break;
00435                case S_PARA_NAME:
00436                   param->name.s = tmp;
00437                   status = PARA_NAME;
00438                   break;
00439                case S_PARA_VALUE:
00440                   param->value.s = tmp;
00441                   status = PARA_VALUE_TOKEN;
00442                   break;
00443                case F_CRLF:
00444                case F_LF:
00445                case F_CR:
00446                   /*previous=crlf and now !=' '*/
00447                   goto endofheader;
00448                default:
00449                   LM_ERR("spitting out [%c] in status %d\n",*tmp,status );
00450                   goto error;
00451             }
00452       }/*switch*/
00453    }/*for*/
00454 
00455 
00456 endofheader:
00457    if (param && (saved_status==S_EQUAL||saved_status==S_PARA_VALUE) ) {
00458       saved_status = E_PARA_VALUE;
00459       param->value.s= 0;
00460       param->value.len=0;
00461       if (param->type==TAG_PARAM)
00462          goto parse_error;
00463       add_param(param, to_b);
00464    }
00465    *returned_status=saved_status;
00466    return tmp;
00467 
00468 parse_error:
00469    LM_ERR("unexpected char [%c] in status %d: <<%.*s>> .\n",
00470       *tmp,status, (int)(tmp-buffer), ZSW(buffer));
00471 error:
00472    if (param) pkg_free(param);
00473    free_to_params(to_b);
00474    to_b->error=PARSE_ERROR;
00475    *returned_status = status;
00476    return tmp;
00477 }
00478 
00479 
00480 
00481 
00482 char* parse_to(char* buffer, char *end, struct to_body *to_b)
00483 {
00484    int status;
00485    int saved_status;
00486    char  *tmp;
00487    char  *end_mark;
00488 
00489    status=START_TO;
00490    saved_status=START_TO;
00491    to_b->error=PARSE_OK;
00492    to_b->uri.len = 0;
00493    to_b->uri.s= 0;
00494    to_b->display.len = 0;
00495    to_b->display.s = 0;
00496    end_mark=0;
00497 
00498    for( tmp=buffer; tmp<end; tmp++)
00499    {
00500       switch(*tmp)
00501       {
00502          case ' ':
00503          case '\t':
00504             switch (status)
00505             {
00506                case F_CRLF:
00507                case F_LF:
00508                case F_CR:
00509                   /*previous=crlf and now =' '*/
00510                   status=saved_status;
00511                   break;
00512                case URI_ENCLOSED:
00513                   to_b->uri.len = tmp - to_b->uri.s;
00514                   status = E_URI_ENCLOSED;
00515                   break;
00516                case URI_OR_TOKEN:
00517                   status = MAYBE_URI_END;
00518                   end_mark = tmp;
00519                   break;
00520                case DISPLAY_TOKEN:
00521                   end_mark = tmp;
00522                   status = DISPLAY_TOKEN2;
00523                   break;
00524             }
00525             break;
00526          case '\n':
00527             switch (status)
00528             {
00529                case URI_OR_TOKEN:
00530                   end_mark = tmp;
00531                   status = MAYBE_URI_END;
00532                case MAYBE_URI_END:
00533                case DISPLAY_TOKEN:
00534                case DISPLAY_TOKEN2:
00535                case E_DISPLAY_QUOTED:
00536                case END:
00537                   saved_status=status;
00538                   status=F_LF;
00539                   break;
00540                case F_CR:
00541                   status=F_CRLF;
00542                   break;
00543                case F_CRLF:
00544                case F_LF:
00545                   status=saved_status;
00546                   goto endofheader;
00547                default:
00548                   goto parse_error;
00549             }
00550             break;
00551          case '\r':
00552             switch (status)
00553             {
00554                case URI_OR_TOKEN:
00555                   end_mark = tmp;
00556                   status = MAYBE_URI_END;
00557                case MAYBE_URI_END:
00558                case DISPLAY_TOKEN:
00559                case DISPLAY_TOKEN2:
00560                case E_DISPLAY_QUOTED:
00561                case END:
00562                   saved_status=status;
00563                   status=F_CR;
00564                   break;
00565                case F_CRLF:
00566                case F_CR:
00567                case F_LF:
00568                   status=saved_status;
00569                   goto endofheader;
00570                default:
00571                   goto parse_error;
00572             }
00573             break;
00574          case 0:
00575             switch (status)
00576             {
00577                case URI_OR_TOKEN:
00578                case MAYBE_URI_END:
00579                   to_b->uri.len = tmp - to_b->uri.s;
00580                case END:
00581                   saved_status = status = END;
00582                   goto endofheader;
00583                default:
00584                   goto parse_error;
00585             }
00586             break;
00587          case '\\':
00588             switch (status)
00589             {
00590                case DISPLAY_QUOTED:
00591                   tmp++; /* jump over next char */
00592                   break;
00593                default:
00594                   goto parse_error;
00595             }
00596             break;
00597          case '<':
00598             switch (status)
00599             {
00600                case START_TO:
00601                   to_b->body.s=tmp;
00602                   status = S_URI_ENCLOSED;
00603                   break;
00604                case DISPLAY_QUOTED:
00605                   break;
00606                case E_DISPLAY_QUOTED:
00607                   status = S_URI_ENCLOSED;
00608                   break;
00609                case URI_OR_TOKEN:
00610                case DISPLAY_TOKEN:
00611                   end_mark = tmp;
00612                case DISPLAY_TOKEN2:
00613                case MAYBE_URI_END:
00614                   to_b->display.len=end_mark-to_b->display.s;
00615                   status = S_URI_ENCLOSED;
00616                   break;
00617                case F_CRLF:
00618                case F_LF:
00619                case F_CR:
00620                   /*previous=crlf and now !=' '*/
00621                   goto endofheader;
00622                default:
00623                   goto parse_error;
00624             }
00625             break;
00626          case '>':
00627             switch (status)
00628             {
00629                case DISPLAY_QUOTED:
00630                   break;
00631                case URI_ENCLOSED:
00632                   to_b->uri.len = tmp - to_b->uri.s;
00633                case E_URI_ENCLOSED:
00634                   status = END;
00635                   break;
00636                case F_CRLF:
00637                case F_LF:
00638                case F_CR:
00639                   /*previous=crlf and now !=' '*/
00640                   goto endofheader;
00641                default:
00642                   goto parse_error;
00643             }
00644             break;
00645          case '"':
00646             switch (status)
00647             {
00648                case START_TO:
00649                   to_b->body.s = tmp;
00650                   to_b->display.s = tmp;
00651                   status = DISPLAY_QUOTED;
00652                   break;
00653                case DISPLAY_QUOTED:
00654                   status = E_DISPLAY_QUOTED;
00655                   to_b->display.len = tmp-to_b->display.s+1;
00656                   break;
00657                case F_CRLF:
00658                case F_LF:
00659                case F_CR:
00660                   /*previous=crlf and now !=' '*/
00661                   goto endofheader;
00662                default:
00663                   goto parse_error;
00664             }
00665             break;
00666          case ';' :
00667             switch (status)
00668             {
00669                case DISPLAY_QUOTED:
00670                case URI_ENCLOSED:
00671                   break;
00672                case URI_OR_TOKEN:
00673                   end_mark = tmp;
00674                case MAYBE_URI_END:
00675                   to_b->uri.len = end_mark - to_b->uri.s;
00676                case END:
00677                   to_b->body.len = tmp-to_b->body.s;
00678                   tmp = parse_to_param(tmp,end,to_b,&saved_status);
00679                   goto endofheader;
00680                case F_CRLF:
00681                case F_LF:
00682                case F_CR:
00683                   /*previous=crlf and now !=' '*/
00684                   goto endofheader;
00685                default:
00686                   goto parse_error;
00687             }
00688             break;
00689          default:
00690             switch (status)
00691             {
00692                case START_TO:
00693                   to_b->uri.s = to_b->body.s = tmp;
00694                   status = URI_OR_TOKEN;
00695                   to_b->display.s=tmp;
00696                   break;
00697                case S_URI_ENCLOSED:
00698                   to_b->uri.s=tmp;
00699                   status=URI_ENCLOSED;
00700                   break;
00701                case MAYBE_URI_END:
00702                case DISPLAY_TOKEN2:
00703                   status = DISPLAY_TOKEN;
00704                case DISPLAY_QUOTED:
00705                case DISPLAY_TOKEN:
00706                case URI_ENCLOSED:
00707                case URI_OR_TOKEN:
00708                   break;
00709                case F_CRLF:
00710                case F_LF:
00711                case F_CR:
00712                   /*previous=crlf and now !=' '*/
00713                   goto endofheader;
00714                default:
00715                   LM_DBG("spitting out [%c] in status %d\n",
00716                   *tmp,status );
00717                   goto error;
00718             }
00719       }/*char switch*/
00720    }/*for*/
00721 
00722 endofheader:
00723    if (to_b->display.len==0) to_b->display.s=0;
00724    status=saved_status;
00725    LM_DBG("end of header reached, state=%d\n", status);
00726    /* check if error*/
00727    switch(status){
00728       case MAYBE_URI_END:
00729          to_b->uri.len = end_mark - to_b->uri.s;
00730       case END:
00731          to_b->body.len = tmp - to_b->body.s;
00732       case E_PARA_VALUE:
00733          break;
00734       default:
00735          LM_ERR("unexpected end of header in state %d\n", status);
00736          goto error;
00737    }
00738 
00739    LM_DBG("display={%.*s}, ruri={%.*s}\n",
00740       to_b->display.len, ZSW(to_b->display.s),
00741       to_b->uri.len, ZSW(to_b->uri.s));
00742    return tmp;
00743 
00744 parse_error:
00745    LM_ERR("unexpected char [%c] in status %d: <<%.*s>> .\n",
00746       *tmp,status, (int)(tmp-buffer), buffer);
00747 error:
00748    to_b->error=PARSE_ERROR;
00749    return tmp;
00750 
00751 }
00752 
00753 
00754 struct sip_uri *parse_to_uri(struct sip_msg *msg)
00755 {
00756    struct to_body *tb = NULL;
00757    if(msg==NULL || msg->to==NULL || msg->to->parsed==NULL)
00758       return NULL;
00759 
00760    tb = get_to(msg);
00761 
00762    if(tb->parsed_uri.user.s!=NULL || tb->parsed_uri.host.s!=NULL)
00763       return &tb->parsed_uri;
00764 
00765    if (parse_uri(tb->uri.s, tb->uri.len , &tb->parsed_uri)<0)
00766    {
00767       LM_ERR("failed to parse To uri\n");
00768       memset(&tb->parsed_uri, 0, sizeof(struct sip_uri));
00769       set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing To uri");
00770       set_err_reply(400, "bad To uri");
00771       return NULL;
00772    }
00773 
00774    return &tb->parsed_uri;
00775 }

Generated on Thu May 24 00:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6