parse_disposition.c

Go to the documentation of this file.
00001 /*
00002  * $Id: parse_disposition.c 4720 2008-08-23 10:56:15Z henningw $
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  * 2003-09-09 created (bogdan)
00024  */
00025 
00026 /*!
00027  * \file
00028  * \brief Parse disposition header field
00029  * \ingroup parser
00030  */
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <sys/types.h>
00035 #include <unistd.h>
00036 #include "../mem/mem.h"
00037 #include "../dprint.h"
00038 #include "../ut.h"
00039 #include "parse_disposition.h"
00040 
00041 
00042 /*! parse a string that supposed to be a disposition and fills up the structure
00043  * Returns: -1 : error
00044  *           o : success */
00045 int parse_disposition( str *s, struct disposition *disp)
00046 {
00047    enum { FIND_TYPE, TYPE, END_TYPE, FIND_PARAM, PARAM, END_PARAM, FIND_VAL,
00048           FIND_QUOTED_VAL, QUOTED_VAL, SKIP_QUOTED_VAL, VAL, END_VAL,
00049           F_LF, F_CR, F_CRLF};
00050    struct disposition_param *disp_p;
00051    struct disposition_param *new_p;
00052    int  state;
00053    int  saved_state;
00054    char *tmp;
00055    char *end;
00056 
00057    state = saved_state = FIND_TYPE;
00058    end = s->s + s->len;
00059    disp_p = 0;
00060 
00061    for( tmp=s->s; tmp<end; tmp++) {
00062       switch(*tmp) {
00063          case ' ':
00064          case '\t':
00065             switch (state) {
00066                case FIND_QUOTED_VAL:
00067                   disp_p->body.s = tmp;
00068                   state = QUOTED_VAL;
00069                   break;
00070                case SKIP_QUOTED_VAL:
00071                   state = QUOTED_VAL;
00072                   break;
00073                case TYPE:
00074                   disp->type.len = tmp - disp->type.s;
00075                   state = END_TYPE;
00076                   break;
00077                case PARAM:
00078                   disp_p->name.len = tmp - disp_p->name.s;
00079                   state = END_PARAM;
00080                   break;
00081                case VAL:
00082                   disp_p->body.len = tmp - disp_p->body.s;
00083                   state = END_VAL;
00084                   break;
00085                case F_CRLF:
00086                case F_LF:
00087                case F_CR:
00088                   /*previous=crlf and now =' '*/
00089                   state=saved_state;
00090                   break;
00091             }
00092             break;
00093          case '\n':
00094             switch (state) {
00095                case TYPE:
00096                   disp->type.len = tmp - disp->type.s;
00097                   saved_state = END_TYPE;
00098                   state = F_LF;
00099                   break;
00100                case PARAM:
00101                   disp_p->name.len = tmp - disp_p->name.s;
00102                   saved_state = END_PARAM;
00103                   state = F_LF;
00104                   break;
00105                case VAL:
00106                   disp_p->body.len = tmp - disp_p->body.s;
00107                   saved_state = END_VAL;
00108                   state = F_CR;
00109                   break;
00110                case FIND_TYPE:
00111                case FIND_PARAM:
00112                   saved_state=state;
00113                   state=F_LF;
00114                   break;
00115                case F_CR:
00116                   state=F_CRLF;
00117                   break;
00118                default:
00119                   LM_ERR("unexpected char [%c] in status %d: <<%.*s>>"
00120                         ".\n", *tmp,state, (int)(tmp-s->s), s->s);
00121                   goto error;
00122             }
00123             break;
00124          case '\r':
00125             switch (state) {
00126                case TYPE:
00127                   disp->type.len = tmp - disp->type.s;
00128                   saved_state = END_TYPE;
00129                   state = F_CR;
00130                   break;
00131                case PARAM:
00132                   disp_p->name.len = tmp - disp_p->name.s;
00133                   saved_state = END_PARAM;
00134                   state = F_CR;
00135                   break;
00136                case VAL:
00137                   disp_p->body.len = tmp - disp_p->body.s;
00138                   saved_state = END_VAL;
00139                   state = F_CR;
00140                   break;
00141                case FIND_TYPE:
00142                case FIND_PARAM:
00143                   saved_state=state;
00144                   state=F_CR;
00145                   break;
00146                default:
00147                   LM_ERR("unexpected char [%c] in status %d: <<%.*s>>"
00148                      ".\n", *tmp,state, (int)(tmp-s->s), ZSW(s->s));
00149                   goto error;
00150             }
00151             break;
00152          case 0:
00153             LM_ERR("unexpected char [%c] in status %d: <<%.*s>> .\n",
00154                *tmp,state, (int)(tmp-s->s), ZSW(s->s));
00155             goto error;
00156             break;
00157          case ';':
00158             switch (state) {
00159                case FIND_QUOTED_VAL:
00160                   disp_p->body.s = tmp;
00161                   state = QUOTED_VAL;
00162                   break;
00163                case SKIP_QUOTED_VAL:
00164                   state = QUOTED_VAL;
00165                case QUOTED_VAL:
00166                   break;
00167                case VAL:
00168                   disp_p->body.len = tmp - disp_p->body.s;
00169                   state = FIND_PARAM;
00170                   break;
00171                case PARAM:
00172                   disp_p->name.len = tmp - disp_p->name.s;
00173                   state = FIND_PARAM;
00174                   break;
00175                case TYPE:
00176                   disp->type.len = tmp - disp->type.s;
00177                case END_TYPE:
00178                case END_VAL:
00179                   state = FIND_PARAM;
00180                   break;
00181                default:
00182                   LM_ERR("unexpected char [%c] in status %d: <<%.*s>> "
00183                      ".\n", *tmp,state, (int)(tmp-s->s), ZSW(s->s));
00184                   goto error;
00185             }
00186             break;
00187          case '=':
00188             switch (state) {
00189                case FIND_QUOTED_VAL:
00190                   disp_p->body.s = tmp;
00191                   state = QUOTED_VAL;
00192                   break;
00193                case SKIP_QUOTED_VAL:
00194                   state = QUOTED_VAL;
00195                case QUOTED_VAL:
00196                   break;
00197                case PARAM:
00198                   disp_p->name.len = tmp - disp_p->name.s;
00199                case END_PARAM:
00200                   state = FIND_VAL;
00201                   break;
00202                default:
00203                   LM_ERR("unexpected char [%c] in status %d: <<%.*s>>"
00204                      ".\n", *tmp,state, (int)(tmp-s->s), ZSW(s->s));
00205                   goto error;
00206             }
00207             break;
00208          case '\"':
00209             switch (state) {
00210                case SKIP_QUOTED_VAL:
00211                   state = QUOTED_VAL;
00212                   break;
00213                case FIND_VAL:
00214                   state = FIND_QUOTED_VAL;
00215                   break;
00216                case QUOTED_VAL:
00217                   disp_p->body.len = tmp - disp_p->body.s;
00218                   disp_p->is_quoted = 1;
00219                   state = END_VAL;
00220                   break;
00221                default:
00222                   LM_ERR("unexpected char [%c] in status %d: <<%.*s>>"
00223                      ".\n", *tmp,state, (int)(tmp-s->s), ZSW(s->s));
00224                   goto error;
00225             }
00226             break;
00227          case '\\':
00228             switch (state) {
00229                case FIND_QUOTED_VAL:
00230                   disp_p->body.s = tmp;
00231                   state = SKIP_QUOTED_VAL;
00232                   break;
00233                case SKIP_QUOTED_VAL:
00234                   state = QUOTED_VAL;
00235                   break;
00236                case QUOTED_VAL:
00237                   state = SKIP_QUOTED_VAL;
00238                   break;
00239                default:
00240                   LM_ERR("unexpected char [%c] in status %d: <<%.*s>>"
00241                      ".\n", *tmp,state, (int)(tmp-s->s), ZSW(s->s));
00242                   goto error;
00243             }
00244             break;
00245          case '(':
00246          case ')':
00247          case '<':
00248          case '>':
00249          case '@':
00250          case ',':
00251          case ':':
00252          case '/':
00253          case '[':
00254          case ']':
00255          case '?':
00256          case '{':
00257          case '}':
00258             switch (state) {
00259                case FIND_QUOTED_VAL:
00260                   disp_p->body.s = tmp;
00261                   state = QUOTED_VAL;
00262                   break;
00263                case SKIP_QUOTED_VAL:
00264                   state = QUOTED_VAL;
00265                case QUOTED_VAL:
00266                   break;
00267                default:
00268                   LM_ERR("unexpected char [%c] in status %d: <<%.*s>>"
00269                      ".\n", *tmp,state, (int)(tmp-s->s), ZSW(s->s));
00270                   goto error;
00271             }
00272             break;
00273          default:
00274             switch (state) {
00275                case SKIP_QUOTED_VAL:
00276                   state = QUOTED_VAL;
00277                case QUOTED_VAL:
00278                   break;
00279                case FIND_TYPE:
00280                   disp->type.s = tmp;
00281                   state = TYPE;
00282                   break;
00283                case FIND_PARAM:
00284                   new_p=(struct disposition_param*)pkg_malloc
00285                      (sizeof(struct disposition_param));
00286                   if (new_p==0) {
00287                      LM_ERR("no more pkg mem\n");
00288                      goto error;
00289                   }
00290                   memset(new_p,0,sizeof(struct disposition_param));
00291                   if (disp_p==0)
00292                      disp->params = new_p;
00293                   else
00294                      disp_p->next = new_p;
00295                   disp_p = new_p;
00296                   disp_p->name.s = tmp;
00297                   state = PARAM;
00298                   break;
00299                case FIND_VAL:
00300                   disp_p->body.s = tmp;
00301                   state = VAL;
00302                   break;
00303                case FIND_QUOTED_VAL:
00304                   disp_p->body.s = tmp;
00305                   state = QUOTED_VAL;
00306                   break;
00307             }
00308       }/*switch*/
00309    }/*for*/
00310 
00311    /* check which was the last parser state */
00312    switch (state) {
00313       case END_PARAM:
00314       case END_TYPE:
00315       case END_VAL:
00316          break;
00317       case TYPE:
00318          disp->type.len = tmp - disp->type.s;
00319          break;
00320       case PARAM:
00321          disp_p->name.len = tmp - disp_p->name.s;
00322          break;
00323       case VAL:
00324          disp_p->body.len = tmp - disp_p->body.s;
00325          break;
00326       default:
00327          LM_ERR("wrong final state (%d)\n", state);
00328          goto error;
00329    }
00330    return 0;
00331 error:
00332    return -1;
00333 }
00334 
00335 
00336 
00337 /*! Frees the entire disposition structure (params + itself) */
00338 void free_disposition( struct disposition **disp)
00339 {
00340    struct disposition_param *param;
00341 
00342    /* free the params */
00343    while((*disp)->params) {
00344       param = (*disp)->params->next;
00345       pkg_free( (*disp)->params);
00346       (*disp)->params = param;
00347    }
00348    pkg_free( *disp );
00349    *disp = 0;
00350 }
00351 
00352 
00353 
00354 /*! looks inside the message, gets the Content-Disposition hdr, parse it, builds
00355  * and fills a disposition structure for it what will be attached to hdr as
00356  * parsed link.
00357  * \return -1 on error, 0 on success, 1 when hdr not found
00358  */
00359 int parse_content_disposition( struct sip_msg *msg )
00360 {
00361    struct disposition *disp;
00362 
00363    /* look for Content-Disposition header */
00364    if (msg->content_disposition==0) {
00365       if (parse_headers(msg, HDR_CONTENTDISPOSITION_F, 0)==-1)
00366          goto error;
00367       if (msg->content_disposition==0) {
00368          LM_DBG("hdr not found\n");
00369          return 1;
00370       }
00371    }
00372 
00373    /* now, we have the header -> look if it isn't already parsed */
00374    if (msg->content_disposition->parsed!=0) {
00375       /* already parsed, nothing more to be done */
00376       return 0;
00377    }
00378 
00379    /* parse the body */
00380    disp = (struct disposition*)pkg_malloc(sizeof(struct disposition));
00381    if (disp==0) {
00382       LM_ERR("no more pkg memory\n");
00383       goto error;
00384    }
00385    memset(disp,0,sizeof(struct disposition));
00386 
00387    if (parse_disposition( &(msg->content_disposition->body), disp)==-1) {
00388       /* error when parsing the body */
00389       free_disposition( &disp );
00390       goto error;
00391    }
00392 
00393    /* attach the parsed form to the header */
00394    msg->content_disposition->parsed = (void*)disp;
00395 
00396    return 0;
00397 error:
00398    return -1;
00399 }
00400 
00401 
00402 /*! Prints recursive a disposition structure */
00403 void print_disposition( struct disposition *disp)
00404 {
00405    struct disposition_param *param;
00406 
00407    LM_DBG("disposition type=<%.*s>[%d]\n",
00408       disp->type.len,disp->type.s,disp->type.len);
00409    for( param=disp->params; param; param=param->next) {
00410       LM_DBG("disposition param: <%.*s>[%d]=<%.*s>[%d] is_quoted=%d\n",
00411          param->name.len,param->name.s, param->name.len,
00412          param->body.len,param->body.s, param->body.len,
00413          param->is_quoted);
00414    }
00415 }
00416 
00417 

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