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