Module: sip-router Branch: master Commit: 33c5fc98db553ae28385608890df1a883aaa51d4 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=33c5fc98...
Author: Alex Hermann alex@speakup.nl Committer: Alex Hermann alex@speakup.nl Date: Thu Aug 11 13:19:21 2011 +0200
modules/textops: allow pseudovariables in re.subst parameter
---
modules_k/textops/txt_var.c | 142 +++++++++++++++++++++++++++++------------- 1 files changed, 98 insertions(+), 44 deletions(-)
diff --git a/modules_k/textops/txt_var.c b/modules_k/textops/txt_var.c index a13e5e1..adcb860 100644 --- a/modules_k/textops/txt_var.c +++ b/modules_k/textops/txt_var.c @@ -42,6 +42,7 @@ int tr_txt_eval_re(struct sip_msg *msg, tr_param_t *tp, int subtype, str* result; #define TR_TXT_BUF_SIZE 2048 static char tr_txt_buf[TR_TXT_BUF_SIZE]; + pv_value_t v;
if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0) return -1; @@ -49,14 +50,31 @@ int tr_txt_eval_re(struct sip_msg *msg, tr_param_t *tp, int subtype, switch(subtype) { case TR_TXT_RE_SUBST: - se = (struct subst_expr*)tp->v.data; - if(se==NULL) - return 0; + if (tp->type == TR_PARAM_SUBST) { + se = (struct subst_expr*)tp->v.data; + if (se==NULL) + return 0; + } else if (tp->type == TR_PARAM_SPEC) { + if (pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0 + || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0) + { + LM_ERR("Can't evaluate regexp\n"); + return -1; + } + se=subst_parser(&v.rs); + if (se==0) { + LM_ERR("Can't compile regexp\n"); + return -1; + } + } else { + LM_ERR("Unknown parameter type\n"); + return -1; + } if(val->rs.len>=TR_TXT_BUF_SIZE-1) { LM_ERR("PV value too big %d, increase buffer size\n", val->rs.len); - return -1; + goto error; } memcpy(tr_txt_buf, val->rs.s, val->rs.len); tr_txt_buf[val->rs.len] = '\0'; @@ -67,17 +85,17 @@ int tr_txt_eval_re(struct sip_msg *msg, tr_param_t *tp, int subtype, if (nmatches==0) { LM_DBG("no match for subst expression\n"); - return 0; + break; } if (nmatches<0) LM_ERR("subst failed\n"); - return -1; + goto error; } if(result->len>=TR_TXT_BUF_SIZE-1) { LM_ERR("subst result too big %d, increase buffer size\n", result->len); - return -1; + goto error; } memcpy(tr_txt_buf, result->s, result->len); tr_txt_buf[result->len] = '\0'; @@ -90,20 +108,80 @@ int tr_txt_eval_re(struct sip_msg *msg, tr_param_t *tp, int subtype, break; default: LM_ERR("unknown subtype %d\n", subtype); - return -1; + goto error; + } + + if (tp->type == TR_PARAM_SPEC) { + subst_expr_free(se); } return 0;
+error: + if (tp->type == TR_PARAM_SPEC) { + subst_expr_free(se); + } + return -1; }
+#define _tr_parse_sparam(_p, _p0, _tp, _spec, _ps, _in, _s) \ + while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) _p++; \ + if(*_p==PV_MARKER) \ + { /* pseudo-variable */ \ + _spec = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t)); \ + if(_spec==NULL) \ + { \ + LM_ERR("no more private memory!\n"); \ + goto error; \ + } \ + _s.s = _p; _s.len = _in->s + _in->len - _p; \ + _p0 = pv_parse_spec(&_s, _spec); \ + if(_p0==NULL) \ + { \ + LM_ERR("invalid spec in substr transformation: %.*s!\n", \ + _in->len, _in->s); \ + goto error; \ + } \ + _p = _p0; \ + _tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t)); \ + if(_tp==NULL) \ + { \ + LM_ERR("no more private memory!\n"); \ + goto error; \ + } \ + memset(_tp, 0, sizeof(tr_param_t)); \ + _tp->type = TR_PARAM_SPEC; \ + _tp->v.data = (void*)_spec; \ + } else { /* string */ \ + _ps = _p; \ + while(is_in_str(_p, _in) && *_p!='\t' && *_p!='\n' \ + && *_p!=TR_PARAM_MARKER && *_p!=TR_RBRACKET) \ + _p++; \ + if(*_p=='\0') \ + { \ + LM_ERR("invalid param in transformation: %.*s!!\n", \ + _in->len, _in->s); \ + goto error; \ + } \ + _tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t)); \ + if(_tp==NULL) \ + { \ + LM_ERR("no more private memory!\n"); \ + goto error; \ + } \ + memset(_tp, 0, sizeof(tr_param_t)); \ + _tp->type = TR_PARAM_STRING; \ + _tp->v.s.s = _ps; \ + _tp->v.s.len = _p - _ps; \ + } + char* tr_txt_parse_re(str *in, trans_t *t) { - char *p; + char *p, *p0, *ps; str name; - str tok; + str s; struct subst_expr *se = NULL; tr_param_t *tp = NULL; - int n; + pv_spec_t *spec = NULL;
if(in==NULL || t==NULL) @@ -127,39 +205,16 @@ char* tr_txt_parse_re(str *in, trans_t *t) if(*p!=TR_PARAM_MARKER) goto error; p++; - /* get trans here */ - n = 0; - tok.s = p; - while(is_in_str(p, in)) - { - if(*p==TR_RBRACKET) - { - if(n==0) - break; - n--; - } - if(*p == TR_LBRACKET) - n++; - p++; - } - if(!is_in_str(p, in)) - goto error; - if(p==tok.s) - goto error; - tok.len = p - tok.s; - tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t)); - if(tp==NULL) - { - LM_ERR("no more private memory!\n"); - goto error; + /* get parameter */ + _tr_parse_sparam(p, p0, tp, spec, ps, in, s); + if (tp->type == TR_PARAM_STRING) { + /* precompile static regexp */ + se=subst_parser(&tp->v.s); + if (se==0) + goto error; + tp->type = TR_PARAM_SUBST; + tp->v.data = (void*)se; } - - se=subst_parser(&tok); - - if (se==0) - goto error; - tp->type = TR_PARAM_SUBST; - tp->v.data = (void*)se; t->params = tp;
while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++; @@ -181,6 +236,5 @@ error: done: t->name = name; return p; - }