mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
5.3 KiB
249 lines
5.3 KiB
/*
|
|
* Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
|
|
*
|
|
* This file is part of kamailio, a free SIP server.
|
|
*
|
|
* Kamailio is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
* Kamailio is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*!
|
|
* \file
|
|
* \brief Regular expressions
|
|
* \ingroup textops
|
|
* Module: \ref textops
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include "../../mem/mem.h"
|
|
#include "../../dprint.h"
|
|
#include "../../trim.h"
|
|
#include "../../re.h"
|
|
#include "../../ut.h"
|
|
|
|
#include "txt_var.h"
|
|
|
|
int tr_txt_eval_re(struct sip_msg *msg, tr_param_t *tp, int subtype,
|
|
pv_value_t *val)
|
|
{
|
|
struct subst_expr *se = NULL;
|
|
int nmatches;
|
|
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;
|
|
|
|
switch(subtype)
|
|
{
|
|
case TR_TXT_RE_SUBST:
|
|
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);
|
|
goto error;
|
|
}
|
|
memcpy(tr_txt_buf, val->rs.s, val->rs.len);
|
|
tr_txt_buf[val->rs.len] = '\0';
|
|
/* pkg malloc'ed result */
|
|
result=subst_str(tr_txt_buf, msg, se, &nmatches);
|
|
if (result == NULL)
|
|
{
|
|
if (nmatches==0)
|
|
{
|
|
LM_DBG("no match for subst expression\n");
|
|
break;
|
|
}
|
|
if (nmatches<0)
|
|
LM_ERR("subst failed\n");
|
|
goto error;
|
|
}
|
|
if(result->len>=TR_TXT_BUF_SIZE-1)
|
|
{
|
|
LM_ERR("subst result too big %d, increase buffer size\n",
|
|
result->len);
|
|
pkg_free(result->s);
|
|
pkg_free(result);
|
|
goto error;
|
|
}
|
|
memcpy(tr_txt_buf, result->s, result->len);
|
|
tr_txt_buf[result->len] = '\0';
|
|
memset(val, 0, sizeof(pv_value_t));
|
|
val->flags = PV_VAL_STR;
|
|
val->rs.s = tr_txt_buf;
|
|
val->rs.len = result->len;
|
|
pkg_free(result->s);
|
|
pkg_free(result);
|
|
break;
|
|
default:
|
|
LM_ERR("unknown subtype %d\n", subtype);
|
|
goto error;
|
|
}
|
|
|
|
if (tp->type == TR_PARAM_SPEC) {
|
|
subst_expr_free(se);
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
if (tp->type == TR_PARAM_SPEC && se!=NULL) {
|
|
subst_expr_free(se);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
char* tr_txt_parse_re(str *in, trans_t *t)
|
|
{
|
|
char *p;
|
|
str name;
|
|
str tok;
|
|
struct subst_expr *se = NULL;
|
|
tr_param_t *tp = NULL;
|
|
int n;
|
|
pv_spec_t *spec = NULL;
|
|
|
|
|
|
if(in==NULL || t==NULL)
|
|
return NULL;
|
|
|
|
p = in->s;
|
|
name.s = in->s;
|
|
t->type = TR_TXT_RE;
|
|
t->trf = tr_txt_eval_re;
|
|
|
|
/* find next token */
|
|
while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
|
|
if(*p=='\0')
|
|
goto error;
|
|
name.len = p - name.s;
|
|
trim(&name);
|
|
|
|
if(name.len==5 && strncasecmp(name.s, "subst", 5)==0)
|
|
{
|
|
t->subtype = TR_TXT_RE_SUBST;
|
|
if(*p!=TR_PARAM_MARKER)
|
|
goto error;
|
|
p++;
|
|
if(*p==PV_MARKER) {
|
|
spec = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
|
|
if(spec==NULL)
|
|
{
|
|
LM_ERR("no more private memory!\n");
|
|
return 0;
|
|
}
|
|
tok.s = p; tok.len = in->s + in->len - p;
|
|
p = pv_parse_spec(&tok, spec);
|
|
if(p==NULL)
|
|
{
|
|
LM_ERR("invalid pv spec in transformation: %.*s!\n",
|
|
in->len, in->s);
|
|
pkg_free(spec);
|
|
return 0;
|
|
}
|
|
|
|
tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t));
|
|
if(tp==NULL)
|
|
{
|
|
LM_ERR("no more private memory!\n");
|
|
pkg_free(spec);
|
|
goto error;
|
|
}
|
|
tp->type = TR_PARAM_SPEC;
|
|
tp->v.data = (void*)spec;
|
|
} else {
|
|
/* 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;
|
|
}
|
|
|
|
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++;
|
|
if(*p!=TR_RBRACKET)
|
|
goto error;
|
|
goto done;
|
|
}
|
|
|
|
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
|
|
name.len, name.s, name.len);
|
|
error:
|
|
LM_ERR("invalid transformation [%.*s] <%d>\n", in->len, in->s,
|
|
(int)(p-in->s));
|
|
if(tp!=NULL)
|
|
pkg_free(tp);
|
|
if(se!=NULL)
|
|
subst_expr_free(se);
|
|
return NULL;
|
|
done:
|
|
t->name = name;
|
|
return p;
|
|
}
|
|
|