modules_s/cpl-c/cpl_switches.h

00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License 
00024  * along with this program; if not, write to the Free Software 
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  * History:
00028  * -------
00029  * 2003-06-27: file created (bogdan)
00030  */
00031 
00032 #include "cpl_time.h"
00033 #include "../../parser/parse_from.h"
00034 #include "../../parser/parse_uri.h"
00035 
00036 
00037 
00038 /* UPDATED + CHECKED
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         /* parse the attributes */
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         /* test the condition from all the sub-nodes */
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                                 /* check the number of attributes */
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                                 /* get the attribute name */
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                                 /* get attribute value */
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                                 /* extract the needed value from the message */
00130                                 if (!msg_val) {
00131                                         switch (field) {
00132                                                 case ORIGIN_VAL: /* FROM */
00133                                                         if (!intr->from) {
00134                                                                 /* get the header */
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: /* RURI */
00142                                                         if (!intr->ruri)
00143                                                                 intr->ruri = GET_RURI( intr->msg );
00144                                                         uri = intr->ruri;
00145                                                         break;
00146                                                 case ORIGINAL_DESTINATION_VAL: /* TO */
00147                                                         if (!intr->to) {
00148                                                                 /* get and parse the header */
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                                 /* does the value from script match the one from message? */
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         /* none of the branches of ADDRESS_SWITCH matched -> go for default */
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 /* UPDATED + CHECKED
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         /* parse the attribute */
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                                 /* check the number of attributes */
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                                 /* get the attribute name */
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                                 /* get attribute value */
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: /* SUBJECT */
00351                                                         if (intr->subject==STR_NOT_FOUND)
00352                                                                 goto not_present;
00353                                                         if (!intr->subject) {
00354                                                                 /* get the subject header */
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                                                                                 /* hdr not present */
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: /* ORGANIZATION */
00374                                                         if (intr->organization==STR_NOT_FOUND)
00375                                                                 goto not_present;
00376                                                         if (!intr->organization) {
00377                                                                 /* get the organization header */
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                                                                                 /* hdr not present */
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: /* User Agent */
00397                                                         if (intr->user_agent==STR_NOT_FOUND)
00398                                                                 goto not_present;
00399                                                         if (!intr->user_agent) {
00400                                                                 /* get the  header */
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                                                                                 /* hdr not present */
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                                 /* does the value from script match the one from message? */
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         /* none of the branches of STRING_SWITCH matched -> go for default */
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         /* look for the NOT_PRESENT node */
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 /* UPDATED + CHECKED
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                                 /* get the attribute */
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                                 /* attribute's encoded value */
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                                         /* if the attr is UNKNOWN, its string value is present  */
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                                                 /* get the PRIORITY header from message */
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                                         /* encode attribute's value from SIP message */
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                                 /* attr_val (from cpl) cannot be UNKNOWN - we already
00603                                  * check it -> check only for msg_attr_val for non-EQUAL op */
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                                 /* does the value from script match the one from message? */
00613                                 switch (attr_name) {
00614                                         case LESS_ATTR:
00615                                                 switch (attr_val) {
00616                                                         case EMERGENCY_VAL:
00617                                                                 if (msg_prio!=EMERGENCY_VAL) break; /*OK*/
00618                                                                 else continue; /* for cycle for all kids */
00619                                                         case URGENT_VAL:
00620                                                                 if (msg_prio!=EMERGENCY_VAL &&
00621                                                                         msg_prio!=URGENT_VAL) break; /* OK */
00622                                                                 else continue; /* for cycle for all kids */
00623                                                         case NORMAL_VAL:
00624                                                                 if (msg_prio==NON_URGENT_VAL) break; /*OK*/
00625                                                                 else continue; /* for cycle for all kids */
00626                                                         case NON_URGENT_VAL:
00627                                                                 continue; /* for cycle for all kids */
00628                                                 }
00629                                                 break;
00630                                         case GREATER_ATTR:
00631                                                 switch (attr_val) {
00632                                                         case EMERGENCY_VAL:
00633                                                                 continue; /* for cycle for all kids */
00634                                                         case URGENT_VAL:
00635                                                                 if (msg_prio!=EMERGENCY_VAL) break; /*OK*/
00636                                                                 else continue; /* for cycle for all kids */
00637                                                         case NORMAL_VAL:
00638                                                                 if (msg_prio!=NON_URGENT_VAL &&
00639                                                                         msg_prio!=NORMAL_VAL) break; /*OK*/
00640                                                                 else continue; /* for cycle for all kids */
00641                                                         case NON_URGENT_VAL:
00642                                                                 if (msg_prio!=NON_URGENT_VAL) break; /*OK*/
00643                                                                 else continue; /* for cycle for all kids */
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; /* OK */
00652                                                                 }
00653                                                         } else {
00654                                                                 break; /* OK */
00655                                                         }
00656                                                 }
00657                                                 continue; /* for cycle for all kids */
00658                                                 break;
00659                                 } /* end switch for attr_name */
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                 } /* end switch for NODE_TYPE */
00669         } /* end for for all kids */
00670 
00671         /* none of the branches of PRIORITY_SWITCH matched -> go for default */
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(); /* just to be sure */
00690         return 0;
00691 }
00692 
00693 
00694 
00695 /* UPDATED + CHECKED
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                                 /* init structures */
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                                 /* let's see how many attributes we have */
00761                                 nr_attrs = NR_OF_ATTR(kid);
00762                                 /* get the attributes */
00763                                 p = ATTR_PTR(kid);
00764                                 for(j=0;j<nr_attrs;j++) {
00765                                         /* get the attribute */
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                                         /* process the attribute */
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                                         } /* end attribute switch */
00829                                 } /* end for*/
00830                                 /* check the mandatory attributes */
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                                 /* does the recv_time match the specified interval?  */
00837                                 j = check_tmrec( &trt, &att, 0);
00838                                 /* restore the orig TZ */
00839                                 if ( flags&(1<<7) )
00840                                         set_TZ(cpl_env.orig_tz.s);
00841                                 /* free structs that I don't need any more */
00842                                 ac_tm_free( &att );
00843                                 tmrec_free( &trt );
00844                                 /* let's see the result ;-) */
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                 } /* end switch for NODE_TYPE */
00866         } /* end for for all kids */
00867 
00868 
00869         /* none of the branches of TIME_SWITCH matched -> go for default */
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                 /* eat all spaces to first letter */
00904                 while(c<end && (*c==' ' || *c=='\t')) c++;
00905                 if (c==end) goto error;
00906                 /* init tag and subtag */
00907                 tag.len = 0;
00908                 subtag.len = 0;
00909                 /* get the tag */
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                         /*DBG("--- tag ---> <%c>[%d]\n",*c,*c);*/
00916                         tag.len++;
00917                         c++;
00918                 }
00919                 if (tag.len==0) goto error;
00920                 if (c<end && *c=='-') {
00921                         /* go for the subtag */
00922                         subtag.s = ++c;
00923                         while (c<end && ((*c)|0x20)>='a' && ((*c)|0x20)<='z' ) {
00924                                 /*DBG("--- subtag ---> <%c>[%d]\n",*c,*c);*/
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                         /* eat all the params to the ',' */
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                         /* do compare */
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                         /* language range of "*" is ignored for the purpose of matching*/
00945                         if ( !(tag.len==1 && *tag.s=='*') ) {
00946                                 /* does the language tag matches ? */
00947                                 if (tag.len==cpl_tag->len && !strncasecmp(tag.s,cpl_tag->s,
00948                                 tag.len)) {
00949                                         DBG("cucu bau \n");
00950                                         /* if the subtag of the range is void -> matche */
00951                                         if (subtag.len==0)
00952                                                 return 1;
00953                                         /* the subtags equals -> matche */
00954                                         if (subtag.len==cpl_subtag->len &&
00955                                         !strncasecmp(subtag.s,cpl_subtag->s,subtag.len) )
00956                                                 return 1;
00957                                 }
00958                         }
00959                         /* if ',' go for the next language range */
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 /* UPDATED + CHECKED
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                                 /* check the number of attributes */
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                                 /* get the attributes */
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                                 /* get the value from the SIP message -> if not yet, do it now
01045                                  * and remember it for the next times */
01046                                 if (!msg_val.s) {
01047                                         if (intr->accept_language==STR_NOT_FOUND)
01048                                                 goto not_present;
01049                                         if (!intr->accept_language) {
01050                                                 /* get the accept_language header */
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                                                                 /* hdr not present */
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                                 /* does the value from script match the one from message? */
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                 } /* end switch for NODE_TYPE */
01089         } /* end for for all kids */
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         /* look for the NOT_PRESENT node */
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