00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00043
00044
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
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 }
00309 }
00310
00311
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
00338 void free_disposition( struct disposition **disp)
00339 {
00340 struct disposition_param *param;
00341
00342
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
00355
00356
00357
00358
00359 int parse_content_disposition( struct sip_msg *msg )
00360 {
00361 struct disposition *disp;
00362
00363
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
00374 if (msg->content_disposition->parsed!=0) {
00375
00376 return 0;
00377 }
00378
00379
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
00389 free_disposition( &disp );
00390 goto error;
00391 }
00392
00393
00394 msg->content_disposition->parsed = (void*)disp;
00395
00396 return 0;
00397 error:
00398 return -1;
00399 }
00400
00401
00402
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