1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111 |
- /*
- * $Id$
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * History:
- * -------
- * 2003-06-27: file created (bogdan)
- */
- #include "cpl_time.h"
- #include "../../parser/parse_from.h"
- #include "../../parser/parse_uri.h"
- /* UPDATED + CHECKED
- */
- static inline char *run_address_switch( struct cpl_interpreter *intr )
- {
- static str def_port_str = STR_STATIC_INIT("5060");
- unsigned short field, subfield;
- char *p;
- char *kid;
- unsigned short attr_name;
- unsigned short n;
- int i;
- int k;
- str cpl_val;
- str *msg_val;
- str *uri;
- struct sip_uri parsed_uri;
- field = subfield = UNDEF_CHAR;
- msg_val = 0;
- p=ATTR_PTR(intr->ip);
- /* parse the attributes */
- for( i=NR_OF_ATTR(intr->ip) ; i>0 ; i-- ) {
- get_basic_attr( p, attr_name, n, intr, script_error);
- switch (attr_name) {
- case FIELD_ATTR:
- if (field!=UNDEF_CHAR) {
- LOG(L_ERR,"ERROR:cpl-c:run_address_switch: multiple FIELD "
- "attrs found\n");
- goto script_error;
- }
- field = n;
- break;
- case SUBFIELD_ATTR:
- if (subfield!=UNDEF_CHAR) {
- LOG(L_ERR,"ERROR:cpl-c:run_address_switch: multiple SUBFIELD"
- " attrs found\n");
- goto script_error;
- }
- subfield = n; break;
- default:
- LOG(L_ERR,"ERROR:cpl_c:run_address_switch: unknown attribute "
- "(%d) in ADDRESS_SWITCH node\n",*p);
- goto script_error;
- }
- }
- if (field==UNDEF_CHAR) {
- LOG(L_ERR,"ERROR:cpl_c:run_address_switch: mandatory param FIELD "
- "no found\n");
- goto script_error;
- }
- /* test the condition from all the sub-nodes */
- for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
- kid = intr->ip + KID_OFFSET(intr->ip,i);
- check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
- switch ( NODE_TYPE(kid) ) {
- case NOT_PRESENT_NODE:
- DBG("DEBUG:run_address_switch: NOT_PRESENT node found ->"
- "skipping (useless in this case)\n");
- break;
- case OTHERWISE_NODE :
- if (i!=NR_OF_KIDS(intr->ip)-1) {
- LOG(L_ERR,"ERROR:run_address_switch: OTHERWISE node "
- "not found as the last sub-node!\n");
- goto script_error;
- }
- DBG("DEBUG:run_address_switch: matching on OTHERWISE node\n");
- return get_first_child(kid);
- case ADDRESS_NODE :
- /* check the number of attributes */
- if (NR_OF_ATTR(kid)!=1) {
- LOG(L_ERR,"ERROR:run_address_switch: incorrect nr of attrs "
- "(%d) in ADDRESS node\n",NR_OF_ATTR(kid));
- goto script_error;
- }
- /* get the attribute name */
- p = ATTR_PTR(kid);
- get_basic_attr( p, attr_name, cpl_val.len, intr, script_error);
- if (attr_name!=IS_ATTR && attr_name!=CONTAINS_ATTR &&
- attr_name!=SUBDOMAIN_OF_ATTR) {
- LOG(L_ERR,"ERROR:run_address_switch: unknown attribute "
- "(%d) in ADDRESS node\n",attr_name);
- goto script_error;
- }
- /* get attribute value */
- get_str_attr( p, cpl_val.s, cpl_val.len, intr, script_error,1);
- DBG("DEBUG:run_address_switch: testing ADDRESS branch "
- " attr_name=%d attr_val=[%.*s](%d)..\n",
- attr_name,cpl_val.len,cpl_val.s,cpl_val.len);
- /* extract the needed value from the message */
- if (!msg_val) {
- switch (field) {
- case ORIGIN_VAL: /* FROM */
- if (!intr->from) {
- /* get the header */
- if (parse_from_header( intr->msg )==-1)
- goto runtime_error;
- intr->from = &(get_from(intr->msg)->uri);
- }
- uri = intr->from;
- break;
- case DESTINATION_VAL: /* RURI */
- if (!intr->ruri)
- intr->ruri = GET_RURI( intr->msg );
- uri = intr->ruri;
- break;
- case ORIGINAL_DESTINATION_VAL: /* TO */
- if (!intr->to) {
- /* get and parse the header */
- if (!intr->msg->to &&
- (parse_headers(intr->msg,HDR_TO_F,0)==-1 ||
- !intr->msg->to)) {
- LOG(L_ERR,"ERROR:run_address_switch: bad "
- "msg or missing TO header\n");
- goto runtime_error;
- }
- intr->to = &(get_to(intr->msg)->uri);
- }
- uri = intr->to;
- break;
- default:
- LOG(L_ERR,"ERROR:run_address_switch: unknown "
- "attribute (%d) in ADDRESS node\n",field);
- goto script_error;
- }
- DBG("DEBUG:run_address_switch: extracted uri is <%.*s>\n",
- uri->len, uri->s);
- switch (subfield) {
- case UNDEF_CHAR:
- msg_val = uri;
- break;
- case USER_VAL:
- if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
- goto runtime_error;
- msg_val = &(parsed_uri.user);
- break;
- case HOST_VAL:
- if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
- goto runtime_error;
- msg_val = &(parsed_uri.host);
- break;
- case PORT_VAL:
- if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
- goto runtime_error;
- if (parsed_uri.port.len!=0)
- msg_val = &(parsed_uri.port);
- else
- msg_val = &def_port_str;
- break;
- case TEL_VAL:
- if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
- goto runtime_error;
- if (parsed_uri.user_param_val.len==5 &&
- memcmp(parsed_uri.user_param_val.s,"phone",5)==0)
- msg_val = &(parsed_uri.user);
- break;
- case ADDRESS_TYPE_VAL:
- case DISPLAY_VAL:
- default:
- LOG(L_ERR,"ERROR:run_address_switch: unsupported "
- "value attribute (%d) in ADDRESS node\n",
- subfield);
- goto script_error;
- }
- DBG("DEBUG:run_address_switch: extracted val. is <%.*s>\n",
- (msg_val==0)?0:msg_val->len, (msg_val==0)?0:msg_val->s);
- }
- /* does the value from script match the one from message? */
- switch (attr_name) {
- case IS_ATTR:
- if ( (!msg_val && !cpl_val.s) ||
- (msg_val && msg_val->len==cpl_val.len &&
- strncasecmp(msg_val->s,cpl_val.s,cpl_val.len)==0)) {
- DBG("DEBUG:run_address_switch: matching on "
- "ADDRESS node (IS)\n");
- return get_first_child(kid);
- }
- break;
- case CONTAINS_ATTR:
- if (subfield!=DISPLAY_VAL) {
- LOG(L_WARN,"WARNING:run_address_switch: operator "
- "CONTAINS applies only to DISPLAY -> ignored\n");
- } else {
- if ( msg_val && cpl_val.len<=msg_val->len &&
- strcasestr_str(msg_val, &cpl_val)!=0 ) {
- DBG("DEBUG:run_address_switch: matching on "
- "ADDRESS node (CONTAINS)\n");
- return get_first_child(kid);
- }
- }
- break;
- case SUBDOMAIN_OF_ATTR:
- switch (subfield) {
- case HOST_VAL:
- k = msg_val->len - cpl_val.len;
- if (k>=0 && (k==0 || msg_val->s[k-1]=='.') &&
- !strncasecmp(cpl_val.s,msg_val->s+k,cpl_val.len)
- ) {
- DBG("DEBUG:run_address_switch: matching on "
- "ADDRESS node (SUBDOMAIN_OF)\n");
- return get_first_child(kid);
- }
- break;
- case TEL_VAL:
- if (msg_val==0) break;
- if (msg_val->len>=cpl_val.len && !strncasecmp(
- cpl_val.s,msg_val->s,cpl_val.len)) {
- DBG("DEBUG:run_address_switch: matching on "
- "ADDRESS node (SUBDOMAIN_OF)\n");
- return get_first_child(kid);
- }
- break;
- default:
- LOG(L_WARN,"WARNING:run_address_switch: operator"
- " SUBDOMAIN_OF applies only to HOST or TEL "
- "-> ignored\n");
- }
- break;
- }
- break;
- default:
- LOG(L_ERR,"ERROR:run_address_switch: unknown output node type "
- "(%d) for ADDRESS_SWITCH node\n",NODE_TYPE(kid));
- goto script_error;
- }
- }
- /* none of the branches of ADDRESS_SWITCH matched -> go for default */
- return DEFAULT_ACTION;
- runtime_error:
- return CPL_RUNTIME_ERROR;
- script_error:
- return CPL_SCRIPT_ERROR;
- }
- /* UPDATED + CHECKED
- */
- static inline char *run_string_switch( struct cpl_interpreter *intr )
- {
- unsigned short field;
- char *p;
- char *kid;
- char *not_present_node;
- unsigned short attr_name;
- int i;
- str cpl_val;
- str msg_val;
- not_present_node = 0;
- msg_val.s = 0;
- msg_val.len = 0;
- /* parse the attribute */
- if (NR_OF_ATTR(intr->ip)!=1) {
- LOG(L_ERR,"ERROR:cpl_c:run_string_switch: node should have 1 attr, not"
- " (%d)\n",NR_OF_ATTR(intr->ip));
- goto script_error;
- }
- p=ATTR_PTR(intr->ip);
- get_basic_attr( p, attr_name, field, intr, script_error);
- if (attr_name!=FIELD_ATTR) {
- LOG(L_ERR,"ERROR:cpl_c:run_string_switch: unknown param type (%d)"
- " for STRING_SWITCH node\n",*p);
- goto script_error;
- }
- for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
- kid = intr->ip + KID_OFFSET(intr->ip,i);
- check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
- switch ( NODE_TYPE(kid) ) {
- case NOT_PRESENT_NODE:
- if (not_present_node) {
- LOG(L_ERR,"ERROR:run_string_switch: NOT_PRESENT node "
- "found twice!\n");
- goto script_error;
- }
- not_present_node = kid;
- break;
- case OTHERWISE_NODE :
- if (i!=NR_OF_KIDS(intr->ip)-1) {
- LOG(L_ERR,"ERROR:run_string_switch: OTHERWISE node "
- "not found as the last sub-node!\n");
- goto script_error;
- }
- DBG("DEBUG:run_string_switch: matching on OTHERWISE node\n");
- return get_first_child(kid);
- case STRING_NODE :
- /* check the number of attributes */
- if (NR_OF_ATTR(kid)!=1) {
- LOG(L_ERR,"ERROR:run_string_switch: incorrect nr of attrs "
- "(%d) in STRING node (expected 1)\n",NR_OF_ATTR(kid));
- goto script_error;
- }
- /* get the attribute name */
- p = ATTR_PTR(kid);
- get_basic_attr( p, attr_name, cpl_val.len, intr, script_error);
- if (attr_name!=IS_ATTR && attr_name!=CONTAINS_ATTR ) {
- LOG(L_ERR,"ERROR:run_string_switch: unknown attribute "
- "(%d) in STRING node\n",attr_name);
- goto script_error;
- }
- /* get attribute value */
- get_str_attr( p, cpl_val.s, cpl_val.len, intr, script_error,1);
- DBG("DEBUG:run_string_switch: testing STRING branch "
- "attr_name=%d attr_val=[%.*s](%d)..\n",
- attr_name,cpl_val.len,cpl_val.s,cpl_val.len);
- if (!msg_val.s) {
- switch (field) {
- case SUBJECT_VAL: /* SUBJECT */
- if (intr->subject==STR_NOT_FOUND)
- goto not_present;
- if (!intr->subject) {
- /* get the subject header */
- if (!intr->msg->subject) {
- if (parse_headers(intr->msg,
- HDR_SUBJECT_F,0)==-1) {
- LOG(L_ERR,"ERROR:run_string_switch: "
- "bad SUBJECT header\n");
- goto runtime_error;
- } else if (!intr->msg->subject) {
- /* hdr not present */
- intr->subject = STR_NOT_FOUND;
- goto not_present;
- }
- }
- intr->subject =
- &(intr->msg->subject->body);
- }
- trim_len( msg_val.len,msg_val.s,
- *(intr->subject));
- break;
- case ORGANIZATION_VAL: /* ORGANIZATION */
- if (intr->organization==STR_NOT_FOUND)
- goto not_present;
- if (!intr->organization) {
- /* get the organization header */
- if (!intr->msg->organization) {
- if (parse_headers(intr->msg,
- HDR_ORGANIZATION_F,0)==-1) {
- LOG(L_ERR,"ERROR:run_string_switch: "
- "bad ORGANIZATION hdr\n");
- goto runtime_error;
- } else if (!intr->msg->organization) {
- /* hdr not present */
- intr->organization = STR_NOT_FOUND;
- goto not_present;
- }
- }
- intr->organization =
- &(intr->msg->organization->body);
- }
- trim_len( msg_val.len,msg_val.s,
- *(intr->organization));
- break;
- case USER_AGENT_VAL: /* User Agent */
- if (intr->user_agent==STR_NOT_FOUND)
- goto not_present;
- if (!intr->user_agent) {
- /* get the header */
- if (!intr->msg->user_agent) {
- if (parse_headers(intr->msg,
- HDR_USERAGENT_F,0)==-1) {
- LOG(L_ERR,"ERROR:run_string_switch: "
- "bad USERAGENT hdr\n");
- goto runtime_error;
- } else if (!intr->msg->user_agent) {
- /* hdr not present */
- intr->user_agent = STR_NOT_FOUND;
- goto not_present;
- }
- }
- intr->user_agent =
- &(intr->msg->user_agent->body);
- }
- trim_len( msg_val.len,msg_val.s,
- *(intr->user_agent));
- break;
- default:
- LOG(L_ERR,"ERROR:run_string_switch: unknown "
- "attribute (%d) in STRING node\n",field);
- goto script_error;
- }
- DBG("DEBUG:run_string_switch: extracted msg string is "
- "<%.*s>\n",msg_val.len, msg_val.s);
- }
- /* does the value from script match the one from message? */
- switch (attr_name) {
- case IS_ATTR:
- if ( (!msg_val.s && !cpl_val.s) ||
- (msg_val.len==cpl_val.len &&
- strncasecmp(msg_val.s,cpl_val.s,cpl_val.len)==0)) {
- DBG("DEBUG:run_string_switch: matching on "
- "STRING node (IS)\n");
- return get_first_child(kid);
- }
- break;
- case CONTAINS_ATTR:
- if (cpl_val.len<=msg_val.len &&
- strcasestr_str(&msg_val, &cpl_val)!=0 ) {
- DBG("DEBUG:run_string_switch: matching on "
- "STRING node (CONTAINS)\n");
- return get_first_child(kid);
- }
- break;
- }
- break;
- default:
- LOG(L_ERR,"ERROR:run_string_switch: unknown output node type "
- "(%d) for STRING_SWITCH node\n",NODE_TYPE(kid));
- goto script_error;
- }
- }
- /* none of the branches of STRING_SWITCH matched -> go for default */
- return DEFAULT_ACTION;
- not_present:
- DBG("DEBUG:run_string_switch: required hdr not present in sip msg\n");
- if (not_present_node)
- return get_first_child(not_present_node);
- /* look for the NOT_PRESENT node */
- DBG("DEBUG:run_string_switch: searching for NOT_PRESENT sub-node..\n");
- for(; i<NR_OF_KIDS(intr->ip) ; i++ ) {
- kid = intr->ip + KID_OFFSET(intr->ip,i);
- check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
- if (NODE_TYPE(kid)==NOT_PRESENT_NODE)
- return get_first_child(kid);
- }
- return DEFAULT_ACTION;
- runtime_error:
- return CPL_RUNTIME_ERROR;
- script_error:
- return CPL_SCRIPT_ERROR;
- }
- /* UPDATED + CHECKED
- */
- static inline char *run_priority_switch( struct cpl_interpreter *intr )
- {
- static str default_val=STR_STATIC_INIT("normal");
- unsigned short n;
- char *p;
- char *kid;
- char *not_present_node;
- unsigned short attr_name;
- unsigned short attr_val;
- unsigned short msg_attr_val;
- unsigned short msg_prio;
- int i;
- str cpl_val = STR_NULL;
- str msg_val = STR_NULL;
- not_present_node = 0;
- msg_attr_val = NORMAL_VAL;
- for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
- kid = intr->ip + KID_OFFSET(intr->ip,i);
- check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
- switch ( NODE_TYPE(kid) ) {
- case NOT_PRESENT_NODE:
- if (not_present_node) {
- LOG(L_ERR,"ERROR:run_priority_switch: NOT_PRESENT node "
- "found twice!\n");
- goto script_error;
- }
- not_present_node = kid;
- break;
- case OTHERWISE_NODE :
- if (i!=NR_OF_KIDS(intr->ip)-1) {
- LOG(L_ERR,"ERROR:run_priority_switch: OTHERWISE node "
- "not found as the last sub-node!\n");
- goto script_error;
- }
- DBG("DEBUG:run_priority_switch: matching on OTHERWISE node\n");
- return get_first_child(kid);
- case PRIORITY_NODE :
- if (NR_OF_ATTR(kid)!=1)
- goto script_error;
- /* get the attribute */
- p = ATTR_PTR(kid);
- get_basic_attr( p, attr_name, attr_val, intr, script_error);
- if (attr_name!=LESS_ATTR && attr_name!=GREATER_ATTR &&
- attr_name!=EQUAL_ATTR){
- LOG(L_ERR,"ERROR:run_priority_switch: unknown attribute "
- "(%d) in PRIORITY node\n",attr_name);
- goto script_error;
- }
- /* attribute's encoded value */
- if (attr_val!=EMERGENCY_VAL && attr_val!=URGENT_VAL &&
- attr_val!=NORMAL_VAL && attr_val!=NON_URGENT_VAL &&
- attr_val!=UNKNOWN_PRIO_VAL) {
- LOG(L_ERR,"ERROR:run_priority_switch: unknown encoded "
- "value (%d) for attribute (*d) in PRIORITY node\n",*p);
- goto script_error;
- }
- if (attr_val==UNKNOWN_PRIO_VAL) {
- if (attr_name!=EQUAL_ATTR) {
- LOG(L_ERR,"ERROR:cpl_c:run_priority_switch:bad PRIORITY"
- " branch: attr=EQUAL doesn't match val=UNKNOWN\n");
- goto script_error;
- }
- /* if the attr is UNKNOWN, its string value is present */
- get_basic_attr(p, n,cpl_val.len, intr, script_error);
- if (n!=PRIOSTR_ATTR) {
- LOG(L_ERR,"ERROR:run_priority_switch: expected PRIOSTR"
- "(%d) attr, found (%d)\n",PRIOSTR_ATTR,n);
- goto script_error;
- }
- get_str_attr(p, cpl_val.s, cpl_val.len,intr,script_error,1);
- }
- DBG("DEBUG:run_priority_switch: testing PRIORITY branch "
- "(attr=%d,val=%d) [%.*s](%d)..\n",
- attr_name,attr_val,cpl_val.len,cpl_val.s,cpl_val.len);
- if (!msg_val.s) {
- if (!intr->priority) {
- /* get the PRIORITY header from message */
- if (!intr->msg->priority) {
- if (parse_headers(intr->msg,HDR_PRIORITY_F,0)==-1){
- LOG(L_ERR,"ERROR:run_priority_switch: bad "
- "sip msg or PRIORITY header !\n");
- goto runtime_error;
- } else if (!intr->msg->priority) {
- LOG(L_NOTICE,"NOTICE:run_priority_switch: "
- "missing PRIORITY header -> using "
- "default value \"normal\"!\n");
- intr->priority = &default_val;
- } else {
- intr->priority =
- &(intr->msg->priority->body);
- }
- } else {
- intr->priority =
- &(intr->msg->priority->body);
- }
- }
- trim_len( msg_val.len, msg_val.s, *(intr->priority));
- /* encode attribute's value from SIP message */
- if ( msg_val.len==EMERGENCY_STR_LEN &&
- !strncasecmp(msg_val.s,EMERGENCY_STR,msg_val.len) ) {
- msg_attr_val = EMERGENCY_VAL;
- } else if ( msg_val.len==URGENT_STR_LEN &&
- !strncasecmp(msg_val.s,URGENT_STR,msg_val.len) ) {
- msg_attr_val = URGENT_VAL;
- } else if ( msg_val.len==NORMAL_STR_LEN &&
- !strncasecmp(msg_val.s,NORMAL_STR,msg_val.len) ) {
- msg_attr_val = NORMAL_VAL;
- } else if ( msg_val.len==NON_URGENT_STR_LEN &&
- !strncasecmp(msg_val.s,NON_URGENT_STR,msg_val.len) ) {
- msg_attr_val = NON_URGENT_VAL;
- } else {
- msg_attr_val = UNKNOWN_PRIO_VAL;
- }
- DBG("DEBUG:run_priority_switch: extracted msg priority is "
- "<%.*s> decoded as [%d]\n",
- msg_val.len,msg_val.s,msg_attr_val);
- }
- DBG("DEBUG:run_priority_switch: using msg string <%.*s>\n",
- msg_val.len, msg_val.s);
- /* attr_val (from cpl) cannot be UNKNOWN - we already
- * check it -> check only for msg_attr_val for non-EQUAL op */
- if (msg_attr_val==UNKNOWN_PRIO_VAL && attr_name!=EQUAL_ATTR) {
- LOG(L_NOTICE,"NOTICE:run_priority_switch: UNKNOWN "
- "value found in sip_msg when string a LESS/GREATER "
- "cmp -> force the value to default \"normal\"\n");
- msg_prio = NORMAL_VAL;
- } else {
- msg_prio = msg_attr_val;
- }
- /* does the value from script match the one from message? */
- switch (attr_name) {
- case LESS_ATTR:
- switch (attr_val) {
- case EMERGENCY_VAL:
- if (msg_prio!=EMERGENCY_VAL) break; /*OK*/
- else continue; /* for cycle for all kids */
- case URGENT_VAL:
- if (msg_prio!=EMERGENCY_VAL &&
- msg_prio!=URGENT_VAL) break; /* OK */
- else continue; /* for cycle for all kids */
- case NORMAL_VAL:
- if (msg_prio==NON_URGENT_VAL) break; /*OK*/
- else continue; /* for cycle for all kids */
- case NON_URGENT_VAL:
- continue; /* for cycle for all kids */
- }
- break;
- case GREATER_ATTR:
- switch (attr_val) {
- case EMERGENCY_VAL:
- continue; /* for cycle for all kids */
- case URGENT_VAL:
- if (msg_prio!=EMERGENCY_VAL) break; /*OK*/
- else continue; /* for cycle for all kids */
- case NORMAL_VAL:
- if (msg_prio!=NON_URGENT_VAL &&
- msg_prio!=NORMAL_VAL) break; /*OK*/
- else continue; /* for cycle for all kids */
- case NON_URGENT_VAL:
- if (msg_prio!=NON_URGENT_VAL) break; /*OK*/
- else continue; /* for cycle for all kids */
- }
- break;
- case EQUAL_ATTR:
- if ( attr_val==msg_prio ) {
- if (attr_val==UNKNOWN_PRIO_VAL) {
- if ( msg_val.len==cpl_val.len &&
- !strncasecmp(msg_val.s,cpl_val.s,msg_val.len)){
- break; /* OK */
- }
- } else {
- break; /* OK */
- }
- }
- continue; /* for cycle for all kids */
- break;
- } /* end switch for attr_name */
- DBG("DEBUG:run_priority_switch: matching current "
- "PRIORITY node\n");
- return get_first_child(kid);
- break;
- default:
- LOG(L_ERR,"ERROR:run_priority_switch: unknown output node type"
- " (%d) for PRIORITY_SWITCH node\n",NODE_TYPE(kid));
- goto script_error;
- } /* end switch for NODE_TYPE */
- } /* end for for all kids */
- /* none of the branches of PRIORITY_SWITCH matched -> go for default */
- return DEFAULT_ACTION;
- runtime_error:
- return CPL_RUNTIME_ERROR;
- script_error:
- return CPL_SCRIPT_ERROR;
- }
- inline static int set_TZ(char *tz_env)
- {
- DBG("DEBUG:cpl-c:set_TZ: switching TZ as \"%s\"\n",tz_env);
- if (putenv( tz_env )==-1) {
- LOG(L_ERR,"ERROR:cpl-c:set_TZ: setenv failed -> unable to set TZ "
- " \"%s\"\n",tz_env);
- return -1;
- }
- tzset(); /* just to be sure */
- return 0;
- }
- /* UPDATED + CHECKED
- */
- static inline char *run_time_switch( struct cpl_interpreter *intr )
- {
- char *p;
- char *kid;
- char *attr_str;
- unsigned short attr_name;
- unsigned short attr_len;
- unsigned char flags = 0;
- int nr_attrs;
- int i,j;
- str user_tz = STR_NULL;
- ac_tm_t att;
- tmrec_t trt;
- DBG("DEBUG:cpl-c:run_time_switch: checking recv. time stamp <%d>\n",
- intr->recv_time);
- switch (NR_OF_ATTR(intr->ip)) {
- case 1:
- p = ATTR_PTR(intr->ip);
- get_basic_attr( p, attr_name, user_tz.len, intr, script_error);
- if (attr_name!=TZID_ATTR) {
- LOG(L_ERR,"ERROR:cpl-c:run_time_switch: bad attribute -> "
- " expected=%d, found=%d\n",TZID_ATTR,attr_name);
- goto script_error;
- }
- get_str_attr( p, user_tz.s, user_tz.len, intr, script_error, 1);
- case 0:
- break;
- default:
- LOG(L_ERR,"ERROR:cpl-c:run_time_switch: incorrect number of attr ->"
- " found=%d expected=(0,1)\n",NR_OF_ATTR(intr->ip));
- goto script_error;
- }
- if (user_tz.s && user_tz.len) {
- if (set_TZ(user_tz.s)==-1)
- goto runtime_error;
- flags |= (1<<7);
- }
- for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
- kid = intr->ip + KID_OFFSET(intr->ip,i);
- check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
- switch ( NODE_TYPE(kid) ) {
- case NOT_PRESENT_NODE:
- DBG("DEBUG:cpl-c:run_time_switch: NOT_PRESENT node found ->"
- "skipping (useless in this case)\n");
- break;
- case OTHERWISE_NODE :
- if (i!=NR_OF_KIDS(intr->ip)-1) {
- LOG(L_ERR,"ERROR:cpl-c:run_time_switch: OTHERWISE node "
- "not found as the last sub-node!\n");
- goto script_error;
- }
- DBG("DEBUG:cpl-c:run_time_switch: matching on "
- "OTHERWISE node\n");
- return get_first_child(kid);
- case TIME_NODE :
- /* init structures */
- memset( &att, 0, sizeof(att));
- memset( &trt, 0, sizeof(trt));
- if(ac_tm_set_time( &att, intr->recv_time))
- goto runtime_error;
- /* let's see how many attributes we have */
- nr_attrs = NR_OF_ATTR(kid);
- /* get the attributes */
- p = ATTR_PTR(kid);
- for(j=0;j<nr_attrs;j++) {
- /* get the attribute */
- get_basic_attr( p, attr_name, attr_len, intr, script_error);
- get_str_attr( p, attr_str, attr_len, intr, script_error,1);
- /* process the attribute */
- DBG("DEBUG:cpl_c:run_time_node: attribute [%d] found :"
- "[%s]\n",attr_name, attr_str);
- switch (attr_name) {
- case DTSTART_ATTR:
- if( !attr_str || tr_parse_dtstart(&trt, attr_str))
- goto parse_err;
- flags ^= (1<<0);
- break;
- case DTEND_ATTR:
- if( !attr_str || tr_parse_dtend(&trt, attr_str))
- goto parse_err;
- flags ^= (1<<1);
- break;
- case DURATION_ATTR:
- if( !attr_str || tr_parse_duration(&trt, attr_str))
- goto parse_err;
- flags ^= (1<<1);
- break;
- case FREQ_ATTR:
- if( attr_str && tr_parse_freq(&trt, attr_str))
- goto parse_err;
- break;
- case UNTIL_ATTR:
- if( attr_str && tr_parse_until(&trt, attr_str))
- goto parse_err;
- break;
- case INTERVAL_ATTR:
- if( attr_str && tr_parse_interval(&trt, attr_str))
- goto parse_err;
- break;
- case BYDAY_ATTR:
- if( attr_str && tr_parse_byday(&trt, attr_str))
- goto parse_err;
- break;
- case BYMONTHDAY_ATTR:
- if( attr_str && tr_parse_bymday(&trt, attr_str))
- goto parse_err;
- break;
- case BYYEARDAY_ATTR:
- if( attr_str && tr_parse_byyday(&trt, attr_str))
- goto parse_err;
- break;
- case BYMONTH_ATTR:
- if( attr_str && tr_parse_bymonth(&trt, attr_str))
- goto parse_err;
- break;
- case BYWEEKNO_ATTR:
- if( attr_str && tr_parse_byweekno(&trt, attr_str))
- goto parse_err;
- break;
- case WKST_ATTR:
- if( attr_str && tr_parse_wkst(&trt, attr_str))
- goto parse_err;
- break;
- default:
- LOG(L_ERR,"ERROR:cpl_c:run_time_switch: "
- "unsupported attribute [%d] found in TIME "
- "node\n",attr_name);
- goto script_error;
- } /* end attribute switch */
- } /* end for*/
- /* check the mandatory attributes */
- if ( (flags&0x03)!=((1<<0)|(1<<1)) ) {
- LOG(L_ERR,"ERROR:cpl_c:run_time_switch: attribute DTSTART"
- ",DTEND,DURATION missing or multi-present\n");
- goto script_error;
- }
- /* does the recv_time match the specified interval? */
- j = check_tmrec( &trt, &att, 0);
- /* restore the orig TZ */
- if ( flags&(1<<7) )
- set_TZ(cpl_env.orig_tz.s);
- /* free structs that I don't need any more */
- ac_tm_free( &att );
- tmrec_free( &trt );
- /* let's see the result ;-) */
- switch (j) {
- case 0:
- DBG("DEBUG:run_time_switch: matching current "
- "TIME node\n");
- return get_first_child(kid);
- case -1:
- LOG(L_ERR,"ERROR:cpl_c:run_time_switch: check_tmrec "
- "ret. err. when testing time cond. !\n");
- goto runtime_error;
- break;
- case 1:
- DBG("DEBUG:cpl_c:run_time_switch: time cond. doesn't"
- " match !\n");
- break;
- }
- break;
- default:
- LOG(L_ERR,"ERROR:cpl-c:run_priority_switch: unknown output node"
- " type (%d) for PRIORITY_SWITCH node\n",NODE_TYPE(kid));
- goto script_error;
- } /* end switch for NODE_TYPE */
- } /* end for for all kids */
- /* none of the branches of TIME_SWITCH matched -> go for default */
- ac_tm_free( &att );
- tmrec_free( &trt );
- return DEFAULT_ACTION;
- runtime_error:
- if ( flags&(1<<7) )
- set_TZ(cpl_env.orig_tz.s);
- ac_tm_free( &att );
- tmrec_free( &trt );
- return CPL_RUNTIME_ERROR;
- parse_err:
- LOG(L_ERR,"ERROR:cpl-c:run_priority_switch: error parsing attr [%d][%s]\n",
- attr_name,attr_str?(char*)attr_str:"NULL");
- script_error:
- if ( flags&(1<<7) )
- set_TZ(cpl_env.orig_tz.s);
- ac_tm_free( &att );
- tmrec_free( &trt );
- return CPL_SCRIPT_ERROR;
- }
- inline static int is_lang_tag_matching(str *range,str *cpl_tag,str *cpl_subtag)
- {
- char *c;
- char *end;
- str tag = STR_NULL;
- str subtag = STR_NULL;
- c = range->s;
- end = range->s + range->len;
- while(c<end) {
- /* eat all spaces to first letter */
- while(c<end && (*c==' ' || *c=='\t')) c++;
- if (c==end) goto error;
- /* init tag and subtag */
- tag.len = 0;
- subtag.len = 0;
- /* get the tag */
- tag.s = c;
- if (*c=='*' && (c+1==end||*(c+1)!='-')) {
- tag.len++;
- c++;
- } else while (c<end && ((*c)|0x20)>='a' && ((*c)|0x20)<='z' ) {
- /*DBG("--- tag ---> <%c>[%d]\n",*c,*c);*/
- tag.len++;
- c++;
- }
- if (tag.len==0) goto error;
- if (c<end && *c=='-') {
- /* go for the subtag */
- subtag.s = ++c;
- while (c<end && ((*c)|0x20)>='a' && ((*c)|0x20)<='z' ) {
- /*DBG("--- subtag ---> <%c>[%d]\n",*c,*c);*/
- subtag.len++;
- c++;
- }
- if (subtag.len==0) goto error;
- } else {
- subtag.s = 0;
- }
- if (c<end && *c==';') {
- /* eat all the params to the ',' */
- while(c<end && *c!=',') c++;
- if (c==end) goto no_matche;
- }
- while(c<end && (*c==' '||*c=='\t')) c++;
- if (c==end || *c==',') {
- /* do compare */
- DBG("DEBUG:cpl-c:is_lang_tag_matching: testing range [%.*s]-[%.*s]"
- " against tag [%.*s]-[%.*s]\n",
- tag.len,tag.s,subtag.len,subtag.s,
- cpl_tag->len,cpl_tag->s,cpl_subtag->len,cpl_subtag->s);
- /* language range of "*" is ignored for the purpose of matching*/
- if ( !(tag.len==1 && *tag.s=='*') ) {
- /* does the language tag matches ? */
- if (tag.len==cpl_tag->len && !strncasecmp(tag.s,cpl_tag->s,
- tag.len)) {
- DBG("cucu bau \n");
- /* if the subtag of the range is void -> matche */
- if (subtag.len==0)
- return 1;
- /* the subtags equals -> matche */
- if (subtag.len==cpl_subtag->len &&
- !strncasecmp(subtag.s,cpl_subtag->s,subtag.len) )
- return 1;
- }
- }
- /* if ',' go for the next language range */
- if (*c==',') c++;
- } else {
- goto error;
- }
- }
- no_matche:
- return 0;
- error:
- LOG(L_ERR,"ERROR:cpl-c:is_lang_tag_matching: parse error in Accept-"
- "Language body <%.*s> at char <%c>[%d] offset %ld!\n",
- range->len,range->s,*c,*c,(long)(c-range->s));
- return -1;
- }
- /* UPDATED + CHECKED
- */
- static inline char *run_language_switch( struct cpl_interpreter *intr )
- {
- char *p;
- char *kid;
- char *not_present_node;
- unsigned short attr_name;
- int nr_attr;
- int i,j;
- str attr = STR_NULL;
- str msg_val = STR_NULL;
- str lang_tag = STR_NULL;
- str lang_subtag = STR_NULL;
- not_present_node = 0;
- for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
- kid = intr->ip + KID_OFFSET(intr->ip,i);
- check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
- switch ( NODE_TYPE(kid) ) {
- case NOT_PRESENT_NODE:
- if (not_present_node) {
- LOG(L_ERR,"ERROR:run_language_switch: NOT_PRESENT node "
- "found twice!\n");
- goto script_error;
- }
- not_present_node = kid;
- break;
- case OTHERWISE_NODE :
- if (i!=NR_OF_KIDS(intr->ip)-1) {
- LOG(L_ERR,"ERROR:run_language_switch: OTHERWISE node "
- "not found as the last sub-node!\n");
- goto script_error;
- }
- DBG("DEBUG:run_language_switch: matching on OTHERWISE node\n");
- return get_first_child(kid);
- case LANGUAGE_NODE :
- /* check the number of attributes */
- nr_attr = NR_OF_ATTR(kid);
- if (nr_attr<1 || nr_attr>2) {
- LOG(L_ERR,"ERROR:run_string_switch: incorrect nr of attrs "
- "(%d) in LANGUAGE node (1 or 2)\n",NR_OF_ATTR(kid));
- goto script_error;
- }
- /* get the attributes */
- p = ATTR_PTR(kid);
- lang_tag.s = lang_subtag.s = 0;
- lang_tag.len = lang_subtag.len = 0;
- for(j=0;j<nr_attr;j++) {
- get_basic_attr( p, attr_name, attr.len, intr, script_error);
- get_str_attr( p, attr.s, attr.len, intr, script_error,0);
- if (attr_name==MATCHES_TAG_ATTR ) {
- lang_tag = attr;
- DBG("DEBUG:cpl-c:run_language_string: language-tag is"
- " [%.*s]\n",attr.len,attr.s);
- }else if (attr_name==MATCHES_SUBTAG_ATTR) {
- lang_subtag = attr;
- DBG("DEBUG:cpl-c:run_language_string: language-subtag"
- " is [%.*s]\n",attr.len,attr.s);
- }else {
- LOG(L_ERR,"ERROR:run_language_switch: unknown attribute"
- " (%d) in LANGUAGE node\n",attr_name);
- goto script_error;
- }
- }
-
- /* get the value from the SIP message -> if not yet, do it now
- * and remember it for the next times */
- if (!msg_val.s) {
- if (intr->accept_language==STR_NOT_FOUND)
- goto not_present;
- if (!intr->accept_language) {
- /* get the accept_language header */
- if (!intr->msg->accept_language) {
- if (parse_headers(intr->msg,
- HDR_ACCEPTLANGUAGE_F,0)==-1) {
- LOG(L_ERR,"ERROR:run_language_switch: "
- "bad ACCEPT_LANGUAGE header\n");
- goto runtime_error;
- } else if (!intr->msg->accept_language) {
- /* hdr not present */
- intr->accept_language = STR_NOT_FOUND;
- goto not_present;
- }
- }
- intr->subject =
- &(intr->msg->accept_language->body);
- }
- }
- trim_len( msg_val.len,msg_val.s, *(intr->subject));
- DBG("DEBUG:run_language_switch: extracted msg string is "
- "<%.*s>\n",msg_val.len, msg_val.s);
-
- /* does the value from script match the one from message? */
- if (msg_val.len && msg_val.s) {
- j = is_lang_tag_matching(&msg_val,&lang_tag,&lang_subtag);
- if (j==1) {
- DBG("DEBUG:run_language_switch: matching on "
- "LANGUAGE node\n");
- return get_first_child(kid);
- }else if (j==-1) {
- goto runtime_error;
- }
- }
- break;
- default:
- LOG(L_ERR,"ERROR:cpl_c:run_language_switch: unknown output "
- "node type (%d) for LANGUAGE_SWITCH node\n",
- NODE_TYPE(kid));
- goto script_error;
- } /* end switch for NODE_TYPE */
- } /* end for for all kids */
- return DEFAULT_ACTION;
- not_present:
- DBG("DEBUG:run_string_switch: required hdr not present in sip msg\n");
- if (not_present_node)
- return get_first_child(not_present_node);
- /* look for the NOT_PRESENT node */
- DBG("DEBUG:run_string_switch: searching for NOT_PRESENT sub-node..\n");
- for(; i<NR_OF_KIDS(intr->ip) ; i++ ) {
- kid = intr->ip + KID_OFFSET(intr->ip,i);
- check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
- if (NODE_TYPE(kid)==NOT_PRESENT_NODE)
- return get_first_child(kid);
- }
- return DEFAULT_ACTION;
- runtime_error:
- return CPL_RUNTIME_ERROR;
- script_error:
- return CPL_SCRIPT_ERROR;
- }
|