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
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
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
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
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
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
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
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
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
00447 goto endofheader;
00448 default:
00449 LM_ERR("spitting out [%c] in status %d\n",*tmp,status );
00450 goto error;
00451 }
00452 }
00453 }
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
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++;
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
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
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
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
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
00713 goto endofheader;
00714 default:
00715 LM_DBG("spitting out [%c] in status %d\n",
00716 *tmp,status );
00717 goto error;
00718 }
00719 }
00720 }
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
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 }