Module: sip-router
Branch: master
Commit: 33c5fc98db553ae28385608890df1a883aaa51d4
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=33c5fc9…
Author: Alex Hermann <alex(a)speakup.nl>
Committer: Alex Hermann <alex(a)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;
-
}