avpops.c

00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2004-2006 Voice Sistem SRL
00005  *
00006  * This file is part of Kamailio.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (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  *  2004-10-04  first version (ramona)
00025  *  2004-11-15  added support for db schemes for avp_db_load (ramona)
00026  *  2004-11-17  aligned to new AVP core global aliases (ramona)
00027  *  2005-01-30  "fm" (fast match) operator added (ramona)
00028  *  2005-01-30  avp_copy (copy/move operation) added (ramona)
00029  */
00030 
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <sys/types.h> /* for regex */
00036 #include <regex.h>
00037 
00038 #include "../../mem/shm_mem.h"
00039 #include "../../mem/mem.h"
00040 #include "../../parser/parse_hname2.h"
00041 #include "../../sr_module.h"
00042 #include "../../str.h"
00043 #include "../../dprint.h"
00044 #include "../../error.h"
00045 #include "../../ut.h"
00046 #include "avpops_parse.h"
00047 #include "avpops_impl.h"
00048 #include "avpops_db.h"
00049 
00050 
00051 MODULE_VERSION
00052 
00053 /* modules param variables */
00054 static str db_url          = {NULL, 0};  /* database url */
00055 static str db_table        = {NULL, 0};  /* table */
00056 static int use_domain      = 0;  /* if domain should be use for avp matching */
00057 static str uuid_col        = str_init("uuid");
00058 static str attribute_col   = str_init("attribute");
00059 static str value_col       = str_init("value");
00060 static str type_col        = str_init("type");
00061 static str username_col    = str_init("username");
00062 static str domain_col      = str_init("domain");
00063 static str* db_columns[6] = {&uuid_col, &attribute_col, &value_col, &type_col, &username_col, &domain_col};
00064 
00065 
00066 static int avpops_init(void);
00067 static int avpops_child_init(int rank);
00068 
00069 static int fixup_db_load_avp(void** param, int param_no);
00070 static int fixup_db_delete_avp(void** param, int param_no);
00071 static int fixup_db_store_avp(void** param, int param_no);
00072 static int fixup_db_query_avp(void** param, int param_no);
00073 static int fixup_delete_avp(void** param, int param_no);
00074 static int fixup_copy_avp(void** param, int param_no);
00075 static int fixup_pushto_avp(void** param, int param_no);
00076 static int fixup_check_avp(void** param, int param_no);
00077 static int fixup_op_avp(void** param, int param_no);
00078 static int fixup_subst(void** param, int param_no);
00079 static int fixup_is_avp_set(void** param, int param_no);
00080 
00081 static int w_print_avps(struct sip_msg* msg, char* foo, char *bar);
00082 static int w_dbload_avps(struct sip_msg* msg, char* source, char* param);
00083 static int w_dbdelete_avps(struct sip_msg* msg, char* source, char* param);
00084 static int w_dbstore_avps(struct sip_msg* msg, char* source, char* param);
00085 static int w_dbquery1_avps(struct sip_msg* msg, char* query, char* param);
00086 static int w_dbquery2_avps(struct sip_msg* msg, char* query, char* dest);
00087 static int w_delete_avps(struct sip_msg* msg, char* param, char *foo);
00088 static int w_copy_avps(struct sip_msg* msg, char* param, char *check);
00089 static int w_pushto_avps(struct sip_msg* msg, char* destination, char *param);
00090 static int w_check_avps(struct sip_msg* msg, char* param, char *check);
00091 static int w_op_avps(struct sip_msg* msg, char* param, char *op);
00092 static int w_subst(struct sip_msg* msg, char* src, char *subst);
00093 static int w_is_avp_set(struct sip_msg* msg, char* param, char *foo);
00094 
00098 static cmd_export_t cmds[] = {
00099         {"avp_print", (cmd_function)w_print_avps, 0, 0, 0,
00100                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00101         {"avp_db_load", (cmd_function)w_dbload_avps,  2, fixup_db_load_avp, 0,
00102                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00103         {"avp_db_delete", (cmd_function)w_dbdelete_avps, 2, fixup_db_delete_avp, 0,
00104                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00105         {"avp_db_store", (cmd_function)w_dbstore_avps,  2, fixup_db_store_avp, 0,
00106                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00107         {"avp_db_query", (cmd_function)w_dbquery1_avps, 1, fixup_db_query_avp, 0,
00108                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00109         {"avp_db_query", (cmd_function)w_dbquery2_avps, 2, fixup_db_query_avp, 0,
00110                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00111         {"avp_delete", (cmd_function)w_delete_avps, 1, fixup_delete_avp, 0,
00112                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00113         {"avp_copy",   (cmd_function)w_copy_avps,  2,  fixup_copy_avp, 0,
00114                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00115         {"avp_pushto", (cmd_function)w_pushto_avps, 2, fixup_pushto_avp, 0,
00116                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00117         {"avp_check",  (cmd_function)w_check_avps, 2, fixup_check_avp, 0,
00118                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00119         {"avp_op",     (cmd_function)w_op_avps, 2, fixup_op_avp, 0,
00120                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00121         {"avp_subst",  (cmd_function)w_subst,   2, fixup_subst, 0,
00122                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00123         {"is_avp_set", (cmd_function)w_is_avp_set, 1, fixup_is_avp_set, 0,
00124                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE},
00125         {0, 0, 0, 0, 0, 0}
00126 };
00127 
00128 
00132 static param_export_t params[] = {
00133         {"db_url",            STR_PARAM, &db_url.s        },
00134         {"avp_table",         STR_PARAM, &db_table.s      },
00135         {"use_domain",        INT_PARAM, &use_domain      },
00136         {"uuid_column",       STR_PARAM, &uuid_col.s      },
00137         {"attribute_column",  STR_PARAM, &attribute_col.s },
00138         {"value_column",      STR_PARAM, &value_col.s     },
00139         {"type_column",       STR_PARAM, &type_col.s      },
00140         {"username_column",   STR_PARAM, &username_col.s  },
00141         {"domain_column",     STR_PARAM, &domain_col.s    },
00142         {"db_scheme",         STR_PARAM|USE_FUNC_PARAM, (void*)avp_add_db_scheme },
00143         {0, 0, 0}
00144 };
00145 
00146 
00147 struct module_exports exports = {
00148         "avpops",
00149         DEFAULT_DLFLAGS, /* dlopen flags */
00150         cmds,       /* Exported functions */
00151         params,     /* Exported parameters */
00152         0,          /* exported statistics */
00153         0,          /* exported MI functions */
00154         0,          /* exported pseudo-variables */
00155         0,          /* extra processes */
00156         avpops_init,/* Module initialization function */
00157         0,
00158         0,
00159         (child_init_function) avpops_child_init /* per-child init function */
00160 };
00161 
00162 
00163 static int avpops_init(void)
00164 {
00165         if (db_url.s)
00166                 db_url.len = strlen(db_url.s);
00167         if (db_table.s)
00168                 db_table.len = strlen(db_table.s);
00169         uuid_col.len = strlen(uuid_col.s);
00170         attribute_col.len = strlen(attribute_col.s);
00171         value_col.len = strlen(value_col.s);
00172         type_col.len = strlen(type_col.s);
00173         username_col.len = strlen(username_col.s);
00174         domain_col.len = strlen(domain_col.s);
00175 
00176         /* if DB_URL defined -> bind to a DB module */
00177         if (db_url.s!=0)
00178         {
00179                 /* check AVP_TABLE param */
00180                 if (db_table.s==0)
00181                 {
00182                         LM_CRIT("\"AVP_DB\" present but \"AVP_TABLE\" found empty\n");
00183                         goto error;
00184                 }
00185                 /* bind to the DB module */
00186                 if (avpops_db_bind(&db_url)<0)
00187                         goto error;
00188         }
00189 
00190         init_store_avps(db_columns);
00191 
00192         return 0;
00193 error:
00194         return -1;
00195 }
00196 
00197 
00198 static int avpops_child_init(int rank)
00199 {
00200         /* init DB only if enabled */
00201         if (db_url.s==0)
00202                 return 0;
00203         /* skip main process and TCP manager process */
00204         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00205                 return 0;
00206         /* init DB connection */
00207         return avpops_db_init(&db_url, &db_table, db_columns);
00208 }
00209 
00210 
00211 static int fixup_db_avp(void** param, int param_no, int allow_scheme)
00212 {
00213         struct fis_param *sp;
00214         struct db_param  *dbp;
00215         int flags;
00216         str s;
00217         char *p;
00218 
00219         flags=0;
00220         if (db_url.s==0)
00221         {
00222                 LM_ERR("you have to configure a db_url for using avp_db_xxx functions\n");
00223                 return E_UNSPEC;
00224         }
00225 
00226         s.s = (char*)*param;
00227         if (param_no==1)
00228         {
00229                 /* prepare the fis_param structure */
00230                 sp = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));
00231                 if (sp==0) {
00232                         LM_ERR("no more pkg mem!\n");
00233                         return E_OUT_OF_MEM;
00234                 }
00235                 memset( sp, 0, sizeof(struct fis_param));
00236 
00237                 if ( (p=strchr(s.s,'/'))!=0)
00238                 {
00239                         *(p++) = 0;
00240                         /* check for extra flags/params */
00241                         if (!strcasecmp("domain",p)) {
00242                                 flags|=AVPOPS_FLAG_DOMAIN0;
00243                         } else if (!strcasecmp("username",p)) {
00244                                 flags|=AVPOPS_FLAG_USER0;
00245                         } else if (!strcasecmp("uri",p)) {
00246                                 flags|=AVPOPS_FLAG_URI0;
00247                         } else if (!strcasecmp("uuid",p)) {
00248                                 flags|=AVPOPS_FLAG_UUID0;
00249                         } else {
00250                                 LM_ERR("unknow flag "
00251                                         "<%s>\n",p);
00252                                 return E_UNSPEC;
00253                         }
00254                 }
00255                 if (*s.s!='$')
00256                 {
00257                         /* is a constant string -> use it as uuid*/
00258                         sp->opd = ((flags==0)?AVPOPS_FLAG_UUID0:flags)|AVPOPS_VAL_STR;
00259                         sp->u.s.s = (char*)pkg_malloc(strlen(s.s)+1);
00260                         if (sp->u.s.s==0) {
00261                                 LM_ERR("no more pkg mem!!\n");
00262                                 return E_OUT_OF_MEM;
00263                         }
00264                         sp->u.s.len = strlen(s.s);
00265                         strcpy(sp->u.s.s, s.s);
00266                 } else {
00267                         /* is a variable $xxxxx */
00268                         s.len = strlen(s.s);
00269                         p = pv_parse_spec(&s, &sp->u.sval);
00270                         if (p==0 || sp->u.sval.type==PVT_NULL || sp->u.sval.type==PVT_EMPTY)
00271                         {
00272                                 LM_ERR("bad param 1; "
00273                                         "expected : $pseudo-variable or int/str value\n");
00274                                 return E_UNSPEC;
00275                         }
00276                         
00277                         if(sp->u.sval.type==PVT_RURI || sp->u.sval.type==PVT_FROM
00278                                         || sp->u.sval.type==PVT_TO || sp->u.sval.type==PVT_OURI)
00279                         {
00280                                 sp->opd = ((flags==0)?AVPOPS_FLAG_URI0:flags)|AVPOPS_VAL_PVAR;
00281                         } else {
00282                                 sp->opd = ((flags==0)?AVPOPS_FLAG_UUID0:flags)|AVPOPS_VAL_PVAR;
00283                         }
00284                 }
00285                 *param=(void*)sp;
00286         } else if (param_no==2) {
00287                 /* compose the db_param structure */
00288                 dbp = (struct db_param*)pkg_malloc(sizeof(struct db_param));
00289                 if (dbp==0)
00290                 {
00291                         LM_ERR("no more pkg mem!!!\n");
00292                         return E_OUT_OF_MEM;
00293                 }
00294                 memset( dbp, 0, sizeof(struct db_param));
00295                 if ( parse_avp_db( s.s, dbp, allow_scheme)!=0 )
00296                 {
00297                         LM_ERR("parse failed\n");
00298                         return E_UNSPEC;
00299                 }
00300                 *param=(void*)dbp;
00301         }
00302 
00303         return 0;
00304 }
00305 
00306 
00307 static int fixup_db_load_avp(void** param, int param_no)
00308 {
00309         return fixup_db_avp( param, param_no, 1/*allow scheme*/);
00310 }
00311 
00312 static int fixup_db_delete_avp(void** param, int param_no)
00313 {
00314         return fixup_db_avp( param, param_no, 0/*no scheme*/);
00315 }
00316 
00317 
00318 static int fixup_db_store_avp(void** param, int param_no)
00319 {
00320         return fixup_db_avp( param, param_no, 0/*no scheme*/);
00321 }
00322 
00323 static int fixup_db_query_avp(void** param, int param_no)
00324 {
00325         pv_elem_t *model = NULL;
00326         pvname_list_t *anlist = NULL;
00327         str s;
00328 
00329         if (db_url.s==0)
00330         {
00331                 LM_ERR("you have to configure db_url for using avp_db_query function\n");
00332                 return E_UNSPEC;
00333         }
00334 
00335         s.s = (char*)(*param);
00336         if (param_no==1)
00337         {
00338                 if(s.s==NULL)
00339                 {
00340                         LM_ERR("null format in P%d\n",
00341                                         param_no);
00342                         return E_UNSPEC;
00343                 }
00344                 s.len = strlen(s.s);
00345                 if(pv_parse_format(&s, &model)<0)
00346                 {
00347                         LM_ERR("wrong format[%s]\n", s.s);
00348                         return E_UNSPEC;
00349                 }
00350                         
00351                 *param = (void*)model;
00352                 return 0;
00353         } else if(param_no==2) {
00354                 if(s.s==NULL)
00355                 {
00356                         LM_ERR("null format in P%d\n", param_no);
00357                         return E_UNSPEC;
00358                 }
00359                                 s.len = strlen(s.s);
00360 
00361                 anlist = parse_pvname_list(&s, PVT_AVP);
00362                 if(anlist==NULL)
00363                 {
00364                         LM_ERR("bad format in P%d [%s]\n", param_no, s.s);
00365                         return E_UNSPEC;
00366                 }
00367                 *param = (void*)anlist;
00368                 return 0;
00369         }
00370 
00371         return 0;
00372 }
00373 
00374 
00375 static int fixup_delete_avp(void** param, int param_no)
00376 {
00377         struct fis_param *ap=NULL;
00378         char *p;
00379         char *s;
00380         unsigned int flags;
00381         str s0;
00382 
00383         s = (char*)(*param);
00384         if (param_no==1) {
00385                 /* attribute name / alias */
00386                 if ( (p=strchr(s,'/'))!=0 )
00387                         *(p++)=0;
00388                 
00389                 if(*s=='$')
00390                 {
00391                         /* is variable */
00392                         ap = avpops_parse_pvar(s);
00393                         if (ap==0)
00394                         {
00395                                 LM_ERR("unable to get"
00396                                         " pseudo-variable in param \n");
00397                                 return E_UNSPEC;
00398                         }
00399                         if (ap->u.sval.type!=PVT_AVP)
00400                         {
00401                                 LM_ERR("bad param; expected : $avp(name)\n");
00402                                 return E_UNSPEC;
00403                         }
00404                         ap->opd|=AVPOPS_VAL_PVAR;
00405                         ap->type = AVPOPS_VAL_PVAR;
00406                 } else {
00407                         if(strlen(s)<1)
00408                         {
00409                                 LM_ERR("bad param - expected : $avp(name), *, s or i value\n");
00410                                 return E_UNSPEC;
00411                         }
00412                         ap = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));
00413                         if (ap==0)
00414                         {
00415                                 LM_ERR(" no more pkg mem\n");
00416                                 return E_OUT_OF_MEM;
00417                         }
00418                         memset(ap, 0, sizeof(struct fis_param));
00419                         ap->opd|=AVPOPS_VAL_NONE;
00420                         switch(*s) {
00421                                 case 's': case 'S':
00422                                         ap->opd = AVPOPS_VAL_NONE|AVPOPS_VAL_STR;
00423                                 break;
00424                                 case 'i': case 'I':
00425                                         ap->opd = AVPOPS_VAL_NONE|AVPOPS_VAL_INT;
00426                                 break;
00427                                 case '*': case 'a': case 'A':
00428                                         ap->opd = AVPOPS_VAL_NONE;
00429                                 break;
00430                                 default:
00431                                         LM_ERR(" bad param - expected : *, s or i AVP flag\n");
00432                                         pkg_free(ap);
00433                                         return E_UNSPEC;
00434                         }
00435                         /* flags */
00436                         flags = 0;
00437                         if(*(s+1)!='\0')
00438                         {
00439                                 s0.s = s+1;
00440                                 s0.len = strlen(s0.s);
00441                                 if(str2int(&s0, &flags)!=0)
00442                                 {
00443                                         LM_ERR("bad avp flags\n");
00444                                         pkg_free(ap);
00445                                         return E_UNSPEC;
00446                                 }
00447                         }
00448                         ap->type = AVPOPS_VAL_INT;
00449                         ap->u.n = flags<<8;
00450                 }
00451 
00452                 /* flags */
00453                 for( ; p&&*p ; p++ )
00454                 {
00455                         switch (*p)
00456                         {
00457                                 case 'g':
00458                                 case 'G':
00459                                         ap->ops|=AVPOPS_FLAG_ALL;
00460                                         break;
00461                                 default:
00462                                         LM_ERR(" bad flag <%c>\n",*p);
00463                                         if(ap!=NULL)
00464                                                 pkg_free(ap);
00465                                         return E_UNSPEC;
00466                         }
00467                 }
00468                 /* force some flags: if no avp name is given, force "all" flag */
00469                 if (ap->opd&AVPOPS_VAL_NONE)
00470                         ap->ops |= AVPOPS_FLAG_ALL;
00471 
00472                 *param=(void*)ap;
00473         }
00474 
00475         return 0;
00476 }
00477 
00478 static int fixup_copy_avp(void** param, int param_no)
00479 {
00480         struct fis_param *ap;
00481         char *s;
00482         char *p;
00483 
00484         s = (char*)*param;
00485         ap = 0;
00486         p = 0;
00487 
00488         if (param_no==2)
00489         {
00490                 /* avp / flags */
00491                 if ( (p=strchr(s,'/'))!=0 )
00492                         *(p++)=0;
00493         }
00494 
00495         ap = avpops_parse_pvar(s);
00496         if (ap==0)
00497         {
00498                 LM_ERR("unable to get pseudo-variable in P%d\n", param_no);
00499                 return E_OUT_OF_MEM;
00500         }
00501 
00502         /* attr name is mandatory */
00503         if (ap->u.sval.type!=PVT_AVP)
00504         {
00505                 LM_ERR("you must specify only AVP as parameter\n");
00506                 return E_UNSPEC;
00507         }
00508 
00509         if (param_no==2)
00510         {
00511                 /* flags */
00512                 for( ; p&&*p ; p++ )
00513                 {
00514                         switch (*p) {
00515                                 case 'g':
00516                                 case 'G':
00517                                         ap->ops|=AVPOPS_FLAG_ALL;
00518                                         break;
00519                                 case 'd':
00520                                 case 'D':
00521                                         ap->ops|=AVPOPS_FLAG_DELETE;
00522                                         break;
00523                                 case 'n':
00524                                 case 'N':
00525                                         ap->ops|=AVPOPS_FLAG_CASTN;
00526                                         break;
00527                                 case 's':
00528                                 case 'S':
00529                                         ap->ops|=AVPOPS_FLAG_CASTS;
00530                                         break;
00531                                 default:
00532                                         LM_ERR("bad flag <%c>\n",*p);
00533                                         return E_UNSPEC;
00534                         }
00535                 }
00536         }
00537 
00538         *param=(void*)ap;
00539         return 0;
00540 }
00541 
00542 static int fixup_pushto_avp(void** param, int param_no)
00543 {
00544         struct fis_param *ap;
00545         char *s;
00546         char *p;
00547 
00548         s = (char*)*param;
00549         ap = 0;
00550 
00551         if (param_no==1)
00552         {
00553                 if ( *s!='$')
00554                 {
00555                         LM_ERR("bad param 1; expected : $ru $du ...\n");
00556                         return E_UNSPEC;
00557                 }
00558                 /* compose the param structure */
00559 
00560                 if ( (p=strchr(s,'/'))!=0 )
00561                         *(p++)=0;
00562                 ap = avpops_parse_pvar(s);
00563                 if (ap==0)
00564                 {
00565                         LM_ERR("unable to get pseudo-variable in param 1\n");
00566                         return E_OUT_OF_MEM;
00567                 }
00568 
00569                 switch(ap->u.sval.type) {
00570                         case PVT_RURI:
00571                                 ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_RURI;
00572                                 if ( p && !(
00573                                         (!strcasecmp("username",p)
00574                                                         && (ap->opd|=AVPOPS_FLAG_USER0)) ||
00575                                         (!strcasecmp("domain",p)
00576                                                         && (ap->opd|=AVPOPS_FLAG_DOMAIN0)) ))
00577                                 {
00578                                         LM_ERR("unknown ruri flag \"%s\"!\n",p);
00579                                         return E_UNSPEC;
00580                                 }
00581                         break;
00582                         case PVT_DSTURI:
00583                                 if ( p!=0 )
00584                                 {
00585                                         LM_ERR("unknown duri flag \"%s\"!\n",p);
00586                                         return E_UNSPEC;
00587                                 }
00588                                 ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_DURI;
00589                         break;
00590                         case PVT_HDR:
00591                                 /* what's the hdr destination ? request or reply? */
00592                                 LM_ERR("push to header  is obsoleted - use append_hf() "
00593                                                 "or append_to_reply() from textops module!\n");
00594                                 return E_UNSPEC;
00595                         break;
00596                         case PVT_BRANCH:
00597                                 if ( p!=0 )
00598                                 {
00599                                         LM_ERR("unknown branch flag \"%s\"!\n",p);
00600                                         return E_UNSPEC;
00601                                 }
00602                                 ap->opd = AVPOPS_VAL_NONE|AVPOPS_USE_BRANCH;
00603                         break;
00604                         default:
00605                                 LM_ERR("unsupported destination \"%s\"; "
00606                                                 "expected $ru,$du,$br\n",s);
00607                                 return E_UNSPEC;
00608                 }
00609         } else if (param_no==2) {
00610                 /* attribute name*/
00611                 if ( *s!='$')
00612                 {
00613                         LM_ERR("bad param 2; expected: $pseudo-variable ...\n");
00614                         return E_UNSPEC;
00615                 }
00616                 /* compose the param structure */
00617 
00618                 if ( (p=strchr(s,'/'))!=0 )
00619                         *(p++)=0;
00620                 ap = avpops_parse_pvar(s);
00621                 if (ap==0)
00622                 {
00623                         LM_ERR("unable to get pseudo-variable in param 2\n");
00624                         return E_OUT_OF_MEM;
00625                 }
00626                 if (ap->u.sval.type==PVT_NULL)
00627                 {
00628                         LM_ERR("bad param 2; expected : $pseudo-variable ...\n");
00629                         pkg_free(ap);
00630                         return E_UNSPEC;
00631                 }
00632                 ap->opd |= AVPOPS_VAL_PVAR;
00633 
00634                 /* flags */
00635                 for( ; p&&*p ; p++ )
00636                 {
00637                         switch (*p) {
00638                                 case 'g':
00639                                 case 'G':
00640                                         ap->ops|=AVPOPS_FLAG_ALL;
00641                                         break;
00642                                 default:
00643                                         LM_ERR("bad flag <%c>\n",*p);
00644                                         pkg_free(ap);
00645                                         return E_UNSPEC;
00646                         }
00647                 }
00648         }
00649 
00650         *param=(void*)ap;
00651         return 0;
00652 }
00653 
00654 static int fixup_check_avp(void** param, int param_no)
00655 {
00656         struct fis_param *ap;
00657         regex_t* re;
00658         char *s;
00659 
00660         s = (char*)*param;
00661         ap = 0;
00662 
00663         if (param_no==1)
00664         {
00665                 ap = avpops_parse_pvar(s);
00666                 if (ap==0)
00667                 {
00668                         LM_ERR("unable to get pseudo-variable in param 1\n");
00669                         return E_OUT_OF_MEM;
00670                 }
00671                 /* attr name is mandatory */
00672                 if (ap->u.sval.type==PVT_NULL)
00673                 {
00674                         LM_ERR("null pseudo-variable in param 1\n");
00675                         return E_UNSPEC;
00676                 }
00677         } else if (param_no==2) {
00678                 if ( (ap=parse_check_value(s))==0 )
00679                 {
00680                         LM_ERR("failed to parse checked value \n");
00681                         return E_UNSPEC;
00682                 }
00683                 /* if REGEXP op -> compile the expresion */
00684                 if (ap->ops&AVPOPS_OP_RE)
00685                 {
00686                         if ( (ap->opd&AVPOPS_VAL_STR)==0 )
00687                         {
00688                                 LM_ERR("regexp operation requires string value\n");
00689                                 return E_UNSPEC;
00690                         }
00691                         re = pkg_malloc(sizeof(regex_t));
00692                         if (re==0)
00693                         {
00694                                 LM_ERR("no more pkg mem\n");
00695                                 return E_OUT_OF_MEM;
00696                         }
00697                         LM_DBG("compiling regexp <%.*s>\n", ap->u.s.len, ap->u.s.s);
00698                         if (regcomp(re, ap->u.s.s,
00699                                                 REG_EXTENDED|REG_ICASE|REG_NEWLINE))
00700                         {
00701                                 pkg_free(re);
00702                                 LM_ERR("bad re <%.*s>\n", ap->u.s.len, ap->u.s.s);
00703                                 return E_BAD_RE;
00704                         }
00705                         /* free the string and link the regexp */
00706                         // pkg_free(ap->sval.p.s);
00707                         ap->u.s.s = (char*)re;
00708                 } else if (ap->ops&AVPOPS_OP_FM) {
00709                         if ( !( ap->opd&AVPOPS_VAL_PVAR ||
00710                         (!(ap->opd&AVPOPS_VAL_PVAR) && ap->opd&AVPOPS_VAL_STR) ) )
00711                         {
00712                                 LM_ERR("fast_match operation requires string value or "
00713                                                 "avp name/alias (%d/%d)\n",     ap->opd, ap->ops);
00714                                 return E_UNSPEC;
00715                         }
00716                 }
00717         }
00718 
00719         *param=(void*)ap;
00720         return 0;
00721 }
00722 
00723 static int fixup_subst(void** param, int param_no)
00724 {
00725         struct subst_expr* se;
00726         str subst;
00727         struct fis_param *ap;
00728         struct fis_param **av;
00729         char *s;
00730         char *p;
00731         
00732         if (param_no==1) {
00733                 s = (char*)*param;
00734                 ap = 0;
00735                 p = 0;
00736                 av = (struct fis_param**)pkg_malloc(2*sizeof(struct fis_param*));
00737                 if(av==NULL)
00738                 {
00739                         LM_ERR("no more pkg memory\n");
00740                         return E_UNSPEC;                        
00741                 }
00742                 memset(av, 0, 2*sizeof(struct fis_param*));
00743 
00744                 /* avp src / avp dst /flags */
00745                 if ( (p=strchr(s,'/'))!=0 )
00746                         *(p++)=0;
00747                 ap = avpops_parse_pvar(s);
00748                 if (ap==0)
00749                 {
00750                         LM_ERR("unable to get pseudo-variable in param 2 [%s]\n", s);
00751                         return E_OUT_OF_MEM;
00752                 }
00753                 if (ap->u.sval.type!=PVT_AVP)
00754                 {
00755                         LM_ERR("bad attribute name <%s>\n", (char*)*param);
00756                         pkg_free(av);
00757                         return E_UNSPEC;
00758                 }
00759                 /* attr name is mandatory */
00760                 if (ap->opd&AVPOPS_VAL_NONE)
00761                 {
00762                         LM_ERR("you must specify a name for the AVP\n");
00763                         return E_UNSPEC;
00764                 }
00765                 av[0] = ap;
00766                 if(p==0 || *p=='\0')
00767                 {
00768                         *param=(void*)av;
00769                         return 0;
00770                 }
00771                 
00772                 /* dst || flags */
00773                 s = p;
00774                 if(*s==PV_MARKER)
00775                 {
00776                         if ( (p=strchr(s,'/'))!=0 )
00777                                 *(p++)=0;
00778                         if(p==0 || (p!=0 && p-s>1))
00779                         {
00780                                 ap = avpops_parse_pvar(s);
00781                                 if (ap==0)
00782                                 {
00783                                         LM_ERR("unable to get pseudo-variable in param 2 [%s]\n",s);
00784                                         return E_OUT_OF_MEM;
00785                                 }
00786                         
00787                                 if (ap->u.sval.type!=PVT_AVP)
00788                                 {
00789                                         LM_ERR("bad attribute name <%s>!\n", s);
00790                                         pkg_free(av);
00791                                         return E_UNSPEC;
00792                                 }
00793                                 /* attr name is mandatory */
00794                                 if (ap->opd&AVPOPS_VAL_NONE)
00795                                 {
00796                                         LM_ERR("you must specify a name for the AVP!\n");
00797                                         return E_UNSPEC;
00798                                 }
00799                                 av[1] = ap;
00800                         }
00801                         if(p==0 || *p=='\0')
00802                         {
00803                                 *param=(void*)av;
00804                                 return 0;
00805                         }
00806                 }
00807                 
00808                 /* flags */
00809                 for( ; p&&*p ; p++ )
00810                 {
00811                         switch (*p) {
00812                                 case 'g':
00813                                 case 'G':
00814                                         av[0]->ops|=AVPOPS_FLAG_ALL;
00815                                         break;
00816                                 case 'd':
00817                                 case 'D':
00818                                         av[0]->ops|=AVPOPS_FLAG_DELETE;
00819                                         break;
00820                                 default:
00821                                         LM_ERR("bad flag <%c>\n",*p);
00822                                         return E_UNSPEC;
00823                         }
00824                 }
00825                 *param=(void*)av;
00826         } else if (param_no==2) {
00827                 LM_DBG("%s fixing %s\n", exports.name, (char*)(*param));
00828                 subst.s=*param;
00829                 subst.len=strlen(*param);
00830                 se=subst_parser(&subst);
00831                 if (se==0){
00832                         LM_ERR("%s: bad subst re %s\n",exports.name, (char*)*param);
00833                         return E_BAD_RE;
00834                 }
00835                 /* don't free string -- needed for specifiers */
00836                 /* pkg_free(*param); */
00837                 /* replace it with the compiled subst. re */
00838                 *param=se;
00839         }
00840 
00841         return 0;
00842 }
00843 
00844 static int fixup_op_avp(void** param, int param_no)
00845 {
00846         struct fis_param *ap;
00847         struct fis_param **av;
00848         char *s;
00849         char *p;
00850 
00851         s = (char*)*param;
00852         ap = 0;
00853 
00854         if (param_no==1)
00855         {
00856                 av = (struct fis_param**)pkg_malloc(2*sizeof(struct fis_param*));
00857                 if(av==NULL)
00858                 {
00859                         LM_ERR("no more pkg memory\n");
00860                         return E_UNSPEC;                        
00861                 }
00862                 memset(av, 0, 2*sizeof(struct fis_param*));
00863                 /* avp src / avp dst */
00864                 if ( (p=strchr(s,'/'))!=0 )
00865                         *(p++)=0;
00866 
00867                 av[0] = avpops_parse_pvar(s);
00868                 if (av[0]==0)
00869                 {
00870                         LM_ERR("unable to get pseudo-variable in param 1\n");
00871                         return E_OUT_OF_MEM;
00872                 }
00873                 if (av[0]->u.sval.type!=PVT_AVP)
00874                 {
00875                         LM_ERR("bad attribute name <%s>\n", (char*)*param);
00876                         pkg_free(av);
00877                         return E_UNSPEC;
00878                 }
00879                 if(p==0 || *p=='\0')
00880                 {
00881                         *param=(void*)av;
00882                         return 0;
00883                 }
00884                 
00885                 s = p;
00886                 ap = avpops_parse_pvar(s);
00887                 if (ap==0)
00888                 {
00889                         LM_ERR("unable to get pseudo-variable in param 1 (2)\n");
00890                         return E_OUT_OF_MEM;
00891                 }
00892                 if (ap->u.sval.type!=PVT_AVP)
00893                 {
00894                         LM_ERR("bad attribute name/alias <%s>!\n", s);
00895                         pkg_free(av);
00896                         return E_UNSPEC;
00897                 }
00898                 av[1] = ap;
00899                 *param=(void*)av;
00900                 return 0;
00901         } else if (param_no==2) {
00902                 if ( (ap=parse_op_value(s))==0 )
00903                 {
00904                         LM_ERR("failed to parse the value \n");
00905                         return E_UNSPEC;
00906                 }
00907                 /* only integer values or avps */
00908                 if ( (ap->opd&AVPOPS_VAL_STR)!=0 && (ap->opd&AVPOPS_VAL_PVAR)==0)
00909                 {
00910                         LM_ERR("operations requires integer values\n");
00911                         return E_UNSPEC;
00912                 }
00913                 *param=(void*)ap;
00914                 return 0;
00915         }
00916         return -1;
00917 }
00918 
00919 static int fixup_is_avp_set(void** param, int param_no)
00920 {
00921         struct fis_param *ap;
00922         char *p;
00923         char *s;
00924         
00925         s = (char*)(*param);
00926         if (param_no==1) {
00927                 /* attribute name | alias / flags */
00928                 if ( (p=strchr(s,'/'))!=0 )
00929                         *(p++)=0;
00930                 
00931                 ap = avpops_parse_pvar(s);
00932                 if (ap==0)
00933                 {
00934                         LM_ERR("unable to get pseudo-variable in param\n");
00935                         return E_OUT_OF_MEM;
00936                 }
00937                 
00938                 if (ap->u.sval.type!=PVT_AVP)
00939                 {
00940                         LM_ERR("bad attribute name <%s>\n", (char*)*param);
00941                         return E_UNSPEC;
00942                 }
00943                 if(p==0 || *p=='\0')
00944                         ap->ops|=AVPOPS_FLAG_ALL;
00945 
00946                 /* flags */
00947                 for( ; p&&*p ; p++ )
00948                 {
00949                         switch (*p) {
00950                                 case 'e':
00951                                 case 'E':
00952                                         ap->ops|=AVPOPS_FLAG_EMPTY;
00953                                         break;
00954                                 case 'n':
00955                                 case 'N':
00956                                         if(ap->ops&AVPOPS_FLAG_CASTS)
00957                                         {
00958                                                 LM_ERR("invalid flag combination <%c> and 's|S'\n",*p);
00959                                                 return E_UNSPEC;
00960                                         }
00961                                         ap->ops|=AVPOPS_FLAG_CASTN;
00962                                         break;
00963                                 case 's':
00964                                 case 'S':
00965                                         if(ap->ops&AVPOPS_FLAG_CASTN)
00966                                         {
00967                                                 LM_ERR("invalid flag combination <%c> and 'n|N'\n",*p);
00968                                                 return E_UNSPEC;
00969                                         }
00970                                         ap->ops|=AVPOPS_FLAG_CASTS;
00971                                         break;
00972                                 default:
00973                                         LM_ERR("bad flag <%c>\n",*p);
00974                                         return E_UNSPEC;
00975                         }
00976                 }
00977                 
00978                 *param=(void*)ap;
00979         }
00980 
00981         return 0;
00982 }
00983 
00984 static int w_dbload_avps(struct sip_msg* msg, char* source, char* param)
00985 {
00986         return ops_dbload_avps ( msg, (struct fis_param*)source,
00987                                                                 (struct db_param*)param, use_domain);
00988 }
00989 
00990 static int w_dbdelete_avps(struct sip_msg* msg, char* source, char* param)
00991 {
00992         return ops_dbdelete_avps ( msg, (struct fis_param*)source,
00993                                                                 (struct db_param*)param, use_domain);
00994 }
00995 
00996 static int w_dbstore_avps(struct sip_msg* msg, char* source, char* param)
00997 {
00998         return ops_dbstore_avps ( msg, (struct fis_param*)source,
00999                                                                 (struct db_param*)param, use_domain);
01000 }
01001 
01002 static int w_dbquery1_avps(struct sip_msg* msg, char* query, char* param)
01003 {
01004         return ops_dbquery_avps ( msg, (pv_elem_t*)query, 0);
01005 }
01006 
01007 static int w_dbquery2_avps(struct sip_msg* msg, char* query, char* dest)
01008 {
01009         return ops_dbquery_avps ( msg, (pv_elem_t*)query, (pvname_list_t*)dest);
01010 }
01011 
01012 static int w_delete_avps(struct sip_msg* msg, char* param, char* foo)
01013 {
01014         return ops_delete_avp ( msg, (struct fis_param*)param);
01015 }
01016 
01017 static int w_copy_avps(struct sip_msg* msg, char* name1, char *name2)
01018 {
01019         return ops_copy_avp ( msg, (struct fis_param*)name1,
01020                                                                 (struct fis_param*)name2);
01021 }
01022 
01023 static int w_pushto_avps(struct sip_msg* msg, char* destination, char *param)
01024 {
01025         return ops_pushto_avp ( msg, (struct fis_param*)destination,
01026                                                                 (struct fis_param*)param);
01027 }
01028 
01029 static int w_check_avps(struct sip_msg* msg, char* param, char *check)
01030 {
01031         return ops_check_avp ( msg, (struct fis_param*)param,
01032                                                                 (struct fis_param*)check);
01033 }
01034 
01035 static int w_op_avps(struct sip_msg* msg, char* param, char *op)
01036 {
01037         return ops_op_avp ( msg, (struct fis_param**)param,
01038                                                                 (struct fis_param*)op);
01039 }
01040 
01041 static int w_subst(struct sip_msg* msg, char* src, char *subst)
01042 {
01043         return ops_subst(msg, (struct fis_param**)src, (struct subst_expr*)subst);
01044 }
01045 
01046 static int w_is_avp_set(struct sip_msg* msg, char* param, char *op)
01047 {
01048         return ops_is_avp_set(msg, (struct fis_param*)param);
01049 }
01050 
01051 static int w_print_avps(struct sip_msg* msg, char* foo, char *bar)
01052 {
01053         return ops_print_avp();
01054 }
01055