cpl_switches.h

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

Generated on Mon May 21 18:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6