00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdlib.h>
00032 #include <ctype.h>
00033
00034 #include "../../ut.h"
00035 #include "../../dprint.h"
00036 #include "../../usr_avp.h"
00037 #include "../../mem/mem.h"
00038 #include "avpops_parse.h"
00039
00040
00041 #define SCHEME_UUID_COL "uuid_col"
00042 #define SCHEME_UUID_COL_LEN (sizeof(SCHEME_UUID_COL)-1)
00043 #define SCHEME_USERNAME_COL "username_col"
00044 #define SCHEME_USERNAME_COL_LEN (sizeof(SCHEME_USERNAME_COL)-1)
00045 #define SCHEME_DOMAIN_COL "domain_col"
00046 #define SCHEME_DOMAIN_COL_LEN (sizeof(SCHEME_DOMAIN_COL)-1)
00047 #define SCHEME_VALUE_COL "value_col"
00048 #define SCHEME_VALUE_COL_LEN (sizeof(SCHEME_VALUE_COL)-1)
00049 #define SCHEME_TABLE "table"
00050 #define SCHEME_TABLE_LEN (sizeof(SCHEME_TABLE)-1)
00051 #define SCHEME_VAL_TYPE "value_type"
00052 #define SCHEME_VAL_TYPE_LEN (sizeof(SCHEME_VAL_TYPE)-1)
00053 #define SCHEME_INT_TYPE "integer"
00054 #define SCHEME_INT_TYPE_LEN (sizeof(SCHEME_INT_TYPE)-1)
00055 #define SCHEME_STR_TYPE "string"
00056 #define SCHEME_STR_TYPE_LEN (sizeof(SCHEME_STR_TYPE)-1)
00057
00058 struct fis_param *avpops_parse_pvar(char *in)
00059 {
00060 struct fis_param *ap;
00061 str s;
00062
00063
00064 ap = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));
00065 if (ap==0)
00066 {
00067 LM_ERR("no more pkg mem\n");
00068 return NULL;
00069 }
00070 memset( ap, 0, sizeof(struct fis_param));
00071 s.s = in; s.len = strlen(s.s);
00072 if(pv_parse_spec(&s, &ap->u.sval)==0)
00073 {
00074 pkg_free(ap);
00075 return NULL;
00076 }
00077
00078 ap->opd |= AVPOPS_VAL_PVAR;
00079 ap->type = AVPOPS_VAL_PVAR;
00080 return ap;
00081 }
00082
00083
00084 int parse_avp_db(char *s, struct db_param *dbp, int allow_scheme)
00085 {
00086 unsigned long ul;
00087 str tmp;
00088 str s0;
00089 char have_scheme;
00090 char *p;
00091 char *p0;
00092 unsigned int flags;
00093
00094 tmp.s = s;
00095
00096 p0=strchr(tmp.s, '/');
00097 if(p0!=NULL)
00098 *p0=0;
00099 if ( *s!='$')
00100 {
00101 if(strlen(s)<1)
00102 {
00103 LM_ERR("bad param - expected : $avp(name), *, s or i value\n");
00104 return E_UNSPEC;
00105 }
00106 switch(*s) {
00107 case 's': case 'S':
00108 dbp->a.opd = AVPOPS_VAL_NONE|AVPOPS_VAL_STR;
00109 break;
00110 case 'i': case 'I':
00111 dbp->a.opd = AVPOPS_VAL_NONE|AVPOPS_VAL_INT;
00112 break;
00113 case '*': case 'a': case 'A':
00114 dbp->a.opd = AVPOPS_VAL_NONE;
00115 break;
00116 default:
00117 LM_ERR("bad param - expected : *, s or i AVP flag\n");
00118 return E_UNSPEC;
00119 }
00120
00121 flags = 0;
00122 if(*(s+1)!='\0')
00123 {
00124 s0.s = s+1;
00125 s0.len = strlen(s0.s);
00126 if(str2int(&s0, &flags)!=0)
00127 {
00128 LM_ERR("error - bad avp flags\n");
00129 goto error;
00130 }
00131 }
00132 dbp->a.u.sval.pvp.pvn.u.isname.type |= (flags<<8)&0xff00;
00133 dbp->a.type = AVPOPS_VAL_NONE;
00134 } else {
00135 s0.s = s; s0.len = strlen(s0.s);
00136 p = pv_parse_spec(&s0, &dbp->a.u.sval);
00137 if (p==0 || *p!='\0' || dbp->a.u.sval.type!=PVT_AVP)
00138 {
00139 LM_ERR("bad param - expected : $avp(name) or int/str value\n");
00140 return E_UNSPEC;
00141 }
00142 dbp->a.type = AVPOPS_VAL_PVAR;
00143 }
00144
00145
00146
00147 if (dbp->a.type == AVPOPS_VAL_PVAR)
00148 {
00149 dbp->a.opd = AVPOPS_VAL_PVAR;
00150 if(pv_has_sname(&dbp->a.u.sval))
00151 {
00152 dbp->sa.s=(char*)pkg_malloc(
00153 dbp->a.u.sval.pvp.pvn.u.isname.name.s.len+1);
00154 if (dbp->sa.s==0)
00155 {
00156 LM_ERR("no more pkg mem\n");
00157 goto error;
00158 }
00159 memcpy(dbp->sa.s, dbp->a.u.sval.pvp.pvn.u.isname.name.s.s,
00160 dbp->a.u.sval.pvp.pvn.u.isname.name.s.len);
00161 dbp->sa.len = dbp->a.u.sval.pvp.pvn.u.isname.name.s.len;
00162 dbp->sa.s[dbp->sa.len] = 0;
00163 dbp->a.opd = AVPOPS_VAL_PVAR|AVPOPS_VAL_STR;
00164 } else if(pv_has_iname(&dbp->a.u.sval)) {
00165 ul = (unsigned long)dbp->a.u.sval.pvp.pvn.u.isname.name.n;
00166 tmp.s = int2str( ul, &(tmp.len) );
00167 dbp->sa.s = (char*)pkg_malloc( tmp.len + 1 );
00168 if (dbp->sa.s==0)
00169 {
00170 LM_ERR("no more pkg mem\n");
00171 goto error;
00172 }
00173 memcpy( dbp->sa.s, tmp.s, tmp.len);
00174 dbp->sa.len = tmp.len;
00175 dbp->sa.s[dbp->sa.len] = 0;
00176 dbp->a.opd = AVPOPS_VAL_PVAR|AVPOPS_VAL_INT;
00177 }
00178 }
00179
00180
00181 if(p0)
00182 *p0 = '/';
00183
00184 s = p0;
00185 if (s && *s)
00186 {
00187 s++;
00188 if (*s=='$')
00189 {
00190 if (allow_scheme==0)
00191 {
00192 LM_ERR("function doesn't support DB schemes\n");
00193 goto error;
00194 }
00195 if (dbp->a.opd&AVPOPS_VAL_NONE)
00196 {
00197 LM_ERR("inconsistent usage of "
00198 "DB scheme without complet specification of AVP name\n");
00199 goto error;
00200 }
00201 have_scheme = 1;
00202 s++;
00203 } else {
00204 have_scheme = 0;
00205 }
00206 tmp.s = s;
00207 tmp.len = 0;
00208 while ( *s ) s++;
00209 tmp.len = s - tmp.s;
00210 if (tmp.len==0)
00211 {
00212 LM_ERR("empty scheme/table name\n");
00213 goto error;
00214 }
00215 if (have_scheme)
00216 {
00217 dbp->scheme = avp_get_db_scheme( &tmp );
00218 if (dbp->scheme==0)
00219 {
00220 LM_ERR("scheme <%s> not found\n", tmp.s);
00221 goto error;
00222 }
00223
00224 dbp->scheme->db_flags|=dbp->a.opd&AVPOPS_VAL_STR?AVP_NAME_STR:0;
00225 } else {
00226
00227 pkg_str_dup(&dbp->table, &tmp);
00228 }
00229 }
00230
00231 return 0;
00232 error:
00233 return -1;
00234 }
00235
00236
00237 struct fis_param* parse_intstr_value(char *p, int len)
00238 {
00239 struct fis_param *vp;
00240 unsigned int uint;
00241 str val_str;
00242 int flags;
00243
00244 if (p==0 || len==0)
00245 goto error;
00246
00247 if (len>1 && *(p+1)==':')
00248 {
00249 if (*p=='i' || *p=='I')
00250 flags = AVPOPS_VAL_INT;
00251 else if (*p=='s' || *p=='S')
00252 flags = AVPOPS_VAL_STR;
00253 else
00254 {
00255 LM_ERR("unknown value type <%c>\n",*p);
00256 goto error;
00257 }
00258 p += 2;
00259 len -= 2;
00260 if (*p==0 || len<=0 )
00261 {
00262 LM_ERR("parse error arround <%.*s>\n",len,p);
00263 goto error;
00264 }
00265 } else {
00266 flags = AVPOPS_VAL_STR;
00267 }
00268
00269 vp = (struct fis_param*)pkg_malloc(sizeof(struct fis_param));
00270 if (vp==0)
00271 {
00272 LM_ERR("no more pkg mem\n");
00273 goto error;;
00274 }
00275 memset( vp, 0, sizeof(struct fis_param));
00276 vp->opd = flags;
00277 val_str.s = p;
00278 val_str.len = len;
00279 if (flags&AVPOPS_VAL_INT) {
00280
00281 if(val_str.len>2 && p[0]=='0' && (p[1]=='x' || p[1]=='X'))
00282 {
00283 if(hexstr2int(val_str.s+2, val_str.len-2, &uint))
00284 {
00285 LM_ERR("value is not hex int as type says <%.*s>\n",
00286 val_str.len, val_str.s);
00287 goto error;
00288 }
00289 } else {
00290 if(str2sint( &val_str, (int*)&uint)==-1)
00291 {
00292 LM_ERR("value is not int"
00293 " as type says <%.*s>\n", val_str.len, val_str.s);
00294 goto error;
00295 }
00296 }
00297 vp->u.n = (int)uint;
00298 vp->type = AVPOPS_VAL_INT;
00299 } else {
00300
00301 vp->u.s.s = (char*)pkg_malloc((val_str.len+1)*sizeof(char));
00302 if (vp->u.s.s==0)
00303 {
00304 LM_ERR("no more pkg mem\n");
00305 goto error;
00306 }
00307 vp->u.s.len = val_str.len;
00308 memcpy(vp->u.s.s, val_str.s, val_str.len);
00309 vp->u.s.s[vp->u.s.len] = 0;
00310 vp->type = AVPOPS_VAL_STR;
00311 }
00312
00313 return vp;
00314 error:
00315 return 0;
00316 }
00317
00318
00319 #define duplicate_str(_p, _str, _error) \
00320 do { \
00321 _p.s = (char*)pkg_malloc(_str.len+1); \
00322 if (_p.s==0) \
00323 { \
00324 LM_ERR("no more pkg memory\n");\
00325 goto _error; \
00326 } \
00327 _p.len = _str.len; \
00328 memcpy( _p.s, _str.s, _str.len); \
00329 _p.s[_str.len] = 0; \
00330 }while(0)
00331
00332 int parse_avp_db_scheme( char *s, struct db_scheme *scheme)
00333 {
00334 str foo;
00335 str bar;
00336 char *p;
00337
00338 if (s==0 || *s==0)
00339 goto error;
00340 p = s;
00341
00342
00343 while (*p && isspace((int)*p)) p++;
00344 foo.s = p;
00345 while (*p && *p!=':' && !isspace((int)*p)) p++;
00346 if (foo.s==p || *p==0)
00347
00348 goto parse_error;
00349 foo.len = p - foo.s;
00350
00351 duplicate_str( scheme->name, foo, error);
00352
00353
00354 while (*p && isspace((int)*p)) p++;
00355 if (*p!=':')
00356 goto parse_error;
00357 p++;
00358 while (*p && isspace((int)*p)) p++;
00359 if (*p==0)
00360 goto parse_error;
00361
00362
00363 scheme->db_flags = AVP_VAL_STR;
00364
00365
00366 while (*p)
00367 {
00368
00369 foo.s = p;
00370 while (*p && *p!='=' && !isspace((int)*p)) p++;
00371 if (p==foo.s || *p==0)
00372
00373 goto parse_error;
00374 foo.len = p - foo.s;
00375
00376
00377 while (*p && isspace((int)*p)) p++;
00378 if (*p!='=')
00379 goto parse_error;
00380 p++;
00381 while (*p && isspace((int)*p)) p++;
00382 if (*p==0)
00383 goto parse_error;
00384
00385
00386 bar.s = p;
00387 while (*p && *p!=';' && !isspace((int)*p)) p++;
00388 if (p==bar.s)
00389
00390 goto parse_error;
00391 bar.len = p - bar.s;
00392
00393
00394 while (*p && isspace((int)*p)) p++;
00395 if (*p!=0 && *p!=';')
00396 goto parse_error;
00397 if (*p==';') p++;
00398 while (*p && isspace((int)*p)) p++;
00399
00400
00401 if ( foo.len==SCHEME_UUID_COL_LEN &&
00402 !strncasecmp( foo.s, SCHEME_UUID_COL, foo.len) )
00403 {
00404 if (scheme->uuid_col.s) goto parse_error;
00405 duplicate_str( scheme->uuid_col, bar, error);
00406 } else
00407 if ( foo.len==SCHEME_USERNAME_COL_LEN &&
00408 !strncasecmp( foo.s, SCHEME_USERNAME_COL, foo.len) )
00409 {
00410 if (scheme->username_col.s) goto parse_error;
00411 duplicate_str( scheme->username_col, bar, error);
00412 } else
00413 if ( foo.len==SCHEME_DOMAIN_COL_LEN &&
00414 !strncasecmp( foo.s, SCHEME_DOMAIN_COL, foo.len) )
00415 {
00416 if (scheme->domain_col.s) goto parse_error;
00417 duplicate_str( scheme->domain_col, bar, error);
00418 } else
00419 if ( foo.len==SCHEME_VALUE_COL_LEN &&
00420 !strncasecmp( foo.s, SCHEME_VALUE_COL, foo.len) )
00421 {
00422 if (scheme->value_col.s) goto parse_error;
00423 duplicate_str( scheme->value_col, bar, error);
00424 } else
00425 if ( foo.len==SCHEME_TABLE_LEN &&
00426 !strncasecmp( foo.s, SCHEME_TABLE, foo.len) )
00427 {
00428 if (scheme->table.s) goto parse_error;
00429 duplicate_str( scheme->table, bar, error);
00430 } else
00431 if ( foo.len==SCHEME_VAL_TYPE_LEN &&
00432 !strncasecmp( foo.s, SCHEME_VAL_TYPE, foo.len) )
00433 {
00434 if ( bar.len==SCHEME_INT_TYPE_LEN &&
00435 !strncasecmp( bar.s, SCHEME_INT_TYPE, bar.len) )
00436 scheme->db_flags &= (~AVP_VAL_STR);
00437 else if ( bar.len==SCHEME_STR_TYPE_LEN &&
00438 !strncasecmp( bar.s, SCHEME_STR_TYPE, bar.len) )
00439 scheme->db_flags = AVP_VAL_STR;
00440 else
00441 {
00442 LM_ERR("unknown value type <%.*s>\n",bar.len,bar.s);
00443 goto error;
00444 }
00445 } else {
00446 LM_ERR("unknown attribute <%.*s>\n",foo.len,foo.s);
00447 goto error;
00448 }
00449 }
00450
00451 return 0;
00452 parse_error:
00453 LM_ERR("parse error in <%s> around %ld\n", s, (long)(p-s));
00454 error:
00455 return -1;
00456 }
00457
00458 struct fis_param* parse_check_value(char *s)
00459 {
00460 struct fis_param *vp;
00461 int ops;
00462 int opd;
00463 char *p;
00464 char *t;
00465 int len;
00466
00467 ops = 0;
00468 opd = 0;
00469 vp = 0;
00470
00471 if ( (p=strchr(s,'/'))==0 || (p-s!=2&&p-s!=3) )
00472 goto parse_error;
00473
00474 if (strncasecmp(s,"eq",2)==0) {
00475 ops |= AVPOPS_OP_EQ;
00476 } else if (strncasecmp(s,"ne",2)==0) {
00477 ops |= AVPOPS_OP_NE;
00478 } else if (strncasecmp(s,"lt",2)==0) {
00479 ops |= AVPOPS_OP_LT;
00480 } else if (strncasecmp(s,"le",2)==0) {
00481 ops |= AVPOPS_OP_LE;
00482 } else if (strncasecmp(s,"gt",2)==0) {
00483 ops |= AVPOPS_OP_GT;
00484 } else if (strncasecmp(s,"ge",2)==0) {
00485 ops |= AVPOPS_OP_GE;
00486 } else if (strncasecmp(s,"re",2)==0) {
00487 ops |= AVPOPS_OP_RE;
00488 } else if (strncasecmp(s,"fm",2)==0) {
00489 ops |= AVPOPS_OP_FM;
00490 } else if (strncasecmp(s,"and",3)==0) {
00491 ops |= AVPOPS_OP_BAND;
00492 } else if (strncasecmp(s,"or",2)==0) {
00493 ops |= AVPOPS_OP_BOR;
00494 } else if (strncasecmp(s,"xor",3)==0) {
00495 ops |= AVPOPS_OP_BXOR;
00496 } else {
00497 LM_ERR("unknown operation <%.*s>\n",2,s);
00498 goto error;
00499 }
00500
00501 if (*(++p)==0)
00502 goto parse_error;
00503 if ( (t=strchr(p,'/'))==0)
00504 len = strlen(p);
00505 else
00506 len = t-p;
00507
00508 if (*p=='$')
00509 {
00510
00511 vp = avpops_parse_pvar(p);
00512 if (vp==0)
00513 {
00514 LM_ERR("unable to get pseudo-variable\n");
00515 goto error;
00516 }
00517 if (vp->u.sval.type==PVT_NULL)
00518 {
00519 LM_ERR("bad param; expected : $pseudo-variable or int/str value\n");
00520 goto error;
00521 }
00522 opd |= AVPOPS_VAL_PVAR;
00523 LM_DBG("flag==%d/%d\n", opd, ops);
00524 } else {
00525
00526 if ( (vp=parse_intstr_value(p,len))==0) {
00527 LM_ERR("unable to parse value\n");
00528 goto error;
00529 }
00530 }
00531
00532 p = t;
00533
00534 if (p!=NULL && *p!=0)
00535 {
00536 if (*p!='/' || *(++p)==0)
00537 goto parse_error;
00538 while (*p)
00539 {
00540 switch (*p)
00541 {
00542 case 'g':
00543 case 'G':
00544 ops|=AVPOPS_FLAG_ALL;
00545 break;
00546 case 'i':
00547 case 'I':
00548 ops|=AVPOPS_FLAG_CI;
00549 break;
00550 default:
00551 LM_ERR("unknown flag <%c>\n",*p);
00552 goto error;
00553 }
00554 p++;
00555 }
00556 }
00557
00558 vp->ops |= ops;
00559 vp->opd |= opd;
00560 return vp;
00561 parse_error:
00562 LM_ERR("parse error in <%s> pos %ld\n", s,(long)(p-s));
00563 error:
00564 if (vp) pkg_free(vp);
00565 return 0;
00566 }
00567
00568 struct fis_param* parse_op_value(char *s)
00569 {
00570 struct fis_param *vp;
00571 int ops;
00572 int opd;
00573 char *p;
00574 char *t;
00575 int len;
00576
00577 ops = 0;
00578 opd = 0;
00579 vp = 0;
00580
00581 if ( (p=strchr(s,'/'))==0 || (p-s!=2&&p-s!=3) )
00582 goto parse_error;
00583
00584 if (strncasecmp(s,"add",3)==0) {
00585 ops |= AVPOPS_OP_ADD;
00586 } else if (strncasecmp(s,"sub",3)==0) {
00587 ops |= AVPOPS_OP_SUB;
00588 } else if (strncasecmp(s,"mul",3)==0) {
00589 ops |= AVPOPS_OP_MUL;
00590 } else if (strncasecmp(s,"div",3)==0) {
00591 ops |= AVPOPS_OP_DIV;
00592 } else if (strncasecmp(s,"mod",3)==0) {
00593 ops |= AVPOPS_OP_MOD;
00594 } else if (strncasecmp(s,"and",3)==0) {
00595 ops |= AVPOPS_OP_BAND;
00596 } else if (strncasecmp(s,"or",2)==0) {
00597 ops |= AVPOPS_OP_BOR;
00598 } else if (strncasecmp(s,"xor",3)==0) {
00599 ops |= AVPOPS_OP_BXOR;
00600 } else if (strncasecmp(s,"not",3)==0) {
00601 ops |= AVPOPS_OP_BNOT;
00602 } else {
00603 LM_ERR("unknown operation <%.*s>\n",2,s);
00604 goto error;
00605 }
00606
00607 if (*(++p)==0)
00608 goto parse_error;
00609 if ( (t=strchr(p,'/'))==0)
00610 len = strlen(p);
00611 else
00612 len = t-p;
00613
00614 if (*p=='$')
00615 {
00616
00617 vp = avpops_parse_pvar(p);
00618 if (vp==0)
00619 {
00620 LM_ERR("unable to get pseudo-variable\n");
00621 goto error;
00622 }
00623 if (vp->u.sval.type==PVT_NULL)
00624 {
00625 LM_ERR("bad param; expected : $pseudo-variable or int/str value\n");
00626 goto error;
00627 }
00628 opd |= AVPOPS_VAL_PVAR;
00629 LM_DBG("flag==%d/%d\n", opd, ops);
00630 } else {
00631
00632 if ( (vp=parse_intstr_value(p,len))==0) {
00633 LM_ERR("unable to parse value\n");
00634 goto error;
00635 }
00636 if((vp->opd&AVPOPS_VAL_INT)==0) {
00637 LM_ERR("value must be int\n");
00638 goto error;
00639 }
00640 }
00641
00642
00643 p = t;
00644 if (p!=0 && *p!=0 )
00645 {
00646 if (*p!='/' || *(++p)==0)
00647 goto parse_error;
00648 while (*p)
00649 {
00650 switch (*p)
00651 {
00652 case 'g':
00653 case 'G':
00654 ops|=AVPOPS_FLAG_ALL;
00655 break;
00656 case 'd':
00657 case 'D':
00658 ops|=AVPOPS_FLAG_DELETE;
00659 break;
00660 default:
00661 LM_ERR("unknown flag <%c>\n",*p);
00662 goto error;
00663 }
00664 p++;
00665 }
00666 }
00667
00668 vp->ops |= ops;
00669 vp->opd |= opd;
00670 return vp;
00671 parse_error:
00672 LM_ERR("parse error in <%s> pos %ld\n", s,(long)(p-s));
00673 error:
00674 if (vp) pkg_free(vp);
00675 return 0;
00676 }
00677