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
00037 #include <fnmatch.h>
00038
00039 #include "../../re.h"
00040 #include "../../mem/shm_mem.h"
00041 #include "dialplan.h"
00042
00043
00044 void repl_expr_free(struct subst_expr *se)
00045 {
00046 if(!se)
00047 return;
00048
00049 if(se->replacement.s){
00050 shm_free(se->replacement.s);
00051 se->replacement.s = 0;
00052 }
00053
00054 shm_free(se);
00055 se = 0;
00056 }
00057
00058
00059 struct subst_expr* repl_exp_parse(str subst)
00060 {
00061 struct replace_with rw[MAX_REPLACE_WITH];
00062 int rw_no;
00063 struct subst_expr * se;
00064 int replace_all;
00065 char * p, *end, *repl, *repl_end;
00066 int max_pmatch, r;
00067 str shms;
00068
00069 se = 0;
00070 replace_all = 0;
00071 shms.s = NULL;
00072
00073 if (!(shms.s=shm_malloc((subst.len+1) * sizeof(char))) ){
00074 LM_ERR("out of shm memory\n");
00075 goto error;
00076 }
00077 memcpy(shms.s, subst.s, subst.len);
00078 shms.len = subst.len;
00079 shms.s[shms.len] = '\0';
00080
00081 p = shms.s;
00082 end = p + shms.len;
00083 rw_no = 0;
00084
00085 repl = p;
00086 if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITHOUT_SEP))< 0)
00087 goto error;
00088
00089 repl_end=p;
00090
00091
00092 se = shm_malloc(sizeof(struct subst_expr)+
00093 ((rw_no)?(rw_no-1)*sizeof(struct replace_with):0));
00094
00095 if (se==0){
00096 LM_ERR("out of shm memory (subst_expr)\n");
00097 goto error;
00098 }
00099 memset((void*)se, 0, sizeof(struct subst_expr));
00100
00101 se->replacement.s = shms.s;
00102 shms.s = NULL;
00103 se->replacement.len=repl_end-repl;
00104 if(!rw_no){
00105 replace_all = 1;
00106 }
00107
00108 LM_DBG("replacement expression is [%.*s]\n", se->replacement.len,
00109 se->replacement.s);
00110 se->re=0;
00111 se->replace_all=replace_all;
00112 se->n_escapes=rw_no;
00113 se->max_pmatch=max_pmatch;
00114
00115
00116 for (r=0; r<rw_no; r++) se->replace[r]=rw[r];
00117 return se;
00118
00119 error:
00120 if(shms.s != NULL)
00121 shm_free(shms.s);
00122 if (se) { repl_expr_free(se);}
00123 return NULL;
00124 }
00125
00126
00127 #define MAX_PHONE_NB_DIGITS 127
00128 static char dp_output_buf[MAX_PHONE_NB_DIGITS+1];
00129 int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
00130 str * result)
00131 {
00132 int repl_nb, offset, match_nb, rc, cap_cnt;
00133 struct replace_with token;
00134 pcre *subst_comp;
00135 struct subst_expr * repl_comp;
00136 str match;
00137 pv_value_t sv;
00138 str* uri;
00139 int ovector[3 * (MAX_REPLACE_WITH + 1)];
00140 char *p;
00141 int size;
00142
00143 dp_output_buf[0] = '\0';
00144 result->s = dp_output_buf;
00145 result->len = 0;
00146
00147 subst_comp = rule->subst_comp;
00148 repl_comp = rule->repl_comp;
00149
00150 if(!repl_comp){
00151 LM_DBG("null replacement\n");
00152 return 0;
00153 }
00154
00155 if(subst_comp){
00156
00157 rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT,
00158 &cap_cnt);
00159 if (rc != 0) {
00160 LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n",
00161 rc);
00162 return -1;;
00163 }
00164 if(repl_comp->max_pmatch > cap_cnt){
00165 LM_ERR("illegal access to the %i-th subexpr of the subst expr\n",
00166 repl_comp->max_pmatch);
00167 return -1;
00168 }
00169
00170
00171 if (pcre_exec(rule->subst_comp, NULL, string.s, string.len,
00172 0, 0, ovector, 3 * (MAX_REPLACE_WITH + 1)) <= 0) {
00173 LM_ERR("the string %.*s matched "
00174 "the match_exp %.*s but not the subst_exp %.*s!\n",
00175 string.len, string.s,
00176 rule->match_exp.len, rule->match_exp.s,
00177 rule->subst_exp.len, rule->subst_exp.s);
00178 return -1;
00179 }
00180 }
00181
00182
00183 if(!subst_comp || (repl_comp->n_escapes <=0)){
00184 if(!repl_comp->replacement.s || repl_comp->replacement.len == 0){
00185 LM_ERR("invalid replacing string\n");
00186 goto error;
00187 }
00188 LM_DBG("simply replace the string, subst_comp %p, n_escapes %i\n",
00189 subst_comp, repl_comp->n_escapes);
00190 memcpy(result->s, repl_comp->replacement.s,
00191 repl_comp->replacement.len);
00192 result->len = repl_comp->replacement.len;
00193 result->s[result->len] = '\0';
00194 return 0;
00195 }
00196
00197
00198 result->len = repl_nb = offset = 0;
00199 p=repl_comp->replacement.s;
00200
00201 while( repl_nb < repl_comp->n_escapes){
00202
00203 token = repl_comp->replace[repl_nb];
00204
00205 if(offset< token.offset){
00206 if((repl_comp->replacement.len < offset)||
00207 (result->len + token.offset -offset >= MAX_PHONE_NB_DIGITS)){
00208 LM_ERR("invalid length\n");
00209 goto error;
00210 }
00211
00212 size = token.offset - offset;
00213 memcpy(result->s + result->len, p + offset, size);
00214 LM_DBG("copying <%.*s> from replacing string\n",
00215 size, p + offset);
00216 result->len += size;
00217 offset = token.offset;
00218 }
00219
00220 switch(token.type) {
00221 case REPLACE_NMATCH:
00222
00223 match_nb = token.u.nmatch * 2;
00224 match.s = string.s + ovector[match_nb];
00225 match.len = ovector[match_nb + 1] - ovector[match_nb];
00226 if(result->len + match.len >= MAX_PHONE_NB_DIGITS){
00227 LM_ERR("overflow\n");
00228 goto error;
00229 }
00230
00231 memcpy(result->s + result->len, match.s, match.len);
00232 LM_DBG("copying match <%.*s> token size %d\n",
00233 match.len, match.s, token.size);
00234 result->len += match.len;
00235 offset += token.size;
00236 break;
00237 case REPLACE_CHAR:
00238 if(result->len + 1>= MAX_PHONE_NB_DIGITS){
00239 LM_ERR("overflow\n");
00240 goto error;
00241 }
00242 *(result->s + result->len) = token.u.c;
00243 LM_DBG("copying char <%c> token size %d\n",
00244 token.u.c, token.size);
00245 result->len++;
00246 offset += token.size;
00247 break;
00248 case REPLACE_URI:
00249 if ( msg== NULL || msg->first_line.type!=SIP_REQUEST){
00250 LM_CRIT("uri substitution attempt on no request"
00251 " message\n");
00252 break;
00253 }
00254 uri= (msg->new_uri.s)?(&msg->new_uri):
00255 (&msg->first_line.u.request.uri);
00256 if(result->len+uri->len>=MAX_PHONE_NB_DIGITS){
00257 LM_ERR("overflow\n");
00258 goto error;
00259 }
00260 memcpy(result->s + result->len, uri->s, uri->len);
00261 LM_DBG("copying uri <%.*s> token size %d\n",
00262 uri->len, uri->s, token.size);
00263 result->len+=uri->len;
00264 offset += token.size;
00265 break;
00266 case REPLACE_SPEC:
00267 if (msg== NULL) {
00268 LM_DBG("replace spec attempted on no message\n");
00269 break;
00270 }
00271 if (pv_get_spec_value(msg, &token.u.spec, &sv) != 0) {
00272 LM_CRIT("item substitution returned error\n");
00273 break;
00274 }
00275 if(result->len+sv.rs.len>=MAX_PHONE_NB_DIGITS){
00276 LM_ERR("rule_translate: overflow\n");
00277 goto error;
00278 }
00279 memcpy(result->s + result->len, sv.rs.s,
00280 sv.rs.len);
00281 LM_DBG("copying pvar value <%.*s> token size %d\n",
00282 sv.rs.len, sv.rs.s, token.size);
00283 result->len+=sv.rs.len;
00284 offset += token.size;
00285 break;
00286 default:
00287 LM_CRIT("unknown type %d\n", repl_comp->replace[repl_nb].type);
00288
00289 }
00290 repl_nb++;
00291 }
00292
00293 if( repl_nb && offset < repl_comp->replacement.len){
00294
00295 size = repl_comp->replacement.len - offset;
00296 memcpy(result->s + result->len, p + offset, size);
00297 LM_DBG("copying leftover <%.*s> from replacing string\n",
00298 size, p + offset);
00299 result->len += size;
00300 }
00301
00302 result->s[result->len] = '\0';
00303 return 0;
00304
00305 error:
00306 result->s = 0;
00307 result->len = 0;
00308 return -1;
00309 }
00310
00311 #define DP_MAX_ATTRS_LEN 128
00312 static char dp_attrs_buf[DP_MAX_ATTRS_LEN+1];
00313 int translate(struct sip_msg *msg, str input, str *output, dpl_id_p idp,
00314 str *attrs)
00315 {
00316 dpl_node_p rulep;
00317 dpl_index_p indexp;
00318 int user_len, rez;
00319 char b;
00320
00321 if(!input.s || !input.len) {
00322 LM_ERR("invalid input string\n");
00323 return -1;
00324 }
00325
00326 user_len = input.len;
00327 for(indexp = idp->first_index; indexp!=NULL; indexp = indexp->next)
00328 if(!indexp->len || (indexp->len!=0 && indexp->len == user_len) )
00329 break;
00330
00331 if(!indexp || (indexp!= NULL && !indexp->first_rule)){
00332 LM_DBG("no rule for len %i\n", input.len);
00333 return -1;
00334 }
00335
00336 search_rule:
00337 for(rulep=indexp->first_rule; rulep!=NULL; rulep= rulep->next) {
00338 switch(rulep->matchop) {
00339
00340 case DP_REGEX_OP:
00341 LM_DBG("regex operator testing\n");
00342 rez = pcre_exec(rulep->match_comp, NULL, input.s, input.len,
00343 0, 0, NULL, 0);
00344 break;
00345
00346 case DP_EQUAL_OP:
00347 LM_DBG("equal operator testing\n");
00348 if(rulep->match_exp.len != input.len) {
00349 rez = -1;
00350 } else {
00351 rez = strncmp(rulep->match_exp.s,input.s,input.len);
00352 rez = (rez==0)?0:-1;
00353 }
00354 break;
00355
00356 case DP_FNMATCH_OP:
00357 LM_DBG("fnmatch operator testing\n");
00358 b = input.s[input.len];
00359 input.s[input.len] = '\0';
00360 rez = fnmatch(rulep->match_exp.s, input.s, 0);
00361 input.s[input.len] = b;
00362 rez = (rez==0)?0:-1;
00363 break;
00364
00365 default:
00366 LM_ERR("bogus match operator code %i\n", rulep->matchop);
00367 return -1;
00368 }
00369 if(rez >= 0)
00370 goto repl;
00371 }
00372
00373 if(indexp->len){
00374 for(indexp = indexp->next; indexp!=NULL; indexp = indexp->next)
00375 if(!indexp->len)
00376 break;
00377 if(indexp)
00378 goto search_rule;
00379 }
00380
00381 LM_DBG("no matching rule\n");
00382 return -1;
00383
00384 repl:
00385 LM_DBG("found a matching rule %p: pr %i, match_exp %.*s\n",
00386 rulep, rulep->pr, rulep->match_exp.len, rulep->match_exp.s);
00387
00388 if(attrs) {
00389 attrs->len = 0;
00390 attrs->s = 0;
00391 if(rulep->attrs.len>0) {
00392 LM_DBG("the rule's attrs are %.*s\n",
00393 rulep->attrs.len, rulep->attrs.s);
00394 if(rulep->attrs.len >= DP_MAX_ATTRS_LEN) {
00395 LM_ERR("out of memory for attributes\n");
00396 return -1;
00397 }
00398 attrs->s = dp_attrs_buf;
00399 memcpy(attrs->s, rulep->attrs.s, rulep->attrs.len*sizeof(char));
00400 attrs->len = rulep->attrs.len;
00401 attrs->s[attrs->len] = '\0';
00402
00403 LM_DBG("the copied attributes are: %.*s\n",
00404 attrs->len, attrs->s);
00405 }
00406 }
00407
00408 if(rule_translate(msg, input, rulep, output)!=0){
00409 LM_ERR("could not build the output\n");
00410 return -1;
00411 }
00412
00413 return 0;
00414 }