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 #include "cpl_time.h"
00028 #include "../../parser/parse_from.h"
00029 #include "../../parser/parse_uri.h"
00030
00031
00032
00033
00034
00035 static inline char *run_address_switch( struct cpl_interpreter *intr )
00036 {
00037 static str def_port_str = {"5060",4};
00038 unsigned short field, subfield;
00039 char *p;
00040 char *kid;
00041 unsigned short attr_name;
00042 unsigned short n;
00043 int i;
00044 int k;
00045 str cpl_val;
00046 str *msg_val;
00047 str *uri;
00048 struct sip_uri parsed_uri;
00049
00050 field = subfield = UNDEF_CHAR;
00051 msg_val = 0;
00052
00053 p=ATTR_PTR(intr->ip);
00054
00055 for( i=NR_OF_ATTR(intr->ip) ; i>0 ; i-- ) {
00056 get_basic_attr( p, attr_name, n, intr, script_error);
00057 switch (attr_name) {
00058 case FIELD_ATTR:
00059 if (field!=UNDEF_CHAR) {
00060 LM_ERR("multiple FIELD attrs found\n");
00061 goto script_error;
00062 }
00063 field = n;
00064 break;
00065 case SUBFIELD_ATTR:
00066 if (subfield!=UNDEF_CHAR) {
00067 LM_ERR("multiple SUBFIELD attrs found\n");
00068 goto script_error;
00069 }
00070 subfield = n; break;
00071 default:
00072 LM_ERR("unknown attribute "
00073 "(%d) in ADDRESS_SWITCH node\n",*p);
00074 goto script_error;
00075 }
00076 }
00077
00078 if (field==UNDEF_CHAR) {
00079 LM_ERR("mandatory param FIELD no found\n");
00080 goto script_error;
00081 }
00082
00083
00084 for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
00085 kid = intr->ip + KID_OFFSET(intr->ip,i);
00086 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
00087 switch ( NODE_TYPE(kid) ) {
00088 case NOT_PRESENT_NODE:
00089 LM_DBG("NOT_PRESENT node found ->"
00090 "skipping (useless in this case)\n");
00091 break;
00092 case OTHERWISE_NODE :
00093 if (i!=NR_OF_KIDS(intr->ip)-1) {
00094 LM_ERR("OTHERWISE node not found as the last sub-node!\n");
00095 goto script_error;
00096 }
00097 LM_DBG("matching on OTHERWISE node\n");
00098 return get_first_child(kid);
00099 case ADDRESS_NODE :
00100
00101 if (NR_OF_ATTR(kid)!=1) {
00102 LM_ERR("incorrect nr of attrs "
00103 "(%d) in ADDRESS node\n",NR_OF_ATTR(kid));
00104 goto script_error;
00105 }
00106
00107 p = ATTR_PTR(kid);
00108 get_basic_attr( p, attr_name, cpl_val.len, intr, script_error);
00109 if (attr_name!=IS_ATTR && attr_name!=CONTAINS_ATTR &&
00110 attr_name!=SUBDOMAIN_OF_ATTR) {
00111 LM_ERR("unknown attribute "
00112 "(%d) in ADDRESS node\n",attr_name);
00113 goto script_error;
00114 }
00115
00116 get_str_attr( p, cpl_val.s, cpl_val.len, intr, script_error,1);
00117 LM_DBG("testing ADDRESS branch "
00118 " attr_name=%d attr_val=[%.*s](%d)..\n",
00119 attr_name,cpl_val.len,cpl_val.s,cpl_val.len);
00120
00121 if (!msg_val) {
00122 switch (field) {
00123 case ORIGIN_VAL:
00124 if (!intr->from) {
00125
00126 if (parse_from_header( intr->msg )<0)
00127 goto runtime_error;
00128 intr->from = &(get_from(intr->msg)->uri);
00129 }
00130 uri = intr->from;
00131 break;
00132 case DESTINATION_VAL:
00133 if (!intr->ruri)
00134 intr->ruri = GET_RURI( intr->msg );
00135 uri = intr->ruri;
00136 break;
00137 case ORIGINAL_DESTINATION_VAL:
00138 if (!intr->to) {
00139
00140 if (!intr->msg->to &&
00141 (parse_headers(intr->msg,HDR_TO_F,0)==-1 ||
00142 !intr->msg->to)) {
00143 LM_ERR("bad msg or missing TO header\n");
00144 goto runtime_error;
00145 }
00146 intr->to = &(get_to(intr->msg)->uri);
00147 }
00148 uri = intr->to;
00149 break;
00150 default:
00151 LM_ERR("unknown "
00152 "attribute (%d) in ADDRESS node\n",field);
00153 goto script_error;
00154 }
00155 LM_DBG("extracted uri is <%.*s>\n",
00156 uri->len, uri->s);
00157 switch (subfield) {
00158 case UNDEF_CHAR:
00159 msg_val = uri;
00160 break;
00161 case USER_VAL:
00162 if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
00163 goto runtime_error;
00164 msg_val = &(parsed_uri.user);
00165 break;
00166 case HOST_VAL:
00167 if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
00168 goto runtime_error;
00169 msg_val = &(parsed_uri.host);
00170 break;
00171 case PORT_VAL:
00172 if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
00173 goto runtime_error;
00174 if (parsed_uri.port.len!=0)
00175 msg_val = &(parsed_uri.port);
00176 else
00177 msg_val = &def_port_str;
00178 break;
00179 case TEL_VAL:
00180 if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
00181 goto runtime_error;
00182 if (parsed_uri.user_param_val.len==5 &&
00183 memcmp(parsed_uri.user_param_val.s,"phone",5)==0)
00184 msg_val = &(parsed_uri.user);
00185 break;
00186 case ADDRESS_TYPE_VAL:
00187 case DISPLAY_VAL:
00188 default:
00189 LM_ERR("unsupported "
00190 "value attribute (%d) in ADDRESS node\n",
00191 subfield);
00192 goto script_error;
00193 }
00194 LM_DBG("extracted val. is <%.*s>\n",
00195 (msg_val==0)?0:msg_val->len, (msg_val==0)?0:msg_val->s);
00196 }
00197
00198 switch (attr_name) {
00199 case IS_ATTR:
00200 if ( (!msg_val && !cpl_val.s) ||
00201 (msg_val && msg_val->len==cpl_val.len &&
00202 strncasecmp(msg_val->s,cpl_val.s,cpl_val.len)==0)) {
00203 LM_DBG("matching on ADDRESS node (IS)\n");
00204 return get_first_child(kid);
00205 }
00206 break;
00207 case CONTAINS_ATTR:
00208 if (subfield!=DISPLAY_VAL) {
00209 LM_WARN("operator "
00210 "CONTAINS applies only to DISPLAY -> ignored\n");
00211 } else {
00212 if ( msg_val && cpl_val.len<=msg_val->len &&
00213 strcasestr_str(msg_val, &cpl_val)!=0 ) {
00214 LM_DBG("matching on "
00215 "ADDRESS node (CONTAINS)\n");
00216 return get_first_child(kid);
00217 }
00218 }
00219 break;
00220 case SUBDOMAIN_OF_ATTR:
00221 switch (subfield) {
00222 case HOST_VAL:
00223 k = msg_val->len - cpl_val.len;
00224 if (k>=0 && (k==0 || msg_val->s[k-1]=='.') &&
00225 !strncasecmp(cpl_val.s,msg_val->s+k,cpl_val.len)
00226 ) {
00227 LM_DBG("matching on "
00228 "ADDRESS node (SUBDOMAIN_OF)\n");
00229 return get_first_child(kid);
00230 }
00231 break;
00232 case TEL_VAL:
00233 if (msg_val==0) break;
00234 if (msg_val->len>=cpl_val.len && !strncasecmp(
00235 cpl_val.s,msg_val->s,cpl_val.len)) {
00236 LM_DBG("matching on "
00237 "ADDRESS node (SUBDOMAIN_OF)\n");
00238 return get_first_child(kid);
00239 }
00240 break;
00241 default:
00242 LM_WARN("operator SUBDOMAIN_OF applies "
00243 "only to HOST or TEL -> ignored\n");
00244 }
00245 break;
00246 }
00247 break;
00248 default:
00249 LM_ERR("unknown output node type "
00250 "(%d) for ADDRESS_SWITCH node\n",NODE_TYPE(kid));
00251 goto script_error;
00252 }
00253 }
00254
00255
00256 return DEFAULT_ACTION;
00257 runtime_error:
00258 return CPL_RUNTIME_ERROR;
00259 script_error:
00260 return CPL_SCRIPT_ERROR;
00261 }
00262
00263
00264
00265
00266
00267 static inline char *run_string_switch( struct cpl_interpreter *intr )
00268 {
00269 unsigned short field;
00270 char *p;
00271 char *kid;
00272 char *not_present_node;
00273 unsigned short attr_name;
00274 int i;
00275 str cpl_val;
00276 str msg_val;
00277
00278 not_present_node = 0;
00279 msg_val.s = 0;
00280 msg_val.len = 0;
00281
00282
00283 if (NR_OF_ATTR(intr->ip)!=1) {
00284 LM_ERR("node should have 1 attr, not"
00285 " (%d)\n",NR_OF_ATTR(intr->ip));
00286 goto script_error;
00287 }
00288 p=ATTR_PTR(intr->ip);
00289 get_basic_attr( p, attr_name, field, intr, script_error);
00290 if (attr_name!=FIELD_ATTR) {
00291 LM_ERR("unknown param type (%d)"
00292 " for STRING_SWITCH node\n",*p);
00293 goto script_error;
00294 }
00295
00296 for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
00297 kid = intr->ip + KID_OFFSET(intr->ip,i);
00298 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
00299 switch ( NODE_TYPE(kid) ) {
00300 case NOT_PRESENT_NODE:
00301 if (not_present_node) {
00302 LM_ERR("NOT_PRESENT node found twice!\n");
00303 goto script_error;
00304 }
00305 not_present_node = kid;
00306 break;
00307 case OTHERWISE_NODE :
00308 if (i!=NR_OF_KIDS(intr->ip)-1) {
00309 LM_ERR("OTHERWISE node "
00310 "not found as the last sub-node!\n");
00311 goto script_error;
00312 }
00313 LM_DBG("matching on OTHERWISE node\n");
00314 return get_first_child(kid);
00315 case STRING_NODE :
00316
00317 if (NR_OF_ATTR(kid)!=1) {
00318 LM_ERR("incorrect nr of attrs "
00319 "(%d) in STRING node (expected 1)\n",NR_OF_ATTR(kid));
00320 goto script_error;
00321 }
00322
00323 p = ATTR_PTR(kid);
00324 get_basic_attr( p, attr_name, cpl_val.len, intr, script_error);
00325 if (attr_name!=IS_ATTR && attr_name!=CONTAINS_ATTR ) {
00326 LM_ERR("unknown attribute "
00327 "(%d) in STRING node\n",attr_name);
00328 goto script_error;
00329 }
00330
00331 get_str_attr( p, cpl_val.s, cpl_val.len, intr, script_error,1);
00332 LM_DBG("testing STRING branch "
00333 "attr_name=%d attr_val=[%.*s](%d)..\n",
00334 attr_name,cpl_val.len,cpl_val.s,cpl_val.len);
00335 if (!msg_val.s) {
00336 switch (field) {
00337 case SUBJECT_VAL:
00338 if (intr->subject==STR_NOT_FOUND)
00339 goto not_present;
00340 if (!intr->subject) {
00341
00342 if (!intr->msg->subject) {
00343 if (parse_headers(intr->msg,
00344 HDR_SUBJECT_F,0)==-1) {
00345 LM_ERR("bad SUBJECT header\n");
00346 goto runtime_error;
00347 } else if (!intr->msg->subject) {
00348
00349 intr->subject = STR_NOT_FOUND;
00350 goto not_present;
00351 }
00352 }
00353 intr->subject =
00354 &(intr->msg->subject->body);
00355 }
00356 trim_len( msg_val.len,msg_val.s,
00357 *(intr->subject));
00358 break;
00359 case ORGANIZATION_VAL:
00360 if (intr->organization==STR_NOT_FOUND)
00361 goto not_present;
00362 if (!intr->organization) {
00363
00364 if (!intr->msg->organization) {
00365 if (parse_headers(intr->msg,
00366 HDR_ORGANIZATION_F,0)==-1) {
00367 LM_ERR("bad ORGANIZATION hdr\n");
00368 goto runtime_error;
00369 } else if (!intr->msg->organization) {
00370
00371 intr->organization = STR_NOT_FOUND;
00372 goto not_present;
00373 }
00374 }
00375 intr->organization =
00376 &(intr->msg->organization->body);
00377 }
00378 trim_len( msg_val.len,msg_val.s,
00379 *(intr->organization));
00380 break;
00381 case USER_AGENT_VAL:
00382 if (intr->user_agent==STR_NOT_FOUND)
00383 goto not_present;
00384 if (!intr->user_agent) {
00385
00386 if (!intr->msg->user_agent) {
00387 if (parse_headers(intr->msg,
00388 HDR_USERAGENT_F,0)==-1) {
00389 LM_ERR("bad USERAGENT hdr\n");
00390 goto runtime_error;
00391 } else if (!intr->msg->user_agent) {
00392
00393 intr->user_agent = STR_NOT_FOUND;
00394 goto not_present;
00395 }
00396 }
00397 intr->user_agent =
00398 &(intr->msg->user_agent->body);
00399 }
00400 trim_len( msg_val.len,msg_val.s,
00401 *(intr->user_agent));
00402 break;
00403 default:
00404 LM_ERR("unknown "
00405 "attribute (%d) in STRING node\n",field);
00406 goto script_error;
00407 }
00408 LM_DBG("extracted msg string is "
00409 "<%.*s>\n",msg_val.len, msg_val.s);
00410 }
00411
00412 switch (attr_name) {
00413 case IS_ATTR:
00414 if ( (!msg_val.s && !cpl_val.s) ||
00415 (msg_val.len==cpl_val.len &&
00416 strncasecmp(msg_val.s,cpl_val.s,cpl_val.len)==0)) {
00417 LM_DBG("matching on STRING node (IS)\n");
00418 return get_first_child(kid);
00419 }
00420 break;
00421 case CONTAINS_ATTR:
00422 if (cpl_val.len<=msg_val.len &&
00423 strcasestr_str(&msg_val, &cpl_val)!=0 ) {
00424 LM_DBG("matching on STRING node (CONTAINS)\n");
00425 return get_first_child(kid);
00426 }
00427 break;
00428 }
00429 break;
00430 default:
00431 LM_ERR("unknown output node type "
00432 "(%d) for STRING_SWITCH node\n",NODE_TYPE(kid));
00433 goto script_error;
00434 }
00435 }
00436
00437
00438 return DEFAULT_ACTION;
00439 not_present:
00440 LM_DBG("required hdr not present in sip msg\n");
00441 if (not_present_node)
00442 return get_first_child(not_present_node);
00443
00444 LM_DBG("searching for NOT_PRESENT sub-node..\n");
00445 for(; i<NR_OF_KIDS(intr->ip) ; i++ ) {
00446 kid = intr->ip + KID_OFFSET(intr->ip,i);
00447 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
00448 if (NODE_TYPE(kid)==NOT_PRESENT_NODE)
00449 return get_first_child(kid);
00450 }
00451 return DEFAULT_ACTION;
00452 runtime_error:
00453 return CPL_RUNTIME_ERROR;
00454 script_error:
00455 return CPL_SCRIPT_ERROR;
00456 }
00457
00458
00459
00460
00461
00462 static inline char *run_priority_switch( struct cpl_interpreter *intr )
00463 {
00464 static str default_val={"normal",6};
00465 unsigned short n;
00466 char *p;
00467 char *kid;
00468 char *not_present_node;
00469 unsigned short attr_name;
00470 unsigned short attr_val;
00471 unsigned short msg_attr_val;
00472 unsigned short msg_prio;
00473 int i;
00474 str cpl_val = {0,0};
00475 str msg_val = {0,0};
00476
00477 not_present_node = 0;
00478 msg_attr_val = NORMAL_VAL;
00479
00480 for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
00481 kid = intr->ip + KID_OFFSET(intr->ip,i);
00482 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
00483 switch ( NODE_TYPE(kid) ) {
00484 case NOT_PRESENT_NODE:
00485 if (not_present_node) {
00486 LM_ERR("NOT_PRESENT node found twice!\n");
00487 goto script_error;
00488 }
00489 not_present_node = kid;
00490 break;
00491 case OTHERWISE_NODE :
00492 if (i!=NR_OF_KIDS(intr->ip)-1) {
00493 LM_ERR("OTHERWISE node not found as the last sub-node!\n");
00494 goto script_error;
00495 }
00496 LM_DBG("matching on OTHERWISE node\n");
00497 return get_first_child(kid);
00498 case PRIORITY_NODE :
00499 if (NR_OF_ATTR(kid)!=1)
00500 goto script_error;
00501
00502 p = ATTR_PTR(kid);
00503 get_basic_attr( p, attr_name, attr_val, intr, script_error);
00504 if (attr_name!=LESS_ATTR && attr_name!=GREATER_ATTR &&
00505 attr_name!=EQUAL_ATTR){
00506 LM_ERR("unknown attribute "
00507 "(%d) in PRIORITY node\n",attr_name);
00508 goto script_error;
00509 }
00510
00511 if (attr_val!=EMERGENCY_VAL && attr_val!=URGENT_VAL &&
00512 attr_val!=NORMAL_VAL && attr_val!=NON_URGENT_VAL &&
00513 attr_val!=UNKNOWN_PRIO_VAL) {
00514 LM_ERR("unknown encoded "
00515 "value (%d) for attribute (*d) in PRIORITY node\n",*p);
00516 goto script_error;
00517 }
00518 if (attr_val==UNKNOWN_PRIO_VAL) {
00519 if (attr_name!=EQUAL_ATTR) {
00520 LM_ERR("bad PRIORITY"
00521 " branch: attr=EQUAL doesn't match val=UNKNOWN\n");
00522 goto script_error;
00523 }
00524
00525 get_basic_attr(p, n,cpl_val.len, intr, script_error);
00526 if (n!=PRIOSTR_ATTR) {
00527 LM_ERR("expected PRIOSTR"
00528 "(%d) attr, found (%d)\n",PRIOSTR_ATTR,n);
00529 goto script_error;
00530 }
00531 get_str_attr(p, cpl_val.s, cpl_val.len,intr,script_error,1);
00532 }
00533
00534 LM_DBG("testing PRIORITY branch "
00535 "(attr=%d,val=%d) [%.*s](%d)..\n",
00536 attr_name,attr_val,cpl_val.len,cpl_val.s,cpl_val.len);
00537 if (!msg_val.s) {
00538 if (!intr->priority) {
00539
00540 if (!intr->msg->priority) {
00541 if (parse_headers(intr->msg,HDR_PRIORITY_F,
00542 0)==-1) {
00543 LM_ERR("bad sip msg or PRIORITY header !\n");
00544 goto runtime_error;
00545 } else if (!intr->msg->priority) {
00546 LM_NOTICE("missing PRIORITY header -> using "
00547 "default value \"normal\"!\n");
00548 intr->priority = &default_val;
00549 } else {
00550 intr->priority =
00551 &(intr->msg->priority->body);
00552 }
00553 } else {
00554 intr->priority =
00555 &(intr->msg->priority->body);
00556 }
00557 }
00558 trim_len( msg_val.len, msg_val.s, *(intr->priority));
00559
00560 if ( msg_val.len==EMERGENCY_STR_LEN &&
00561 !strncasecmp(msg_val.s,EMERGENCY_STR,msg_val.len) ) {
00562 msg_attr_val = EMERGENCY_VAL;
00563 } else if ( msg_val.len==URGENT_STR_LEN &&
00564 !strncasecmp(msg_val.s,URGENT_STR,msg_val.len) ) {
00565 msg_attr_val = URGENT_VAL;
00566 } else if ( msg_val.len==NORMAL_STR_LEN &&
00567 !strncasecmp(msg_val.s,NORMAL_STR,msg_val.len) ) {
00568 msg_attr_val = NORMAL_VAL;
00569 } else if ( msg_val.len==NON_URGENT_STR_LEN &&
00570 !strncasecmp(msg_val.s,NON_URGENT_STR,msg_val.len) ) {
00571 msg_attr_val = NON_URGENT_VAL;
00572 } else {
00573 msg_attr_val = UNKNOWN_PRIO_VAL;
00574 }
00575 LM_DBG("extracted msg priority is "
00576 "<%.*s> decoded as [%d]\n",
00577 msg_val.len,msg_val.s,msg_attr_val);
00578 }
00579 LM_DBG("using msg string <%.*s>\n",
00580 msg_val.len, msg_val.s);
00581
00582
00583 if (msg_attr_val==UNKNOWN_PRIO_VAL && attr_name!=EQUAL_ATTR) {
00584 LM_NOTICE("UNKNOWN "
00585 "value found in sip_msg when string a LESS/GREATER "
00586 "cmp -> force the value to default \"normal\"\n");
00587 msg_prio = NORMAL_VAL;
00588 } else {
00589 msg_prio = msg_attr_val;
00590 }
00591
00592 switch (attr_name) {
00593 case LESS_ATTR:
00594 switch (attr_val) {
00595 case EMERGENCY_VAL:
00596 if (msg_prio!=EMERGENCY_VAL) break;
00597 else continue;
00598 case URGENT_VAL:
00599 if (msg_prio!=EMERGENCY_VAL &&
00600 msg_prio!=URGENT_VAL) break;
00601 else continue;
00602 case NORMAL_VAL:
00603 if (msg_prio==NON_URGENT_VAL) break;
00604 else continue;
00605 case NON_URGENT_VAL:
00606 continue;
00607 }
00608 break;
00609 case GREATER_ATTR:
00610 switch (attr_val) {
00611 case EMERGENCY_VAL:
00612 continue;
00613 case URGENT_VAL:
00614 if (msg_prio!=EMERGENCY_VAL) break;
00615 else continue;
00616 case NORMAL_VAL:
00617 if (msg_prio!=NON_URGENT_VAL &&
00618 msg_prio!=NORMAL_VAL) break;
00619 else continue;
00620 case NON_URGENT_VAL:
00621 if (msg_prio!=NON_URGENT_VAL) break;
00622 else continue;
00623 }
00624 break;
00625 case EQUAL_ATTR:
00626 if ( attr_val==msg_prio ) {
00627 if (attr_val==UNKNOWN_PRIO_VAL) {
00628 if ( msg_val.len==cpl_val.len &&
00629 !strncasecmp(msg_val.s,cpl_val.s,msg_val.len)){
00630 break;
00631 }
00632 } else {
00633 break;
00634 }
00635 }
00636 continue;
00637 break;
00638 }
00639 LM_DBG("matching current PRIORITY node\n");
00640 return get_first_child(kid);
00641 break;
00642 default:
00643 LM_ERR("unknown output node type"
00644 " (%d) for PRIORITY_SWITCH node\n",NODE_TYPE(kid));
00645 goto script_error;
00646 }
00647 }
00648
00649
00650 return DEFAULT_ACTION;
00651 runtime_error:
00652 return CPL_RUNTIME_ERROR;
00653 script_error:
00654 return CPL_SCRIPT_ERROR;
00655 }
00656
00657
00658
00659 inline static int set_TZ(char *tz_env)
00660 {
00661 LM_DBG("switching TZ as \"%s\"\n",tz_env);
00662 if (putenv( tz_env )==-1) {
00663 LM_ERR("setenv failed -> unable to set TZ "
00664 " \"%s\"\n",tz_env);
00665 return -1;
00666 }
00667 tzset();
00668 return 0;
00669 }
00670
00671
00672
00673
00674
00675 static inline char *run_time_switch( struct cpl_interpreter *intr )
00676 {
00677 char *p;
00678 char *kid;
00679 char *attr_str;
00680 unsigned short attr_name;
00681 unsigned short attr_len;
00682 unsigned char flags = 0;
00683 int nr_attrs;
00684 int i,j;
00685 str user_tz = {0,0};
00686 ac_tm_t att;
00687 tmrec_t trt;
00688
00689 LM_DBG("checking recv. time stamp <%d>\n",
00690 intr->recv_time);
00691 switch (NR_OF_ATTR(intr->ip)) {
00692 case 1:
00693 p = ATTR_PTR(intr->ip);
00694 get_basic_attr( p, attr_name, user_tz.len, intr, script_error);
00695 if (attr_name!=TZID_ATTR) {
00696 LM_ERR("bad attribute -> "
00697 " expected=%d, found=%d\n",TZID_ATTR,attr_name);
00698 goto script_error;
00699 }
00700 get_str_attr( p, user_tz.s, user_tz.len, intr, script_error, 1);
00701 case 0:
00702 break;
00703 default:
00704 LM_ERR("incorrect number of attr ->"
00705 " found=%d expected=(0,1)\n",NR_OF_ATTR(intr->ip));
00706 goto script_error;
00707 }
00708
00709 if (user_tz.s && user_tz.len) {
00710 if (set_TZ(user_tz.s)==-1)
00711 goto runtime_error;
00712 flags |= (1<<7);
00713 }
00714
00715 for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
00716 kid = intr->ip + KID_OFFSET(intr->ip,i);
00717 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
00718 switch ( NODE_TYPE(kid) ) {
00719 case NOT_PRESENT_NODE:
00720 LM_DBG("NOT_PRESENT node found ->"
00721 "skipping (useless in this case)\n");
00722 break;
00723 case OTHERWISE_NODE :
00724 if (i!=NR_OF_KIDS(intr->ip)-1) {
00725 LM_ERR("OTHERWISE node "
00726 "not found as the last sub-node!\n");
00727 goto script_error;
00728 }
00729 LM_DBG("matching on OTHERWISE node\n");
00730 return get_first_child(kid);
00731 case TIME_NODE :
00732
00733 memset( &att, 0, sizeof(att));
00734 memset( &trt, 0, sizeof(trt));
00735 if(ac_tm_set_time( &att, intr->recv_time))
00736 goto runtime_error;
00737
00738 nr_attrs = NR_OF_ATTR(kid);
00739
00740 p = ATTR_PTR(kid);
00741 for(j=0;j<nr_attrs;j++) {
00742
00743 get_basic_attr( p, attr_name, attr_len, intr, script_error);
00744 get_str_attr( p, attr_str, attr_len, intr, script_error,1);
00745
00746 LM_DBG("attribute [%d] found :"
00747 "[%s]\n",attr_name, attr_str);
00748 switch (attr_name) {
00749 case DTSTART_ATTR:
00750 if( !attr_str || tr_parse_dtstart(&trt, attr_str))
00751 goto parse_err;
00752 flags ^= (1<<0);
00753 break;
00754 case DTEND_ATTR:
00755 if( !attr_str || tr_parse_dtend(&trt, attr_str))
00756 goto parse_err;
00757 flags ^= (1<<1);
00758 break;
00759 case DURATION_ATTR:
00760 if( !attr_str || tr_parse_duration(&trt, attr_str))
00761 goto parse_err;
00762 flags ^= (1<<1);
00763 break;
00764 case FREQ_ATTR:
00765 if( attr_str && tr_parse_freq(&trt, attr_str))
00766 goto parse_err;
00767 break;
00768 case UNTIL_ATTR:
00769 if( attr_str && tr_parse_until(&trt, attr_str))
00770 goto parse_err;
00771 break;
00772 case INTERVAL_ATTR:
00773 if( attr_str && tr_parse_interval(&trt, attr_str))
00774 goto parse_err;
00775 break;
00776 case BYDAY_ATTR:
00777 if( attr_str && tr_parse_byday(&trt, attr_str))
00778 goto parse_err;
00779 break;
00780 case BYMONTHDAY_ATTR:
00781 if( attr_str && tr_parse_bymday(&trt, attr_str))
00782 goto parse_err;
00783 break;
00784 case BYYEARDAY_ATTR:
00785 if( attr_str && tr_parse_byyday(&trt, attr_str))
00786 goto parse_err;
00787 break;
00788 case BYMONTH_ATTR:
00789 if( attr_str && tr_parse_bymonth(&trt, attr_str))
00790 goto parse_err;
00791 break;
00792 case BYWEEKNO_ATTR:
00793 if( attr_str && tr_parse_byweekno(&trt, attr_str))
00794 goto parse_err;
00795 break;
00796 case WKST_ATTR:
00797 if( attr_str && tr_parse_wkst(&trt, attr_str))
00798 goto parse_err;
00799 break;
00800 default:
00801 LM_ERR("unsupported attribute [%d] found in TIME "
00802 "node\n",attr_name);
00803 goto script_error;
00804 }
00805 }
00806
00807 if ( (flags&0x03)!=((1<<0)|(1<<1)) ) {
00808 LM_ERR("attribute DTSTART"
00809 ",DTEND,DURATION missing or multi-present\n");
00810 goto script_error;
00811 }
00812
00813 j = check_tmrec( &trt, &att, 0);
00814
00815 if ( flags&(1<<7) )
00816 set_TZ(cpl_env.orig_tz.s);
00817
00818 ac_tm_free( &att );
00819 tmrec_free( &trt );
00820
00821 switch (j) {
00822 case 0:
00823 LM_DBG("matching current TIME node\n");
00824 return get_first_child(kid);
00825 case -1:
00826 LM_ERR("check_tmrec "
00827 "ret. err. when testing time cond. !\n");
00828 goto runtime_error;
00829 break;
00830 case 1:
00831 LM_DBG("time cond. doesn't match !\n");
00832 break;
00833 }
00834 break;
00835 default:
00836 LM_ERR("unknown output node"
00837 " type (%d) for PRIORITY_SWITCH node\n",NODE_TYPE(kid));
00838 goto script_error;
00839 }
00840 }
00841
00842
00843
00844 ac_tm_free( &att );
00845 tmrec_free( &trt );
00846 return DEFAULT_ACTION;
00847 runtime_error:
00848 if ( flags&(1<<7) )
00849 set_TZ(cpl_env.orig_tz.s);
00850 ac_tm_free( &att );
00851 tmrec_free( &trt );
00852 return CPL_RUNTIME_ERROR;
00853 parse_err:
00854 LM_ERR("error parsing attr [%d][%s]\n",
00855 attr_name,attr_str?(char*)attr_str:"NULL");
00856 script_error:
00857 if ( flags&(1<<7) )
00858 set_TZ(cpl_env.orig_tz.s);
00859 ac_tm_free( &att );
00860 tmrec_free( &trt );
00861 return CPL_SCRIPT_ERROR;
00862 }
00863
00864
00865
00866 inline static int is_lang_tag_matching(str *range,str *cpl_tag,str *cpl_subtag)
00867 {
00868 char *c;
00869 char *end;
00870 str tag = {0,0};
00871 str subtag = {0,0};
00872
00873 c = range->s;
00874 end = range->s + range->len;
00875
00876 while(c<end) {
00877
00878 while(c<end && (*c==' ' || *c=='\t')) c++;
00879 if (c==end) goto error;
00880
00881 tag.len = 0;
00882 subtag.len = 0;
00883
00884 tag.s = c;
00885 if (*c=='*' && (c+1==end||*(c+1)!='-')) {
00886 tag.len++;
00887 c++;
00888 } else while (c<end && ((*c)|0x20)>='a' && ((*c)|0x20)<='z' ) {
00889
00890 tag.len++;
00891 c++;
00892 }
00893 if (tag.len==0) goto error;
00894 if (c<end && *c=='-') {
00895
00896 subtag.s = ++c;
00897 while (c<end && ((*c)|0x20)>='a' && ((*c)|0x20)<='z' ) {
00898
00899 subtag.len++;
00900 c++;
00901 }
00902 if (subtag.len==0) goto error;
00903 } else {
00904 subtag.s = 0;
00905 }
00906 if (c<end && *c==';') {
00907
00908 while(c<end && *c!=',') c++;
00909 if (c==end) goto no_matche;
00910 }
00911 while(c<end && (*c==' '||*c=='\t')) c++;
00912 if (c==end || *c==',') {
00913
00914 LM_DBG("testing range [%.*s]-[%.*s] against tag [%.*s]-[%.*s]\n",
00915 tag.len,tag.s,subtag.len,subtag.s,
00916 cpl_tag->len,cpl_tag->s,cpl_subtag->len,cpl_subtag->s);
00917
00918 if ( !(tag.len==1 && *tag.s=='*') ) {
00919
00920 if (tag.len==cpl_tag->len && !strncasecmp(tag.s,cpl_tag->s,
00921 tag.len)) {
00922
00923 if (subtag.len==0)
00924 return 1;
00925
00926 if (subtag.len==cpl_subtag->len &&
00927 !strncasecmp(subtag.s,cpl_subtag->s,subtag.len) )
00928 return 1;
00929 }
00930 }
00931
00932 if (*c==',') c++;
00933 } else {
00934 goto error;
00935 }
00936 }
00937
00938 no_matche:
00939 return 0;
00940 error:
00941 LM_ERR("parse error in Accept-"
00942 "Language body <%.*s> at char <%c>[%d] offset %ld!\n",
00943 range->len,range->s,*c,*c,(long)(c-range->s));
00944 return -1;
00945 }
00946
00947
00948
00949
00950
00951 static inline char *run_language_switch( struct cpl_interpreter *intr )
00952 {
00953 char *p;
00954 char *kid;
00955 char *not_present_node;
00956 unsigned short attr_name;
00957 int nr_attr;
00958 int i,j;
00959 str attr = {0,0};
00960 str msg_val = {0,0};
00961 str lang_tag = {0,0};
00962 str lang_subtag = {0,0};
00963
00964 not_present_node = 0;
00965
00966 for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
00967 kid = intr->ip + KID_OFFSET(intr->ip,i);
00968 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
00969 switch ( NODE_TYPE(kid) ) {
00970 case NOT_PRESENT_NODE:
00971 if (not_present_node) {
00972 LM_ERR("NOT_PRESENT node found twice!\n");
00973 goto script_error;
00974 }
00975 not_present_node = kid;
00976 break;
00977 case OTHERWISE_NODE :
00978 if (i!=NR_OF_KIDS(intr->ip)-1) {
00979 LM_ERR("OTHERWISE node "
00980 "not found as the last sub-node!\n");
00981 goto script_error;
00982 }
00983 LM_DBG("matching on OTHERWISE node\n");
00984 return get_first_child(kid);
00985 case LANGUAGE_NODE :
00986
00987 nr_attr = NR_OF_ATTR(kid);
00988 if (nr_attr<1 || nr_attr>2) {
00989 LM_ERR("incorrect nr of attrs "
00990 "(%d) in LANGUAGE node (1 or 2)\n",NR_OF_ATTR(kid));
00991 goto script_error;
00992 }
00993
00994 p = ATTR_PTR(kid);
00995 lang_tag.s = lang_subtag.s = 0;
00996 lang_tag.len = lang_subtag.len = 0;
00997 for(j=0;j<nr_attr;j++) {
00998 get_basic_attr( p, attr_name, attr.len, intr, script_error);
00999 get_str_attr( p, attr.s, attr.len, intr, script_error,0);
01000 if (attr_name==MATCHES_TAG_ATTR ) {
01001 lang_tag = attr;
01002 LM_DBG("language-tag is"
01003 " [%.*s]\n",attr.len,attr.s);
01004 }else if (attr_name==MATCHES_SUBTAG_ATTR) {
01005 lang_subtag = attr;
01006 LM_DBG("language-subtag"
01007 " is [%.*s]\n",attr.len,attr.s);
01008 }else {
01009 LM_ERR("unknown attribute"
01010 " (%d) in LANGUAGE node\n",attr_name);
01011 goto script_error;
01012 }
01013 }
01014
01015
01016
01017 if (!msg_val.s) {
01018 if (intr->accept_language==STR_NOT_FOUND)
01019 goto not_present;
01020 if (!intr->accept_language) {
01021
01022 if (!intr->msg->accept_language) {
01023 if (parse_headers(intr->msg,
01024 HDR_ACCEPTLANGUAGE_F,0)==-1) {
01025 LM_ERR("bad ACCEPT_LANGUAGE header\n");
01026 goto runtime_error;
01027 } else if (!intr->msg->accept_language) {
01028
01029 intr->accept_language = STR_NOT_FOUND;
01030 goto not_present;
01031 }
01032 }
01033 intr->subject =
01034 &(intr->msg->accept_language->body);
01035 }
01036 }
01037 trim_len( msg_val.len,msg_val.s, *(intr->subject));
01038 LM_DBG("extracted msg string is "
01039 "<%.*s>\n",msg_val.len, msg_val.s);
01040
01041
01042 if (msg_val.len && msg_val.s) {
01043 j = is_lang_tag_matching(&msg_val,&lang_tag,&lang_subtag);
01044 if (j==1) {
01045 LM_DBG("matching on LANGUAGE node\n");
01046 return get_first_child(kid);
01047 }else if (j==-1) {
01048 goto runtime_error;
01049 }
01050 }
01051 break;
01052 default:
01053 LM_ERR("unknown output "
01054 "node type (%d) for LANGUAGE_SWITCH node\n",
01055 NODE_TYPE(kid));
01056 goto script_error;
01057 }
01058 }
01059
01060 return DEFAULT_ACTION;
01061 not_present:
01062 LM_DBG("required hdr not present in sip msg\n");
01063 if (not_present_node)
01064 return get_first_child(not_present_node);
01065
01066 LM_DBG("searching for NOT_PRESENT sub-node..\n");
01067 for(; i<NR_OF_KIDS(intr->ip) ; i++ ) {
01068 kid = intr->ip + KID_OFFSET(intr->ip,i);
01069 check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
01070 if (NODE_TYPE(kid)==NOT_PRESENT_NODE)
01071 return get_first_child(kid);
01072 }
01073 return DEFAULT_ACTION;
01074 runtime_error:
01075 return CPL_RUNTIME_ERROR;
01076 script_error:
01077 return CPL_SCRIPT_ERROR;
01078 }