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